From 672006fe631b0063a4bf8e44373ffba529111f41 Mon Sep 17 00:00:00 2001 From: Felix <51097237+f321x@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:56:29 +0000 Subject: [PATCH] trader bond assemblz --- taptrade-cli-demo/trader/.env | 4 +- taptrade-cli-demo/trader/src/cli/mod.rs | 11 ++-- taptrade-cli-demo/trader/src/trading/mod.rs | 10 ++-- taptrade-cli-demo/trader/src/wallet/bond.rs | 44 ++++++++++++++++ taptrade-cli-demo/trader/src/wallet/mod.rs | 58 +++++++++++---------- taptrade-cli-demo/trader/todos.md | 1 + 6 files changed, 88 insertions(+), 40 deletions(-) create mode 100644 taptrade-cli-demo/trader/todos.md diff --git a/taptrade-cli-demo/trader/.env b/taptrade-cli-demo/trader/.env index 6fee24c..f6c3cc0 100644 --- a/taptrade-cli-demo/trader/.env +++ b/taptrade-cli-demo/trader/.env @@ -2,6 +2,6 @@ ELECTRUM_ENDPOINT="ssl://mempool.space:40002" # testnet 4 electrum server COORDINATOR_ENDPOINT="http://127.0.0.1:9999" ROBOHASH_BASE91="o!kfNkee;RF?m6FT87:1bjASE2/(1NFTnR;ILmHB<1p/vP%STz~IWolNDJa.#PmTI)sfBk+Gs!,(w8M" # "robot21" TRADE_TYPE="buy" -PAYOUT_ADDRESS="tb1pxg64k0729s327n7u4n34vcmjxg42phvjykyt3f0xvcs3x5xfdxgqpt5sql" +PAYOUT_ADDRESS="tb1p45daj2eaza6drcd85c3wvn0zrpqxuduk3rzcmla4eu7a02cep9kqjzkc64" BOND_RATIO=5 -FUNDED_WALLET_DESCRIPTOR="tr([3ed82ea5/86h/1h/0h]tpubDCi4JkK1113yExq1Jc42fFYkWt4cfXMSnv47kz6HrU3giqpY6Cu19jc7uXgj5szMyiUnRD4tC8R9mBHLNZw1cKttySbAUEDAYo7bQGSi625/<0;1>/*)#fh3av2m4" # sparrow wallet taproot wallet descriptor +XPRV="tprv8ZgxMBicQKsPdHuCSjhQuSZP1h6ZTeiRqREYS5guGPdtL7D1uNLpnJmb2oJep99Esq1NbNZKVJBNnD2ZhuXSK7G5eFmmcx73gsoa65e2U32" # wallet xprv diff --git a/taptrade-cli-demo/trader/src/cli/mod.rs b/taptrade-cli-demo/trader/src/cli/mod.rs index 4eb4876..84d65d6 100755 --- a/taptrade-cli-demo/trader/src/cli/mod.rs +++ b/taptrade-cli-demo/trader/src/cli/mod.rs @@ -76,7 +76,7 @@ impl CliSettings { let trade_type: OfferType = Self::get_trade_type(None); let payout_address = Self::get_user_input("Enter a payout address for refunded bonds or your trade payout: "); // bdk can be used for validation let bond_ratio: u8 = Self::get_user_input("Enter bond ration in [2, 50]%: ").parse()?; - let funded_wallet_descriptor = Self::get_wallet_descriptors(Some(Self::get_user_input("Enter funded testnet wallet descriptor: ")))?; + let funded_wallet_descriptor = Self::get_wallet_descriptors(Some(Self::get_user_input("Enter funded testnet wallet xprv or leave empty to generate: ")))?; Ok(TraderSettings { electrum_endpoint, coordinator_endpoint, @@ -91,13 +91,10 @@ impl CliSettings { fn get_wallet_descriptors(cli_input: Option) -> Result { if let Some(user_input) = cli_input { if !(user_input.is_empty()) { - return Ok(WalletDescriptors { - descriptor: user_input, - change_descriptor: None - }); + return generate_descriptor_wallet(Some(user_input)); } }; - generate_descriptor_wallet() + generate_descriptor_wallet(None) } fn load_from_env() -> Result { @@ -109,7 +106,7 @@ impl CliSettings { trade_type: Self::get_trade_type(Some(env::var("TRADE_TYPE")?)), payout_address: env::var("PAYOUT_ADDRESS")?, bond_ratio: env::var("BOND_RATIO")?.parse()?, - funded_wallet_descriptor: Self::get_wallet_descriptors(Some(env::var("FUNDED_WALLET_DESCRIPTOR")?))?, + funded_wallet_descriptor: Self::get_wallet_descriptors(Some(env::var("XPRV")?))?, }) } diff --git a/taptrade-cli-demo/trader/src/trading/mod.rs b/taptrade-cli-demo/trader/src/trading/mod.rs index 1ec23cf..4173c6b 100644 --- a/taptrade-cli-demo/trader/src/trading/mod.rs +++ b/taptrade-cli-demo/trader/src/trading/mod.rs @@ -1,16 +1,18 @@ // use maker_utils; // use taker_utils; // use utils; + use anyhow::Result; use crate::cli::TraderSettings; use crate::communication::api::OfferCreationResponse; -use crate::wallet::load_wallet; +use crate::wallet::{load_wallet, bond::Bond}; + pub fn run_maker(maker_config: &TraderSettings) -> Result<()> { - // let offer_conditions = OfferCreationResponse::fetch(maker_config)?; - load_wallet(maker_config)?; - // maker_utils::maker(offer_conditions, maker_config) + let offer_conditions = OfferCreationResponse::fetch(maker_config)?; + let wallet = load_wallet(maker_config)?; + let bond = Bond::assemble(&wallet, &offer_conditions, maker_config)?; Ok(()) } diff --git a/taptrade-cli-demo/trader/src/wallet/bond.rs b/taptrade-cli-demo/trader/src/wallet/bond.rs index e69de29..719274f 100644 --- a/taptrade-cli-demo/trader/src/wallet/bond.rs +++ b/taptrade-cli-demo/trader/src/wallet/bond.rs @@ -0,0 +1,44 @@ +use anyhow::Result; +use bdk::{database::MemoryDatabase, wallet::coin_selection::BranchAndBoundCoinSelection, Wallet}; + +use crate::communication::api::OfferCreationResponse; +use crate::wallet::TraderSettings; + +pub struct Outpoint { + pub txid_hex: String, + pub index: u32 +} + +pub struct Bond { + pub signed_bond_tx_hex: String, + pub used_outpoint: Outpoint +} + +impl Bond { + pub fn assemble(wallet: &Wallet, + bond_target: &OfferCreationResponse, + trader_input: &TraderSettings) -> Result { + // let send_to = wallet.get_address(New)?; + + let (psbt, details) = { + let mut builder = wallet.build_tx(); + builder + .coin_selection(BranchAndBoundCoinSelection::new(10000)) + .add_recipient(send_to.script_pubkey(), 50_000) + .enable_rbf() + .do_not_spend_change() + .fee_rate(FeeRate::from_sat_per_vb(5.0)); + // coin_select + // manually_selected_only + // add_unspendable + // do_not_spend_change + // builder.finish()? + }; + + Ok(_) + } +} + +// impl BranchAndBoundCoinSelection +// pub fn new(size_of_change: u64) -> Self +// Create new instance with target size for change output diff --git a/taptrade-cli-demo/trader/src/wallet/mod.rs b/taptrade-cli-demo/trader/src/wallet/mod.rs index f83ce67..2d7830f 100644 --- a/taptrade-cli-demo/trader/src/wallet/mod.rs +++ b/taptrade-cli-demo/trader/src/wallet/mod.rs @@ -1,52 +1,56 @@ -mod bond; +pub mod bond; -use bdk::{Wallet, KeychainKind, SyncOptions, bitcoin, template::{Bip86, DescriptorTemplate}}; +use bdk::{bitcoin, keys::DescriptorPublicKey, miniscript::Descriptor, template::{Bip86, DescriptorTemplate}, KeychainKind, SyncOptions, Wallet}; use bdk::database::MemoryDatabase; use bdk::blockchain::ElectrumBlockchain; use bdk::bitcoin::{Network, secp256k1::rand::{self, RngCore}, bip32::ExtendedPrivKey}; use bdk::electrum_client::Client; use anyhow::Result; +use std::str::FromStr; use crate::cli::TraderSettings; // https://github.com/bitcoindevkit/book-of-bdk #[derive(Debug)] pub struct WalletDescriptors { - pub descriptor: String, - pub change_descriptor: Option + pub descriptor: Descriptor, + pub change_descriptor: Option> } -pub fn generate_descriptor_wallet() -> Result { - let mut seed: [u8; 32] = [0u8; 32]; - rand::thread_rng().fill_bytes(&mut seed); // verify this is secure randomness! +pub fn generate_descriptor_wallet(xprv_input: Option) -> Result { + let xprv: ExtendedPrivKey; + let network: Network = Network::Testnet; + + if let Some(xprv_i) = xprv_input { + xprv = ExtendedPrivKey::from_str(&xprv_i)?; + } else { + let mut seed: [u8; 32] = [0u8; 32]; + rand::thread_rng().fill_bytes(&mut seed); // verify this is secure randomness! + xprv = ExtendedPrivKey::new_master(network, &seed)?; + dbg!("Generated xprv: ", xprv.to_string()); + } - let network: Network = Network::Testnet; - let xprv: ExtendedPrivKey = ExtendedPrivKey::new_master(network, &seed)?; let (descriptor, key_map, _) = Bip86(xprv, KeychainKind::External).build(network).unwrap(); let (change_descriptor, change_key_map, _) = Bip86(xprv, KeychainKind::Internal).build(network)?; let descriptors = WalletDescriptors { - descriptor: descriptor.to_string_with_secret(&key_map), - change_descriptor: Some(change_descriptor.to_string_with_secret(&change_key_map)), + descriptor, + change_descriptor: Some(change_descriptor) }; - dbg!("Generated wallet descriptors: ", &descriptors); Ok(descriptors) } -pub fn load_wallet(trader_config: &TraderSettings) -> Result<()> { - // let client = Client::new(&trader_config.electrum_endpoint)?; +pub fn load_wallet(trader_config: &TraderSettings) -> Result> { + let client = Client::new(&trader_config.electrum_endpoint)?; + let blockchain = ElectrumBlockchain::from(client); + let wallet = Wallet::new( + trader_config.funded_wallet_descriptor.descriptor.clone(), + trader_config.funded_wallet_descriptor.change_descriptor.clone(), + bitcoin::Network::Testnet, + MemoryDatabase::default(), // non-permanent storage + )?; - // let blockchain = ElectrumBlockchain::from(client); - // let wallet = Wallet::new( - // trader_config.funded_wallet_descriptor.as_str(), - // None, - // bitcoin::Network::Testnet, - // MemoryDatabase::default(), // non-permanent storage - // )?; - // panic!("yeet"); - // wallet.sync(&blockchain, SyncOptions::default())?; - - // println!("Descriptor balance: {} SAT", wallet.get_balance()?); - // panic!("yeet"); - Ok(()) + wallet.sync(&blockchain, SyncOptions::default())?; + println!("Descriptor balance: {} SAT", wallet.get_balance()?); + Ok(wallet) } diff --git a/taptrade-cli-demo/trader/todos.md b/taptrade-cli-demo/trader/todos.md new file mode 100644 index 0000000..0601a09 --- /dev/null +++ b/taptrade-cli-demo/trader/todos.md @@ -0,0 +1 @@ +tbd