2021-06-21 17:01:53 -07:00
|
|
|
use crate::error::get_name;
|
2021-06-10 17:22:33 -07:00
|
|
|
use ::safer_ffi::prelude::*;
|
|
|
|
use bdk::bitcoin::network::constants::Network::Testnet;
|
|
|
|
use bdk::blockchain::{
|
|
|
|
log_progress, AnyBlockchain, AnyBlockchainConfig, ConfigurableBlockchain,
|
|
|
|
ElectrumBlockchainConfig,
|
|
|
|
};
|
|
|
|
use bdk::database::{AnyDatabase, AnyDatabaseConfig, ConfigurableDatabase};
|
|
|
|
use bdk::wallet::AddressIndex::New;
|
2021-06-19 22:53:26 -07:00
|
|
|
use bdk::{Error, Wallet};
|
2021-06-10 17:22:33 -07:00
|
|
|
use safer_ffi::boxed::Box;
|
|
|
|
use safer_ffi::char_p::{char_p_boxed, char_p_ref};
|
|
|
|
|
|
|
|
#[derive_ReprC]
|
|
|
|
#[ReprC::opaque]
|
2021-06-19 22:53:26 -07:00
|
|
|
pub struct VoidResult {
|
2021-06-21 17:01:53 -07:00
|
|
|
raw: Result<(), Error>,
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
2021-06-19 22:53:26 -07:00
|
|
|
#[ffi_export]
|
|
|
|
fn get_void_err(void_result: &VoidResult) -> Option<char_p_boxed> {
|
|
|
|
void_result
|
|
|
|
.raw
|
|
|
|
.as_ref()
|
|
|
|
.err()
|
2021-06-21 17:01:53 -07:00
|
|
|
.map(|e| char_p_boxed::try_from(get_name(e)).unwrap())
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
2021-06-19 22:53:26 -07:00
|
|
|
fn free_void_result(void_result: Option<Box<VoidResult>>) {
|
|
|
|
drop(void_result)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive_ReprC]
|
|
|
|
#[ReprC::opaque]
|
|
|
|
pub struct StringResult {
|
2021-06-21 17:01:53 -07:00
|
|
|
raw: Result<String, Error>,
|
2021-06-19 22:53:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn get_string_ok(string_result: &StringResult) -> Option<char_p_boxed> {
|
|
|
|
string_result
|
|
|
|
.raw
|
|
|
|
.as_ref()
|
|
|
|
.ok()
|
|
|
|
.map(|s| char_p_boxed::try_from(s.clone()).unwrap())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn get_string_err(string_result: &StringResult) -> Option<char_p_boxed> {
|
|
|
|
string_result
|
|
|
|
.raw
|
|
|
|
.as_ref()
|
|
|
|
.err()
|
2021-06-21 17:01:53 -07:00
|
|
|
.map(|e| char_p_boxed::try_from(get_name(e)).unwrap())
|
2021-06-19 22:53:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn free_string_result(string_result: Option<Box<StringResult>>) {
|
|
|
|
drop(string_result)
|
|
|
|
}
|
|
|
|
|
2021-06-21 17:01:53 -07:00
|
|
|
#[derive_ReprC]
|
|
|
|
#[ReprC::opaque]
|
|
|
|
pub struct WalletRef<'lt> {
|
|
|
|
raw: &'lt Wallet<AnyBlockchain, AnyDatabase>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn free_wallet_ref(wallet_ref: Option<Box<WalletRef>>) {
|
|
|
|
drop(wallet_ref)
|
|
|
|
}
|
|
|
|
|
2021-06-19 22:53:26 -07:00
|
|
|
#[derive_ReprC]
|
|
|
|
#[ReprC::opaque]
|
|
|
|
pub struct WalletResult {
|
2021-06-21 17:01:53 -07:00
|
|
|
raw: Result<Wallet<AnyBlockchain, AnyDatabase>, Error>,
|
2021-06-19 22:53:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn new_wallet_result(
|
2021-06-10 17:22:33 -07:00
|
|
|
name: char_p_ref,
|
|
|
|
descriptor: char_p_ref,
|
|
|
|
change_descriptor: Option<char_p_ref>,
|
2021-06-19 22:53:26 -07:00
|
|
|
) -> Box<WalletResult> {
|
|
|
|
let name = name.to_string();
|
2021-06-10 17:22:33 -07:00
|
|
|
let descriptor = descriptor.to_string();
|
|
|
|
let change_descriptor = change_descriptor.map(|s| s.to_string());
|
2021-06-21 17:01:53 -07:00
|
|
|
let wallet_result = new_wallet(name, descriptor, change_descriptor);
|
2021-06-19 22:53:26 -07:00
|
|
|
Box::new(WalletResult { raw: wallet_result })
|
|
|
|
}
|
2021-06-10 17:22:33 -07:00
|
|
|
|
2021-06-19 22:53:26 -07:00
|
|
|
fn new_wallet(
|
2021-06-21 17:01:53 -07:00
|
|
|
_name: String,
|
2021-06-19 22:53:26 -07:00
|
|
|
descriptor: String,
|
|
|
|
change_descriptor: Option<String>,
|
|
|
|
) -> Result<Wallet<AnyBlockchain, AnyDatabase>, Error> {
|
|
|
|
let network = Testnet;
|
2021-06-10 17:22:33 -07:00
|
|
|
let electrum_config = AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
|
|
|
|
url: "ssl://electrum.blockstream.info:60002".to_string(),
|
|
|
|
socks5: None,
|
|
|
|
retry: 5,
|
|
|
|
timeout: None,
|
|
|
|
});
|
|
|
|
let blockchain_config = electrum_config;
|
2021-06-19 22:53:26 -07:00
|
|
|
let client = AnyBlockchain::from_config(&blockchain_config)?;
|
2021-06-10 17:22:33 -07:00
|
|
|
|
|
|
|
let database_config = AnyDatabaseConfig::Memory(());
|
2021-06-19 22:53:26 -07:00
|
|
|
let database = AnyDatabase::from_config(&database_config)?;
|
2021-06-10 17:22:33 -07:00
|
|
|
|
|
|
|
let descriptor: &str = descriptor.as_str();
|
|
|
|
let change_descriptor: Option<&str> = change_descriptor.as_deref();
|
|
|
|
|
2021-06-19 22:53:26 -07:00
|
|
|
Wallet::new(descriptor, change_descriptor, network, database, client)
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
2021-06-19 22:53:26 -07:00
|
|
|
fn get_wallet_err(wallet_result: &WalletResult) -> Option<char_p_boxed> {
|
|
|
|
wallet_result
|
|
|
|
.raw
|
|
|
|
.as_ref()
|
|
|
|
.err()
|
2021-06-21 17:01:53 -07:00
|
|
|
.map(|e| char_p_boxed::try_from(get_name(&e)).unwrap())
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
2021-06-21 17:01:53 -07:00
|
|
|
fn get_wallet_ok<'lt>(wallet_result: &'lt WalletResult) -> Option<Box<WalletRef<'lt>>> {
|
|
|
|
wallet_result
|
|
|
|
.raw
|
|
|
|
.as_ref()
|
|
|
|
.ok()
|
|
|
|
.map(|w| Box::new(WalletRef { raw: w}))
|
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn sync_wallet<'lt>(wallet_ref: &'lt WalletRef<'lt>) -> Box<VoidResult> {
|
|
|
|
let void_result = wallet_ref
|
|
|
|
.raw.sync(log_progress(), Some(100));
|
2021-06-19 22:53:26 -07:00
|
|
|
Box::new(VoidResult { raw: void_result })
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
2021-06-21 17:01:53 -07:00
|
|
|
fn new_address<'lt>(wallet_ref: &'lt WalletRef<'lt>) -> Box<StringResult> {
|
|
|
|
let new_address = wallet_ref.raw.get_address(New);
|
2021-06-19 22:53:26 -07:00
|
|
|
let string_result = new_address.map(|a| a.to_string());
|
|
|
|
Box::new(StringResult { raw: string_result })
|
|
|
|
}
|
|
|
|
|
|
|
|
#[ffi_export]
|
|
|
|
fn free_wallet_result(wallet_result: Option<Box<WalletResult>>) {
|
|
|
|
drop(wallet_result)
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|
|
|
|
|
2021-06-19 22:53:26 -07:00
|
|
|
/// Frees a Rust-allocated string
|
2021-06-10 17:22:33 -07:00
|
|
|
#[ffi_export]
|
2021-06-19 22:53:26 -07:00
|
|
|
fn free_string(string: Option<char_p_boxed>) {
|
|
|
|
drop(string)
|
2021-06-10 17:22:33 -07:00
|
|
|
}
|