Skip to content

Commit

Permalink
Temp 12: Add Wallet type
Browse files Browse the repository at this point in the history
  • Loading branch information
thunderbiscuit committed Sep 29, 2023
1 parent 5c2bbfb commit 45b107d
Show file tree
Hide file tree
Showing 4 changed files with 263 additions and 160 deletions.
32 changes: 32 additions & 0 deletions bdk-ffi/src/bdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
314 changes: 163 additions & 151 deletions bdk-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -99,54 +66,86 @@ impl From<BdkNetwork> 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<Address>,
// /// Type of keychain.
// pub keychain: KeychainKind,
// }
//
// impl From<BdkAddressInfo> 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<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),
// }
// }
// }
/// 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<Address>,
/// Type of keychain.
pub keychain: KeychainKind,
}

impl From<BdkAddressInfo> 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<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),
}
}
}

// 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<BdkAddressIndex> 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)]
Expand Down Expand Up @@ -389,66 +388,79 @@ impl From<BdkNetwork> for Network {
// }
// }
//
// /// A Bitcoin address.
// #[derive(Debug, PartialEq, Eq)]
// pub struct Address {
// inner: BdkAddress,
// }
//
// impl Address {
// fn new(address: String) -> Result<Self, BdkError> {
// 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<Script>, network: Network) -> Result<Self, BdkError> {
// BdkAddress::from_script(&script.inner, network)
// .map(|a| Address { inner: a })
// .map_err(|e| BdkError::Generic(e.to_string()))
// }
//
// fn payload(&self) -> Payload {
// match &self.inner.payload.clone() {
// BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
// pubkey_hash: pubkey_hash.to_vec(),
// },
// BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
// script_hash: script_hash.to_vec(),
// },
// BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
// version: *version,
// program: program.clone(),
// },
// }
// }
//
// fn network(&self) -> Network {
// self.inner.network
// }
//
// fn script_pubkey(&self) -> Arc<Script> {
// Arc::new(Script {
// inner: self.inner.script_pubkey(),
// })
// }
//
// fn to_qr_uri(&self) -> String {
// self.inner.to_qr_uri()
// }
//
// fn as_string(&self) -> String {
// self.inner.to_string()
// }
// }
//
// impl From<BdkAddress> for Address {
// fn from(address: BdkAddress) -> Self {
// Address { inner: address }
// }
// }
//
/// A Bitcoin address.
#[derive(Debug, PartialEq, Eq)]
pub struct Address {
inner: BdkAddress<NetworkChecked>,
}

impl Address {
fn new(
address: String,
network: Network,
) -> Result<Self, BdkError> {
Ok(Address {
inner: address
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
.unwrap() // TODO 7: Handle error correctly by rethrowing it as a BdkError
.require_network(network.into())
.map_err(|e| BdkError::Generic(e.to_string()))?,
})
}

/// alternative constructor
// fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
// BdkAddress::from_script(&script.inner, network)
// .map(|a| Address { inner: a })
// .map_err(|e| BdkError::Generic(e.to_string()))
// }
//
// fn payload(&self) -> Payload {
// match &self.inner.payload.clone() {
// BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
// pubkey_hash: pubkey_hash.to_vec(),
// },
// BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
// script_hash: script_hash.to_vec(),
// },
// BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
// version: *version,
// program: program.clone(),
// },
// }
// }

// fn network(&self) -> Network {
// self.inner.network
// }

// fn script_pubkey(&self) -> Arc<Script> {
// Arc::new(Script {
// inner: self.inner.script_pubkey(),
// })
// }

fn to_qr_uri(&self) -> String {
self.inner.to_qr_uri()
}

fn as_string(&self) -> String {
self.inner.to_string()
}
}

impl From<BdkAddress> for Address {
fn from(address: BdkAddress) -> Self {
Address { inner: address }
}
}

impl From<Address> for BdkAddress {
fn from(address: Address) -> Self {
address.inner
}
}

// /// The method used to produce an address.
// #[derive(Debug)]
// pub enum Payload {
Expand Down
Loading

0 comments on commit 45b107d

Please sign in to comment.