1#![crate_name = "liquid_rpc"]
17#![crate_type = "rlib"]
18
19pub extern crate bitcoincore_rpc;
20pub extern crate elements;
21pub extern crate jsonrpc;
22extern crate serde;
23extern crate serde_json;
24
25pub extern crate liquid_rpc_json;
26pub use json::{bitcoin_asset, AssetId, BITCOIN_ASSET_HEX};
27pub use liquid_rpc_json as json;
28
29mod error;
30
31pub use error::Error;
32pub use bitcoincore_rpc::json as btcjson;
33pub use bitcoincore_rpc::Auth;
34
35pub type Result<T> = ::std::result::Result<T, Error>;
36
37use std::collections::HashMap;
38
39use elements::bitcoin;
40
41use bitcoin::hashes::hex::{FromHex, ToHex};
42use bitcoin::util::bip32;
43use bitcoin::{PublicKey, Script};
45use bitcoin::hashes::sha256d;
46use bitcoin::secp256k1::SecretKey;
47use bitcoin::util::amount::{self, Amount};
48use elements::encode;
49
50fn ser_amount(amount: &Amount) -> serde_json::Value {
52 amount.to_float_in(amount::Denomination::Bitcoin).into()
53}
54
55fn deser_amount(val: serde_json::Value) -> Result<Amount> {
56 Amount::from_float_in(val.as_f64().unwrap(), amount::Denomination::Bitcoin).map_err(From::from)
57}
58
59fn convert_balances(balances: HashMap<String, serde_json::Value>) -> Result<HashMap<String, Amount>> {
60 let mut ret = HashMap::new();
61 for (k, v) in balances.into_iter() {
62 ret.insert(k, deser_amount(v)?);
63 }
64 Ok(ret)
65}
66
67fn into_json<T>(val: T) -> Result<serde_json::Value>
69where
70 T: serde::ser::Serialize,
71{
72 Ok(serde_json::to_value(val)?)
73}
74
75fn into_json_hex<T: AsRef<[u8]>>(val: T) -> Result<serde_json::Value> {
77 Ok(serde_json::to_value(val.as_ref().to_hex())?)
78}
79
80fn opt_into_json<T>(opt: Option<T>) -> Result<serde_json::Value>
82where
83 T: serde::ser::Serialize,
84{
85 match opt {
86 Some(val) => Ok(into_json(val)?),
87 None => Ok(serde_json::Value::Null),
88 }
89}
90
91fn opt_into_json_hex<T: AsRef<[u8]>>(opt: Option<T>) -> Result<serde_json::Value> {
93 match opt {
94 Some(b) => Ok(serde_json::to_value(b.as_ref().to_hex())?),
95 None => Ok(serde_json::Value::Null),
96 }
97}
98
99fn null() -> serde_json::Value {
101 serde_json::Value::Null
102}
103
104fn empty() -> serde_json::Value {
106 serde_json::Value::Array(vec![])
107}
108
109fn empty_obj() -> serde_json::Value {
111 serde_json::Value::Object(Default::default())
112}
113
114fn handle_defaults<'a, 'b>(
130 args: &'a mut [serde_json::Value],
131 defaults: &'b [serde_json::Value],
132) -> &'a [serde_json::Value] {
133 assert!(args.len() >= defaults.len());
134
135 let mut first_non_null_optional_idx = None;
138 for i in 0..defaults.len() {
139 let args_i = args.len() - 1 - i;
140 let defaults_i = defaults.len() - 1 - i;
141 if args[args_i] == serde_json::Value::Null {
142 if first_non_null_optional_idx.is_some() {
143 if defaults[defaults_i] == serde_json::Value::Null {
144 panic!("Missing `default` for argument idx {}", args_i);
145 }
146 args[args_i] = defaults[defaults_i].clone();
147 }
148 } else if first_non_null_optional_idx.is_none() {
149 first_non_null_optional_idx = Some(args_i);
150 }
151 }
152
153 let required_num = args.len() - defaults.len();
154
155 if let Some(i) = first_non_null_optional_idx {
156 &args[..i + 1]
157 } else {
158 &args[..required_num]
159 }
160}
161
162fn opt_result<T: for<'a> serde::de::Deserialize<'a>>(
164 result: serde_json::Value,
165) -> Result<Option<T>> {
166 if result == serde_json::Value::Null {
167 Ok(None)
168 } else {
169 Ok(serde_json::from_value(result)?)
170 }
171}
172
173pub trait RawTx: Sized {
175 fn raw_hex(self) -> String;
176}
177
178impl<'a> RawTx for &'a elements::Transaction {
179 fn raw_hex(self) -> String {
180 encode::serialize(self).to_hex()
181 }
182}
183
184impl<'a> RawTx for &'a [u8] {
185 fn raw_hex(self) -> String {
186 self.to_hex()
187 }
188}
189
190impl<'a> RawTx for &'a Vec<u8> {
191 fn raw_hex(self) -> String {
192 self.to_hex()
193 }
194}
195
196impl<'a> RawTx for &'a str {
197 fn raw_hex(self) -> String {
198 self.to_owned()
199 }
200}
201
202impl RawTx for String {
203 fn raw_hex(self) -> String {
204 self
205 }
206}
207
208pub trait LiquidRpcApi: Sized {
210 fn call<T: for<'a> serde::de::Deserialize<'a>>(
211 &self,
212 cmd: &str,
213 args: &[serde_json::Value],
214 ) -> Result<T>;
215
216 fn get_block_header_raw(&self, hash: &sha256d::Hash) -> Result<elements::BlockHeader> {
217 let hex: String = self.call("getblockheader", &[into_json(hash)?, false.into()])?;
218 let bytes = Vec::<u8>::from_hex(&hex)?;
219 Ok(encode::deserialize(&bytes)?)
220 }
221
222 fn get_block_header_verbose(&self, hash: &sha256d::Hash) -> Result<json::GetBlockHeaderResult> {
223 self.call("getblockheader", &[into_json(hash)?, true.into()])
224 }
225
226 fn get_blockchain_info(&self) -> Result<json::GetBlockchainInfoResult> {
229 self.call("getblockchaininfo", &[])
230 }
231
232 fn get_raw_transaction(
233 &self,
234 txid: &sha256d::Hash,
235 block_hash: Option<&sha256d::Hash>,
236 ) -> Result<elements::Transaction> {
237 let mut args = [into_json(txid)?, into_json(false)?, opt_into_json(block_hash)?];
238 let hex: String = self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))?;
239 let bytes = Vec::<u8>::from_hex(&hex)?;
240 Ok(encode::deserialize(&bytes)?)
241 }
242
243 fn get_raw_transaction_verbose(
244 &self,
245 txid: &sha256d::Hash,
246 block_hash: Option<&sha256d::Hash>,
247 ) -> Result<json::GetRawTransactionResult> {
248 let mut args = [into_json(txid)?, into_json(true)?, opt_into_json(block_hash)?];
249 self.call("getrawtransaction", handle_defaults(&mut args, &[null()]))
250 }
251
252 fn send_to_address(
253 &self,
254 address: &str,
255 amount: f64,
256 comment: Option<&str>,
257 comment_to: Option<&str>,
258 substract_fee: Option<bool>,
259 replaceable: Option<bool>,
260 confirmation_target: Option<u32>,
261 estimate_mode: Option<btcjson::EstimateMode>,
262 asset_label: Option<&str>,
263 ignore_blind_fail: Option<bool>,
264 ) -> Result<sha256d::Hash> {
265 let mut args = [
266 address.into(),
267 into_json(amount)?,
268 opt_into_json(comment)?,
269 opt_into_json(comment_to)?,
270 opt_into_json(substract_fee)?,
271 opt_into_json(replaceable)?,
272 opt_into_json(confirmation_target)?,
273 opt_into_json(estimate_mode)?,
274 opt_into_json(asset_label)?,
275 opt_into_json(ignore_blind_fail)?,
276 ];
277 self.call("sendtoaddress", handle_defaults(&mut args, &vec![null(); 8]))
278 }
279
280 fn create_raw_transaction_hex(
281 &self,
282 utxos: &[btcjson::CreateRawTransactionInput],
283 outs: &HashMap<String, f64>,
284 locktime: Option<i64>,
285 replaceable: Option<bool>,
286 assets: Option<&HashMap<String, AssetId>>,
287 ) -> Result<String> {
288 let mut args = [
289 into_json(utxos)?,
290 into_json(outs)?,
291 opt_into_json(locktime)?,
292 opt_into_json(replaceable)?,
293 opt_into_json(assets)?,
294 ];
295 let defaults = [into_json(0i64)?, false.into(), null()];
296 self.call("createrawtransaction", handle_defaults(&mut args, &defaults))
297 }
298
299 fn create_raw_transaction(
300 &self,
301 utxos: &[btcjson::CreateRawTransactionInput],
302 outs: &HashMap<String, f64>,
303 locktime: Option<i64>,
304 replaceable: Option<bool>,
305 assets: Option<&HashMap<String, AssetId>>,
306 ) -> Result<elements::Transaction> {
307 let hex: String =
308 self.create_raw_transaction_hex(utxos, outs, locktime, replaceable, assets)?;
309 let bytes = Vec::<u8>::from_hex(&hex)?;
310 Ok(encode::deserialize(&bytes)?)
311 }
312
313 fn fund_raw_transaction<R: RawTx>(
314 &self,
315 tx: R,
316 options: Option<&json::FundRawTransactionOptions>,
317 is_witness: Option<bool>,
318 ) -> Result<json::FundRawTransactionResult> {
319 let mut args = [tx.raw_hex().into(), opt_into_json(options)?, opt_into_json(is_witness)?];
320 let defaults = [empty_obj(), null()];
321 self.call("fundrawtransaction", handle_defaults(&mut args, &defaults))
322 }
323
324 fn sign_raw_transaction_with_wallet<R: RawTx>(
325 &self,
326 tx: R,
327 utxos: Option<&[json::SignRawTransactionInput]>,
328 sighash_type: Option<btcjson::SigHashType>,
329 ) -> Result<json::SignRawTransactionResult> {
330 let mut args = [tx.raw_hex().into(), opt_into_json(utxos)?, opt_into_json(sighash_type)?];
331 let defaults = [empty(), null()];
332 self.call("signrawtransactionwithwallet", handle_defaults(&mut args, &defaults))
333 }
334
335 fn sign_raw_transaction_with_key<R: RawTx>(
339 &self,
340 tx: R,
341 privkeys: &[bitcoin::PrivateKey],
342 prevtxs: Option<&[json::SignRawTransactionInput]>,
343 sighash_type: Option<btcjson::SigHashType>,
344 ) -> Result<json::SignRawTransactionResult> {
345 let mut args = [
346 tx.raw_hex().into(),
347 into_json(privkeys)?,
348 opt_into_json(prevtxs)?,
349 opt_into_json(sighash_type)?,
350 ];
351 let defaults = [empty(), null()];
352 self.call("signrawtransactionwithkey", handle_defaults(&mut args, &defaults))
353 }
354
355 fn send_raw_transaction<R: RawTx>(&self, tx: R) -> Result<sha256d::Hash> {
356 self.call("sendrawtransaction", handle_defaults(&mut [tx.raw_hex().into()], &[]))
357 }
358
359 fn list_unspent(
360 &self,
361 minconf: Option<usize>,
362 maxconf: Option<usize>,
363 addresses: Option<&[&str]>,
364 include_unsafe: Option<bool>,
365 query_options: Option<&json::ListUnspentQueryOptions>,
366 ) -> Result<Vec<json::ListUnspentResultEntry>> {
367 let mut args = [
368 opt_into_json(minconf)?,
369 opt_into_json(maxconf)?,
370 opt_into_json(addresses)?,
371 opt_into_json(include_unsafe)?,
372 opt_into_json(query_options)?,
373 ];
374 let defaults = [0.into(), 9999999.into(), empty(), true.into(), null()];
375 self.call("listunspent", handle_defaults(&mut args, &defaults))
376 }
377
378 fn list_transactions(
379 &self,
380 count: Option<usize>,
381 skip: Option<usize>,
382 include_watch_only: Option<bool>,
383 ) -> Result<Vec<json::ListTransactionsResultEntry>> {
384 let mut args = [
385 "*".into(),
386 opt_into_json(count)?,
387 opt_into_json(skip)?,
388 opt_into_json(include_watch_only)?,
389 ];
390 let defaults = [10.into(), 0.into(), null()];
391 self.call("listtransactions", handle_defaults(&mut args, &defaults))
392 }
393
394 fn list_since_block(
395 &self,
396 block_hash: Option<&sha256d::Hash>,
397 target_confirmations: Option<u32>,
398 include_watch_only: Option<bool>,
399 include_removed: Option<bool>,
400 ) -> Result<json::ListSinceBlockResult> {
401 let mut args = [
402 opt_into_json(block_hash)?,
403 opt_into_json(target_confirmations)?,
404 opt_into_json(include_watch_only)?,
405 opt_into_json(include_removed)?,
406 ];
407 let defaults = ["".into(), 1.into(), false.into(), null()];
408 self.call("listsinceblock", handle_defaults(&mut args, &defaults))
409 }
410
411 fn get_new_address(
412 &self,
413 label: Option<&str>,
414 address_type: Option<btcjson::AddressType>,
415 ) -> Result<String> {
416 self.call("getnewaddress", &[opt_into_json(label)?, opt_into_json(address_type)?])
417 }
418
419 fn get_raw_change_address(&self, address_type: Option<btcjson::AddressType>) -> Result<String> {
420 self.call("getrawchangeaddress", &[opt_into_json(address_type)?])
421 }
422
423 fn validate_address(&self, address: &str) -> Result<json::ValidateAddressResult> {
424 self.call("validateaddress", &[address.into()])
425 }
426
427 fn get_address_info(&self, address: &str) -> Result<json::GetAddressInfoResult> {
428 self.call("getaddressinfo", &[address.into()])
429 }
430
431 fn get_tx_out(
432 &self,
433 txid: &sha256d::Hash,
434 vout: u32,
435 include_mempool: Option<bool>,
436 ) -> Result<Option<json::GetTxOutResult>> {
437 let mut args = [into_json(txid)?, vout.into(), opt_into_json(include_mempool)?];
438 self.call("gettxout", handle_defaults(&mut args, &[null()])).and_then(opt_result)
439 }
440
441 fn get_balance(
442 &self,
443 min_confirmations: Option<u32>,
444 include_watch_only: Option<bool>,
445 ) -> Result<HashMap<String, Amount>> {
446 let mut args = [
447 "*".into(), opt_into_json(min_confirmations)?,
449 opt_into_json(include_watch_only)?,
450 ];
451 self.call("getbalance", handle_defaults(&mut args, &[0.into(), null()]))
452 .and_then(convert_balances)
453 }
454
455 fn get_balance_asset(
456 &self,
457 asset_label: &str,
458 min_confirmations: Option<u32>,
459 include_watch_only: Option<bool>,
460 ) -> Result<Amount> {
461 let mut args = [
462 "*".into(), opt_into_json(min_confirmations)?,
464 opt_into_json(include_watch_only)?,
465 opt_into_json(Some(asset_label))?,
466 ];
467 self.call("getbalance", handle_defaults(&mut args, &[0.into(), false.into(), null()]))
468 .and_then(deser_amount)
469 }
470
471 fn get_unconfirmed_balance(&self) -> Result<HashMap<String, Amount>> {
472 self.call("getunconfirmedbalance", handle_defaults(&mut [], &[])).and_then(convert_balances)
473 }
474
475 fn get_received_by_address(
476 &self,
477 address: &str,
478 min_confirmations: Option<u32>,
479 ) -> Result<HashMap<String, Amount>> {
480 let mut args = [address.into(), opt_into_json(min_confirmations)?];
481 self.call("getreceivedbyaddress", handle_defaults(&mut args, &[null()]))
482 .and_then(convert_balances)
483 }
484
485 fn get_received_by_address_asset(
486 &self,
487 address: &str,
488 asset_label: &str,
489 min_confirmations: Option<u32>,
490 ) -> Result<Amount> {
491 let mut args =
492 [address.into(), opt_into_json(min_confirmations)?, opt_into_json(Some(asset_label))?];
493 self.call("getreceivedbyaddress", handle_defaults(&mut args, &[0.into(), null()]))
494 .and_then(deser_amount)
495 }
496
497 fn get_sidechain_info(&self) -> Result<json::GetSidechainInfoResult> {
503 self.call("getsidechaininfo", &[])
504 }
505
506 fn get_pegin_address(&self) -> Result<json::GetPeginAddressResult> {
507 self.call("getpeginaddress", &[])
508 }
509
510 fn create_raw_pegin<R: bitcoincore_rpc::RawTx, B: AsRef<[u8]>>(
511 &self,
512 raw_bitcoin_tx: R,
513 txout_proof: B,
514 claim_script: Option<&Script>,
515 ) -> Result<json::CreateRawPeginResult> {
516 let mut args = [
517 raw_bitcoin_tx.raw_hex().into(),
518 into_json_hex(txout_proof)?,
519 opt_into_json_hex(claim_script.map(|s| s.as_bytes()))?,
520 ];
521 self.call("createrawpegin", handle_defaults(&mut args, &[null()]))
522 }
523
524 fn claim_pegin<R: bitcoincore_rpc::RawTx, B: AsRef<[u8]>>(
525 &self,
526 raw_bitcoin_tx: R,
527 txout_proof: B,
528 claim_script: Option<&Script>,
529 ) -> Result<sha256d::Hash> {
530 let mut args = [
531 raw_bitcoin_tx.raw_hex().into(),
532 into_json_hex(txout_proof)?,
533 opt_into_json_hex(claim_script.map(|s| s.as_bytes()))?,
534 ];
535 self.call("claimpegin", handle_defaults(&mut args, &[null()]))
536 }
537
538 fn init_pegout_wallet(
539 &self,
540 bitcoin_descriptor: &bip32::ExtendedPubKey,
541 bip32_counter: Option<bip32::ChildNumber>,
542 liquid_pak: Option<&str>,
543 ) -> Result<json::InitPegoutWalletResult> {
544 let mut args = [
545 "".into(), bitcoin_descriptor.to_string().into(),
547 opt_into_json(bip32_counter)?,
548 opt_into_json(liquid_pak)?,
549 ];
550 self.call("initpegoutwallet", handle_defaults(&mut args, &[0.into(), null()]))
551 }
552
553 fn send_to_main_chain(
554 &self,
555 amount: Amount,
556 subtract_fee_from_amount: Option<bool>,
557 ) -> Result<json::SendToMainChainResult> {
558 let mut args = [
559 "".into(), into_json(ser_amount(&amount))?,
561 opt_into_json(subtract_fee_from_amount)?,
562 ];
563 self.call("sendtomainchain", handle_defaults(&mut args, &[null()]))
564 }
565
566 fn get_wallet_pak_info(&self) -> Result<json::GetWalletPakInfoResult> {
567 self.call("getwalletpakinfo", &[])
568 }
569
570 fn get_pak_info(&self) -> Result<json::GetPakInfoResult> {
571 self.call("getpakinfo", &[])
572 }
573
574 fn tweak_fedpeg_script(&self, claim_script: &Script) -> Result<json::TweakFedpegScriptResult> {
575 self.call("tweakfedpegscript", &[into_json_hex(claim_script.as_bytes())?])
576 }
577
578 fn list_issuances(&self, asset: Option<AssetId>) -> Result<Vec<json::ListIssuancesResult>> {
579 let mut args = [opt_into_json(asset)?];
580 self.call("listissuances", handle_defaults(&mut args, &[null()]))
581 }
582
583 fn issue_asset(
584 &self,
585 asset_amount: Amount,
586 token_amount: Amount,
587 blind: Option<bool>,
588 ) -> Result<json::IssueAssetResult> {
589 let mut args = [
590 into_json(ser_amount(&asset_amount))?,
591 into_json(ser_amount(&token_amount))?,
592 opt_into_json(blind)?,
593 ];
594 self.call("issueasset", handle_defaults(&mut args, &[null()]))
595 }
596
597 fn reissue_asset(
598 &self,
599 asset: AssetId,
600 asset_amount: Amount,
601 ) -> Result<json::ReissueAssetResult> {
602 self.call("reissueasset", &[into_json(asset)?, into_json(ser_amount(&asset_amount))?])
603 }
604
605 fn raw_issue_asset<R: RawTx>(
606 &self,
607 raw_tx: R,
608 issuances: &[json::RawIssuanceDetails],
609 ) -> Result<json::IssueAssetResult> {
610 self.call("rawissueasset", &[raw_tx.raw_hex().into(), into_json(issuances)?])
611 }
612
613 fn raw_reissue_asset<R: RawTx>(
614 &self,
615 raw_tx: R,
616 issuances: &[json::RawReissuanceDetails],
617 ) -> Result<json::RawReissueAssetResult> {
618 self.call("rawreissueasset", &[raw_tx.raw_hex().into(), into_json(issuances)?])
619 }
620
621 fn dump_asset_labels(&self) -> Result<HashMap<String, AssetId>> {
622 self.call("dumpassetlabels", &[])
623 }
624
625 fn destroy_amount(
626 &self,
627 asset: AssetId,
628 amount: Amount,
629 comment: Option<&str>,
630 ) -> Result<sha256d::Hash> {
631 let mut args =
632 [into_json(asset)?, into_json(ser_amount(&amount))?, opt_into_json(comment)?];
633 self.call("destropamount", handle_defaults(&mut args, &[null()]))
634 }
635
636 fn blind_raw_transaction<R: RawTx, B: AsRef<[u8]>>(
637 &self,
638 raw_tx: R,
639 ignore_blind_fail: Option<bool>,
640 asset_commitments: Option<&[B]>,
641 blind_issuances: Option<bool>,
642 ) -> Result<elements::Transaction> {
643 let commitments = asset_commitments
644 .map(|v| {
645 let ret: Result<Vec<serde_json::Value>> = v.iter().map(into_json_hex).collect();
646 ret
647 })
648 .transpose()?;
649 let mut args = [
650 raw_tx.raw_hex().into(),
651 opt_into_json(ignore_blind_fail)?,
652 opt_into_json(commitments)?,
653 opt_into_json(blind_issuances)?,
654 ];
655 let hex: String = self.call(
656 "blindrawtransaction",
657 handle_defaults(&mut args, &[true.into(), empty(), null()]),
658 )?;
659 let bytes = Vec::<u8>::from_hex(&hex)?;
660 Ok(encode::deserialize(&bytes)?)
661 }
662
663 fn unblind_raw_transaction<R: RawTx>(
664 &self,
665 raw_tx: R,
666 ) -> Result<json::UnblindRawTransactionResult> {
667 self.call("unblindrawtransaction", &[raw_tx.raw_hex().into()])
668 }
669
670 fn raw_blind_raw_transaction<R: RawTx, B: AsRef<[u8]>>(
671 &self,
672 raw_tx: R,
673 input_amount_blinding_factors: &[B],
674 input_amounts: &[Amount],
675 input_assets: &[AssetId],
676 input_asset_blinding_factors: &[B],
677 ignore_blind_fail: Option<bool>,
678 ) -> Result<elements::Transaction> {
679 let amount_bfs: Result<Vec<serde_json::Value>> =
680 input_amount_blinding_factors.into_iter().map(into_json_hex).collect();
681 let amounts: Vec<serde_json::Value> = input_amounts.into_iter().map(ser_amount).collect();
682 let assets: Result<Vec<serde_json::Value>> =
683 input_assets.into_iter().map(into_json).collect();
684 let asset_bfs: Result<Vec<serde_json::Value>> =
685 input_asset_blinding_factors.into_iter().map(into_json_hex).collect();
686 let mut args = [
687 raw_tx.raw_hex().into(),
688 into_json(amount_bfs?)?,
689 into_json(amounts)?,
690 into_json(assets?)?,
691 into_json(asset_bfs?)?,
692 opt_into_json(ignore_blind_fail)?,
693 ];
694 let hex: String =
695 self.call("rawblindrawtransaction", handle_defaults(&mut args, &[null()]))?;
696 let bytes = Vec::<u8>::from_hex(&hex)?;
697 Ok(encode::deserialize(&bytes)?)
698 }
699
700 fn create_blinded_address(&self, address: &str, blinding_pubkey: &PublicKey) -> Result<String> {
701 let mut args = [
702 into_json_hex(address)?,
703 blinding_pubkey.to_string().into(),
705 ];
706 self.call("createblindedaddress", handle_defaults(&mut args, &[]))
707 }
708
709 fn dump_blinding_key(&self, address: &str) -> Result<SecretKey> {
710 let hex: String = self.call("dumpblindingkey", &[into_json_hex(address)?])?;
711 let bytes = Vec::<u8>::from_hex(&hex)?;
712 Ok(SecretKey::from_slice(&bytes).map_err(Error::Secp256k1)?)
713 }
714
715 fn import_blinding_key(&self, address: &str, blinding_key: &SecretKey) -> Result<()> {
716 let args = [address.into(), blinding_key.to_string().into()];
717 self.call("importblindingkey", &args)
718 }
719
720 fn dump_master_blinding_key(&self) -> Result<SecretKey> {
721 let hex: String = self.call("dumpmasterblindingkey", &[])?;
722 let bytes = Vec::<u8>::from_hex(&hex)?;
723 Ok(SecretKey::from_slice(&bytes).map_err(Error::Secp256k1)?)
724 }
725
726 fn import_master_blinding_key(&self, master_blinding_key: &SecretKey) -> Result<()> {
727 self.call("importmasterblindingkey", &[master_blinding_key.to_string().into()])
728 }
729
730 fn dump_issuance_blinding_key(&self, txid: &sha256d::Hash, vin: u32) -> Result<SecretKey> {
731 let hex: String = self.call("dumpissuanceblindingkey", &[into_json(txid)?, vin.into()])?;
732 let bytes = Vec::<u8>::from_hex(&hex)?;
733 Ok(SecretKey::from_slice(&bytes).map_err(Error::Secp256k1)?)
734 }
735
736 fn import_issuance_blinding_key(
737 &self,
738 txid: &sha256d::Hash,
739 vin: u32,
740 blinding_key: &SecretKey,
741 ) -> Result<()> {
742 let args = [into_json(txid)?, vin.into(), blinding_key.to_string().into()];
743 self.call("importissuanceblindingkey", &args)
744 }
745
746 fn get_new_block(&self, min_tx_age_secs: Option<usize>) -> Result<elements::Block> {
747 let mut args = [opt_into_json(min_tx_age_secs)?];
748 let hex: String = self.call("getnewblockhex", handle_defaults(&mut args, &[null()]))?;
749 let bytes = Vec::<u8>::from_hex(&hex)?;
750 Ok(encode::deserialize(&bytes)?)
751 }
752
753 fn sign_block(&self, block: &elements::Block) -> Result<Vec<json::SignedBlockSignature>> {
754 self.call("signblock", &[into_json_hex(encode::serialize(block))?])
755 }
756
757 fn combine_block_signatures(
758 &self,
759 block: &elements::Block,
760 signatures: &[json::SignedBlockSignature],
761 ) -> Result<json::CombineBlockSigsResult> {
762 let args = [into_json_hex(encode::serialize(block))?, into_json(signatures)?];
763 self.call("combineblocksigs", &args)
764 }
765
766 fn test_proposed_block(
767 &self,
768 block: &elements::Block,
769 accept_non_standard: Option<bool>,
770 ) -> Result<()> {
771 let mut args =
772 [into_json_hex(encode::serialize(block))?, opt_into_json(accept_non_standard)?];
773 self.call("testproposedblock", handle_defaults(&mut args, &[null()]))
774 }
775
776 fn submit_block(&self, block: &elements::Block) -> Result<String> {
777 self.call("submitblock", &[into_json_hex(encode::serialize(block))?])
778 }
779
780 }
786
787pub struct Client(pub bitcoincore_rpc::Client);
794
795impl Client {
796 pub fn new(url: String, auth: Auth) -> Result<Self> {
798 bitcoincore_rpc::Client::new(url, auth).map(Client).map_err(From::from)
799 }
800
801 pub fn from_jsonrpc(client: jsonrpc::client::Client) -> Self {
803 Client(bitcoincore_rpc::Client::from_jsonrpc(client))
804 }
805}
806
807impl bitcoincore_rpc::RpcApi for Client {
808 fn call<T: for<'a> serde::de::Deserialize<'a>>(
809 &self,
810 cmd: &str,
811 args: &[serde_json::Value],
812 ) -> bitcoincore_rpc::Result<T> {
813 bitcoincore_rpc::RpcApi::call(&self.0, cmd, args)
814 }
815}
816
817impl LiquidRpcApi for Client {
818 fn call<T: for<'a> serde::de::Deserialize<'a>>(
819 &self,
820 cmd: &str,
821 args: &[serde_json::Value],
822 ) -> Result<T> {
823 bitcoincore_rpc::RpcApi::call(self, cmd, args).map_err(From::from)
824 }
825}