feat: add Transaction and PartiallySignedTransaction types
This commit is contained in:
parent
1521811e9b
commit
13c751cebc
@ -94,7 +94,7 @@ interface TxBuilder {
|
|||||||
TxBuilder fee_rate(float sat_per_vbyte);
|
TxBuilder fee_rate(float sat_per_vbyte);
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
string finish([ByRef] Wallet wallet);
|
PartiallySignedTransaction finish([ByRef] Wallet wallet);
|
||||||
};
|
};
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
@ -225,7 +225,37 @@ interface Address {
|
|||||||
|
|
||||||
Network network();
|
Network network();
|
||||||
|
|
||||||
|
Script script_pubkey();
|
||||||
|
|
||||||
string to_qr_uri();
|
string to_qr_uri();
|
||||||
|
|
||||||
string as_string();
|
string as_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface Transaction {
|
||||||
|
[Throws=BdkError]
|
||||||
|
constructor(sequence<u8> transaction_bytes);
|
||||||
|
|
||||||
|
string txid();
|
||||||
|
|
||||||
|
u64 size();
|
||||||
|
|
||||||
|
u64 vsize();
|
||||||
|
|
||||||
|
boolean is_coin_base();
|
||||||
|
|
||||||
|
boolean is_explicitly_rbf();
|
||||||
|
|
||||||
|
boolean is_lock_time_enabled();
|
||||||
|
|
||||||
|
i32 version();
|
||||||
|
};
|
||||||
|
|
||||||
|
interface PartiallySignedTransaction {
|
||||||
|
[Throws=BdkError]
|
||||||
|
constructor(string psbt_base64);
|
||||||
|
|
||||||
|
string serialize();
|
||||||
|
|
||||||
|
Transaction extract_tx();
|
||||||
|
};
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
|
use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked};
|
||||||
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
||||||
|
use bdk::bitcoin::consensus::Decodable;
|
||||||
|
use bdk::bitcoin::network::constants::Network as BdkNetwork;
|
||||||
|
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
||||||
|
use bdk::bitcoin::Address as BdkAddress;
|
||||||
|
use bdk::bitcoin::Transaction as BdkTransaction;
|
||||||
|
use bdk::Error as BdkError;
|
||||||
|
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
/// A Bitcoin script.
|
/// A Bitcoin script.
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -20,3 +31,251 @@ impl From<BdkScriptBuf> for Script {
|
|||||||
Script(script)
|
Script(script)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Network {
|
||||||
|
/// Mainnet Bitcoin.
|
||||||
|
Bitcoin,
|
||||||
|
/// Bitcoin's testnet network.
|
||||||
|
Testnet,
|
||||||
|
/// Bitcoin's signet network.
|
||||||
|
Signet,
|
||||||
|
/// Bitcoin's regtest network.
|
||||||
|
Regtest,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Network> for BdkNetwork {
|
||||||
|
fn from(network: Network) -> Self {
|
||||||
|
match network {
|
||||||
|
Network::Bitcoin => BdkNetwork::Bitcoin,
|
||||||
|
Network::Testnet => BdkNetwork::Testnet,
|
||||||
|
Network::Signet => BdkNetwork::Signet,
|
||||||
|
Network::Regtest => BdkNetwork::Regtest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BdkNetwork> for Network {
|
||||||
|
fn from(network: BdkNetwork) -> Self {
|
||||||
|
match network {
|
||||||
|
BdkNetwork::Bitcoin => Network::Bitcoin,
|
||||||
|
BdkNetwork::Testnet => Network::Testnet,
|
||||||
|
BdkNetwork::Signet => Network::Signet,
|
||||||
|
BdkNetwork::Regtest => Network::Regtest,
|
||||||
|
_ => panic!("Network {} not supported", network),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Bitcoin address.
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct Address {
|
||||||
|
inner: BdkAddress<NetworkChecked>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Address {
|
||||||
|
pub fn new(address: String, network: Network) -> Result<Self, BdkError> {
|
||||||
|
Ok(Address {
|
||||||
|
inner: address
|
||||||
|
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
|
||||||
|
.unwrap() // TODO 11: 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(),
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn network(&self) -> Network {
|
||||||
|
self.inner.network.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn script_pubkey(&self) -> Arc<Script> {
|
||||||
|
Arc::new(Script(self.inner.script_pubkey()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_qr_uri(&self) -> String {
|
||||||
|
self.inner.to_qr_uri()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_string(&self) -> String {
|
||||||
|
self.inner.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Address> for BdkAddress {
|
||||||
|
fn from(address: Address) -> Self {
|
||||||
|
address.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BdkAddress> for Address {
|
||||||
|
fn from(address: BdkAddress) -> Self {
|
||||||
|
Address { inner: address }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A Bitcoin transaction.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct Transaction {
|
||||||
|
inner: BdkTransaction,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Transaction {
|
||||||
|
pub fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
|
||||||
|
let mut decoder = Cursor::new(transaction_bytes);
|
||||||
|
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
|
Ok(Transaction { inner: tx })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn txid(&self) -> String {
|
||||||
|
self.inner.txid().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn weight(&self) -> u64 {
|
||||||
|
// self.inner.weight() as u64
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
self.inner.size() as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn vsize(&self) -> u64 {
|
||||||
|
self.inner.vsize() as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn serialize(&self) -> Vec<u8> {
|
||||||
|
// self.inner.serialize()
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn is_coin_base(&self) -> bool {
|
||||||
|
self.inner.is_coin_base()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_explicitly_rbf(&self) -> bool {
|
||||||
|
self.inner.is_explicitly_rbf()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_lock_time_enabled(&self) -> bool {
|
||||||
|
self.inner.is_lock_time_enabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn version(&self) -> i32 {
|
||||||
|
self.inner.version
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn lock_time(&self) -> u32 {
|
||||||
|
// self.inner.lock_time.0
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn input(&self) -> Vec<TxIn> {
|
||||||
|
// self.inner.input.iter().map(|x| x.into()).collect()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fn output(&self) -> Vec<TxOut> {
|
||||||
|
// self.inner.output.iter().map(|x| x.into()).collect()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BdkTransaction> for Transaction {
|
||||||
|
fn from(tx: BdkTransaction) -> Self {
|
||||||
|
Transaction { inner: tx }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct PartiallySignedTransaction {
|
||||||
|
pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartiallySignedTransaction {
|
||||||
|
pub(crate) fn new(psbt_base64: String) -> Result<Self, BdkError> {
|
||||||
|
let psbt: BdkPartiallySignedTransaction =
|
||||||
|
BdkPartiallySignedTransaction::from_str(&psbt_base64)
|
||||||
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
|
|
||||||
|
Ok(PartiallySignedTransaction {
|
||||||
|
inner: Mutex::new(psbt),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn serialize(&self) -> String {
|
||||||
|
let psbt = self.inner.lock().unwrap().clone();
|
||||||
|
psbt.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub(crate) fn txid(&self) -> String {
|
||||||
|
// let tx = self.inner.lock().unwrap().clone().extract_tx();
|
||||||
|
// let txid = tx.txid();
|
||||||
|
// txid.to_hex()
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Return the transaction.
|
||||||
|
pub(crate) fn extract_tx(&self) -> Arc<Transaction> {
|
||||||
|
let tx = self.inner.lock().unwrap().clone().extract_tx();
|
||||||
|
Arc::new(tx.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
// /// Combines this PartiallySignedTransaction with other PSBT as described by BIP 174.
|
||||||
|
// ///
|
||||||
|
// /// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
|
||||||
|
// pub(crate) fn combine(
|
||||||
|
// &self,
|
||||||
|
// other: Arc<PartiallySignedTransaction>,
|
||||||
|
// ) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
||||||
|
// let other_psbt = other.inner.lock().unwrap().clone();
|
||||||
|
// let mut original_psbt = self.inner.lock().unwrap().clone();
|
||||||
|
//
|
||||||
|
// original_psbt.combine(other_psbt)?;
|
||||||
|
// Ok(Arc::new(PartiallySignedTransaction {
|
||||||
|
// inner: Mutex::new(original_psbt),
|
||||||
|
// }))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
|
||||||
|
// /// If the PSBT is missing a TxOut for an input returns None.
|
||||||
|
// pub(crate) fn fee_amount(&self) -> Option<u64> {
|
||||||
|
// self.inner.lock().unwrap().fee_amount()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
|
||||||
|
// /// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the
|
||||||
|
// /// transaction.
|
||||||
|
// /// If the PSBT is missing a TxOut for an input returns None.
|
||||||
|
// pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
|
||||||
|
// self.inner.lock().unwrap().fee_rate().map(Arc::new)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /// Serialize the PSBT data structure as a String of JSON.
|
||||||
|
// pub(crate) fn json_serialize(&self) -> String {
|
||||||
|
// let psbt = self.inner.lock().unwrap();
|
||||||
|
// serde_json::to_string(psbt.deref()).unwrap()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BdkPartiallySignedTransaction> for PartiallySignedTransaction {
|
||||||
|
fn from(psbt: BdkPartiallySignedTransaction) -> Self {
|
||||||
|
PartiallySignedTransaction {
|
||||||
|
inner: Mutex::new(psbt),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
use crate::keys::DescriptorPublicKey;
|
||||||
|
use crate::keys::DescriptorSecretKey;
|
||||||
|
use crate::Network;
|
||||||
|
|
||||||
use bdk::bitcoin::bip32::Fingerprint;
|
use bdk::bitcoin::bip32::Fingerprint;
|
||||||
use bdk::bitcoin::key::Secp256k1;
|
use bdk::bitcoin::key::Secp256k1;
|
||||||
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
|
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
|
||||||
@ -9,13 +13,10 @@ use bdk::template::{
|
|||||||
};
|
};
|
||||||
use bdk::Error as BdkError;
|
use bdk::Error as BdkError;
|
||||||
use bdk::KeychainKind;
|
use bdk::KeychainKind;
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::keys::DescriptorPublicKey;
|
|
||||||
use crate::keys::DescriptorSecretKey;
|
|
||||||
use crate::Network;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Descriptor {
|
pub struct Descriptor {
|
||||||
pub extended_descriptor: ExtendedDescriptor,
|
pub extended_descriptor: ExtendedDescriptor,
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
use crate::wallet::{Update, Wallet};
|
use crate::wallet::{Update, Wallet};
|
||||||
|
|
||||||
use bdk::wallet::Update as BdkUpdate;
|
use bdk::wallet::Update as BdkUpdate;
|
||||||
use bdk::Error as BdkError;
|
use bdk::Error as BdkError;
|
||||||
use bdk_esplora::esplora_client::{BlockingClient, Builder};
|
use bdk_esplora::esplora_client::{BlockingClient, Builder};
|
||||||
use bdk_esplora::EsploraExt;
|
use bdk_esplora::EsploraExt;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct EsploraClient(BlockingClient);
|
pub struct EsploraClient(BlockingClient);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use crate::Network;
|
||||||
|
|
||||||
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
|
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
|
||||||
use bdk::bitcoin::key::Secp256k1;
|
use bdk::bitcoin::key::Secp256k1;
|
||||||
use bdk::bitcoin::secp256k1::rand;
|
use bdk::bitcoin::secp256k1::rand;
|
||||||
@ -11,14 +13,13 @@ use bdk::keys::{
|
|||||||
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
|
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
|
||||||
use bdk::miniscript::BareCtx;
|
use bdk::miniscript::BareCtx;
|
||||||
use bdk::Error as BdkError;
|
use bdk::Error as BdkError;
|
||||||
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crate::Network;
|
/// Mnemonic phrases are a human-readable version of the private keys.
|
||||||
|
/// Supported number of words are 12, 15, 18, 21 and 24.
|
||||||
// /// Mnemonic phrases are a human-readable version of the private keys.
|
|
||||||
// /// Supported number of words are 12, 15, 18, 21 and 24.
|
|
||||||
pub(crate) struct Mnemonic {
|
pub(crate) struct Mnemonic {
|
||||||
inner: BdkMnemonic,
|
inner: BdkMnemonic,
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,14 @@ mod bitcoin;
|
|||||||
mod descriptor;
|
mod descriptor;
|
||||||
mod esplora;
|
mod esplora;
|
||||||
mod keys;
|
mod keys;
|
||||||
mod psbt;
|
|
||||||
mod wallet;
|
mod wallet;
|
||||||
|
|
||||||
use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked};
|
|
||||||
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
|
||||||
use bdk::bitcoin::Address as BdkAddress;
|
|
||||||
use bdk::bitcoin::Network as BdkNetwork;
|
|
||||||
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
|
||||||
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
|
||||||
use bdk::wallet::Balance as BdkBalance;
|
|
||||||
use bdk::Error as BdkError;
|
|
||||||
use bdk::KeychainKind;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
// TODO 6: Why are these imports required?
|
// TODO 6: Why are these imports required?
|
||||||
|
use crate::bitcoin::Address;
|
||||||
|
use crate::bitcoin::Network;
|
||||||
|
use crate::bitcoin::PartiallySignedTransaction;
|
||||||
use crate::bitcoin::Script;
|
use crate::bitcoin::Script;
|
||||||
|
use crate::bitcoin::Transaction;
|
||||||
use crate::descriptor::Descriptor;
|
use crate::descriptor::Descriptor;
|
||||||
use crate::esplora::EsploraClient;
|
use crate::esplora::EsploraClient;
|
||||||
use crate::keys::DerivationPath;
|
use crate::keys::DerivationPath;
|
||||||
@ -27,50 +19,24 @@ use crate::keys::Mnemonic;
|
|||||||
use crate::wallet::TxBuilder;
|
use crate::wallet::TxBuilder;
|
||||||
use crate::wallet::Update;
|
use crate::wallet::Update;
|
||||||
use crate::wallet::Wallet;
|
use crate::wallet::Wallet;
|
||||||
|
|
||||||
use bdk::keys::bip39::WordCount;
|
use bdk::keys::bip39::WordCount;
|
||||||
|
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
||||||
|
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
||||||
|
use bdk::wallet::Balance as BdkBalance;
|
||||||
|
use bdk::Error as BdkError;
|
||||||
|
use bdk::KeychainKind;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
uniffi::include_scaffolding!("bdk");
|
uniffi::include_scaffolding!("bdk");
|
||||||
|
|
||||||
pub enum Network {
|
/// A output script and an amount of satoshis.
|
||||||
/// Mainnet Bitcoin.
|
|
||||||
Bitcoin,
|
|
||||||
/// Bitcoin's testnet network.
|
|
||||||
Testnet,
|
|
||||||
/// Bitcoin's signet network.
|
|
||||||
Signet,
|
|
||||||
/// Bitcoin's regtest network.
|
|
||||||
Regtest,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Network> for BdkNetwork {
|
|
||||||
fn from(network: Network) -> Self {
|
|
||||||
match network {
|
|
||||||
Network::Bitcoin => BdkNetwork::Bitcoin,
|
|
||||||
Network::Testnet => BdkNetwork::Testnet,
|
|
||||||
Network::Signet => BdkNetwork::Signet,
|
|
||||||
Network::Regtest => BdkNetwork::Regtest,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BdkNetwork> for Network {
|
|
||||||
fn from(network: BdkNetwork) -> Self {
|
|
||||||
match network {
|
|
||||||
BdkNetwork::Bitcoin => Network::Bitcoin,
|
|
||||||
BdkNetwork::Testnet => Network::Testnet,
|
|
||||||
BdkNetwork::Signet => Network::Signet,
|
|
||||||
BdkNetwork::Regtest => Network::Regtest,
|
|
||||||
_ => panic!("Network {} not supported", network),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// /// A output script and an amount of satoshis.
|
|
||||||
// pub struct ScriptAmount {
|
// pub struct ScriptAmount {
|
||||||
// pub script: Arc<Script>,
|
// pub script: Arc<Script>,
|
||||||
// pub amount: u64,
|
// pub amount: u64,
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
/// A derived address and the index it was found at.
|
/// A derived address and the index it was found at.
|
||||||
pub struct AddressInfo {
|
pub struct AddressInfo {
|
||||||
/// Child index of this address.
|
/// Child index of this address.
|
||||||
@ -343,144 +309,6 @@ impl Balance {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// /// A Bitcoin transaction.
|
|
||||||
// #[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
// pub struct Transaction {
|
|
||||||
// inner: BdkTransaction,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// impl Transaction {
|
|
||||||
// fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
|
|
||||||
// let mut decoder = Cursor::new(transaction_bytes);
|
|
||||||
// let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
|
|
||||||
// Ok(Transaction { inner: tx })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn txid(&self) -> String {
|
|
||||||
// self.inner.txid().to_string()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn weight(&self) -> u64 {
|
|
||||||
// self.inner.weight() as u64
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn size(&self) -> u64 {
|
|
||||||
// self.inner.size() as u64
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn vsize(&self) -> u64 {
|
|
||||||
// self.inner.vsize() as u64
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn serialize(&self) -> Vec<u8> {
|
|
||||||
// self.inner.serialize()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn is_coin_base(&self) -> bool {
|
|
||||||
// self.inner.is_coin_base()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn is_explicitly_rbf(&self) -> bool {
|
|
||||||
// self.inner.is_explicitly_rbf()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn is_lock_time_enabled(&self) -> bool {
|
|
||||||
// self.inner.is_lock_time_enabled()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn version(&self) -> i32 {
|
|
||||||
// self.inner.version
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn lock_time(&self) -> u32 {
|
|
||||||
// self.inner.lock_time.0
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn input(&self) -> Vec<TxIn> {
|
|
||||||
// self.inner.input.iter().map(|x| x.into()).collect()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn output(&self) -> Vec<TxOut> {
|
|
||||||
// self.inner.output.iter().map(|x| x.into()).collect()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// impl From<BdkTransaction> for Transaction {
|
|
||||||
// fn from(tx: BdkTransaction) -> Self {
|
|
||||||
// Transaction { inner: tx }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/// 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 11: 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.into()
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
// /// The method used to produce an address.
|
||||||
// #[derive(Debug)]
|
// #[derive(Debug)]
|
||||||
@ -498,23 +326,6 @@ impl From<Address> for BdkAddress {
|
|||||||
// },
|
// },
|
||||||
// }
|
// }
|
||||||
|
|
||||||
/// A Bitcoin script.
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
||||||
pub struct Script {
|
|
||||||
inner: BdkScriptBuf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Script {
|
|
||||||
fn new(raw_output_script: Vec<u8>) -> Self {
|
|
||||||
let script: BdkScriptBuf = BdkScriptBuf::from(raw_output_script);
|
|
||||||
Script { inner: script }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
|
||||||
self.inner.to_bytes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// impl From<BdkScript> for Script {
|
// impl From<BdkScript> for Script {
|
||||||
// fn from(bdk_script: BdkScript) -> Self {
|
// fn from(bdk_script: BdkScript) -> Self {
|
||||||
// Script { inner: bdk_script }
|
// Script { inner: bdk_script }
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
// use bdk::bitcoin::hashes::hex::ToHex;
|
|
||||||
// use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
|
||||||
// use bdk::bitcoincore_rpc::jsonrpc::serde_json;
|
|
||||||
// use bdk::psbt::PsbtUtils;
|
|
||||||
// use std::ops::Deref;
|
|
||||||
// use std::str::FromStr;
|
|
||||||
// use std::sync::{Arc, Mutex};
|
|
||||||
//
|
|
||||||
// use crate::{BdkError, FeeRate, Transaction};
|
|
||||||
//
|
|
||||||
// #[derive(Debug)]
|
|
||||||
// pub(crate) struct PartiallySignedTransaction {
|
|
||||||
// pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// impl PartiallySignedTransaction {
|
|
||||||
// pub(crate) fn new(psbt_base64: String) -> Result<Self, BdkError> {
|
|
||||||
// let psbt: BdkPartiallySignedTransaction =
|
|
||||||
// BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
|
|
||||||
// Ok(PartiallySignedTransaction {
|
|
||||||
// inner: Mutex::new(psbt),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub(crate) fn serialize(&self) -> String {
|
|
||||||
// let psbt = self.inner.lock().unwrap().clone();
|
|
||||||
// psbt.to_string()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// pub(crate) fn txid(&self) -> String {
|
|
||||||
// let tx = self.inner.lock().unwrap().clone().extract_tx();
|
|
||||||
// let txid = tx.txid();
|
|
||||||
// txid.to_hex()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// Return the transaction.
|
|
||||||
// pub(crate) fn extract_tx(&self) -> Arc<Transaction> {
|
|
||||||
// let tx = self.inner.lock().unwrap().clone().extract_tx();
|
|
||||||
// Arc::new(tx.into())
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// Combines this PartiallySignedTransaction with other PSBT as described by BIP 174.
|
|
||||||
// ///
|
|
||||||
// /// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
|
|
||||||
// pub(crate) fn combine(
|
|
||||||
// &self,
|
|
||||||
// other: Arc<PartiallySignedTransaction>,
|
|
||||||
// ) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
|
||||||
// let other_psbt = other.inner.lock().unwrap().clone();
|
|
||||||
// let mut original_psbt = self.inner.lock().unwrap().clone();
|
|
||||||
//
|
|
||||||
// original_psbt.combine(other_psbt)?;
|
|
||||||
// Ok(Arc::new(PartiallySignedTransaction {
|
|
||||||
// inner: Mutex::new(original_psbt),
|
|
||||||
// }))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
|
|
||||||
// /// If the PSBT is missing a TxOut for an input returns None.
|
|
||||||
// pub(crate) fn fee_amount(&self) -> Option<u64> {
|
|
||||||
// self.inner.lock().unwrap().fee_amount()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// The transaction's fee rate. This value will only be accurate if calculated AFTER the
|
|
||||||
// /// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the
|
|
||||||
// /// transaction.
|
|
||||||
// /// If the PSBT is missing a TxOut for an input returns None.
|
|
||||||
// pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
|
|
||||||
// self.inner.lock().unwrap().fee_rate().map(Arc::new)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// Serialize the PSBT data structure as a String of JSON.
|
|
||||||
// pub(crate) fn json_serialize(&self) -> String {
|
|
||||||
// let psbt = self.inner.lock().unwrap();
|
|
||||||
// serde_json::to_string(psbt.deref()).unwrap()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
|
|
||||||
// // These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
|
|
||||||
// // crate.
|
|
||||||
// #[cfg(test)]
|
|
||||||
// mod test {
|
|
||||||
// use crate::wallet::{TxBuilder, Wallet};
|
|
||||||
// use bdk::wallet::get_funded_wallet;
|
|
||||||
// use std::sync::Mutex;
|
|
||||||
//
|
|
||||||
// #[test]
|
|
||||||
// fn test_psbt_fee() {
|
|
||||||
// let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
|
||||||
// let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
|
||||||
// let test_wallet = Wallet {
|
|
||||||
// inner_mutex: Mutex::new(funded_wallet),
|
|
||||||
// };
|
|
||||||
// let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
|
|
||||||
// let drain_to_script = crate::Address::new(drain_to_address)
|
|
||||||
// .unwrap()
|
|
||||||
// .script_pubkey();
|
|
||||||
//
|
|
||||||
// let tx_builder = TxBuilder::new()
|
|
||||||
// .fee_rate(2.0)
|
|
||||||
// .drain_wallet()
|
|
||||||
// .drain_to(drain_to_script.clone());
|
|
||||||
// //dbg!(&tx_builder);
|
|
||||||
// assert!(tx_builder.drain_wallet);
|
|
||||||
// assert_eq!(tx_builder.drain_to, Some(drain_to_script.inner.clone()));
|
|
||||||
//
|
|
||||||
// let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
|
|
||||||
//
|
|
||||||
// assert!(tx_builder_result.psbt.fee_rate().is_some());
|
|
||||||
// assert_eq!(
|
|
||||||
// tx_builder_result.psbt.fee_rate().unwrap().as_sat_per_vb(),
|
|
||||||
// 2.682927
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// assert!(tx_builder_result.psbt.fee_amount().is_some());
|
|
||||||
// assert_eq!(tx_builder_result.psbt.fee_amount().unwrap(), 220);
|
|
||||||
// }
|
|
||||||
// }
|
|
@ -1,11 +1,14 @@
|
|||||||
|
use crate::bitcoin::PartiallySignedTransaction;
|
||||||
use crate::descriptor::Descriptor;
|
use crate::descriptor::Descriptor;
|
||||||
use crate::{AddressIndex, AddressInfo, Network};
|
use crate::{AddressIndex, AddressInfo, Network};
|
||||||
use crate::{Balance, Script};
|
use crate::{Balance, Script};
|
||||||
|
|
||||||
|
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
||||||
use bdk::wallet::Update as BdkUpdate;
|
use bdk::wallet::Update as BdkUpdate;
|
||||||
use bdk::Wallet as BdkWallet;
|
use bdk::Wallet as BdkWallet;
|
||||||
use bdk::{Error as BdkError, FeeRate};
|
use bdk::{Error as BdkError, FeeRate};
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Wallet {
|
pub struct Wallet {
|
||||||
@ -353,7 +356,7 @@ impl TxBuilder {
|
|||||||
/// Add a recipient to the internal list.
|
/// Add a recipient to the internal list.
|
||||||
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
|
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
|
||||||
let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
|
let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
|
||||||
recipients.append(&mut vec![(script.inner.clone(), amount)]);
|
recipients.append(&mut vec![(script.0.clone(), amount)]);
|
||||||
|
|
||||||
Arc::new(TxBuilder {
|
Arc::new(TxBuilder {
|
||||||
recipients,
|
recipients,
|
||||||
@ -502,7 +505,10 @@ impl TxBuilder {
|
|||||||
//
|
//
|
||||||
/// Finish building the transaction. Returns the BIP174 PSBT.
|
/// Finish building the transaction. Returns the BIP174 PSBT.
|
||||||
/// TODO: The TxBuilder in bdk returns a Psbt type
|
/// TODO: The TxBuilder in bdk returns a Psbt type
|
||||||
pub(crate) fn finish(&self, wallet: &Wallet) -> Result<String, BdkError> {
|
pub(crate) fn finish(
|
||||||
|
&self,
|
||||||
|
wallet: &Wallet,
|
||||||
|
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
||||||
// TODO: I had to change the wallet here to be mutable. Why is that now required with the 1.0 API?
|
// TODO: I had to change the wallet here to be mutable. Why is that now required with the 1.0 API?
|
||||||
let mut wallet = wallet.get_wallet();
|
let mut wallet = wallet.get_wallet();
|
||||||
let mut tx_builder = wallet.build_tx();
|
let mut tx_builder = wallet.build_tx();
|
||||||
@ -551,7 +557,11 @@ impl TxBuilder {
|
|||||||
// tx_builder.add_data(self.data.as_slice());
|
// tx_builder.add_data(self.data.as_slice());
|
||||||
// }
|
// }
|
||||||
|
|
||||||
tx_builder.finish().map(|psbt| psbt.serialize_hex())
|
// tx_builder.finish().map(|psbt| psbt.serialize_hex())
|
||||||
|
// tx_builder.finish().into()
|
||||||
|
let psbt = tx_builder.finish()?;
|
||||||
|
|
||||||
|
Ok(Arc::new(psbt.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user