CrypteCipher/bindings/src/lib.rs
MoCipher 267d8f6edd
Some checks failed
CI / build (macos-latest, stable) (push) Has been cancelled
CI / build (ubuntu-latest, stable) (push) Has been cancelled
CI / build (windows-latest, stable) (push) Has been cancelled
Initial CrypteCipher scaffold and features
2026-02-12 00:02:00 +01:00

272 lines
10 KiB
Rust

use napi::bindgen_prelude::*;
use napi_derive::napi;
use cryptec_core::{WalletCore, Mnemonic, BdkWallet, LightningClient, encrypt_seed_file, decrypt_seed_file, LndClient, LedgerHw};
#[napi]
fn core_fingerprint() -> String {
let w = WalletCore::new();
w.fingerprint()
}
#[napi]
fn core_generate_seed_hex() -> String {
let s = WalletCore::generate_seed();
hex::encode(s)
}
#[napi]
fn core_example_btc_privkey_hex() -> String {
let w = WalletCore::new();
w.example_btc_privkey_hex()
}
#[napi]
fn generate_mnemonic(strength: u32) -> String {
// strength should be 128, 160, 192, 224, 256
let m = Mnemonic::generate(strength as usize);
m.phrase
}
#[napi]
fn bdk_first_receive_address(phrase: String) -> String {
// For simplicity use Testnet; in real binding allow network selection
let w = BdkWallet::new_from_mnemonic(&phrase, "", bitcoin::Network::Testnet).expect("create wallet");
w.get_new_address().expect("get address")
}
#[napi]
fn bdk_sync_electrum(phrase: String, electrum_url: String) -> String {
let w = BdkWallet::new_from_mnemonic(&phrase, "", bitcoin::Network::Testnet).expect("create wallet");
w.sync_with_electrum(&electrum_url).expect("sync");
"ok".to_string()
}
#[napi]
fn bdk_create_psbt(phrase: String, to_address: String, satoshis: u64) -> String {
let w = BdkWallet::new_from_mnemonic(&phrase, "", bitcoin::Network::Testnet).expect("create wallet");
w.create_psbt(&to_address, satoshis).expect("create psbt")
}
#[napi]
fn bdk_sign_psbt(phrase: String, psbt_b64: String) -> String {
let w = BdkWallet::new_from_mnemonic(&phrase, "", bitcoin::Network::Testnet).expect("create wallet");
w.sign_psbt_base64(&psbt_b64).expect("sign psbt")
}
#[napi]
fn bdk_create_persistent_wallet(phrase: String, db_path: String) -> String {
let w = PersistentBdkWallet::new_from_mnemonic_sqlite(&phrase, "", bitcoin::Network::Testnet, &db_path).expect("create persistent");
w.get_new_address().expect("get address")
}
#[napi]
fn bdk_persistent_sync_electrum(db_path: String, electrum_url: String) -> String {
// open the wallet using the sqlite DB file path
// Note: in a full implementation we'd store wallet metadata/config; here we recreate wallet from DB + descriptors
// For demo purposes require that DB was created with same mnemonic via create_persistent_wallet
let client = PersistentBdkWallet::new_from_mnemonic_sqlite("", "", bitcoin::Network::Testnet, &db_path);
if client.is_err() {
return format!("error: {}", client.err().unwrap());
}
let w = client.unwrap();
w.sync_with_electrum(&electrum_url).expect("sync");
"ok".to_string()
}
#[napi]
fn encrypt_seed(path: String, password: String) -> String {
let seed = WalletCore::generate_seed();
encrypt_seed_file(&seed, &password, &path).expect("encrypt");
"ok".to_string()
}
#[napi]
fn decrypt_seed(path: String, password: String) -> String {
let seed = decrypt_seed_file(&path, &password).expect("decrypt");
hex::encode(seed)
}
#[napi]
fn keystore_generate_db_key(service: String, user: String) -> String {
crate::keystore::generate_db_master_key(&service, &user).expect("generate key");
"ok".to_string()
}
#[napi]
fn bdk_create_encrypted_persistent_wallet(phrase: String, db_path_encrypted: String, service: String, user: String) -> String {
// Uses a temp plaintext DB which is removed after encryption
let network = bitcoin::Network::Testnet;
PersistentBdkWallet::create_encrypted_persistent_wallet(&phrase, "", network, &db_path_encrypted, &service, &user).expect("create encrypted wallet");
"ok".to_string()
}
#[napi]
fn bdk_encrypt_db(plain_path: String, encrypted_path: String, service: String, user: String) -> String {
// ensures master key exists and encrypts a plain DB file
if let Err(_) = crate::keystore::get_db_master_key(&service, &user) {
crate::keystore::generate_db_master_key(&service, &user).expect("generate key");
}
PersistentBdkWallet::encrypt_db_file(&plain_path, &encrypted_path, &service, &user).expect("encrypt db");
"ok".to_string()
}
#[napi]
fn bdk_decrypt_db_to_temp(encrypted_path: String, service: String, user: String) -> String {
let tmp = PersistentBdkWallet::decrypt_db_to_tempfile(&encrypted_path, &service, &user).expect("decrypt tmp");
tmp.path().to_str().unwrap().to_string()
}
#[napi]
fn bdk_decrypted_db_close(path: String) -> String {
// attempt to securely delete the decrypted DB file
let _ = crate::keystore::secure_delete(&path);
"ok".to_string()
}
#[napi]
fn bdk_open_inmemory_db(encrypted_path: String, service: String, user: String) -> String {
let im = InMemoryDb::from_encrypted_file_in_memory(&encrypted_path, &service, &user).expect("open in-memory db");
let id = crate::wallet_manager::register_inmemory_db(im);
id
}
#[napi]
fn bdk_inmemory_table_list(handle_id: String) -> String {
// convenience wrapper using the run query helper to get tables
let q = "SELECT name FROM sqlite_master WHERE type='table'".to_string();
crate::wallet_manager::inmemory_run_query(&handle_id, &q).unwrap_or_else(|_| "[]".to_string())
}
#[napi]
fn bdk_inmemory_run_query(handle_id: String, sql: String) -> String {
crate::wallet_manager::inmemory_run_query(&handle_id, &sql).unwrap_or_else(|_| "[]".to_string())
}
#[napi]
fn bdk_inmemory_export_snapshot(handle_id: String) -> String {
crate::wallet_manager::inmemory_export_snapshot_base64(&handle_id).unwrap_or_else(|_| "".to_string())
}
#[napi]
fn bdk_close_inmemory_handle(handle_id: String) -> String {
let _ = crate::wallet_manager::close_inmemory_db(&handle_id);
"ok".to_string()
}
#[napi]
fn bdk_list_handles() -> String {
let list = crate::wallet_manager::list_handles();
serde_json::to_string(&list).unwrap_or_else(|_| "[]".to_string())
}
#[napi]
fn bdk_close_all_handles() -> String {
let _ = crate::wallet_manager::close_all();
"ok".to_string()
}
#[napi]
fn monero_get_balance(rpc_url: String, user: Option<String>, pass: Option<String>) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.get_balance() {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_get_address(rpc_url: String, user: Option<String>, pass: Option<String>) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.get_address() {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_get_tx_proof(rpc_url: String, user: Option<String>, pass: Option<String>, txid: String, address: Option<String>) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.get_tx_proof(&txid, address.as_deref()) {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_check_tx_proof(rpc_url: String, user: Option<String>, pass: Option<String>, txid: String, address: String, signature: String) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.check_tx_proof(&txid, &address, &signature) {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_transfer(rpc_url: String, user: Option<String>, pass: Option<String>, amount: u64, address: String) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.transfer(amount, &address) {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_create_swap(btc_sats: u64, xmr_piconero: u64, role: String) -> String {
let r = if role == "maker" { SwapRole::Maker } else { SwapRole::Taker };
let s = AtomicSwap::new(r, btc_sats, xmr_piconero);
let js = s.create_swap_contract();
match js {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_make_integrated_address(rpc_url: String, user: Option<String>, pass: Option<String>, payment_id: Option<String>) -> String {
let client = MoneroClient::new(&rpc_url, user.as_deref(), pass.as_deref());
match client.make_integrated_address(payment_id.as_deref()) {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn monero_simulate_swap(btc_sats: u64, xmr_piconero: u64) -> String {
let s = SwapSimulation::new(btc_sats, xmr_piconero);
let offer = s.maker_create_offer();
let proof = s.taker_provide_proof();
let reveal = s.maker_validate_and_reveal(proof.clone());
let prehex = reveal.get("preimage").unwrap().as_str().unwrap().to_string();
let redeem = s.taker_redeem_with_preimage(&prehex);
let out = serde_json::json!({"offer": offer, "proof": proof, "reveal": reveal, "redeem": redeem});
serde_json::to_string(&out).unwrap()
}
#[napi]
fn monero_swap_step(proof: String) -> String {
let v: serde_json::Value = serde_json::from_str(&proof).unwrap_or_else(|_| serde_json::json!(null));
let s = AtomicSwap::new(SwapRole::Taker, 0, 0);
let res = s.validate_and_step(v);
match res {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn lnd_getinfo(host: String, macaroon: Option<String>) -> String {
let client = LndClient::new(&host, macaroon.as_deref());
let v = client.get_info();
match v {
Ok(val) => serde_json::to_string(&val).unwrap_or_else(|_| "{}".to_string()),
Err(e) => format!("error: {}", e)
}
}
#[napi]
fn hardware_ledger_status() -> String {
let l = LedgerHw::new();
if l.connected { "connected".to_string() } else { "disconnected".to_string() }
}