From 45b107d8b118888c8dfbf3442155c372a4546937 Mon Sep 17 00:00:00 2001 From: thunderbiscuit Date: Fri, 29 Sep 2023 13:08:44 -0400 Subject: [PATCH] Temp 12: Add Wallet type --- bdk-ffi/src/bdk.udl | 32 ++ bdk-ffi/src/lib.rs | 314 +++++++++--------- bdk-ffi/src/wallet.rs | 66 +++- .../kotlin/org/bitcoindevkit/JvmLibTest.kt | 11 + 4 files changed, 263 insertions(+), 160 deletions(-) diff --git a/bdk-ffi/src/bdk.udl b/bdk-ffi/src/bdk.udl index 537a92e8..f189076b 100644 --- a/bdk-ffi/src/bdk.udl +++ b/bdk-ffi/src/bdk.udl @@ -131,3 +131,35 @@ interface Descriptor { string as_string_private(); }; + +interface Wallet { + [Throws=BdkError] + constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, WalletType wallet_type); + + AddressInfo get_address(AddressIndex address_index); +}; + +enum WalletType { + "Memory", + "FlatFile", +}; + +interface Address { + [Throws=BdkError] + constructor(string address, Network network); + + string as_string(); +}; + +dictionary AddressInfo { + u32 index; + Address address; + KeychainKind keychain; +}; + +[Enum] +interface AddressIndex { + New(); + LastUnused(); + Peek(u32 index); +}; diff --git a/bdk-ffi/src/lib.rs b/bdk-ffi/src/lib.rs index b5cc71b6..a750119c 100644 --- a/bdk-ffi/src/lib.rs +++ b/bdk-ffi/src/lib.rs @@ -5,57 +5,24 @@ mod keys; mod psbt; mod wallet; -// use crate::blockchain::{ -// Auth, Blockchain, BlockchainConfig, ElectrumConfig, EsploraConfig, RpcConfig, RpcSyncParams, -// }; -// use crate::database::DatabaseConfig; -// use crate::descriptor::Descriptor; -// use crate::keys::DerivationPath; -// use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic}; -// use crate::psbt::PartiallySignedTransaction; -// use crate::wallet::SignOptions; -// use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet}; -// use bdk::bitcoin::blockdata::script::Script as BdkScript; -// use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn; -// use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut; -// use bdk::bitcoin::consensus::Decodable; -// // use bdk::bitcoin::psbt::serialize::Serialize; -// use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion}; -// use bdk::bitcoin::{ -// Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid, -// }; -// use bdk::blockchain::Progress as BdkProgress; -// use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration}; -// use bdk::keys::bip39::WordCount; -// use bdk::wallet::AddressIndex as BdkAddressIndex; -// use bdk::wallet::AddressInfo as BdkAddressInfo; -// use bdk::LocalUtxo as BdkLocalUtxo; -// use bdk::TransactionDetails as BdkTransactionDetails; -// use bdk::{ -// // Balance as BdkBalance, -// BlockTime, -// Error as BdkError, -// FeeRate, -// KeychainKind -// }; -// use bdk::wallet::Balance as BdkBalance; -// use std::convert::From; -// use std::fmt; -// use std::fmt::Debug; -// use std::io::Cursor; -// use std::str::FromStr; -// use std::sync::Arc; +use std::sync::Arc; +use bdk::bitcoin::{Network as BdkNetwork}; +use bdk::wallet::AddressIndex as BdkAddressIndex; +use bdk::wallet::AddressInfo as BdkAddressInfo; +use bdk::bitcoin::Address as BdkAddress; +use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked}; +use bdk::KeychainKind; +use bdk::Error as BdkError; -use bdk::bitcoin::Network as BdkNetwork; // TODO 6: Why are these imports required? use crate::keys::DerivationPath; -use bdk::Error as BdkError; use bdk::keys::bip39::WordCount; use crate::keys::Mnemonic; use crate::keys::DescriptorPublicKey; use crate::keys::DescriptorSecretKey; -use bdk::KeychainKind; use crate::descriptor::Descriptor; +use crate::wallet::Wallet; +use crate::wallet::WalletType; uniffi::include_scaffolding!("bdk"); @@ -99,54 +66,86 @@ impl From for Network { // pub amount: u64, // } // -// /// A derived address and the index it was found at. -// pub struct AddressInfo { -// /// Child index of this address. -// pub index: u32, -// /// Address. -// pub address: Arc
, -// /// Type of keychain. -// pub keychain: KeychainKind, -// } -// -// impl From for AddressInfo { -// fn from(address_info: BdkAddressInfo) -> Self { -// AddressInfo { -// index: address_info.index, -// address: Arc::new(Address::from(address_info.address)), -// keychain: address_info.keychain, -// } -// } -// } -// -// /// The address index selection strategy to use to derived an address from the wallet's external -// /// descriptor. -// pub enum AddressIndex { -// /// Return a new address after incrementing the current descriptor index. -// New, -// /// Return the address for the current descriptor index if it has not been used in a received -// /// transaction. Otherwise return a new address as with AddressIndex::New. -// /// Use with caution, if the wallet has not yet detected an address has been used it could -// /// return an already used address. This function is primarily meant for situations where the -// /// caller is untrusted; for example when deriving donation addresses on-demand for a public -// /// web page. -// LastUnused, -// /// Return the address for a specific descriptor index. Does not change the current descriptor -// /// index used by `AddressIndex::New` and `AddressIndex::LastUsed`. -// /// Use with caution, if an index is given that is less than the current descriptor index -// /// then the returned address may have already been used. -// Peek { index: u32 }, -// } -// -// impl From for BdkAddressIndex { -// fn from(address_index: AddressIndex) -> Self { -// match address_index { -// AddressIndex::New => BdkAddressIndex::New, -// AddressIndex::LastUnused => BdkAddressIndex::LastUnused, -// AddressIndex::Peek { index } => BdkAddressIndex::Peek(index), -// } -// } -// } +/// A derived address and the index it was found at. +pub struct AddressInfo { + /// Child index of this address. + pub index: u32, + /// Address. + pub address: Arc
, + /// Type of keychain. + pub keychain: KeychainKind, +} + +impl From for AddressInfo { + fn from(address_info: BdkAddressInfo) -> Self { + AddressInfo { + index: address_info.index, + address: Arc::new(address_info.address.into()), + keychain: address_info.keychain, + } + } +} + +/// The address index selection strategy to use to derived an address from the wallet's external +/// descriptor. +pub enum AddressIndex { + /// Return a new address after incrementing the current descriptor index. + New, + /// Return the address for the current descriptor index if it has not been used in a received + /// transaction. Otherwise return a new address as with AddressIndex::New. + /// Use with caution, if the wallet has not yet detected an address has been used it could + /// return an already used address. This function is primarily meant for situations where the + /// caller is untrusted; for example when deriving donation addresses on-demand for a public + /// web page. + LastUnused, + /// Return the address for a specific descriptor index. Does not change the current descriptor + /// index used by `AddressIndex::New` and `AddressIndex::LastUsed`. + /// Use with caution, if an index is given that is less than the current descriptor index + /// then the returned address may have already been used. + Peek { index: u32 }, +} + +impl From for BdkAddressIndex { + fn from(address_index: AddressIndex) -> Self { + match address_index { + AddressIndex::New => BdkAddressIndex::New, + AddressIndex::LastUnused => BdkAddressIndex::LastUnused, + AddressIndex::Peek { index } => BdkAddressIndex::Peek(index), + } + } +} + +// TODO 9: Peek is not correctly implemented +impl From<&AddressIndex> for BdkAddressIndex { + fn from(address_index: &AddressIndex) -> Self { + match address_index { + AddressIndex::New => BdkAddressIndex::New, + AddressIndex::LastUnused => BdkAddressIndex::LastUnused, + AddressIndex::Peek { index } => BdkAddressIndex::Peek(*index), + } + } +} + +impl From for AddressIndex { + fn from(address_index: BdkAddressIndex) -> Self { + match address_index { + BdkAddressIndex::New => AddressIndex::New, + BdkAddressIndex::LastUnused => AddressIndex::LastUnused, + _ => panic!("Mmmm not working"), + } + } +} + +impl From<&BdkAddressIndex> for AddressIndex { + fn from(address_index: &BdkAddressIndex) -> Self { + match address_index { + BdkAddressIndex::New => AddressIndex::New, + BdkAddressIndex::LastUnused => AddressIndex::LastUnused, + _ => panic!("Mmmm not working"), + } + } +} + // // /// A wallet transaction // #[derive(Debug, Clone, PartialEq, Eq, Default)] @@ -389,66 +388,79 @@ impl From for Network { // } // } // -// /// A Bitcoin address. -// #[derive(Debug, PartialEq, Eq)] -// pub struct Address { -// inner: BdkAddress, -// } -// -// impl Address { -// fn new(address: String) -> Result { -// BdkAddress::from_str(address.as_str()) -// .map(|a| Address { inner: a }) -// .map_err(|e| BdkError::Generic(e.to_string())) -// } -// -// /// alternative constructor -// fn from_script(script: Arc