Ok the bdk looks like a far better bet!
This commit is contained in:
818
Cargo.lock
generated
818
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,11 @@ edition = "2021"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.86"
|
||||||
async-trait = "0.1.52"
|
async-trait = "0.1.52"
|
||||||
|
bdk = "0.29.0"
|
||||||
|
bdk_esplora = "0.15.0"
|
||||||
|
bdk_sqlite = "0.2.0"
|
||||||
bdk_wallet = { version = "1.0.0-alpha.13", features = ["all-keys"] }
|
bdk_wallet = { version = "1.0.0-alpha.13", features = ["all-keys"] }
|
||||||
bft-json-crdt = { path = "../crates/bft-json-crdt" }
|
bft-json-crdt = { path = "../crates/bft-json-crdt" }
|
||||||
bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" }
|
bft-crdt-derive = { path = "../crates/bft-json-crdt/bft-crdt-derive" }
|
||||||
@@ -15,15 +19,16 @@ clap = { version = "4.5.4", features = ["derive"] }
|
|||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
ezsockets = { version = "*", features = ["client"] }
|
ezsockets = { version = "*", features = ["client"] }
|
||||||
fastcrypto = "0.1.8"
|
fastcrypto = "0.1.8"
|
||||||
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
# serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR
|
# serde_cbor = "0.11.2" # move to this once we need to pack things in CBOR
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0.117"
|
serde_json = "1.0.117"
|
||||||
sha256 = "1.5.0"
|
sha256 = "1.5.0"
|
||||||
tokio = { version = "1.37.0", features = ["full"] }
|
tokio = { version = "1.37.0", features = ["full"] }
|
||||||
|
toml = "0.8.14"
|
||||||
tracing = "0.1.32"
|
tracing = "0.1.32"
|
||||||
# tracing-subscriber = "0.3.9"
|
# tracing-subscriber = "0.3.9"
|
||||||
toml = "0.8.14"
|
|
||||||
indexmap = { version = "2.2.6", features = ["serde"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
uuid = { version = "1.8.0", features = ["v4"] }
|
uuid = { version = "1.8.0", features = ["v4"] }
|
||||||
|
|||||||
@@ -1,3 +1,114 @@
|
|||||||
pub fn run(name: &str) {
|
use std::{collections::BTreeSet, io::Write, str::FromStr};
|
||||||
println!("running btc_rpc...");
|
|
||||||
|
use bdk_esplora::{esplora_client, EsploraAsyncExt};
|
||||||
|
use bdk_wallet::{
|
||||||
|
bitcoin::{Address, Amount, Network, Script},
|
||||||
|
KeychainKind, SignOptions, Wallet,
|
||||||
|
};
|
||||||
|
|
||||||
|
use bdk_sqlite::{rusqlite::Connection, Store};
|
||||||
|
|
||||||
|
const SEND_AMOUNT: Amount = Amount::from_sat(5000);
|
||||||
|
const STOP_GAP: usize = 50;
|
||||||
|
const PARALLEL_REQUESTS: usize = 5;
|
||||||
|
|
||||||
|
pub async fn run() -> Result<(), anyhow::Error> {
|
||||||
|
let db_path = "/tmp/bdk-esplora-async-example.sqlite";
|
||||||
|
let conn = Connection::open(db_path)?;
|
||||||
|
let mut db = Store::new(conn)?;
|
||||||
|
let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
|
||||||
|
let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";
|
||||||
|
let changeset = db.read()?;
|
||||||
|
|
||||||
|
let mut wallet = Wallet::new_or_load(
|
||||||
|
external_descriptor,
|
||||||
|
internal_descriptor,
|
||||||
|
changeset,
|
||||||
|
Network::Signet,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let address = wallet.next_unused_address(KeychainKind::External);
|
||||||
|
if let Some(changeset) = wallet.take_staged() {
|
||||||
|
db.write(&changeset)?;
|
||||||
|
}
|
||||||
|
println!("Generated Address: {}", address);
|
||||||
|
|
||||||
|
let balance = wallet.balance();
|
||||||
|
println!("Wallet balance before syncing: {} sats", balance.total());
|
||||||
|
|
||||||
|
print!("Syncing...");
|
||||||
|
let client = esplora_client::Builder::new("http://signet.bitcoindevkit.net").build_async()?;
|
||||||
|
|
||||||
|
fn generate_inspect(kind: KeychainKind) -> impl FnMut(u32, &Script) + Send + Sync + 'static {
|
||||||
|
let mut once = Some(());
|
||||||
|
let mut stdout = std::io::stdout();
|
||||||
|
move |spk_i, _| {
|
||||||
|
match once.take() {
|
||||||
|
Some(_) => print!("\nScanning keychain [{:?}]", kind),
|
||||||
|
None => print!(" {:<3}", spk_i),
|
||||||
|
};
|
||||||
|
stdout.flush().expect("must flush");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let request = wallet
|
||||||
|
.start_full_scan()
|
||||||
|
.inspect_spks_for_all_keychains({
|
||||||
|
let mut once = BTreeSet::<KeychainKind>::new();
|
||||||
|
move |keychain, spk_i, _| {
|
||||||
|
match once.insert(keychain) {
|
||||||
|
true => print!("\nScanning keychain [{:?}]", keychain),
|
||||||
|
false => print!(" {:<3}", spk_i),
|
||||||
|
}
|
||||||
|
std::io::stdout().flush().expect("must flush")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.inspect_spks_for_keychain(
|
||||||
|
KeychainKind::External,
|
||||||
|
generate_inspect(KeychainKind::External),
|
||||||
|
)
|
||||||
|
.inspect_spks_for_keychain(
|
||||||
|
KeychainKind::Internal,
|
||||||
|
generate_inspect(KeychainKind::Internal),
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut update = client
|
||||||
|
.full_scan(request, STOP_GAP, PARALLEL_REQUESTS)
|
||||||
|
.await?;
|
||||||
|
let now = std::time::UNIX_EPOCH.elapsed().unwrap().as_secs();
|
||||||
|
let _ = update.graph_update.update_last_seen_unconfirmed(now);
|
||||||
|
|
||||||
|
wallet.apply_update(update)?;
|
||||||
|
if let Some(changeset) = wallet.take_staged() {
|
||||||
|
db.write(&changeset)?;
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let balance = wallet.balance();
|
||||||
|
println!("Wallet balance after syncing: {} sats", balance.total());
|
||||||
|
|
||||||
|
if balance.total() < SEND_AMOUNT {
|
||||||
|
println!(
|
||||||
|
"Please send at least {} sats to the receiving address",
|
||||||
|
SEND_AMOUNT
|
||||||
|
);
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?
|
||||||
|
.require_network(Network::Signet)?;
|
||||||
|
|
||||||
|
let mut tx_builder = wallet.build_tx();
|
||||||
|
tx_builder
|
||||||
|
.add_recipient(faucet_address.script_pubkey(), SEND_AMOUNT)
|
||||||
|
.enable_rbf();
|
||||||
|
|
||||||
|
let mut psbt = tx_builder.finish()?;
|
||||||
|
let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
|
||||||
|
assert!(finalized);
|
||||||
|
|
||||||
|
let tx = psbt.extract_tx()?;
|
||||||
|
client.broadcast(&tx).await?;
|
||||||
|
println!("Tx broadcasted! Txid: {}", tx.compute_txid());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pub async fn run() {
|
|||||||
node.start().await;
|
node.start().await;
|
||||||
}
|
}
|
||||||
Some(Commands::Btc {}) => {
|
Some(Commands::Btc {}) => {
|
||||||
clients::btc_rpc::run("sammy_wallet");
|
let _ = clients::btc_rpc::run().await;
|
||||||
}
|
}
|
||||||
None => println!("No command provided. Exiting. See --help for more information."),
|
None => println!("No command provided. Exiting. See --help for more information."),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use bft_json_crdt::json_crdt::SignedOp;
|
use bft_json_crdt::json_crdt::SignedOp;
|
||||||
use bitcoin::{absolute, key::Keypair, transaction::Version, TxIn, TxOut};
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
pub(crate) const BITCOIN_KEY_FILE: &str = "bitcoin_keys.pem";
|
pub(crate) const BITCOIN_KEY_FILE: &str = "bitcoin_keys.pem";
|
||||||
pub(crate) const BFT_CRDT_KEY_FILE: &str = "keys.pem";
|
pub(crate) const BFT_CRDT_KEY_FILE: &str = "keys.pem";
|
||||||
@@ -40,29 +38,29 @@ pub fn fake_generic_transaction_json(from: String) -> Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a Bitcoin transaction from this node's bitcoin_keys
|
/// Generate a Bitcoin transaction from this node's bitcoin_keys
|
||||||
pub fn fake_bitcoin_transaction(key_pair: Keypair) -> bitcoin::Transaction {
|
// pub fn fake_bitcoin_transaction(key_pair: Keypair) -> bitcoin::Transaction {
|
||||||
let from = key_pair.public_key().to_string();
|
// let from = key_pair.public_key().to_string();
|
||||||
let to = "Bob";
|
// let to = "Bob";
|
||||||
let amount = 1;
|
// let amount = 1;
|
||||||
let lock_time = absolute::LockTime::from_height(0).expect("couldn't format btc lock time");
|
// let lock_time = absolute::LockTime::from_height(0).expect("couldn't format btc lock time");
|
||||||
let input = TxIn {
|
// let input = TxIn {
|
||||||
previous_output: todo!(),
|
// previous_output: todo!(),
|
||||||
script_sig: todo!(),
|
// script_sig: todo!(),
|
||||||
sequence: todo!(),
|
// sequence: todo!(),
|
||||||
witness: todo!(),
|
// witness: todo!(),
|
||||||
};
|
// };
|
||||||
let output = TxOut {
|
// let output = TxOut {
|
||||||
value: todo!(),
|
// value: todo!(),
|
||||||
script_pubkey: todo!(),
|
// script_pubkey: todo!(),
|
||||||
};
|
// };
|
||||||
let tx = bitcoin::Transaction {
|
// let tx = bitcoin::Transaction {
|
||||||
version: Version(1),
|
// version: Version(1),
|
||||||
lock_time,
|
// lock_time,
|
||||||
input: vec![input],
|
// input: vec![input],
|
||||||
output: vec![output],
|
// output: vec![output],
|
||||||
};
|
// };
|
||||||
tx
|
// tx
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn shappy(op: SignedOp) -> String {
|
pub fn shappy(op: SignedOp) -> String {
|
||||||
let b = serde_json::to_string(&op).unwrap().into_bytes();
|
let b = serde_json::to_string(&op).unwrap().into_bytes();
|
||||||
|
|||||||
Reference in New Issue
Block a user