Skip to content

Commit a3df1c2

Browse files
committed
added importdescriptors command, updated createwallet command with descriptors parameter and added bech32m address type
1 parent af7ac9f commit a3df1c2

File tree

4 files changed

+92
-12
lines changed

4 files changed

+92
-12
lines changed

client/src/client.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -276,20 +276,33 @@ pub trait RpcApi: Sized {
276276
blank: Option<bool>,
277277
passphrase: Option<&str>,
278278
avoid_reuse: Option<bool>,
279+
descriptors: Option<bool>,
279280
) -> Result<json::LoadWalletResult> {
280281
let mut args = [
281282
wallet.into(),
282283
opt_into_json(disable_private_keys)?,
283284
opt_into_json(blank)?,
284285
opt_into_json(passphrase)?,
285286
opt_into_json(avoid_reuse)?,
287+
opt_into_json(descriptors)?,
286288
];
287289
self.call(
288290
"createwallet",
289-
handle_defaults(&mut args, &[false.into(), false.into(), into_json("")?, false.into()]),
291+
handle_defaults(
292+
&mut args,
293+
&[false.into(), false.into(), into_json("")?, false.into(), false.into()],
294+
),
290295
)
291296
}
292297

298+
fn import_descriptors(
299+
&self,
300+
descriptors: Vec<json::ImportDescriptorRequest>,
301+
) -> Result<Vec<json::ImportDescriptorResult>> {
302+
let arg = into_json(descriptors)?;
303+
self.call("importdescriptors", &[arg])
304+
}
305+
293306
fn list_wallets(&self) -> Result<Vec<String>> {
294307
self.call("listwallets", &[])
295308
}
@@ -1136,7 +1149,6 @@ impl RpcApi for Client {
11361149
if log_enabled!(Debug) {
11371150
debug!(target: "bitcoincore_rpc", "JSON-RPC request: {} {}", cmd, serde_json::Value::from(args));
11381151
}
1139-
11401152
let resp = self.client.send_request(req).map_err(Error::from);
11411153
log_response(cmd, &resp);
11421154
Ok(resp?.result()?)

integration_test/run.sh

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ PID1=$!
1919
sleep 3
2020

2121
BLOCKFILTERARG=""
22-
if bitcoind -version | grep -q "v0\.\(19\|2\)"; then
22+
if bitcoind -version | grep -q "v\(0\.19\|0\.2\|2\)"; then
2323
BLOCKFILTERARG="-blockfilterindex=1"
2424
fi
2525

2626
FALLBACKFEEARG=""
27-
if bitcoind -version | grep -q "v0\.2"; then
27+
if bitcoind -version | grep -q "v\(0\.2\|2\)"; then
2828
FALLBACKFEEARG="-fallbackfee=0.00001000"
2929
fi
3030

integration_test/src/main.rs

+38-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ extern crate log;
1919
use bitcoincore_rpc::core_rpc_json as bitcoincore_rpc_json;
2020

2121
use std::collections::HashMap;
22+
use std::str::FromStr;
2223

2324
use bitcoincore_rpc::json;
2425
use bitcoincore_rpc::jsonrpc::error::Error as JsonRpcError;
@@ -32,9 +33,7 @@ use bitcoin::{
3233
Address, Amount, Network, OutPoint, PrivateKey, Script, SigHashType, SignedAmount, Transaction,
3334
TxIn, TxOut, Txid,
3435
};
35-
use bitcoincore_rpc_json::{
36-
GetBlockTemplateModes, GetBlockTemplateRules, ScanTxOutRequest,
37-
};
36+
use bitcoincore_rpc_json::{GetBlockTemplateModes, GetBlockTemplateRules, ScanTxOutRequest};
3837

3938
lazy_static! {
4039
static ref SECP: secp256k1::Secp256k1<secp256k1::All> = secp256k1::Secp256k1::new();
@@ -127,15 +126,13 @@ fn main() {
127126
log::set_logger(&LOGGER).map(|()| log::set_max_level(log::LevelFilter::max())).unwrap();
128127

129128
let rpc_url = format!("{}/wallet/testwallet", get_rpc_url());
130-
let auth = get_auth();
131-
132-
let cl = Client::new(&rpc_url, auth).unwrap();
129+
let cl = Client::new(&rpc_url, get_auth()).unwrap();
133130

134131
test_get_network_info(&cl);
135132
unsafe { VERSION = cl.version().unwrap() };
136133
println!("Version: {}", version());
137134

138-
cl.create_wallet("testwallet", None, None, None, None).unwrap();
135+
cl.create_wallet("testwallet", None, None, None, None, None).unwrap();
139136

140137
test_get_mining_info(&cl);
141138
test_get_blockchain_info(&cl);
@@ -205,6 +202,11 @@ fn main() {
205202
//TODO load_wallet(&self, wallet: &str) -> Result<json::LoadWalletResult> {
206203
//TODO unload_wallet(&self, wallet: Option<&str>) -> Result<()> {
207204
//TODO backup_wallet(&self, destination: Option<&str>) -> Result<()> {
205+
206+
let rpc_url = format!("{}/wallet/testdescriptorwallet", get_rpc_url());
207+
let desc_cl = Client::new(&rpc_url, get_auth()).unwrap();
208+
209+
test_descriptor_wallet(&desc_cl);
208210
test_stop(cl);
209211
}
210212

@@ -907,6 +909,7 @@ fn test_create_wallet(cl: &Client) {
907909
blank: Option<bool>,
908910
passphrase: Option<&'a str>,
909911
avoid_reuse: Option<bool>,
912+
descriptors: Option<bool>,
910913
}
911914

912915
let mut wallet_params = vec![
@@ -916,20 +919,23 @@ fn test_create_wallet(cl: &Client) {
916919
blank: None,
917920
passphrase: None,
918921
avoid_reuse: None,
922+
descriptors: None,
919923
},
920924
WalletParams {
921925
name: wallet_names[1],
922926
disable_private_keys: Some(true),
923927
blank: None,
924928
passphrase: None,
925929
avoid_reuse: None,
930+
descriptors: None,
926931
},
927932
WalletParams {
928933
name: wallet_names[2],
929934
disable_private_keys: None,
930935
blank: Some(true),
931936
passphrase: None,
932937
avoid_reuse: None,
938+
descriptors: None,
933939
},
934940
];
935941

@@ -940,13 +946,15 @@ fn test_create_wallet(cl: &Client) {
940946
blank: None,
941947
passphrase: Some("pass"),
942948
avoid_reuse: None,
949+
descriptors: None,
943950
});
944951
wallet_params.push(WalletParams {
945952
name: wallet_names[4],
946953
disable_private_keys: None,
947954
blank: None,
948955
passphrase: None,
949956
avoid_reuse: Some(true),
957+
descriptors: None,
950958
});
951959
}
952960

@@ -958,6 +966,7 @@ fn test_create_wallet(cl: &Client) {
958966
wallet_param.blank,
959967
wallet_param.passphrase,
960968
wallet_param.avoid_reuse,
969+
wallet_param.descriptors,
961970
)
962971
.unwrap();
963972

@@ -1052,3 +1061,25 @@ fn test_getblocktemplate(cl: &Client) {
10521061
fn test_stop(cl: Client) {
10531062
println!("Stopping: '{}'", cl.stop().unwrap());
10541063
}
1064+
1065+
fn test_descriptor_wallet(cl: &Client) {
1066+
cl.create_wallet(
1067+
"testdescriptorwallet",
1068+
Some(false),
1069+
Some(true),
1070+
Some(""),
1071+
Some(false),
1072+
Some(true),
1073+
)
1074+
.unwrap();
1075+
1076+
cl.import_descriptors(
1077+
vec![
1078+
json::ImportDescriptorRequest::new("wpkh(tprv8ZgxMBicQKsPeRBCAfUGsZhyHy9dwWyPqhSJmaMnMJQWWtt8L2SkTeHaiF82CUCGtiTiHAs3cMkjdKckGKiCWeYtvMPF1jDTWYTryRMicpx/86h/1h/0h/0/*)#ymr4jlz6", false),
1079+
json::ImportDescriptorRequest::new("wpkh(tprv8ZgxMBicQKsPeRBCAfUGsZhyHy9dwWyPqhSJmaMnMJQWWtt8L2SkTeHaiF82CUCGtiTiHAs3cMkjdKckGKiCWeYtvMPF1jDTWYTryRMicpx/86h/1h/0h/1/*)#40x502jz", true),
1080+
]
1081+
).unwrap();
1082+
1083+
let add = cl.get_new_address(None, Some(json::AddressType::Bech32)).unwrap();
1084+
assert_eq!(add, Address::from_str("bcrt1q7crcza94drr00skmu5x0n00rhmwnthde2frhwk").unwrap());
1085+
}

json/src/lib.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -1066,11 +1066,13 @@ pub struct GetPeerInfoResult {
10661066
}
10671067

10681068
#[derive(Copy, Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1069-
#[serde(rename_all = "lowercase")]
1069+
#[serde(rename_all = "snake_case")]
10701070
pub enum GetPeerInfoResultNetwork {
10711071
Ipv4,
10721072
Ipv6,
10731073
Onion,
1074+
I2p,
1075+
NotPubliclyRoutable,
10741076
// this is undocumented upstream
10751077
Unroutable,
10761078
}
@@ -1607,6 +1609,7 @@ pub enum AddressType {
16071609
Legacy,
16081610
P2shSegwit,
16091611
Bech32,
1612+
Bech32m,
16101613
}
16111614

16121615
/// Used to represent arguments that can either be an address or a public key.
@@ -1686,3 +1689,37 @@ where
16861689
}
16871690
Ok(Some(res))
16881691
}
1692+
1693+
/// Import Descriptor Request
1694+
#[derive(Serialize, Clone, PartialEq, Eq, Debug)]
1695+
pub struct ImportDescriptorRequest {
1696+
pub active: bool,
1697+
#[serde(rename = "desc")]
1698+
pub descriptor: String,
1699+
pub range: [i64; 2],
1700+
pub next_index: i64,
1701+
pub timestamp: String,
1702+
pub internal: bool,
1703+
}
1704+
1705+
impl ImportDescriptorRequest {
1706+
/// Create a new Import Descriptor request providing just the descriptor and internal flags
1707+
pub fn new(descriptor: &str, internal: bool) -> Self {
1708+
ImportDescriptorRequest {
1709+
descriptor: descriptor.to_string(),
1710+
internal,
1711+
active: true,
1712+
range: [0, 100],
1713+
next_index: 0,
1714+
timestamp: "now".to_string(),
1715+
}
1716+
}
1717+
}
1718+
1719+
/// Imported Descriptor Result
1720+
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
1721+
pub struct ImportDescriptorResult {
1722+
pub success: bool,
1723+
pub warnings: Option<Vec<String>>,
1724+
pub error: Option<String>,
1725+
}

0 commit comments

Comments
 (0)