feat: add Transaction and PartiallySignedTransaction types

This commit is contained in:
thunderbiscuit 2023-10-19 14:18:03 -04:00
parent 1521811e9b
commit 13c751cebc
No known key found for this signature in database
GPG Key ID: 88253696EB836462
8 changed files with 330 additions and 335 deletions

View File

@ -94,7 +94,7 @@ interface TxBuilder {
TxBuilder fee_rate(float sat_per_vbyte);
[Throws=BdkError]
string finish([ByRef] Wallet wallet);
PartiallySignedTransaction finish([ByRef] Wallet wallet);
};
// ------------------------------------------------------------------------
@ -225,7 +225,37 @@ interface Address {
Network network();
Script script_pubkey();
string to_qr_uri();
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();
};

View File

@ -1,4 +1,15 @@
use bdk::bitcoin::address::{NetworkChecked, NetworkUnchecked};
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.
#[derive(Clone, Debug, PartialEq, Eq)]
@ -20,3 +31,251 @@ impl From<BdkScriptBuf> for 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),
}
}
}

View File

@ -1,3 +1,7 @@
use crate::keys::DescriptorPublicKey;
use crate::keys::DescriptorSecretKey;
use crate::Network;
use bdk::bitcoin::bip32::Fingerprint;
use bdk::bitcoin::key::Secp256k1;
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
@ -9,13 +13,10 @@ use bdk::template::{
};
use bdk::Error as BdkError;
use bdk::KeychainKind;
use std::str::FromStr;
use std::sync::Arc;
use crate::keys::DescriptorPublicKey;
use crate::keys::DescriptorSecretKey;
use crate::Network;
#[derive(Debug)]
pub struct Descriptor {
pub extended_descriptor: ExtendedDescriptor,

View File

@ -1,8 +1,10 @@
use crate::wallet::{Update, Wallet};
use bdk::wallet::Update as BdkUpdate;
use bdk::Error as BdkError;
use bdk_esplora::esplora_client::{BlockingClient, Builder};
use bdk_esplora::EsploraExt;
use std::sync::Arc;
pub struct EsploraClient(BlockingClient);

View File

@ -1,3 +1,5 @@
use crate::Network;
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::key::Secp256k1;
use bdk::bitcoin::secp256k1::rand;
@ -11,14 +13,13 @@ use bdk::keys::{
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
use bdk::miniscript::BareCtx;
use bdk::Error as BdkError;
use std::ops::Deref;
use std::str::FromStr;
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 {
inner: BdkMnemonic,
}

View File

@ -2,22 +2,14 @@ mod bitcoin;
mod descriptor;
mod esplora;
mod keys;
mod psbt;
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?
use crate::bitcoin::Address;
use crate::bitcoin::Network;
use crate::bitcoin::PartiallySignedTransaction;
use crate::bitcoin::Script;
use crate::bitcoin::Transaction;
use crate::descriptor::Descriptor;
use crate::esplora::EsploraClient;
use crate::keys::DerivationPath;
@ -27,50 +19,24 @@ use crate::keys::Mnemonic;
use crate::wallet::TxBuilder;
use crate::wallet::Update;
use crate::wallet::Wallet;
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");
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 output script and an amount of satoshis.
/// A output script and an amount of satoshis.
// pub struct ScriptAmount {
// pub script: Arc<Script>,
// pub amount: u64,
// }
//
/// A derived address and the index it was found at.
pub struct AddressInfo {
/// 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.
// #[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 {
// fn from(bdk_script: BdkScript) -> Self {
// Script { inner: bdk_script }

View File

@ -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);
// }
// }

View File

@ -1,11 +1,14 @@
use crate::bitcoin::PartiallySignedTransaction;
use crate::descriptor::Descriptor;
use crate::{AddressIndex, AddressInfo, Network};
use crate::{Balance, Script};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::wallet::Update as BdkUpdate;
use bdk::Wallet as BdkWallet;
use bdk::{Error as BdkError, FeeRate};
use std::sync::{Arc, Mutex, MutexGuard};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
#[derive(Debug)]
pub struct Wallet {
@ -353,7 +356,7 @@ impl TxBuilder {
/// Add a recipient to the internal list.
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
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 {
recipients,
@ -502,7 +505,10 @@ impl TxBuilder {
//
/// Finish building the transaction. Returns the BIP174 PSBT.
/// 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?
let mut wallet = wallet.get_wallet();
let mut tx_builder = wallet.build_tx();
@ -551,7 +557,11 @@ impl TxBuilder {
// 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()))
}
}
//