Merge branch 'master' into feature/more-getters
This commit is contained in:
commit
8cd055090d
3
.github/workflows/cont_integration.yml
vendored
3
.github/workflows/cont_integration.yml
vendored
@ -28,6 +28,7 @@ jobs:
|
|||||||
- async-interface
|
- async-interface
|
||||||
- use-esplora-reqwest
|
- use-esplora-reqwest
|
||||||
- sqlite
|
- sqlite
|
||||||
|
- sqlite-bundled
|
||||||
steps:
|
steps:
|
||||||
- name: checkout
|
- name: checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@ -114,7 +115,7 @@ jobs:
|
|||||||
override: true
|
override: true
|
||||||
- name: Test
|
- name: Test
|
||||||
run: cargo test --no-default-features --features ${{ matrix.blockchain.features }} ${{ matrix.blockchain.name }}::bdk_blockchain_tests
|
run: cargo test --no-default-features --features ${{ matrix.blockchain.features }} ${{ matrix.blockchain.name }}::bdk_blockchain_tests
|
||||||
|
|
||||||
check-wasm:
|
check-wasm:
|
||||||
name: Check WASM
|
name: Check WASM
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Add `sqlite-bundled` feature for deployments that need a bundled version of sqlite, ie. for mobile platforms.
|
||||||
- Added `Wallet::get_signers()`, `Wallet::descriptor_checksum()` and `Wallet::get_address_validators()`, exposed the `AsDerived` trait.
|
- Added `Wallet::get_signers()`, `Wallet::descriptor_checksum()` and `Wallet::get_address_validators()`, exposed the `AsDerived` trait.
|
||||||
|
|
||||||
## [v0.17.0] - [v0.16.1]
|
## [v0.17.0] - [v0.16.1]
|
||||||
@ -440,4 +440,4 @@ final transaction is created by calling `finish` on the builder.
|
|||||||
[v0.16.0]: https://github.com/bitcoindevkit/bdk/compare/v0.15.0...v0.16.0
|
[v0.16.0]: https://github.com/bitcoindevkit/bdk/compare/v0.15.0...v0.16.0
|
||||||
[v0.16.1]: https://github.com/bitcoindevkit/bdk/compare/v0.16.0...v0.16.1
|
[v0.16.1]: https://github.com/bitcoindevkit/bdk/compare/v0.16.0...v0.16.1
|
||||||
[v0.17.0]: https://github.com/bitcoindevkit/bdk/compare/v0.16.1...v0.17.0
|
[v0.17.0]: https://github.com/bitcoindevkit/bdk/compare/v0.16.1...v0.17.0
|
||||||
[unreleased]: https://github.com/bitcoindevkit/bdk/compare/v0.17.0...HEAD
|
[unreleased]: https://github.com/bitcoindevkit/bdk/compare/v0.17.0...HEAD
|
@ -55,6 +55,7 @@ compiler = ["miniscript/compiler"]
|
|||||||
verify = ["bitcoinconsensus"]
|
verify = ["bitcoinconsensus"]
|
||||||
default = ["key-value-db", "electrum"]
|
default = ["key-value-db", "electrum"]
|
||||||
sqlite = ["rusqlite", "ahash"]
|
sqlite = ["rusqlite", "ahash"]
|
||||||
|
sqlite-bundled = ["sqlite", "rusqlite/bundled"]
|
||||||
compact_filters = ["rocksdb", "socks", "lazy_static", "cc"]
|
compact_filters = ["rocksdb", "socks", "lazy_static", "cc"]
|
||||||
key-value-db = ["sled"]
|
key-value-db = ["sled"]
|
||||||
all-keys = ["keys-bip39"]
|
all-keys = ["keys-bip39"]
|
||||||
@ -109,6 +110,11 @@ name = "miniscriptc"
|
|||||||
path = "examples/compiler.rs"
|
path = "examples/compiler.rs"
|
||||||
required-features = ["compiler"]
|
required-features = ["compiler"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "rpcwallet"
|
||||||
|
path = "examples/rpcwallet.rs"
|
||||||
|
required-features = ["keys-bip39", "key-value-db", "rpc"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["macros"]
|
members = ["macros"]
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
233
examples/rpcwallet.rs
Normal file
233
examples/rpcwallet.rs
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
|
||||||
|
//
|
||||||
|
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
||||||
|
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
|
||||||
|
// You may not use this file except in accordance with one or both of these
|
||||||
|
// licenses.
|
||||||
|
|
||||||
|
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||||
|
use bdk::bitcoin::util::bip32::ExtendedPrivKey;
|
||||||
|
use bdk::bitcoin::Amount;
|
||||||
|
use bdk::bitcoin::Network;
|
||||||
|
use bdk::bitcoincore_rpc::RpcApi;
|
||||||
|
|
||||||
|
use bdk::blockchain::rpc::{Auth, RpcBlockchain, RpcConfig};
|
||||||
|
use bdk::blockchain::ConfigurableBlockchain;
|
||||||
|
|
||||||
|
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
|
||||||
|
use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey};
|
||||||
|
|
||||||
|
use bdk::miniscript::miniscript::Segwitv0;
|
||||||
|
|
||||||
|
use bdk::sled;
|
||||||
|
use bdk::template::Bip84;
|
||||||
|
use bdk::wallet::{signer::SignOptions, wallet_name_from_descriptor, AddressIndex, SyncOptions};
|
||||||
|
use bdk::KeychainKind;
|
||||||
|
use bdk::Wallet;
|
||||||
|
|
||||||
|
use bdk::blockchain::Blockchain;
|
||||||
|
|
||||||
|
use electrsd;
|
||||||
|
|
||||||
|
use std::error::Error;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
/// This example demonstrates a typical way to create a wallet and work with bdk.
|
||||||
|
///
|
||||||
|
/// This example bdk wallet is connected to a bitcoin core rpc regtest node,
|
||||||
|
/// and will attempt to receive, create and broadcast transactions.
|
||||||
|
///
|
||||||
|
/// To start a bitcoind regtest node programmatically, this example uses
|
||||||
|
/// `electrsd` library, which is also a bdk dev-dependency.
|
||||||
|
///
|
||||||
|
/// But you can start your own bitcoind backend, and the rest of the example should work fine.
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
// -- Setting up background bitcoind process
|
||||||
|
|
||||||
|
println!(">> Setting up bitcoind");
|
||||||
|
|
||||||
|
// Start the bitcoind process
|
||||||
|
let bitcoind_conf = electrsd::bitcoind::Conf::default();
|
||||||
|
|
||||||
|
// electrsd will automatically download the bitcoin core binaries
|
||||||
|
let bitcoind_exe =
|
||||||
|
electrsd::bitcoind::downloaded_exe_path().expect("We should always have downloaded path");
|
||||||
|
|
||||||
|
// Launch bitcoind and gather authentication access
|
||||||
|
let bitcoind = electrsd::bitcoind::BitcoinD::with_conf(bitcoind_exe, &bitcoind_conf).unwrap();
|
||||||
|
let bitcoind_auth = Auth::Cookie {
|
||||||
|
file: bitcoind.params.cookie_file.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get a new core address
|
||||||
|
let core_address = bitcoind.client.get_new_address(None, None)?;
|
||||||
|
|
||||||
|
// Generate 101 blocks and use the above address as coinbase
|
||||||
|
bitcoind.client.generate_to_address(101, &core_address)?;
|
||||||
|
|
||||||
|
println!(">> bitcoind setup complete");
|
||||||
|
println!(
|
||||||
|
"Available coins in Core wallet : {}",
|
||||||
|
bitcoind.client.get_balance(None, None)?
|
||||||
|
);
|
||||||
|
|
||||||
|
// -- Setting up the Wallet
|
||||||
|
|
||||||
|
println!("\n>> Setting up BDK wallet");
|
||||||
|
|
||||||
|
// Get a random private key
|
||||||
|
let xprv = generate_random_ext_privkey()?;
|
||||||
|
|
||||||
|
// Use the derived descriptors from the privatekey to
|
||||||
|
// create unique wallet name.
|
||||||
|
// This is a special utility function exposed via `bdk::wallet_name_from_descriptor()`
|
||||||
|
let wallet_name = wallet_name_from_descriptor(
|
||||||
|
Bip84(xprv, KeychainKind::External),
|
||||||
|
Some(Bip84(xprv, KeychainKind::Internal)),
|
||||||
|
Network::Regtest,
|
||||||
|
&Secp256k1::new(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Create a database (using default sled type) to store wallet data
|
||||||
|
let mut datadir = PathBuf::from_str("/tmp/")?;
|
||||||
|
datadir.push(".bdk-example");
|
||||||
|
let database = sled::open(datadir)?;
|
||||||
|
let database = database.open_tree(wallet_name.clone())?;
|
||||||
|
|
||||||
|
// Create a RPC configuration of the running bitcoind backend we created in last step
|
||||||
|
// Note: If you are using custom regtest node, use the appropriate url and auth
|
||||||
|
let rpc_config = RpcConfig {
|
||||||
|
url: bitcoind.params.rpc_socket.to_string(),
|
||||||
|
auth: bitcoind_auth,
|
||||||
|
network: Network::Regtest,
|
||||||
|
wallet_name,
|
||||||
|
skip_blocks: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use the above configuration to create a RPC blockchain backend
|
||||||
|
let blockchain = RpcBlockchain::from_config(&rpc_config)?;
|
||||||
|
|
||||||
|
// Combine Database + Descriptor to create the final wallet
|
||||||
|
let wallet = Wallet::new(
|
||||||
|
Bip84(xprv, KeychainKind::External),
|
||||||
|
Some(Bip84(xprv, KeychainKind::Internal)),
|
||||||
|
Network::Regtest,
|
||||||
|
database,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// The `wallet` and the `blockchain` are independent structs.
|
||||||
|
// The wallet will be used to do all wallet level actions
|
||||||
|
// The blockchain can be used to do all blockchain level actions.
|
||||||
|
// For certain actions (like sync) the wallet will ask for a blockchain.
|
||||||
|
|
||||||
|
// Sync the wallet
|
||||||
|
// The first sync is important as this will instantiate the
|
||||||
|
// wallet files.
|
||||||
|
wallet.sync(&blockchain, SyncOptions::default())?;
|
||||||
|
|
||||||
|
println!(">> BDK wallet setup complete.");
|
||||||
|
println!(
|
||||||
|
"Available initial coins in BDK wallet : {} sats",
|
||||||
|
wallet.get_balance()?
|
||||||
|
);
|
||||||
|
|
||||||
|
// -- Wallet transaction demonstration
|
||||||
|
|
||||||
|
println!("\n>> Sending coins: Core --> BDK, 10 BTC");
|
||||||
|
// Get a new address to receive coins
|
||||||
|
let bdk_new_addr = wallet.get_address(AddressIndex::New)?.address;
|
||||||
|
|
||||||
|
// Send 10 BTC from core wallet to bdk wallet
|
||||||
|
bitcoind.client.send_to_address(
|
||||||
|
&bdk_new_addr,
|
||||||
|
Amount::from_btc(10.0)?,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Confirm transaction by generating 1 block
|
||||||
|
bitcoind.client.generate_to_address(1, &core_address)?;
|
||||||
|
|
||||||
|
// Sync the BDK wallet
|
||||||
|
// This time the sync will fetch the new transaction and update it in
|
||||||
|
// wallet database
|
||||||
|
wallet.sync(&blockchain, SyncOptions::default())?;
|
||||||
|
|
||||||
|
println!(">> Received coins in BDK wallet");
|
||||||
|
println!(
|
||||||
|
"Available balance in BDK wallet: {} sats",
|
||||||
|
wallet.get_balance()?
|
||||||
|
);
|
||||||
|
|
||||||
|
println!("\n>> Sending coins: BDK --> Core, 5 BTC");
|
||||||
|
// Attempt to send back 5.0 BTC to core address by creating a transaction
|
||||||
|
//
|
||||||
|
// Transactions are created using a `TxBuilder`.
|
||||||
|
// This helps us to systematically build a transaction with all
|
||||||
|
// required customization.
|
||||||
|
// A full list of APIs offered by `TxBuilder` can be found at
|
||||||
|
// https://docs.rs/bdk/latest/bdk/wallet/tx_builder/struct.TxBuilder.html
|
||||||
|
let mut tx_builder = wallet.build_tx();
|
||||||
|
|
||||||
|
// For a regular transaction, just set the recipient and amount
|
||||||
|
tx_builder.set_recipients(vec![(core_address.script_pubkey(), 500000000)]);
|
||||||
|
|
||||||
|
// Finalize the transaction and extract the PSBT
|
||||||
|
let (mut psbt, _) = tx_builder.finish()?;
|
||||||
|
|
||||||
|
// Set signing option
|
||||||
|
let signopt = SignOptions {
|
||||||
|
assume_height: None,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sign the psbt
|
||||||
|
wallet.sign(&mut psbt, signopt)?;
|
||||||
|
|
||||||
|
// Extract the signed transaction
|
||||||
|
let tx = psbt.extract_tx();
|
||||||
|
|
||||||
|
// Broadcast the transaction
|
||||||
|
blockchain.broadcast(&tx)?;
|
||||||
|
|
||||||
|
// Confirm transaction by generating some blocks
|
||||||
|
bitcoind.client.generate_to_address(1, &core_address)?;
|
||||||
|
|
||||||
|
// Sync the BDK wallet
|
||||||
|
wallet.sync(&blockchain, SyncOptions::default())?;
|
||||||
|
|
||||||
|
println!(">> Coins sent to Core wallet");
|
||||||
|
println!(
|
||||||
|
"Remaining BDK wallet balance: {} sats",
|
||||||
|
wallet.get_balance()?
|
||||||
|
);
|
||||||
|
println!("\nCongrats!! you made your first test transaction with bdk and bitcoin core.");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function demonstrating privatekey extraction using bip39 mnemonic
|
||||||
|
// The mnemonic can be shown to user to safekeeping and the same wallet
|
||||||
|
// private descriptors can be recreated from it.
|
||||||
|
fn generate_random_ext_privkey() -> Result<ExtendedPrivKey, Box<dyn Error>> {
|
||||||
|
// a Bip39 passphrase can be set optionally
|
||||||
|
let password = Some("random password".to_string());
|
||||||
|
|
||||||
|
// Generate a random mnemonic, and use that to create an Extended PrivateKey
|
||||||
|
let mnemonic: GeneratedKey<_, Segwitv0> =
|
||||||
|
Mnemonic::generate((WordCount::Words12, Language::English))
|
||||||
|
.map_err(|e| e.expect("Unknown Error"))?;
|
||||||
|
let mnemonic = mnemonic.into_key();
|
||||||
|
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
|
||||||
|
let xprv = xkey
|
||||||
|
.into_xprv(Network::Regtest)
|
||||||
|
.expect("Expected Private Key");
|
||||||
|
Ok(xprv)
|
||||||
|
}
|
@ -46,12 +46,13 @@
|
|||||||
//! ```toml
|
//! ```toml
|
||||||
//! bdk = "0.17.0"
|
//! bdk = "0.17.0"
|
||||||
//! ```
|
//! ```
|
||||||
|
//!
|
||||||
|
//! # Examples
|
||||||
# mnemonic codes for generating deterministic keys
|
//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
|
||||||
//!
|
//!
|
||||||
//! ## Internal features
|
//! # Internal features
|
||||||
//!
|
//!
|
||||||
//! These features do not expose any new API, but influence internal implementation aspects of
|
//! These features do not expose any new API, but influence internal implementation aspects of
|
||||||
//! BDK.
|
//! BDK.
|
||||||
|
@ -140,6 +140,8 @@ pub struct AddressInfo {
|
|||||||
pub index: u32,
|
pub index: u32,
|
||||||
/// Address
|
/// Address
|
||||||
pub address: Address,
|
pub address: Address,
|
||||||
|
/// Type of keychain
|
||||||
|
pub keychain: KeychainKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for AddressInfo {
|
impl Deref for AddressInfo {
|
||||||
@ -246,6 +248,7 @@ where
|
|||||||
.map(|address| AddressInfo {
|
.map(|address| AddressInfo {
|
||||||
address,
|
address,
|
||||||
index: incremented_index,
|
index: incremented_index,
|
||||||
|
keychain,
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
||||||
}
|
}
|
||||||
@ -276,6 +279,7 @@ where
|
|||||||
.map(|address| AddressInfo {
|
.map(|address| AddressInfo {
|
||||||
address,
|
address,
|
||||||
index: current_index,
|
index: current_index,
|
||||||
|
keychain,
|
||||||
})
|
})
|
||||||
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
||||||
}
|
}
|
||||||
@ -286,7 +290,11 @@ where
|
|||||||
self.get_descriptor_for_keychain(keychain)
|
self.get_descriptor_for_keychain(keychain)
|
||||||
.as_derived(index, &self.secp)
|
.as_derived(index, &self.secp)
|
||||||
.address(self.network)
|
.address(self.network)
|
||||||
.map(|address| AddressInfo { index, address })
|
.map(|address| AddressInfo {
|
||||||
|
index,
|
||||||
|
address,
|
||||||
|
keychain,
|
||||||
|
})
|
||||||
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +306,11 @@ where
|
|||||||
self.get_descriptor_for_keychain(keychain)
|
self.get_descriptor_for_keychain(keychain)
|
||||||
.as_derived(index, &self.secp)
|
.as_derived(index, &self.secp)
|
||||||
.address(self.network)
|
.address(self.network)
|
||||||
.map(|address| AddressInfo { index, address })
|
.map(|address| AddressInfo {
|
||||||
|
index,
|
||||||
|
address,
|
||||||
|
keychain,
|
||||||
|
})
|
||||||
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
.map_err(|_| Error::ScriptDoesntHaveAddressForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3964,6 +3976,7 @@ pub(crate) mod test {
|
|||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 0,
|
index: 0,
|
||||||
address: Address::from_str("tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a").unwrap(),
|
address: Address::from_str("tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3972,7 +3985,8 @@ pub(crate) mod test {
|
|||||||
wallet.get_address(New).unwrap(),
|
wallet.get_address(New).unwrap(),
|
||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 1,
|
index: 1,
|
||||||
address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
|
address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3981,7 +3995,8 @@ pub(crate) mod test {
|
|||||||
wallet.get_address(Peek(25)).unwrap(),
|
wallet.get_address(Peek(25)).unwrap(),
|
||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 25,
|
index: 25,
|
||||||
address: Address::from_str("tb1qsp7qu0knx3sl6536dzs0703u2w2ag6ppl9d0c2").unwrap()
|
address: Address::from_str("tb1qsp7qu0knx3sl6536dzs0703u2w2ag6ppl9d0c2").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3990,7 +4005,8 @@ pub(crate) mod test {
|
|||||||
wallet.get_address(New).unwrap(),
|
wallet.get_address(New).unwrap(),
|
||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 2,
|
index: 2,
|
||||||
address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
|
address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -3999,7 +4015,8 @@ pub(crate) mod test {
|
|||||||
wallet.get_address(Reset(1)).unwrap(),
|
wallet.get_address(Reset(1)).unwrap(),
|
||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 1,
|
index: 1,
|
||||||
address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
|
address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -4008,7 +4025,8 @@ pub(crate) mod test {
|
|||||||
wallet.get_address(New).unwrap(),
|
wallet.get_address(New).unwrap(),
|
||||||
AddressInfo {
|
AddressInfo {
|
||||||
index: 2,
|
index: 2,
|
||||||
address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
|
address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -4037,15 +4055,21 @@ pub(crate) mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wallet.get_address(AddressIndex::New).unwrap().address,
|
wallet.get_address(AddressIndex::New).unwrap(),
|
||||||
Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap()
|
AddressInfo {
|
||||||
|
index: 0,
|
||||||
|
address: Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap(),
|
||||||
|
keychain: KeychainKind::External,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wallet
|
wallet.get_internal_address(AddressIndex::New).unwrap(),
|
||||||
.get_internal_address(AddressIndex::New)
|
AddressInfo {
|
||||||
.unwrap()
|
index: 0,
|
||||||
.address,
|
address: Address::from_str("bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa").unwrap(),
|
||||||
Address::from_str("bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa").unwrap()
|
keychain: KeychainKind::Internal,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let wallet = Wallet::new(
|
let wallet = Wallet::new(
|
||||||
@ -4057,11 +4081,12 @@ pub(crate) mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
wallet
|
wallet.get_internal_address(AddressIndex::New).unwrap(),
|
||||||
.get_internal_address(AddressIndex::New)
|
AddressInfo {
|
||||||
.unwrap()
|
index: 0,
|
||||||
.address,
|
address: Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap(),
|
||||||
Address::from_str("bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s").unwrap(),
|
keychain: KeychainKind::Internal,
|
||||||
|
},
|
||||||
"when there's no internal descriptor it should just use external"
|
"when there's no internal descriptor it should just use external"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user