generate descriptors

This commit is contained in:
Felix
2024-06-06 10:49:19 +00:00
parent cde36f32a9
commit ef57aaba32
8 changed files with 115 additions and 8 deletions

View File

@ -0,0 +1,7 @@
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"
BOND_RATIO=5
FUNDED_WALLET_DESCRIPTOR="tr([3ed82ea5/86h/1h/0h]tpubDCi4JkK1113yExq1Jc42fFYkWt4cfXMSnv47kz6HrU3giqpY6Cu19jc7uXgj5szMyiUnRD4tC8R9mBHLNZw1cKttySbAUEDAYo7bQGSi625/<0;1>/*)#fh3av2m4" # sparrow wallet taproot wallet descriptor

View File

@ -363,6 +363,12 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]] [[package]]
name = "electrum-client" name = "electrum-client"
version = "0.18.0" version = "0.18.0"
@ -1501,6 +1507,7 @@ dependencies = [
"base91", "base91",
"bdk", "bdk",
"clap", "clap",
"dotenv",
"reqwest", "reqwest",
"serde", "serde",
"sha2", "sha2",

View File

@ -8,6 +8,7 @@ anyhow = "1.0.86"
base91 = "0.1.0" base91 = "0.1.0"
bdk = "0.29.0" bdk = "0.29.0"
clap = { version = "4.5.4", features = ["derive", "cargo"] } clap = { version = "4.5.4", features = ["derive", "cargo"] }
dotenv = "0.15.0"
reqwest = { version = "0.12.4", features = ["blocking", "json"] } reqwest = { version = "0.12.4", features = ["blocking", "json"] }
serde = "1.0.203" serde = "1.0.203"
sha2 = "0.10.8" sha2 = "0.10.8"

View File

@ -1,6 +1,9 @@
use std::io::{self, Write}; use std::io::{self, Write};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use sha2::{Sha256, Digest}; use sha2::{Sha256, Digest};
use std::env;
use crate::wallet::{generate_descriptor_wallet, WalletDescriptors};
#[derive(Debug)] #[derive(Debug)]
pub struct Coordinator; pub struct Coordinator;
@ -19,6 +22,7 @@ pub struct TraderSettings {
pub trade_type: OfferType, pub trade_type: OfferType,
pub payout_address: String, pub payout_address: String,
pub bond_ratio: u8, pub bond_ratio: u8,
pub funded_wallet_descriptor: WalletDescriptors,
} }
#[derive(Debug)] #[derive(Debug)]
@ -53,8 +57,11 @@ impl CliSettings {
buffer.trim().to_string() buffer.trim().to_string()
} }
fn get_trade_type() -> OfferType { fn get_trade_type(trade_type: Option<String>) -> OfferType {
let trade_type = Self::get_user_input("Do you want to buy or sell satoshis: "); let trade_type = match trade_type {
Some(value) => value,
None => Self::get_user_input("Do you want to buy or sell satoshis: "),
};
match trade_type.as_str() { match trade_type.as_str() {
"buy" => OfferType::Buy(Self::get_user_input("How many satoshi do you want to buy: ").parse().unwrap()), "buy" => OfferType::Buy(Self::get_user_input("How many satoshi do you want to buy: ").parse().unwrap()),
"sell" => OfferType::Sell(Self::get_user_input("How many satoshi do you want to sell: ").parse().unwrap()), "sell" => OfferType::Sell(Self::get_user_input("How many satoshi do you want to sell: ").parse().unwrap()),
@ -66,22 +73,53 @@ impl CliSettings {
let electrum_endpoint = Self::get_user_input("Enter electrum endpoint: "); let electrum_endpoint = Self::get_user_input("Enter electrum endpoint: ");
let coordinator_endpoint = Self::get_user_input("Enter coordinator endpoint: "); let coordinator_endpoint = Self::get_user_input("Enter coordinator endpoint: ");
let robosats_robohash_base91 = bytes_to_base91(&hash256(&Self::get_user_input("Enter your robosats robot key: "))); let robosats_robohash_base91 = bytes_to_base91(&hash256(&Self::get_user_input("Enter your robosats robot key: ")));
let trade_type = Self::get_trade_type(); 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 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 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: ")))?;
Ok(TraderSettings { Ok(TraderSettings {
electrum_endpoint, electrum_endpoint,
coordinator_endpoint, coordinator_endpoint,
robosats_robohash_base91, robosats_robohash_base91,
trade_type, trade_type,
payout_address, payout_address,
bond_ratio bond_ratio,
funded_wallet_descriptor
})
}
fn get_wallet_descriptors(cli_input: Option<String>) -> Result<WalletDescriptors> {
if let Some(user_input) = cli_input {
if !(user_input.is_empty()) {
return Ok(WalletDescriptors {
descriptor: user_input,
change_descriptor: None
});
}
};
generate_descriptor_wallet()
}
fn load_from_env() -> Result<TraderSettings> {
dotenv::from_filename(".env")?;
Ok(TraderSettings {
electrum_endpoint: env::var("ELECTRUM_ENDPOINT")?,
coordinator_endpoint: env::var("COORDINATOR_ENDPOINT")?,
robosats_robohash_base91: env::var("ROBOHASH_BASE91")?,
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")?))?,
}) })
} }
pub fn parse_cli_args() -> Result<Self> { pub fn parse_cli_args() -> Result<Self> {
let mode = Self::get_user_input("Enter mode, 'taker' or 'maker': "); let mode = Self::get_user_input("Enter mode, 'taker' or 'maker': ");
let trader_settings = Self::get_trader_settings()?; let trader_settings = match Self::get_user_input("Load from .env (y/N): ").trim() {
"y" => Self::load_from_env()?,
"N" => Self::get_trader_settings()?,
_ => return Err(anyhow!("Not a valid input!")),
};
match mode.to_lowercase().as_str() { match mode.to_lowercase().as_str() {
"maker" => Ok(Self::Maker(trader_settings)), "maker" => Ok(Self::Maker(trader_settings)),
"taker" => Ok(Self::Taker(trader_settings)), "taker" => Ok(Self::Taker(trader_settings)),

View File

@ -2,6 +2,7 @@
mod cli; mod cli;
mod communication; mod communication;
mod trading; mod trading;
mod wallet;
use core::panic; use core::panic;

View File

@ -4,10 +4,12 @@
use anyhow::Result; use anyhow::Result;
use crate::cli::TraderSettings; use crate::cli::TraderSettings;
use crate::communication::api::OfferCreationResponse; use crate::communication::api::OfferCreationResponse;
use crate::wallet::load_wallet;
pub fn run_maker(maker_config: &TraderSettings) -> Result<()> { pub fn run_maker(maker_config: &TraderSettings) -> Result<()> {
let offer_conditions = OfferCreationResponse::fetch(maker_config)?; // let offer_conditions = OfferCreationResponse::fetch(maker_config)?;
load_wallet(maker_config)?;
// maker_utils::maker(offer_conditions, maker_config) // maker_utils::maker(offer_conditions, maker_config)
Ok(()) Ok(())

View File

@ -1 +1,52 @@
// create bdk wallet mod bond;
use bdk::{Wallet, KeychainKind, SyncOptions, bitcoin, template::{Bip86, DescriptorTemplate}};
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 crate::cli::TraderSettings;
// https://github.com/bitcoindevkit/book-of-bdk
#[derive(Debug)]
pub struct WalletDescriptors {
pub descriptor: String,
pub change_descriptor: Option<String>
}
pub fn generate_descriptor_wallet() -> Result<WalletDescriptors> {
let mut seed: [u8; 32] = [0u8; 32];
rand::thread_rng().fill_bytes(&mut seed); // verify this is secure randomness!
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)),
};
dbg!("Generated wallet descriptors: ", &descriptors);
Ok(descriptors)
}
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.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(())
}