Skip to content

Commit

Permalink
feat: add RPC wallet example
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimirfomene committed Oct 12, 2023
1 parent 529e8b5 commit 2dc9575
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 2 deletions.
3 changes: 3 additions & 0 deletions example-crates/wallet_rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bdk = { path = "../../crates/bdk" }
bdk_file_store = { path = "../../crates/file_store" }
bdk_bitcoind_rpc = { path = "../../crates/bitcoind_rpc" }
100 changes: 98 additions & 2 deletions example-crates/wallet_rpc/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,99 @@
fn main() {
println!("Hello, world!");
use std::str::FromStr;
use bdk_file_store::Store;
use bdk::{
bitcoin::{ Address, Network},
wallet::{AddressIndex, Wallet, ChangeSet },
SignOptions,
};
use bdk_bitcoind_rpc::{
Emitter,
bitcoincore_rpc::{Auth, Client, RpcApi},
};

const DB_MAGIC: &str = "bdk-rpc-wallet-example";
const FALLBACK_HEIGHT: u32 = 2532323;
const SEND_AMOUNT: u64 = 5000;
const LOOKAHEAD: u32 = 20;
const RPC_USER: &str = "bitcoin";
const RPC_PASS: &str = "password";
const RPC_URL : &str = "127.0.0.1:18332";


fn main() -> Result<(), Box<dyn std::error::Error>> {
let db_path = std::env::temp_dir().join("bdk-rpc-example");
let db = Store::<bdk::wallet::ChangeSet>::new_from_path(DB_MAGIC.as_bytes(), db_path)?;

let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/0/*)";
let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/1'/0'/1/*)";

let mut wallet = Wallet::new(
external_descriptor,
Some(internal_descriptor),
db,
Network::Testnet,
)?;

let address = wallet.get_address(AddressIndex::New);
println!("Generated Address: {}", address);

let balance = wallet.get_balance();
println!("Wallet balance before syncing: {} sats", balance.total());

let rpc_client = Client::new(
RPC_URL,
Auth::UserPass(RPC_USER.to_string(), RPC_PASS.to_string()),
)?;

println!("Connected to Bitcoin Core RPC at {:?}", rpc_client.get_blockchain_info().unwrap());

wallet.set_lookahead_for_all(LOOKAHEAD);

let chain_tip = wallet.latest_checkpoint();
let mut emitter = match chain_tip {
Some(cp) => Emitter::from_checkpoint(&rpc_client, cp),
None => Emitter::from_height(&rpc_client, FALLBACK_HEIGHT),
};

while let Some((height, block)) = emitter.next_block()? {
println!("Applying block {} at height {}", block.block_hash(), height);
let wallet_changeset = wallet.apply_block_relevant(block, height)?;
wallet.stage(wallet_changeset);
wallet.commit()?;
}

let unconfirmed_txs = emitter.mempool()?;
let mempool_changeset = wallet.batch_insert_relevant_unconfirmed(unconfirmed_txs.iter().map(|(tx, time)| (tx, *time)));
println!("Applying unconfirmed transactions: {:?}", mempool_changeset);
let wallet_changeset = ChangeSet::from(mempool_changeset);
wallet.stage(wallet_changeset);
wallet.commit()?;

let balance = wallet.get_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("tb1qw2c3lxufxqe2x9s4rdzh65tpf4d7fssjgh8nv6")?
.require_network(Network::Testnet)?;

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();
rpc_client.send_raw_transaction(&tx)?;
println!("Tx broadcasted! Txid: {}", tx.txid());

Ok(())
}

0 comments on commit 2dc9575

Please sign in to comment.