From 9fdf771656c337c59b6d35ce1dad6ca84c93fd80 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 15 Apr 2024 20:15:25 +0000 Subject: [PATCH] deploy: d902b31b5e73df8ecc7513e320bbd1d1efdb0fe6 --- 404.html | 6 +- assets/js/{19.785a19b0.js => 19.cd75d4ee.js} | 2 +- assets/js/{39.b76a2ad0.js => 39.089a397e.js} | 2 +- assets/js/{40.578db781.js => 40.40d30668.js} | 2 +- assets/js/{45.251f6700.js => 45.41387e37.js} | 2 +- assets/js/{46.5ebccb0a.js => 46.883464d4.js} | 2 +- assets/js/{47.95bbbc17.js => 47.a9e58080.js} | 2 +- assets/js/{48.f74437f6.js => 48.9a448976.js} | 2 +- assets/js/{49.fd2860a9.js => 49.17ce6e83.js} | 2 +- assets/js/{51.1ead12c8.js => 51.29907970.js} | 2 +- assets/js/{53.f85cebcd.js => 53.fb891878.js} | 2 +- assets/js/{55.aa8604b5.js => 55.f2658f8a.js} | 2 +- assets/js/{56.06ad83c0.js => 56.56539c8a.js} | 2 +- assets/js/{57.3820b93c.js => 57.cd2a1739.js} | 2 +- assets/js/{60.e9dd6778.js => 60.08677303.js} | 2 +- assets/js/{61.d25557c6.js => 61.63feb9f0.js} | 2 +- assets/js/{62.3606e160.js => 62.b483815a.js} | 2 +- assets/js/{63.2518a4ae.js => 63.2a61731d.js} | 2 +- assets/js/{64.c74d4d9a.js => 64.1a1630c4.js} | 2 +- assets/js/{65.836aeb00.js => 65.5db91110.js} | 2 +- assets/js/{66.371047c4.js => 66.584abb88.js} | 2 +- assets/js/{70.c2fb4c8e.js => 70.42bd691e.js} | 2 +- assets/js/{71.d8561b66.js => 71.2b84faa7.js} | 2 +- assets/js/{75.b98ce942.js => 75.24e75de4.js} | 2 +- assets/js/{76.e04e7796.js => 76.2c842c7e.js} | 2 +- assets/js/{77.4d718ed0.js => 77.1bd88a81.js} | 2 +- assets/js/{79.675cb888.js => 79.bf24138b.js} | 2 +- assets/js/{80.79a4d68e.js => 80.9c59a7bc.js} | 2 +- .../js/{app.93627953.js => app.2350a6e1.js} | 4 +- bdk-cli/compiler/index.html | 6 +- bdk-cli/concept/index.html | 6 +- bdk-cli/index.html | 6 +- bdk-cli/installation/index.html | 6 +- bdk-cli/interface/index.html | 6 +- bdk-cli/introduction/index.html | 6 +- bdk-cli/playground/index.html | 6 +- bdk-cli/regtest/index.html | 6 +- blog/2020/12/hello-world/index.html | 6 +- blog/2020/12/release-v0.2.0/index.html | 6 +- .../index.html | 6 +- .../index.html | 6 +- .../index.html | 6 +- blog/2021/01/release-v0.3.0/index.html | 6 +- blog/2021/02/release-v0.4.0/index.html | 6 +- blog/2021/03/release-v0.5.0/index.html | 6 +- blog/2021/04/release-v0.6.0/index.html | 6 +- blog/2021/05/release-v0.7.0/index.html | 6 +- blog/2021/06/release-v0.8.0/index.html | 6 +- blog/2021/07/release-v0.9.0/index.html | 6 +- .../index.html | 6 +- .../index.html | 6 +- blog/_2024-q4-update/index.html | 6 +- blog/author/Alekos Filini/index.html | 4 +- blog/author/Alekos Filini/page/2/index.html | 4 +- blog/author/Bitcoin Zavior/index.html | 4 +- .../C\303\251sar Alvarez Vallero/index.html" | 4 +- blog/author/Daniela Brozzoni/index.html | 4 +- blog/author/Gabriele Domenichini/index.html | 4 +- blog/author/Lloyd Fournier/index.html | 4 +- blog/author/Rajarshi Maitra/index.html | 4 +- blog/author/Riccardo Casatta/index.html | 4 +- blog/author/Sandipan Dey/index.html | 4 +- blog/author/Steve Myers/index.html | 4 +- blog/author/Wszdexdrf/index.html | 4 +- blog/author/index.html | 6 +- blog/author/rorp/index.html | 4 +- blog/author/thunderbiscuit/index.html | 4 +- blog/author/waterst0ne/index.html | 4 +- blog/bdk-cli-basics-multisig-2of3/index.html | 6 +- blog/bdk-cli-basics/index.html | 6 +- blog/bdk-core-pt1/index.html | 6 +- blog/bdk-rn-making-of/index.html | 6 +- blog/bdk-with-tor/index.html | 6 +- blog/bindings-scope/index.html | 6 +- blog/bitcoin-core-rpc-demo/index.html | 6 +- blog/compact-filters-demo/index.html | 6 +- blog/descriptor-based-paper-wallet/index.html | 6 +- blog/descriptors-in-the-wild/index.html | 6 +- blog/exploring-bdk-flutter/index.html | 6 +- blog/exploring-bdk-rn/index.html | 6 +- blog/getting-started-with-rust-hwi/index.html | 6 +- blog/hidden-power-of-bitcoin/index.html | 6 +- .../index.html | 6 +- blog/index.html | 4 +- blog/miniscript-vulnerability/index.html | 6 +- blog/page/2/index.html | 4 +- blog/page/3/index.html | 4 +- blog/page/4/index.html | 4 +- blog/road-to-bdk-1/index.html | 6 +- blog/spending-policy-demo/index.html | 6 +- blog/tags/Android/index.html | 4 +- blog/tags/Architecture/index.html | 4 +- blog/tags/BDK-RN/index.html | 4 +- blog/tags/BDK/index.html | 4 +- blog/tags/BIP157/index.html | 4 +- blog/tags/Bitcoin Core/index.html | 4 +- blog/tags/Development/index.html | 4 +- blog/tags/Flutter/index.html | 4 +- blog/tags/Hardware Wallets/index.html | 4 +- blog/tags/Neutrino/index.html | 4 +- blog/tags/RPC/index.html | 4 +- blog/tags/React Native/index.html | 4 +- blog/tags/Wallet/index.html | 4 +- blog/tags/architecture/index.html | 4 +- blog/tags/basics/index.html | 4 +- blog/tags/bdk-cli/index.html | 4 +- blog/tags/bdk-rn/index.html | 4 +- blog/tags/bdk/index.html | 4 +- blog/tags/bindings/index.html | 4 +- blog/tags/bitcoin-cli/index.html | 4 +- blog/tags/bitcoin/index.html | 4 +- blog/tags/blockchain/index.html | 4 +- blog/tags/coin selection/index.html | 4 +- blog/tags/compact_filters/index.html | 4 +- blog/tags/descriptor/index.html | 4 +- blog/tags/development/index.html | 4 +- blog/tags/fee/index.html | 4 +- blog/tags/getting started/index.html | 4 +- blog/tags/guide/index.html | 4 +- blog/tags/iOS/index.html | 4 +- blog/tags/index.html | 6 +- blog/tags/machine learning/index.html | 4 +- blog/tags/miniscript/index.html | 4 +- blog/tags/mobile/index.html | 4 +- blog/tags/multi-sig/index.html | 4 +- blog/tags/novice/index.html | 4 +- blog/tags/paper wallets/index.html | 4 +- blog/tags/project/index.html | 4 +- blog/tags/release/index.html | 4 +- blog/tags/rust/index.html | 4 +- blog/tags/security/index.html | 4 +- blog/tags/summer of bitcoin/index.html | 4 +- blog/tags/taproot/index.html | 4 +- blog/tags/tor/index.html | 4 +- blog/tags/tutorial/index.html | 4 +- blog/tags/wallet/index.html | 4 +- .../index.html | 6 +- case-studies/index.html | 4 +- descriptors/index.html | 6 +- .../bdk/descriptor/enum.Descriptor.html | 6 +- docs-rs/bdk/nightly/latest/bdk/index.html | 4 +- .../latest/bdk/struct.LocalOutput.html | 4 +- .../bdk/wallet/enum.ApplyBlockError.html | 4 +- .../latest/bdk/wallet/struct.Balance.html | 10 +-- .../latest/bdk/wallet/struct.ChangeSet.html | 10 +-- .../latest/bdk/wallet/struct.Update.html | 12 ++-- .../latest/bdk/wallet/struct.Wallet.html | 64 +++++++++---------- .../wallet/tx_builder/struct.TxBuilder.html | 2 +- .../latest/bdk_bitcoind_rpc/index.html | 2 +- .../bdk_bitcoind_rpc/struct.BlockEvent.html | 12 ++-- .../bdk_bitcoind_rpc/struct.Emitter.html | 2 +- .../bdk/nightly/latest/bdk_chain/index.html | 2 +- .../nightly/latest/bdk_electrum/index.html | 8 +-- .../bdk_electrum/struct.ElectrumUpdate.html | 4 +- .../bdk_electrum/struct.RelevantTxids.html | 12 ++-- .../bdk_electrum/trait.ElectrumExt.html | 14 ++-- .../bdk/nightly/latest/bdk_esplora/index.html | 4 +- .../bdk_esplora/trait.EsploraAsyncExt.html | 24 +++---- .../latest/bdk_esplora/trait.EsploraExt.html | 24 +++---- .../nightly/latest/bdk_file_store/index.html | 4 +- .../latest/bdk_file_store/struct.Store.html | 4 +- docs-rs/bdk/nightly/latest/bdk_hwi/index.html | 2 +- .../latest/bdk_hwi/struct.HWISigner.html | 2 +- .../bdk/nightly/latest/bdk_testenv/index.html | 2 +- .../latest/bdk_testenv/struct.TestEnv.html | 10 ++- .../type.ChangeSet.html | 2 +- .../latest/example_cli/fn.create_tx.html | 2 +- .../example_cli/fn.handle_commands.html | 2 +- .../nightly/latest/example_cli/fn.init.html | 2 +- .../latest/example_cli/fn.planned_utxos.html | 2 +- .../example_cli/struct.CreateTxChange.html | 4 +- .../latest/example_cli/struct.Init.html | 4 +- .../latest/example_cli/type.Database.html | 2 +- .../example_cli/type.KeychainChangeSet.html | 2 +- .../example_cli/type.KeychainTxGraph.html | 2 +- .../latest/example_cli/type.PlannedUtxo.html | 2 +- .../example_electrum/type.ChangeSet.html | 2 +- .../example_esplora/enum.EsploraCommands.html | 10 ++- .../example_esplora/struct.EsploraArgs.html | 10 ++- .../example_esplora/struct.ScanOptions.html | 10 ++- .../example_esplora/type.ChangeSet.html | 2 +- .../bdk/wallet/signer/trait.SignerCommon.js | 2 +- .../wallet/signer/trait.TransactionSigner.js | 2 +- .../bdk_chain/persist/trait.PersistBackend.js | 2 +- .../bdk_chain/tx_data_traits/trait.Append.js | 2 +- .../implementors/core/convert/trait.AsRef.js | 2 +- .../implementors/core/convert/trait.From.js | 2 +- docs-rs/bdk/nightly/latest/search-index.js | 2 +- examples/index.html | 6 +- foundation/index.html | 4 +- getting-started/index.html | 6 +- index.html | 4 +- sitemap.xml | 2 +- supporters/index.html | 6 +- 194 files changed, 484 insertions(+), 460 deletions(-) rename assets/js/{19.785a19b0.js => 19.cd75d4ee.js} (99%) rename assets/js/{39.b76a2ad0.js => 39.089a397e.js} (99%) rename assets/js/{40.578db781.js => 40.40d30668.js} (99%) rename assets/js/{45.251f6700.js => 45.41387e37.js} (99%) rename assets/js/{46.5ebccb0a.js => 46.883464d4.js} (99%) rename assets/js/{47.95bbbc17.js => 47.a9e58080.js} (99%) rename assets/js/{48.f74437f6.js => 48.9a448976.js} (99%) rename assets/js/{49.fd2860a9.js => 49.17ce6e83.js} (99%) rename assets/js/{51.1ead12c8.js => 51.29907970.js} (99%) rename assets/js/{53.f85cebcd.js => 53.fb891878.js} (99%) rename assets/js/{55.aa8604b5.js => 55.f2658f8a.js} (99%) rename assets/js/{56.06ad83c0.js => 56.56539c8a.js} (99%) rename assets/js/{57.3820b93c.js => 57.cd2a1739.js} (99%) rename assets/js/{60.e9dd6778.js => 60.08677303.js} (98%) rename assets/js/{61.d25557c6.js => 61.63feb9f0.js} (99%) rename assets/js/{62.3606e160.js => 62.b483815a.js} (99%) rename assets/js/{63.2518a4ae.js => 63.2a61731d.js} (99%) rename assets/js/{64.c74d4d9a.js => 64.1a1630c4.js} (99%) rename assets/js/{65.836aeb00.js => 65.5db91110.js} (99%) rename assets/js/{66.371047c4.js => 66.584abb88.js} (99%) rename assets/js/{70.c2fb4c8e.js => 70.42bd691e.js} (98%) rename assets/js/{71.d8561b66.js => 71.2b84faa7.js} (99%) rename assets/js/{75.b98ce942.js => 75.24e75de4.js} (98%) rename assets/js/{76.e04e7796.js => 76.2c842c7e.js} (99%) rename assets/js/{77.4d718ed0.js => 77.1bd88a81.js} (99%) rename assets/js/{79.675cb888.js => 79.bf24138b.js} (97%) rename assets/js/{80.79a4d68e.js => 80.9c59a7bc.js} (99%) rename assets/js/{app.93627953.js => app.2350a6e1.js} (74%) diff --git a/404.html b/404.html index f885ec872a..895ee6fc84 100644 --- a/404.html +++ b/404.html @@ -15,7 +15,7 @@ - + @@ -39,7 +39,7 @@ Blog GitHub - (opens new window)

404 - Not Found

How did we get here?
+ (opens new window)

404 - Not Found

That's a Four-Oh-Four.
Take me home.
- + diff --git a/assets/js/19.785a19b0.js b/assets/js/19.cd75d4ee.js similarity index 99% rename from assets/js/19.785a19b0.js rename to assets/js/19.cd75d4ee.js index eb98dc08f6..bd758b15f0 100644 --- a/assets/js/19.785a19b0.js +++ b/assets/js/19.cd75d4ee.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{347:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_complete_app.c74da859.png"},348:function(t,a,s){t.exports=s.p+"assets/img/default_flutter_app.31b31721.png"},349:function(t,a,s){t.exports=s.p+"assets/img/assets_section.b43d75e9.png"},350:function(t,a,s){t.exports=s.p+"assets/img/folder_structure.b2750bd6.png"},351:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_title.e4e3484a.png"},352:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_tutorial_screen_mnemonic.df703b77.png"},353:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_tutorial_screen_createwallet.3b052736.png"},354:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_balance.bfdf9ced.png"},355:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_address.5db2e3cc.png"},356:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_restore.db8e7e55.png"},357:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_send.1688372b.png"},394:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" is the "),a("strong",[t._v("Bitcoin Dev kit")]),t._v("'s "),a("strong",[t._v("Flutter")]),t._v(" library which enables building bitcoin applications for Android and iOS mobile platforms. Using "),a("code",[t._v("bdk-flutter")]),t._v(" is similar to using any other Flutter module. Just do "),a("code",[t._v("flutter pub add bdk_flutter")]),t._v(" and you are ready to code! This is the first tutorial on how to use "),a("code",[t._v("bdk-flutter")]),t._v(", more coming soon, make sure to "),a("a",{attrs:{href:"https://twitter.com/BitcoinZavior",target:"_blank",rel:"noopener noreferrer"}},[t._v("follow"),a("OutboundLink")],1),t._v(" to be notified of new ones. There will also be a "),a("strong",[a("code",[t._v("bdk-flutter")])]),t._v(" focused Livestream on "),a("a",{attrs:{href:"https://www.twitch.tv/bitcoindevelopers",target:"_blank",rel:"noopener noreferrer"}},[t._v("Twitch"),a("OutboundLink")],1),t._v(" on the Bitcoin Developers "),a("a",{attrs:{href:"https://www.youtube.com/channel/UCUq_ZdezVWKPvkWRicAYxLA/videos",target:"_blank",rel:"noopener noreferrer"}},[t._v("YouTube Channel"),a("OutboundLink")],1),t._v(" so make sure to subscribe.")]),t._v(" "),a("p",[t._v("This tutorial will explore "),a("code",[t._v("bdk-flutter")]),t._v(" usage and the API it provides. This guide will walk through the development process and code for making a bitcoin application. The bitcoin application we create will be a non-custodial HD Wallet. The application will have the functionality to create a new wallet or restore from a known mnemonic seed phrase. This application will also be able to interact with the bitcoin network to sync UTXOs from new blocks and broadcast transactions.")]),t._v(" "),a("p",[t._v("The tutorial will focus on bitcoin concepts and "),a("code",[t._v("bdk-flutter")]),t._v(" API. So it will gloss over Flutter and Dart. If you are interested in learning more about Flutter and Dart please refer to the Flutter "),a("a",{attrs:{href:"https://flutter.dev/learn",target:"_blank",rel:"noopener noreferrer"}},[t._v("learning portal"),a("OutboundLink")],1),t._v(". The code for this tutorial is available on the "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart",target:"_blank",rel:"noopener noreferrer"}},[t._v("LtbLightning GitHub"),a("OutboundLink")],1)]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(347)}}),t._v(" "),a("h3",{attrs:{id:"prerequisites"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),a("p",[t._v("To use "),a("code",[t._v("bdk-flutter")]),t._v(" in a Flutter App, a Flutter development environment is required. Please refer to resources out there on the internet if you need to set this up, here is one of many good resources to guide you on "),a("a",{attrs:{href:"https://docs.flutter.dev/get-started/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("environment setup"),a("OutboundLink")],1)]),t._v(" "),a("h3",{attrs:{id:"bitcoin-basics"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bitcoin-basics"}},[t._v("#")]),t._v(" Bitcoin Basics")]),t._v(" "),a("p",[t._v("The bitcoin concepts used in this blog post are detailed and explained very well in external bitcoin resources. Here are some links for reference:")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mastering Bitcoin(HD Wallet chapter)"),a("OutboundLink")],1)]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Output Descriptors from bitcoin GitHub"),a("OutboundLink")],1)]),t._v(" "),a("p",[t._v("Now let's jump into Bitcoin Dev Kit")]),t._v(" "),a("h2",{attrs:{id:"bitcoin-dev-kit-and-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bitcoin-dev-kit-and-bdk-flutter"}},[t._v("#")]),t._v(" Bitcoin Dev Kit and bdk-flutter")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" is "),a("strong",[t._v("Bitcoin Dev kit")]),t._v("'s "),a("strong",[t._v("Flutter")]),t._v(" library for building Bitcoin apps in "),a("strong",[t._v("Flutter")]),t._v(".\nIt encapsulates all of the low-level APIs and methods for BDK and exposes them in a Flutter context. To use BDK in Flutter apps only the "),a("code",[t._v("bdk-flutter")]),t._v(" module is required. "),a("code",[t._v("bdk-flutter")]),t._v(" can be used like any other Flutter library and is available on "),a("a",{attrs:{href:"https://pub.dev/packages/bdk_flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("pub.dev"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[t._v("Although we won't delve deep into Flutter we will focus more on bitcoin and "),a("code",[t._v("bdk-flutter")]),t._v(", however, some rudimentary Flutter setup is required, especially a basic Flutter app to add our code.")]),t._v(" "),a("p",[t._v("start by creating a new Flutter project.")]),t._v(" "),a("p",[a("code",[t._v("flutter create bdk-flutter-quickstart")])]),t._v(" "),a("p",[t._v("Once done let's "),a("code",[t._v("cd")]),t._v(" into the new project directory and run the basic Flutter app that's created")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" bdk-flutter-quickstart\nflutter run\n")])])]),a("p",[t._v("This should start building the app and then launch the app in a simulator. So far we have created a basic Flutter project if this doesn't work then refer to the Flutter development setup guide to troubleshoot.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(348),alt:"BDK Flutter Quick Start"}}),t._v(" "),a("h2",{attrs:{id:"setting-up-flutter-app-structure"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-flutter-app-structure"}},[t._v("#")]),t._v(" Setting up Flutter app structure")]),t._v(" "),a("p",[t._v("Let's set up a very basic app structure. Let's create an "),a("code",[t._v("assets")]),t._v(" folder in the project root and then add new folders "),a("code",[t._v("widgets")]),t._v(", "),a("code",[t._v("screens")]),t._v(", and "),a("code",[t._v("styles")]),t._v(" inside the existing "),a("code",[t._v("lib")]),t._v(" folder.")]),t._v(" "),a("p",[t._v("Paste the following code in your "),a("code",[t._v("pubspec.yaml")]),t._v(" file, assets section.")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",[a("code",[t._v("- assets/\n")])])]),a("p",[t._v("Please make sure your assets section looks like the screenshot below.\n"),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"60%"},attrs:{src:s(349),alt:"BDK Flutter Quick Start"}})]),t._v(" "),a("p",[t._v("Once done let's run a "),a("code",[t._v("get")]),t._v(" command from the pub tool commands, this will get all the required dependencies for our project.")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("flutter pub get\n")])])]),a("p",[t._v("To make this quick you can download the theme, styled widgets and images used in the tutorial from the repository. The "),a("code",[t._v("theme.dart")]),t._v(" file has the theme we will use and this can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/blob/master/lib/styles/theme.dart",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" and moved to the styles folder. The "),a("code",[t._v("widgets.dart")]),t._v(" file has the styled widgets we will use and these can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/blob/master/lib/widgets/widgets.dart",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" and moved to the widgets folder. The image assets can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/tree/master/assets",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" Alternatively, you can write your theme, widgets and use your images if you intend to style the app differently.")]),t._v(" "),a("p",[t._v("In addition to the the theme, widgets and assets. We also need to create a "),a("code",[t._v("screens")]),t._v(" folder and create a "),a("code",[t._v("home.dart")]),t._v(" file inside it, this will be where most of the code will be added.")]),t._v(" "),a("p",[t._v("Once done the file structure should look like this:")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"60%"},attrs:{src:s(350)}}),t._v(" "),a("p",[a("br"),t._v("Locate "),a("code",[t._v("main.dart")]),t._v(" in the project root, this will have the default code added by "),a("code",[t._v("flutter create")]),t._v(", let's delete all contents of "),a("code",[t._v("main.dart")]),t._v(" and replace it with the following code to use "),a("code",[t._v("home.dart")]),t._v(" as our main screen. This will probably crash the app but that's fine, it will be up and running once we add code to "),a("code",[t._v("home.dart")]),t._v(" in the next few steps")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// main.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/screens/home.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/styles/theme.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/material.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("runApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatelessWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This widget is the root of your application.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MaterialApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n debugShowCheckedModeBanner"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n title"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'BDK-FLUTTER TUTORIAL'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n theme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n home"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"installing-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#installing-bdk-flutter"}},[t._v("#")]),t._v(" Installing "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[t._v("With the Flutter project in place, we can now add "),a("code",[t._v("bdk-flutter")]),t._v(" using "),a("code",[t._v("flutter pub add")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("flutter pub "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),t._v(" bdk_flutter\n")])])]),a("p",[t._v("This will add a line like this to your package's "),a("code",[t._v("pubspec.yaml")]),t._v(" and this will also run an implicit flutter pub get to download "),a("code",[t._v("bdk-flutter")]),t._v(" from "),a("code",[t._v("pub.dev")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("dependencies:\n bdk_flutter: ^0.28.2\n")])])]),a("h2",{attrs:{id:"configuring"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuring"}},[t._v("#")]),t._v(" Configuring")]),t._v(" "),a("p",[t._v("Make sure your app meets the following requirements for using "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[a("strong",[t._v("Android")])]),t._v(" "),a("p",[t._v("MinSdkVersion : API 23 or higher.")]),t._v(" "),a("p",[a("strong",[t._v("IOS")])]),t._v(" "),a("p",[t._v("Deployment target: iOS 12.0 or greater.")]),t._v(" "),a("p",[t._v("Locate your Podfile in the ios folder of your project and paste the following code at the beginning")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("platform :ios, '12.0'\n")])])]),a("p",[t._v("After changing the deployment target in your project's "),a("code",[t._v("PodFile")]),t._v(", let's use the following "),a("code",[t._v("command")]),t._v(" to install pod dependencies for iOS.")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" ios "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" pod "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v("\n")])])]),a("p",[t._v("Once done, bdk-flutter is installed and configured and ready to be used in our "),a("strong",[t._v("bdk-flutter-quickstart")]),t._v(" App.")]),t._v(" "),a("h2",{attrs:{id:"importing-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#importing-bdk-flutter"}},[t._v("#")]),t._v(" Importing "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[t._v("Locate "),a("code",[t._v("home.dart")]),t._v(" which we added in the setup section and import "),a("code",[t._v("bdk-flutter")]),t._v(" at the top of the file. Create a stateful widget called "),a("code",[t._v("Home")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Before we start using "),a("code",[t._v("bdk-flutter")]),t._v(" let's add some additional imports and also import styles, to create a basic layout to build our home screen")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/widgets/widgets.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/cupertino.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/material.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Scaffold")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n resizeToAvoidBottomInset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n backgroundColor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Colors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("white"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* AppBar */")]),t._v("\n appBar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildAppBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SingleChildScrollView")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n padding"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EdgeInsets")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("symmetric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("horizontal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Create Wallet */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Send Transaction */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("We now have an app title section and a structure to hold the rest of our app components.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"33%"},attrs:{src:s(351)}}),t._v(" "),a("h2",{attrs:{id:"calling-bdk-flutter-methods"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#calling-bdk-flutter-methods"}},[t._v("#")]),t._v(" Calling bdk-flutter methods")]),t._v(" "),a("p",[t._v("To call all methods properly from the "),a("code",[t._v("bdk-flutter")]),t._v(" package, first, we need to create state variables to store "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(" objects.")]),t._v(" "),a("p",[t._v("Here we use the late keyword to declare both "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(". These are non-nullable variables that are initialized after the declaration.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nlate "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nlate "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("The first step in creating a non-custodial bitcoin app is creating a mnemonic seed phrase for the wallet.")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" provides a "),a("code",[t._v("Mnemonic")]),t._v(" class to create a "),a("code",[t._v("Mnemonic")]),t._v(". The "),a("code",[t._v("create")]),t._v(" method is a named constructor and can be used to create a mnemonic, it takes "),a("code",[t._v("WordCount")]),t._v(" as its required parameter.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can generate a mnemonic of longer length by passing in a wordCount argument of required length.")]),t._v(" "),a("p",[t._v("To create a mnemonic with a "),a("code",[t._v("WordCount")]),t._v(" of 18 words, we can use "),a("code",[t._v("(WordCount.Words18)")]),t._v("\nRefer to the API docs on "),a("a",{attrs:{href:"https://pub.dev/documentation/bdk_flutter/latest/bdk_flutter/bdk_flutter-library.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("pub.dev"),a("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words18")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// here response is saved as a 'Mnemonic' object")]),t._v("\n")])])]),a("p",[t._v("In order to use this in our Flutter app, we want a button that will generate a mnemonic when clicked, and a text input box to show the generated mnemonic. Let's first create a "),a("code",[t._v("TextEditingController")]),t._v(" for the "),a("code",[t._v("mnemonic")]),t._v(" textfield to store the mnemonic, and an internal "),a("code",[t._v("generateMnemonicHandler")]),t._v(" method which can be called on button click. We will also need a button that will call the internal "),a("code",[t._v("generateMnemonicHandler")]),t._v(" method when clicked. Adding the following code achieves all of this.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n late "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n late "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Scaffold")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n resizeToAvoidBottomInset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n backgroundColor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Colors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("white"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Header */")]),t._v("\n appBar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildAppBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SingleChildScrollView")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n padding"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EdgeInsets")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("symmetric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("horizontal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Create Wallet */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StyledContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mainAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MainAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n crossAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CrossAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("center"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Generate Mnemonic"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keyboardType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextInputType")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("multiline"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n maxLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter your mnemonic"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Send Transaction Buttons */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Now we need to add a component to display the output of our method calls and this will also need a "),a("code",[t._v("displayText")]),t._v(" variable to track our method call response. To achieve this add the following code.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add this as another state variable under mnemonic")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" displayText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// modify the generateMnemonicHandler method to also set mnemonic as displayText")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("and finally, let's add the component to display the output under "),a("code",[t._v("/* Result */")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// display the component only if displayText has a value")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ResponseContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"No Response"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v('We should now have a working "Generate Mnemonic" button that displays the new mnemonic')]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(352)}}),t._v(" "),a("p",[t._v("A quick recap, we added a button to call a click handler ("),a("code",[t._v("generateMnemonicHandler")]),t._v(") which calls "),a("code",[t._v("generateMnemonic")]),t._v(" API of "),a("code",[t._v("bdk-flutter")]),t._v(". The click handler also sets the state for the app and also updates the "),a("code",[t._v("displayText")]),t._v(" variable to display the output of the call in the display section. We will follow this pattern for the remaining calls to "),a("code",[t._v("bdk-flutter")]),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"creating-a-wallet"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#creating-a-wallet"}},[t._v("#")]),t._v(" Creating a wallet")]),t._v(" "),a("p",[t._v("Before moving on to creating a wallet, let's add a section at the top to display the balance of the wallet.")]),t._v(" "),a("p",[t._v("To display the balance we will need a state variable to store the balance and a display component to display it. We will also be creating a receive address for the wallet so a state variable will be required for the address as well.")]),t._v(" "),a("p",[t._v("Under the "),a("code",[t._v("mnemonic")]),t._v(" and "),a("code",[t._v("displayText")]),t._v(" state variables, let's add one for "),a("code",[t._v("balance")]),t._v(" and one for "),a("code",[t._v("address")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" displayText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" balance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Just below "),a("code",[t._v("/* Balance */")]),t._v(" and above "),a("code",[t._v("/* Result */")]),t._v(" add the following UI components to display the balance. We only want to show the balance when it has a value so we will use a null-aware operator "),a("code",[t._v("??")]),t._v(" for a quick "),a("code",[t._v("null")]),t._v(" check and use "),a("code",[t._v("0")]),t._v(" in case of a "),a("code",[t._v("null")]),t._v(" value.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BalanceContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"${balance ?? "')])]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"} Sats"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n")])])]),a("p",[a("code",[t._v("bdk_flutter")]),t._v(" creates a wallet using output descriptors which define the derivation path to derive addresses and sign transactions. More about output descriptors "),a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(". Before creating the "),a("code",[t._v("Wallet")]),t._v(" we need to create a "),a("code",[t._v("descriptor")]),t._v(" object which will be used to generate receive addresses and a "),a("code",[t._v("changeDescriptor")]),t._v(" object to to create change addresses to collect from outgoing transactions.")]),t._v(" "),a("p",[a("code",[t._v("bdk_flutter")]),t._v("'s "),a("code",[t._v("Descriptor")]),t._v(" class has a number of descriptor templates that will help you create a simple wallet.")]),t._v(" "),a("p",[t._v("Let's add some code to create a simple "),a("code",[t._v("wpkh")]),t._v(" descriptor object by using the "),a("code",[t._v("BIP84")]),t._v(" template. This template will create a descriptor in the format "),a("code",[t._v("wpkh(key/84'/{0,1}'/0'/{0,1}/*)")])]),t._v(" "),a("p",[t._v("This descriptor will create receive ("),a("code",[t._v("KeyChainKind.External")]),t._v(") and change descriptor ("),a("code",[t._v("KeyChainKind.Internal")]),t._v(") for a specified mnemonic.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDescriptors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptors "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeychainKind.External")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeychainKind.Internal")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" mnemonicObj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptorSecretKey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorSecretKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonicObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptor "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("newBip84")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n secretKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptorSecretKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n keychain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("descriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error : ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("rethrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("Under the "),a("code",[t._v("address")]),t._v(" state variable, let's add a state variable called "),a("code",[t._v("wallet")]),t._v(" of the type "),a("code",[t._v("Wallet")]),t._v(" for saving the bitcoin wallet.")]),t._v(" "),a("p",[t._v("To create a wallet with "),a("code",[t._v("bdk-flutter")]),t._v(" call the "),a("code",[t._v("create")]),t._v(" constructor with "),a("code",[t._v("descriptor")]),t._v(", "),a("code",[t._v("changeDescriptor")]),t._v(" "),a("code",[t._v("network")]),t._v(", and the "),a("code",[t._v("databaseConfig")]),t._v(". For database, we can use memory as the database by specifying "),a("code",[t._v("DatabaseConfig.memory()")]),t._v("\nFollowing our pattern of a button, click handler and bdk-flutter API call, Let's add an internal method which will serve as the click handler for the \"Create Wallet\" button. We want to see the output of this call so let's use "),a("code",[t._v("setState()")]),t._v(" to set the "),a("code",[t._v("wallet")]),t._v(" object created and the "),a("code",[t._v("displayText")]),t._v(" variable with the wallet's first receive address.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createOrRestoreWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),t._v(" network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" password"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptors "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDescriptors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDescriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n databaseConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DatabaseConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("memory")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" addressInfo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addressInfo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n wallet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Wallet Created: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("address")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A new button will be required to call "),a("code",[t._v("createOrRestoreWallet()")])]),t._v(" "),a("p",[t._v("Let's add a new button just below the mnemonic "),a("code",[t._v("TextFieldContainer")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Create Wallet"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createOrRestoreWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("The response returned by "),a("code",[t._v("create()")]),t._v(" is a "),a("code",[t._v("Wallet")]),t._v(" object.")]),t._v(" "),a("p",[t._v("The App should now be creating a wallet when we click "),a("strong",[t._v("Create Mnemonic")]),t._v(" followed by "),a("strong",[t._v("Create Wallet")]),t._v(".")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(353)}}),t._v(" "),a("p",[t._v("Before going forward, we need to create a "),a("code",[t._v("Blockchain")]),t._v(" object as well. The Blockchain object will encapsulate the bitcoin node configuration which the wallet will use for syncing blocks and broadcasting transactions.")]),t._v(" "),a("p",[t._v("Let's add an internal method to create and initialize the "),a("code",[t._v("Blockchain")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("blockchainInit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("electrum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ElectrumConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n stopGap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n retry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ssl://electrum.blockstream.info:60002"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validateDomain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here we are initializing the "),a("code",[t._v("late")]),t._v(" non-nullable "),a("code",[t._v("blockchain")]),t._v(" variable, by calling the named constructor "),a("code",[t._v("create")]),t._v(", which takes a "),a("code",[t._v("BlockchainConfig")]),t._v(" object.\nThe bitcoin node specified is an Electrum node and we are specifying the url for Blockstream's public Electrum Testnet servers over SSL.")]),t._v(" "),a("p",[t._v("After creating the "),a("code",[t._v("blockchainInit()")]),t._v(" method, call it from "),a("code",[t._v("createOrRestoreWallet()")]),t._v(", so the "),a("code",[t._v("blockchain")]),t._v(" variable gets initialized before the "),a("code",[t._v("wallet")]),t._v(" is created.")]),t._v(" "),a("p",[t._v("Include the following line of code inside "),a("code",[t._v("createOrRestoreWallet()")]),t._v(" just before calling Wallet.create().")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("blockchainInit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n")])])]),a("p",[a("strong",[t._v("blockChainConfig")]),t._v(": BlockchainConfig is an enum that has 3 values, "),a("code",[t._v("BlockchainConfig.electrum")]),t._v(" for "),a("a",{attrs:{href:"https://github.com/romanz/electrs",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("electrum")]),a("OutboundLink")],1),t._v(" ,"),a("code",[t._v("BlockchainConfig.esplora")]),t._v(" for "),a("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("esplora")]),a("OutboundLink")],1),t._v(" and "),a("code",[t._v("BlockchainConfig.rpc")]),t._v(" .")]),t._v(" "),a("p",[a("code",[t._v("BlockchainConfig.electrum")]),t._v(", "),a("code",[t._v("BlockchainConfig.rpc")]),t._v(" & "),a("code",[t._v("BlockchainConfig.esplora")]),t._v(" has "),a("code",[t._v("ElectrumConfig")]),t._v(" object, "),a("code",[t._v("RpcConfig")]),t._v(" object and "),a("code",[t._v("EsploraConfig")]),t._v(" object, respectively as its parameter.")]),t._v(" "),a("p",[a("strong",[t._v("ElectrumConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.electrum")]),t._v("'s config that takes a timeout, retry & url as its required parameter.")]),t._v(" "),a("p",[a("strong",[t._v("EsploraConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.esplora")]),t._v("'s config that takes baseUrl & stopGap as its required parameter.")]),t._v(" "),a("p",[a("strong",[t._v("RpcConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.rpc")]),t._v("'s config that takes url, network, & walletName as its required parameter. If "),a("code",[t._v("Rpc Blockchain")]),t._v(" has its authentication values inside a cookie file, please pass in cookie path as authCookie parameter, or you can pass in rpc username and password using "),a("code",[t._v("UserPass")]),t._v(" class.")]),t._v(" "),a("p",[t._v("Refer to the readme for a complete list of options for "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#createwallet",target:"_blank",rel:"noopener noreferrer"}},[t._v("createWallet()"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"utxos-and-balance"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#utxos-and-balance"}},[t._v("#")]),t._v(" UTXOs and balance")]),t._v(" "),a("p",[t._v("With the "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(" created, we can now add methods to sync UTXOs and compute balance.")]),t._v(" "),a("p",[a("code",[t._v("Wallet")]),t._v(" has a "),a("code",[t._v("sync")]),t._v(" method to sync all UTXOs belonging to the wallet using the "),a("code",[t._v("Blockchain")]),t._v(" object. Once the wallet sync is complete balance is computed and "),a("code",[t._v("getBalance")]),t._v(" can fetch the balance.")]),t._v(" "),a("p",[t._v("Earlier we have already added a variable for "),a("code",[t._v("balance")]),t._v(". Now we will add buttons to call "),a("code",[t._v("sync")]),t._v(" and "),a("code",[t._v("getBalance")]),t._v(". Just below the Create Wallet button let's add two buttons as follows:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Sync Wallet"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("syncWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Get Balance"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("Let's add two internal functions for syncing UTXOs and compute balance.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" balanceObj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Total Balance: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("balanceObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("total"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n balance "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" balanceObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("total"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("syncWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("We should now be able to create a wallet, sync UTXOs, and get the balance")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(354)}}),t._v(" "),a("p",[t._v("We can use a public testnet faucet to send testnet coins to the wallet and check that the UTXO sync and balance fetch are working correctly. Before we do that add one more method to generate a new address we can then use this address to get testnet coins from a faucet.")]),t._v(" "),a("p",[t._v("Let's use the "),a("code",[t._v("address")]),t._v(" variable that was created before for this, we need to add a button for "),a("strong",[t._v("Get Address")]),t._v(" and an internal function to call "),a("code",[t._v("Wallet")]),t._v(" and create a new address. Let's do the following")]),t._v(" "),a("p",[t._v("Add a new "),a("code",[t._v("getNewAddress")]),t._v(" function below the "),a("code",[t._v("syncWallet()")]),t._v(" function:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And a "),a("strong",[t._v("Get Address")]),t._v(" button below the existing "),a("strong",[t._v("Get Balance")]),t._v(" button:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Get Address"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("We should now have the following, and "),a("strong",[t._v("Get Address")]),t._v(" will be able to display a new address.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(355)}}),t._v(" "),a("p",[t._v("Now that we are able to generate a receive address we can get some testnet bitcoin from one of the public "),a("a",{attrs:{href:"https://coinfaucet.eu/en/btc-testnet/",target:"_blank",rel:"noopener noreferrer"}},[t._v("testnet faucets"),a("OutboundLink")],1)]),t._v(" "),a("p",[t._v("After we send and after the transaction is confirmed we will need to sync the wallet before we can see the new balance from the received transaction.")]),t._v(" "),a("h2",{attrs:{id:"restoring-a-wallet"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#restoring-a-wallet"}},[t._v("#")]),t._v(" Restoring a wallet")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("create")]),t._v(" method creates a wallet using a "),a("code",[t._v("mnemonic")]),t._v(", to restore we can use the same method, we won't need to call "),a("code",[t._v("generateMnemonic")]),t._v(" as we will already have a "),a("code",[t._v("mnemonic")]),t._v(" to restore with.")]),t._v(" "),a("p",[t._v("This text field below the "),a("code",[t._v("Generate Mnemonic")]),t._v(" button will also display the mnemonic variable if we click Generate Mnemonic' button. The generated mnemonic will show up in the text field. We can overwrite it with our mnemonic and doing so will also overwrite the mnemonic state variable. This way the mnemonic displayed will be the one used to create the wallet.")]),t._v(" "),a("p",[t._v("We can now use our mnemonic and use it to restore a wallet. This will come in handy if we have a wallet with testnet bitcoin as these are hard to come by.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(356)}}),t._v(" "),a("h2",{attrs:{id:"sending-bitcoin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sending-bitcoin"}},[t._v("#")]),t._v(" Sending bitcoin")]),t._v(" "),a("p",[t._v("We are now able to receive bitcoin, now its time to add functionality to send a bitcoin transaction.")]),t._v(" "),a("p",[t._v("For making a successful bitcoin transaction "),a("code",[t._v("bdk-flutter")]),t._v(" utilizes a couple of methods. A new unsigned transaction can be created by using TxBuilder](https://github.com/LtbLightning/bdk-flutter#quicksend).")]),t._v(" "),a("p",[t._v("First, we have to initialize the "),a("code",[t._v("TxBuilder")]),t._v(" object and call the "),a("code",[t._v("addRecipient()")]),t._v(" method.\n"),a("code",[t._v("addRecipient()")]),t._v(" takes a "),a("code",[t._v("Script")]),t._v(" object and the transaction "),a("code",[t._v("amount")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can create the"),a("code",[t._v("Script")]),t._v(" object by using the "),a("code",[t._v("Address")]),t._v(" class, by specifying the recipient address.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can create a "),a("code",[t._v("psbt")]),t._v(" object by calling the "),a("code",[t._v("finish()")]),t._v(" method using the response object from "),a("code",[t._v("addRecipient()")]),t._v(" method.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" psbt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("This "),a("code",[t._v("psbt")]),t._v(" can be signed later with "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#signtx",target:"_blank",rel:"noopener noreferrer"}},[t._v("sign()"),a("OutboundLink")],1),t._v(" method from the "),a("code",[t._v("Wallet")]),t._v(" and broadcast using "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#broadcasttx",target:"_blank",rel:"noopener noreferrer"}},[t._v("broadcast()"),a("OutboundLink")],1),t._v(" from the "),a("code",[t._v("Blockchain")]),t._v(" .")]),t._v(" "),a("p",[t._v("We will need textfield controllers for the recipient address, amount, and for transaction, these can be added below our existing variable for "),a("code",[t._v("mnemonic")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" recipientAddress "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Let's make an internal function to send a bitcoin transaction, using "),a("code",[t._v("Wallet")]),t._v(", "),a("code",[t._v("Blockchain")]),t._v(" and "),a("code",[t._v("TxBuilder")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" int amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilderResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" sbt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txBuilderResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" tx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" sbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Successfully broadcast ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("amount")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" Sats to ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("addressStr")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("Add a new section for send transaction functionality. We will need a "),a("code",[t._v("form")]),t._v(", a "),a("code",[t._v("TextFormField")]),t._v(" for the receiver address and a "),a("code",[t._v("TextFormField")]),t._v(" for the amount to send. We will also need a button to call the "),a("code",[t._v("sendTx")]),t._v(" function.")]),t._v(" "),a("p",[t._v("Before submitting the form we need to make sure all the input fields are valid, for that purpose, we need to initialize a "),a("a",{attrs:{href:"https://api.flutter.dev/flutter/widgets/GlobalKey-class.html",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("GlobalKey")]),a("OutboundLink")],1),t._v(". This can be added above our "),a("code",[t._v("Scaffold")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" _formKey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GlobalKey")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FormState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Let's add the send transaction section and UI components below "),a("code",[t._v("/* Send Transaction */")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StyledContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Form")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _formKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mainAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MainAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n crossAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CrossAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("center"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" recipientAddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validator"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Please enter your address'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter Address"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validator"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Please enter the amount'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keyboardType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextInputType")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("number"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter Amount"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Send Bit"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_formKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("currentState"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("validate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("recipientAddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n int"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("parse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),a("p",[t._v("We should now be able to send a transaction as long as there is sufficient balance.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(357)}}),t._v(" "),a("h2",{attrs:{id:"conclusion"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[t._v("#")]),t._v(" Conclusion")]),t._v(" "),a("p",[t._v("The App we created can be built and distributed for both iOS and Android thus sharing a code base and reducing development time. The development and coding focused on application-level code for use cases and we did not have to code intricate internal bitcoin protocol-level code or bitcoin node interactions, and transactions. UTXOs and sync-related functionalities were also not required. All this was managed by "),a("code",[t._v("bdk-flutter")]),t._v(" allowing us to focus on the product, functionality, and user journey. This is how "),a("code",[t._v("bdk")]),t._v(" and "),a("code",[t._v("bdk-flutter")]),t._v(" intend to make Rapid Bitcoin Application Development possible by allowing product and application developers to focus on what they know best while "),a("code",[t._v("bdk")]),t._v(" handles bitcoin complexity.")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" intends to expose functionality and APIs from "),a("code",[t._v("bdk")]),t._v(" which has a wide variety of APIs with granular details allowing for many interesting use cases to be implemented. "),a("code",[t._v("bdk-flutter")]),t._v(" and "),a("code",[t._v("bdk")]),t._v(" are constantly updated and enhanced based on feedback from product teams and developers in the bitcoin community.")]),t._v(" "),a("p",[t._v("Stay tuned for more APIs and enhancements coming to "),a("code",[t._v("bdk-flutter")]),t._v(" in the near future. Feature and API requests are most welcome. New blogs and tutorials will be published soon for a more in-depth exploration of "),a("code",[t._v("bdk-flutter")]),t._v(".")]),t._v(" "),a("p",[t._v("In the meantime keep in touch with the project by following us on "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub"),a("OutboundLink")],1),t._v(" and "),a("a",{attrs:{href:"https://twitter.com/BitcoinZavior",target:"_blank",rel:"noopener noreferrer"}},[t._v("Twitter"),a("OutboundLink")],1)]),t._v(" "),a("h4",{attrs:{id:"references"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#references"}},[t._v("#")]),t._v(" References:")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/bitcoindevkit",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk-flutter"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk-flutter-quickstart GitHub Repository"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://docs.flutter.dev/get-started/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("Setup Flutter Development Environment"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mastering Bitcoin(HD Wallet chapter)"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Output Descriptors from bitcoin GitHub"),a("OutboundLink")],1)]),t._v(" "),a("li",[t._v("Testnet Faucet: "),a("a",{attrs:{href:"https://coinfaucet.eu/en/btc-testnet/",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://coinfaucet.eu/en/btc-testnet/"),a("OutboundLink")],1),t._v(" or "),a("a",{attrs:{href:"https://bitcoinfaucet.uo1.net",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://bitcoinfaucet.uo1.net"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{347:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_complete_app.c74da859.png"},348:function(t,a,s){t.exports=s.p+"assets/img/default_flutter_app.31b31721.png"},349:function(t,a,s){t.exports=s.p+"assets/img/assets_section.b43d75e9.png"},350:function(t,a,s){t.exports=s.p+"assets/img/folder_structure.b2750bd6.png"},351:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_title.e4e3484a.png"},352:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_tutorial_screen_mnemonic.df703b77.png"},353:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_tutorial_screen_createwallet.3b052736.png"},354:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_balance.bfdf9ced.png"},355:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_address.5db2e3cc.png"},356:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_get_restore.db8e7e55.png"},357:function(t,a,s){t.exports=s.p+"assets/img/bdk_flutter_send.1688372b.png"},395:function(t,a,s){"use strict";s.r(a);var n=s(7),e=Object(n.a)({},(function(){var t=this,a=t._self._c;return a("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[a("h2",{attrs:{id:"introduction"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" is the "),a("strong",[t._v("Bitcoin Dev kit")]),t._v("'s "),a("strong",[t._v("Flutter")]),t._v(" library which enables building bitcoin applications for Android and iOS mobile platforms. Using "),a("code",[t._v("bdk-flutter")]),t._v(" is similar to using any other Flutter module. Just do "),a("code",[t._v("flutter pub add bdk_flutter")]),t._v(" and you are ready to code! This is the first tutorial on how to use "),a("code",[t._v("bdk-flutter")]),t._v(", more coming soon, make sure to "),a("a",{attrs:{href:"https://twitter.com/BitcoinZavior",target:"_blank",rel:"noopener noreferrer"}},[t._v("follow"),a("OutboundLink")],1),t._v(" to be notified of new ones. There will also be a "),a("strong",[a("code",[t._v("bdk-flutter")])]),t._v(" focused Livestream on "),a("a",{attrs:{href:"https://www.twitch.tv/bitcoindevelopers",target:"_blank",rel:"noopener noreferrer"}},[t._v("Twitch"),a("OutboundLink")],1),t._v(" on the Bitcoin Developers "),a("a",{attrs:{href:"https://www.youtube.com/channel/UCUq_ZdezVWKPvkWRicAYxLA/videos",target:"_blank",rel:"noopener noreferrer"}},[t._v("YouTube Channel"),a("OutboundLink")],1),t._v(" so make sure to subscribe.")]),t._v(" "),a("p",[t._v("This tutorial will explore "),a("code",[t._v("bdk-flutter")]),t._v(" usage and the API it provides. This guide will walk through the development process and code for making a bitcoin application. The bitcoin application we create will be a non-custodial HD Wallet. The application will have the functionality to create a new wallet or restore from a known mnemonic seed phrase. This application will also be able to interact with the bitcoin network to sync UTXOs from new blocks and broadcast transactions.")]),t._v(" "),a("p",[t._v("The tutorial will focus on bitcoin concepts and "),a("code",[t._v("bdk-flutter")]),t._v(" API. So it will gloss over Flutter and Dart. If you are interested in learning more about Flutter and Dart please refer to the Flutter "),a("a",{attrs:{href:"https://flutter.dev/learn",target:"_blank",rel:"noopener noreferrer"}},[t._v("learning portal"),a("OutboundLink")],1),t._v(". The code for this tutorial is available on the "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart",target:"_blank",rel:"noopener noreferrer"}},[t._v("LtbLightning GitHub"),a("OutboundLink")],1)]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(347)}}),t._v(" "),a("h3",{attrs:{id:"prerequisites"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),a("p",[t._v("To use "),a("code",[t._v("bdk-flutter")]),t._v(" in a Flutter App, a Flutter development environment is required. Please refer to resources out there on the internet if you need to set this up, here is one of many good resources to guide you on "),a("a",{attrs:{href:"https://docs.flutter.dev/get-started/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("environment setup"),a("OutboundLink")],1)]),t._v(" "),a("h3",{attrs:{id:"bitcoin-basics"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bitcoin-basics"}},[t._v("#")]),t._v(" Bitcoin Basics")]),t._v(" "),a("p",[t._v("The bitcoin concepts used in this blog post are detailed and explained very well in external bitcoin resources. Here are some links for reference:")]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mastering Bitcoin(HD Wallet chapter)"),a("OutboundLink")],1)]),t._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Output Descriptors from bitcoin GitHub"),a("OutboundLink")],1)]),t._v(" "),a("p",[t._v("Now let's jump into Bitcoin Dev Kit")]),t._v(" "),a("h2",{attrs:{id:"bitcoin-dev-kit-and-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#bitcoin-dev-kit-and-bdk-flutter"}},[t._v("#")]),t._v(" Bitcoin Dev Kit and bdk-flutter")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" is "),a("strong",[t._v("Bitcoin Dev kit")]),t._v("'s "),a("strong",[t._v("Flutter")]),t._v(" library for building Bitcoin apps in "),a("strong",[t._v("Flutter")]),t._v(".\nIt encapsulates all of the low-level APIs and methods for BDK and exposes them in a Flutter context. To use BDK in Flutter apps only the "),a("code",[t._v("bdk-flutter")]),t._v(" module is required. "),a("code",[t._v("bdk-flutter")]),t._v(" can be used like any other Flutter library and is available on "),a("a",{attrs:{href:"https://pub.dev/packages/bdk_flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("pub.dev"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"getting-started"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#getting-started"}},[t._v("#")]),t._v(" Getting Started")]),t._v(" "),a("p",[t._v("Although we won't delve deep into Flutter we will focus more on bitcoin and "),a("code",[t._v("bdk-flutter")]),t._v(", however, some rudimentary Flutter setup is required, especially a basic Flutter app to add our code.")]),t._v(" "),a("p",[t._v("start by creating a new Flutter project.")]),t._v(" "),a("p",[a("code",[t._v("flutter create bdk-flutter-quickstart")])]),t._v(" "),a("p",[t._v("Once done let's "),a("code",[t._v("cd")]),t._v(" into the new project directory and run the basic Flutter app that's created")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" bdk-flutter-quickstart\nflutter run\n")])])]),a("p",[t._v("This should start building the app and then launch the app in a simulator. So far we have created a basic Flutter project if this doesn't work then refer to the Flutter development setup guide to troubleshoot.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(348),alt:"BDK Flutter Quick Start"}}),t._v(" "),a("h2",{attrs:{id:"setting-up-flutter-app-structure"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#setting-up-flutter-app-structure"}},[t._v("#")]),t._v(" Setting up Flutter app structure")]),t._v(" "),a("p",[t._v("Let's set up a very basic app structure. Let's create an "),a("code",[t._v("assets")]),t._v(" folder in the project root and then add new folders "),a("code",[t._v("widgets")]),t._v(", "),a("code",[t._v("screens")]),t._v(", and "),a("code",[t._v("styles")]),t._v(" inside the existing "),a("code",[t._v("lib")]),t._v(" folder.")]),t._v(" "),a("p",[t._v("Paste the following code in your "),a("code",[t._v("pubspec.yaml")]),t._v(" file, assets section.")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",[a("code",[t._v("- assets/\n")])])]),a("p",[t._v("Please make sure your assets section looks like the screenshot below.\n"),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"60%"},attrs:{src:s(349),alt:"BDK Flutter Quick Start"}})]),t._v(" "),a("p",[t._v("Once done let's run a "),a("code",[t._v("get")]),t._v(" command from the pub tool commands, this will get all the required dependencies for our project.")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("flutter pub get\n")])])]),a("p",[t._v("To make this quick you can download the theme, styled widgets and images used in the tutorial from the repository. The "),a("code",[t._v("theme.dart")]),t._v(" file has the theme we will use and this can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/blob/master/lib/styles/theme.dart",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" and moved to the styles folder. The "),a("code",[t._v("widgets.dart")]),t._v(" file has the styled widgets we will use and these can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/blob/master/lib/widgets/widgets.dart",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" and moved to the widgets folder. The image assets can be taken from "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart/tree/master/assets",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(" Alternatively, you can write your theme, widgets and use your images if you intend to style the app differently.")]),t._v(" "),a("p",[t._v("In addition to the the theme, widgets and assets. We also need to create a "),a("code",[t._v("screens")]),t._v(" folder and create a "),a("code",[t._v("home.dart")]),t._v(" file inside it, this will be where most of the code will be added.")]),t._v(" "),a("p",[t._v("Once done the file structure should look like this:")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"60%"},attrs:{src:s(350)}}),t._v(" "),a("p",[a("br"),t._v("Locate "),a("code",[t._v("main.dart")]),t._v(" in the project root, this will have the default code added by "),a("code",[t._v("flutter create")]),t._v(", let's delete all contents of "),a("code",[t._v("main.dart")]),t._v(" and replace it with the following code to use "),a("code",[t._v("home.dart")]),t._v(" as our main screen. This will probably crash the app but that's fine, it will be up and running once we add code to "),a("code",[t._v("home.dart")]),t._v(" in the next few steps")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// main.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/screens/home.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/styles/theme.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/material.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("main")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("runApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatelessWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MyApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// This widget is the root of your application.")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MaterialApp")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n debugShowCheckedModeBanner"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n title"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'BDK-FLUTTER TUTORIAL'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n theme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n home"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("h2",{attrs:{id:"installing-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#installing-bdk-flutter"}},[t._v("#")]),t._v(" Installing "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[t._v("With the Flutter project in place, we can now add "),a("code",[t._v("bdk-flutter")]),t._v(" using "),a("code",[t._v("flutter pub add")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("flutter pub "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),t._v(" bdk_flutter\n")])])]),a("p",[t._v("This will add a line like this to your package's "),a("code",[t._v("pubspec.yaml")]),t._v(" and this will also run an implicit flutter pub get to download "),a("code",[t._v("bdk-flutter")]),t._v(" from "),a("code",[t._v("pub.dev")]),t._v(":")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[t._v("dependencies:\n bdk_flutter: ^0.28.2\n")])])]),a("h2",{attrs:{id:"configuring"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#configuring"}},[t._v("#")]),t._v(" Configuring")]),t._v(" "),a("p",[t._v("Make sure your app meets the following requirements for using "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[a("strong",[t._v("Android")])]),t._v(" "),a("p",[t._v("MinSdkVersion : API 23 or higher.")]),t._v(" "),a("p",[a("strong",[t._v("IOS")])]),t._v(" "),a("p",[t._v("Deployment target: iOS 12.0 or greater.")]),t._v(" "),a("p",[t._v("Locate your Podfile in the ios folder of your project and paste the following code at the beginning")]),t._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[t._v("platform :ios, '12.0'\n")])])]),a("p",[t._v("After changing the deployment target in your project's "),a("code",[t._v("PodFile")]),t._v(", let's use the following "),a("code",[t._v("command")]),t._v(" to install pod dependencies for iOS.")]),t._v(" "),a("div",{staticClass:"language-shell extra-class"},[a("pre",{pre:!0,attrs:{class:"language-shell"}},[a("code",[a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" ios "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" pod "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&&")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v("\n")])])]),a("p",[t._v("Once done, bdk-flutter is installed and configured and ready to be used in our "),a("strong",[t._v("bdk-flutter-quickstart")]),t._v(" App.")]),t._v(" "),a("h2",{attrs:{id:"importing-bdk-flutter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#importing-bdk-flutter"}},[t._v("#")]),t._v(" Importing "),a("code",[t._v("bdk-flutter")])]),t._v(" "),a("p",[t._v("Locate "),a("code",[t._v("home.dart")]),t._v(" which we added in the setup section and import "),a("code",[t._v("bdk-flutter")]),t._v(" at the top of the file. Create a stateful widget called "),a("code",[t._v("Home")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Before we start using "),a("code",[t._v("bdk-flutter")]),t._v(" let's add some additional imports and also import styles, to create a basic layout to build our home screen")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter_quickstart/widgets/widgets.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/cupertino.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:flutter/material.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Scaffold")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n resizeToAvoidBottomInset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n backgroundColor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Colors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("white"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* AppBar */")]),t._v("\n appBar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildAppBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SingleChildScrollView")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n padding"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EdgeInsets")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("symmetric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("horizontal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Create Wallet */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Send Transaction */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("We now have an app title section and a structure to hold the rest of our app components.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"33%"},attrs:{src:s(351)}}),t._v(" "),a("h2",{attrs:{id:"calling-bdk-flutter-methods"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#calling-bdk-flutter-methods"}},[t._v("#")]),t._v(" Calling bdk-flutter methods")]),t._v(" "),a("p",[t._v("To call all methods properly from the "),a("code",[t._v("bdk-flutter")]),t._v(" package, first, we need to create state variables to store "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(" objects.")]),t._v(" "),a("p",[t._v("Here we use the late keyword to declare both "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(". These are non-nullable variables that are initialized after the declaration.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'package:bdk_flutter/bdk_flutter.dart'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\nlate "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\nlate "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("The first step in creating a non-custodial bitcoin app is creating a mnemonic seed phrase for the wallet.")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" provides a "),a("code",[t._v("Mnemonic")]),t._v(" class to create a "),a("code",[t._v("Mnemonic")]),t._v(". The "),a("code",[t._v("create")]),t._v(" method is a named constructor and can be used to create a mnemonic, it takes "),a("code",[t._v("WordCount")]),t._v(" as its required parameter.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can generate a mnemonic of longer length by passing in a wordCount argument of required length.")]),t._v(" "),a("p",[t._v("To create a mnemonic with a "),a("code",[t._v("WordCount")]),t._v(" of 18 words, we can use "),a("code",[t._v("(WordCount.Words18)")]),t._v("\nRefer to the API docs on "),a("a",{attrs:{href:"https://pub.dev/documentation/bdk_flutter/latest/bdk_flutter/bdk_flutter-library.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("pub.dev"),a("OutboundLink")],1),t._v(" for more details.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words18")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// here response is saved as a 'Mnemonic' object")]),t._v("\n")])])]),a("p",[t._v("In order to use this in our Flutter app, we want a button that will generate a mnemonic when clicked, and a text input box to show the generated mnemonic. Let's first create a "),a("code",[t._v("TextEditingController")]),t._v(" for the "),a("code",[t._v("mnemonic")]),t._v(" textfield to store the mnemonic, and an internal "),a("code",[t._v("generateMnemonicHandler")]),t._v(" method which can be called on button click. We will also need a button that will call the internal "),a("code",[t._v("generateMnemonicHandler")]),t._v(" method when clicked. Adding the following code achieves all of this.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StatefulWidget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Key")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("super")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("_HomeState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n late "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n late "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token metadata function"}},[t._v("@override")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Widget")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("build")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BuildContext")]),t._v(" context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Scaffold")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n resizeToAvoidBottomInset"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("true")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n backgroundColor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Colors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("white"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Header */")]),t._v("\n appBar"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("buildAppBar")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n body"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SingleChildScrollView")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Container")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n padding"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("EdgeInsets")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("symmetric")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("horizontal"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("30")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Create Wallet */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StyledContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mainAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MainAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n crossAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CrossAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("center"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Generate Mnemonic"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keyboardType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextInputType")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("multiline"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n maxLines"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter your mnemonic"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Send Transaction Buttons */")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Now we need to add a component to display the output of our method calls and this will also need a "),a("code",[t._v("displayText")]),t._v(" variable to track our method call response. To achieve this add the following code.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// add this as another state variable under mnemonic")]),t._v("\n"),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" displayText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// modify the generateMnemonicHandler method to also set mnemonic as displayText")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("generateMnemonicHandler")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("WordCount.Words12")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("asString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("and finally, let's add the component to display the output under "),a("code",[t._v("/* Result */")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// screens/home.dart")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// display the component only if displayText has a value")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ResponseContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v("displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"No Response"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v('We should now have a working "Generate Mnemonic" button that displays the new mnemonic')]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(352)}}),t._v(" "),a("p",[t._v("A quick recap, we added a button to call a click handler ("),a("code",[t._v("generateMnemonicHandler")]),t._v(") which calls "),a("code",[t._v("generateMnemonic")]),t._v(" API of "),a("code",[t._v("bdk-flutter")]),t._v(". The click handler also sets the state for the app and also updates the "),a("code",[t._v("displayText")]),t._v(" variable to display the output of the call in the display section. We will follow this pattern for the remaining calls to "),a("code",[t._v("bdk-flutter")]),t._v(".")]),t._v(" "),a("h2",{attrs:{id:"creating-a-wallet"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#creating-a-wallet"}},[t._v("#")]),t._v(" Creating a wallet")]),t._v(" "),a("p",[t._v("Before moving on to creating a wallet, let's add a section at the top to display the balance of the wallet.")]),t._v(" "),a("p",[t._v("To display the balance we will need a state variable to store the balance and a display component to display it. We will also be creating a receive address for the wallet so a state variable will be required for the address as well.")]),t._v(" "),a("p",[t._v("Under the "),a("code",[t._v("mnemonic")]),t._v(" and "),a("code",[t._v("displayText")]),t._v(" state variables, let's add one for "),a("code",[t._v("balance")]),t._v(" and one for "),a("code",[t._v("address")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("class")]),t._v(" _HomeState "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("extends")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("State")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Home")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" mnemonic "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" displayText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" balance"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Just below "),a("code",[t._v("/* Balance */")]),t._v(" and above "),a("code",[t._v("/* Result */")]),t._v(" add the following UI components to display the balance. We only want to show the balance when it has a value so we will use a null-aware operator "),a("code",[t._v("??")]),t._v(" for a quick "),a("code",[t._v("null")]),t._v(" check and use "),a("code",[t._v("0")]),t._v(" in case of a "),a("code",[t._v("null")]),t._v(" value.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Balance */")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BalanceContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"${balance ?? "')])]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"} Sats"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/* Result */")]),t._v("\n")])])]),a("p",[a("code",[t._v("bdk_flutter")]),t._v(" creates a wallet using output descriptors which define the derivation path to derive addresses and sign transactions. More about output descriptors "),a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),a("OutboundLink")],1),t._v(". Before creating the "),a("code",[t._v("Wallet")]),t._v(" we need to create a "),a("code",[t._v("descriptor")]),t._v(" object which will be used to generate receive addresses and a "),a("code",[t._v("changeDescriptor")]),t._v(" object to to create change addresses to collect from outgoing transactions.")]),t._v(" "),a("p",[a("code",[t._v("bdk_flutter")]),t._v("'s "),a("code",[t._v("Descriptor")]),t._v(" class has a number of descriptor templates that will help you create a simple wallet.")]),t._v(" "),a("p",[t._v("Let's add some code to create a simple "),a("code",[t._v("wpkh")]),t._v(" descriptor object by using the "),a("code",[t._v("BIP84")]),t._v(" template. This template will create a descriptor in the format "),a("code",[t._v("wpkh(key/84'/{0,1}'/0'/{0,1}/*)")])]),t._v(" "),a("p",[t._v("This descriptor will create receive ("),a("code",[t._v("KeyChainKind.External")]),t._v(") and change descriptor ("),a("code",[t._v("KeyChainKind.Internal")]),t._v(") for a specified mnemonic.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("List")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDescriptors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptors "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" e "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeychainKind.External")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeychainKind.Internal")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" mnemonicObj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("fromString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptorSecretKey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorSecretKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" mnemonicObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptor "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("newBip84")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n secretKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptorSecretKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n keychain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("add")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("descriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error : ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("rethrow")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("Under the "),a("code",[t._v("address")]),t._v(" state variable, let's add a state variable called "),a("code",[t._v("wallet")]),t._v(" of the type "),a("code",[t._v("Wallet")]),t._v(" for saving the bitcoin wallet.")]),t._v(" "),a("p",[t._v("To create a wallet with "),a("code",[t._v("bdk-flutter")]),t._v(" call the "),a("code",[t._v("create")]),t._v(" constructor with "),a("code",[t._v("descriptor")]),t._v(", "),a("code",[t._v("changeDescriptor")]),t._v(" "),a("code",[t._v("network")]),t._v(", and the "),a("code",[t._v("databaseConfig")]),t._v(". For database, we can use memory as the database by specifying "),a("code",[t._v("DatabaseConfig.memory()")]),t._v("\nFollowing our pattern of a button, click handler and bdk-flutter API call, Let's add an internal method which will serve as the click handler for the \"Create Wallet\" button. We want to see the output of this call so let's use "),a("code",[t._v("setState()")]),t._v(" to set the "),a("code",[t._v("wallet")]),t._v(" object created and the "),a("code",[t._v("displayText")]),t._v(" variable with the wallet's first receive address.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createOrRestoreWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),t._v(" network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("?")]),t._v(" password"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" descriptors "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getDescriptors")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n descriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n changeDescriptor"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" descriptors"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" network"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n databaseConfig"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DatabaseConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("memory")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("var")]),t._v(" addressInfo "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" addressInfo"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n wallet "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Wallet Created: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("address")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("A new button will be required to call "),a("code",[t._v("createOrRestoreWallet()")])]),t._v(" "),a("p",[t._v("Let's add a new button just below the mnemonic "),a("code",[t._v("TextFieldContainer")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Create Wallet"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("createOrRestoreWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mnemonic"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" \n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network.Testnet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("The response returned by "),a("code",[t._v("create()")]),t._v(" is a "),a("code",[t._v("Wallet")]),t._v(" object.")]),t._v(" "),a("p",[t._v("The App should now be creating a wallet when we click "),a("strong",[t._v("Create Mnemonic")]),t._v(" followed by "),a("strong",[t._v("Create Wallet")]),t._v(".")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(353)}}),t._v(" "),a("p",[t._v("Before going forward, we need to create a "),a("code",[t._v("Blockchain")]),t._v(" object as well. The Blockchain object will encapsulate the bitcoin node configuration which the wallet will use for syncing blocks and broadcasting transactions.")]),t._v(" "),a("p",[t._v("Let's add an internal method to create and initialize the "),a("code",[t._v("Blockchain")]),t._v(" object.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("blockchainInit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n blockchain "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Blockchain")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("BlockchainConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("electrum")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n config"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ElectrumConfig")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n stopGap"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n timeout"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n retry"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("5")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n url"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"ssl://electrum.blockstream.info:60002"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validateDomain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("Here we are initializing the "),a("code",[t._v("late")]),t._v(" non-nullable "),a("code",[t._v("blockchain")]),t._v(" variable, by calling the named constructor "),a("code",[t._v("create")]),t._v(", which takes a "),a("code",[t._v("BlockchainConfig")]),t._v(" object.\nThe bitcoin node specified is an Electrum node and we are specifying the url for Blockstream's public Electrum Testnet servers over SSL.")]),t._v(" "),a("p",[t._v("After creating the "),a("code",[t._v("blockchainInit()")]),t._v(" method, call it from "),a("code",[t._v("createOrRestoreWallet()")]),t._v(", so the "),a("code",[t._v("blockchain")]),t._v(" variable gets initialized before the "),a("code",[t._v("wallet")]),t._v(" is created.")]),t._v(" "),a("p",[t._v("Include the following line of code inside "),a("code",[t._v("createOrRestoreWallet()")]),t._v(" just before calling Wallet.create().")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("blockchainInit")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n")])])]),a("p",[a("strong",[t._v("blockChainConfig")]),t._v(": BlockchainConfig is an enum that has 3 values, "),a("code",[t._v("BlockchainConfig.electrum")]),t._v(" for "),a("a",{attrs:{href:"https://github.com/romanz/electrs",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("electrum")]),a("OutboundLink")],1),t._v(" ,"),a("code",[t._v("BlockchainConfig.esplora")]),t._v(" for "),a("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("esplora")]),a("OutboundLink")],1),t._v(" and "),a("code",[t._v("BlockchainConfig.rpc")]),t._v(" .")]),t._v(" "),a("p",[a("code",[t._v("BlockchainConfig.electrum")]),t._v(", "),a("code",[t._v("BlockchainConfig.rpc")]),t._v(" & "),a("code",[t._v("BlockchainConfig.esplora")]),t._v(" has "),a("code",[t._v("ElectrumConfig")]),t._v(" object, "),a("code",[t._v("RpcConfig")]),t._v(" object and "),a("code",[t._v("EsploraConfig")]),t._v(" object, respectively as its parameter.")]),t._v(" "),a("p",[a("strong",[t._v("ElectrumConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.electrum")]),t._v("'s config that takes a timeout, retry & url as its required parameter.")]),t._v(" "),a("p",[a("strong",[t._v("EsploraConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.esplora")]),t._v("'s config that takes baseUrl & stopGap as its required parameter.")]),t._v(" "),a("p",[a("strong",[t._v("RpcConfig")]),t._v(": This is the object type of "),a("code",[t._v("BlockchainConfig.rpc")]),t._v("'s config that takes url, network, & walletName as its required parameter. If "),a("code",[t._v("Rpc Blockchain")]),t._v(" has its authentication values inside a cookie file, please pass in cookie path as authCookie parameter, or you can pass in rpc username and password using "),a("code",[t._v("UserPass")]),t._v(" class.")]),t._v(" "),a("p",[t._v("Refer to the readme for a complete list of options for "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#createwallet",target:"_blank",rel:"noopener noreferrer"}},[t._v("createWallet()"),a("OutboundLink")],1)]),t._v(" "),a("h2",{attrs:{id:"utxos-and-balance"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#utxos-and-balance"}},[t._v("#")]),t._v(" UTXOs and balance")]),t._v(" "),a("p",[t._v("With the "),a("code",[t._v("Wallet")]),t._v(" and "),a("code",[t._v("Blockchain")]),t._v(" created, we can now add methods to sync UTXOs and compute balance.")]),t._v(" "),a("p",[a("code",[t._v("Wallet")]),t._v(" has a "),a("code",[t._v("sync")]),t._v(" method to sync all UTXOs belonging to the wallet using the "),a("code",[t._v("Blockchain")]),t._v(" object. Once the wallet sync is complete balance is computed and "),a("code",[t._v("getBalance")]),t._v(" can fetch the balance.")]),t._v(" "),a("p",[t._v("Earlier we have already added a variable for "),a("code",[t._v("balance")]),t._v(". Now we will add buttons to call "),a("code",[t._v("sync")]),t._v(" and "),a("code",[t._v("getBalance")]),t._v(". Just below the Create Wallet button let's add two buttons as follows:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Sync Wallet"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("syncWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v(" callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Get Balance"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("Let's add two internal functions for syncing UTXOs and compute balance.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" balanceObj "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getBalance")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Total Balance: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("balanceObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("total"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("print")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n balance "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" balanceObj"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("total"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("syncWallet")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("sync")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("We should now be able to create a wallet, sync UTXOs, and get the balance")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0 auto",zoom:"25%"},attrs:{src:s(354)}}),t._v(" "),a("p",[t._v("We can use a public testnet faucet to send testnet coins to the wallet and check that the UTXO sync and balance fetch are working correctly. Before we do that add one more method to generate a new address we can then use this address to get testnet coins from a faucet.")]),t._v(" "),a("p",[t._v("Let's use the "),a("code",[t._v("address")]),t._v(" variable that was created before for this, we need to add a button for "),a("strong",[t._v("Get Address")]),t._v(" and an internal function to call "),a("code",[t._v("Wallet")]),t._v(" and create a new address. Let's do the following")]),t._v(" "),a("p",[t._v("Add a new "),a("code",[t._v("getNewAddress")]),t._v(" function below the "),a("code",[t._v("syncWallet()")]),t._v(" function:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("addressIndex"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" res"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),a("p",[t._v("And a "),a("strong",[t._v("Get Address")]),t._v(" button below the existing "),a("strong",[t._v("Get Balance")]),t._v(" button:")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("getNewAddress")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Get Address"')])]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n")])])]),a("p",[t._v("We should now have the following, and "),a("strong",[t._v("Get Address")]),t._v(" will be able to display a new address.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(355)}}),t._v(" "),a("p",[t._v("Now that we are able to generate a receive address we can get some testnet bitcoin from one of the public "),a("a",{attrs:{href:"https://coinfaucet.eu/en/btc-testnet/",target:"_blank",rel:"noopener noreferrer"}},[t._v("testnet faucets"),a("OutboundLink")],1)]),t._v(" "),a("p",[t._v("After we send and after the transaction is confirmed we will need to sync the wallet before we can see the new balance from the received transaction.")]),t._v(" "),a("h2",{attrs:{id:"restoring-a-wallet"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#restoring-a-wallet"}},[t._v("#")]),t._v(" Restoring a wallet")]),t._v(" "),a("p",[t._v("The "),a("code",[t._v("create")]),t._v(" method creates a wallet using a "),a("code",[t._v("mnemonic")]),t._v(", to restore we can use the same method, we won't need to call "),a("code",[t._v("generateMnemonic")]),t._v(" as we will already have a "),a("code",[t._v("mnemonic")]),t._v(" to restore with.")]),t._v(" "),a("p",[t._v("This text field below the "),a("code",[t._v("Generate Mnemonic")]),t._v(" button will also display the mnemonic variable if we click Generate Mnemonic' button. The generated mnemonic will show up in the text field. We can overwrite it with our mnemonic and doing so will also overwrite the mnemonic state variable. This way the mnemonic displayed will be the one used to create the wallet.")]),t._v(" "),a("p",[t._v("We can now use our mnemonic and use it to restore a wallet. This will come in handy if we have a wallet with testnet bitcoin as these are hard to come by.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(356)}}),t._v(" "),a("h2",{attrs:{id:"sending-bitcoin"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#sending-bitcoin"}},[t._v("#")]),t._v(" Sending bitcoin")]),t._v(" "),a("p",[t._v("We are now able to receive bitcoin, now its time to add functionality to send a bitcoin transaction.")]),t._v(" "),a("p",[t._v("For making a successful bitcoin transaction "),a("code",[t._v("bdk-flutter")]),t._v(" utilizes a couple of methods. A new unsigned transaction can be created by using TxBuilder](https://github.com/LtbLightning/bdk-flutter#quicksend).")]),t._v(" "),a("p",[t._v("First, we have to initialize the "),a("code",[t._v("TxBuilder")]),t._v(" object and call the "),a("code",[t._v("addRecipient()")]),t._v(" method.\n"),a("code",[t._v("addRecipient()")]),t._v(" takes a "),a("code",[t._v("Script")]),t._v(" object and the transaction "),a("code",[t._v("amount")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can create the"),a("code",[t._v("Script")]),t._v(" object by using the "),a("code",[t._v("Address")]),t._v(" class, by specifying the recipient address.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" res "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("We can create a "),a("code",[t._v("psbt")]),t._v(" object by calling the "),a("code",[t._v("finish()")]),t._v(" method using the response object from "),a("code",[t._v("addRecipient()")]),t._v(" method.")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" psbt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("This "),a("code",[t._v("psbt")]),t._v(" can be signed later with "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#signtx",target:"_blank",rel:"noopener noreferrer"}},[t._v("sign()"),a("OutboundLink")],1),t._v(" method from the "),a("code",[t._v("Wallet")]),t._v(" and broadcast using "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter#broadcasttx",target:"_blank",rel:"noopener noreferrer"}},[t._v("broadcast()"),a("OutboundLink")],1),t._v(" from the "),a("code",[t._v("Blockchain")]),t._v(" .")]),t._v(" "),a("p",[t._v("We will need textfield controllers for the recipient address, amount, and for transaction, these can be added below our existing variable for "),a("code",[t._v("mnemonic")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" recipientAddress "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),t._v(" amount "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextEditingController")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Let's make an internal function to send a bitcoin transaction, using "),a("code",[t._v("Wallet")]),t._v(", "),a("code",[t._v("Blockchain")]),t._v(" and "),a("code",[t._v("TxBuilder")]),t._v(".")]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Future")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("void")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" int amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("try")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilder "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TxBuilder")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" address "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Address")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("create")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" addressStr"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" script "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" address"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("scriptPubKey")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" txBuilderResult "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" txBuilder\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("addRecipient")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("script"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("feeRate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" sbt "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" wallet"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" txBuilderResult"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("psbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" tx "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" sbt"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("extractTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" blockchain"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Successfully broadcast ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("amount")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v(" Sats to ")]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("$")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("addressStr")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("on")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Exception")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("catch")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("setState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n displayText "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Error: ')]),a("span",{pre:!0,attrs:{class:"token interpolation"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("${")]),a("span",{pre:!0,attrs:{class:"token expression"}},[t._v("e"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("toString")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")])]),a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n")])])]),a("p",[t._v("Add a new section for send transaction functionality. We will need a "),a("code",[t._v("form")]),t._v(", a "),a("code",[t._v("TextFormField")]),t._v(" for the receiver address and a "),a("code",[t._v("TextFormField")]),t._v(" for the amount to send. We will also need a button to call the "),a("code",[t._v("sendTx")]),t._v(" function.")]),t._v(" "),a("p",[t._v("Before submitting the form we need to make sure all the input fields are valid, for that purpose, we need to initialize a "),a("a",{attrs:{href:"https://api.flutter.dev/flutter/widgets/GlobalKey-class.html",target:"_blank",rel:"noopener noreferrer"}},[a("code",[t._v("GlobalKey")]),a("OutboundLink")],1),t._v(". This can be added above our "),a("code",[t._v("Scaffold")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("final")]),t._v(" _formKey "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GlobalKey")]),a("span",{pre:!0,attrs:{class:"token generics"}},[a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("<")]),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FormState")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(">")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),a("p",[t._v("Let's add the send transaction section and UI components below "),a("code",[t._v("/* Send Transaction */")])]),t._v(" "),a("div",{staticClass:"language-dart extra-class"},[a("pre",{pre:!0,attrs:{class:"language-dart"}},[a("code",[t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("StyledContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Form")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n key"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" _formKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Column")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n mainAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MainAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("start"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n crossAxisAlignment"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("CrossAxisAlignment")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("center"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n children"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" recipientAddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validator"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Please enter your address'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter Address"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFieldContainer")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n child"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextFormField")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n controller"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n validator"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("value "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("||")]),t._v(" value"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("isEmpty"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v("'Please enter the amount'")])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("return")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("null")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n keyboardType"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TextInputType")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("number"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n style"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Theme")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("of")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("context"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("textTheme"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("bodyText1"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n decoration"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("const")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("InputDecoration")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n hintText"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Enter Amount"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SubmitButton")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token string-literal"}},[a("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Send Bit"')])]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n callback"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("async")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("_formKey"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("currentState"),a("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("validate")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("await")]),t._v(" "),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("sendTx")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("recipientAddress"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n int"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),a("span",{pre:!0,attrs:{class:"token function"}},[t._v("parse")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("amount"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("text"),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),a("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),a("p",[t._v("We should now be able to send a transaction as long as there is sufficient balance.")]),t._v(" "),a("img",{staticStyle:{display:"block",margin:"0px auto",zoom:"25%"},attrs:{src:s(357)}}),t._v(" "),a("h2",{attrs:{id:"conclusion"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[t._v("#")]),t._v(" Conclusion")]),t._v(" "),a("p",[t._v("The App we created can be built and distributed for both iOS and Android thus sharing a code base and reducing development time. The development and coding focused on application-level code for use cases and we did not have to code intricate internal bitcoin protocol-level code or bitcoin node interactions, and transactions. UTXOs and sync-related functionalities were also not required. All this was managed by "),a("code",[t._v("bdk-flutter")]),t._v(" allowing us to focus on the product, functionality, and user journey. This is how "),a("code",[t._v("bdk")]),t._v(" and "),a("code",[t._v("bdk-flutter")]),t._v(" intend to make Rapid Bitcoin Application Development possible by allowing product and application developers to focus on what they know best while "),a("code",[t._v("bdk")]),t._v(" handles bitcoin complexity.")]),t._v(" "),a("p",[a("code",[t._v("bdk-flutter")]),t._v(" intends to expose functionality and APIs from "),a("code",[t._v("bdk")]),t._v(" which has a wide variety of APIs with granular details allowing for many interesting use cases to be implemented. "),a("code",[t._v("bdk-flutter")]),t._v(" and "),a("code",[t._v("bdk")]),t._v(" are constantly updated and enhanced based on feedback from product teams and developers in the bitcoin community.")]),t._v(" "),a("p",[t._v("Stay tuned for more APIs and enhancements coming to "),a("code",[t._v("bdk-flutter")]),t._v(" in the near future. Feature and API requests are most welcome. New blogs and tutorials will be published soon for a more in-depth exploration of "),a("code",[t._v("bdk-flutter")]),t._v(".")]),t._v(" "),a("p",[t._v("In the meantime keep in touch with the project by following us on "),a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("GitHub"),a("OutboundLink")],1),t._v(" and "),a("a",{attrs:{href:"https://twitter.com/BitcoinZavior",target:"_blank",rel:"noopener noreferrer"}},[t._v("Twitter"),a("OutboundLink")],1)]),t._v(" "),a("h4",{attrs:{id:"references"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#references"}},[t._v("#")]),t._v(" References:")]),t._v(" "),a("ul",[a("li",[a("a",{attrs:{href:"https://github.com/bitcoindevkit",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk-flutter"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/LtbLightning/bdk-flutter-quickstart",target:"_blank",rel:"noopener noreferrer"}},[t._v("bdk-flutter-quickstart GitHub Repository"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://docs.flutter.dev/get-started/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("Setup Flutter Development Environment"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/bitcoinbook/bitcoinbook/blob/develop/ch04.asciidoc",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mastering Bitcoin(HD Wallet chapter)"),a("OutboundLink")],1)]),t._v(" "),a("li",[a("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Output Descriptors from bitcoin GitHub"),a("OutboundLink")],1)]),t._v(" "),a("li",[t._v("Testnet Faucet: "),a("a",{attrs:{href:"https://coinfaucet.eu/en/btc-testnet/",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://coinfaucet.eu/en/btc-testnet/"),a("OutboundLink")],1),t._v(" or "),a("a",{attrs:{href:"https://bitcoinfaucet.uo1.net",target:"_blank",rel:"noopener noreferrer"}},[t._v("https://bitcoinfaucet.uo1.net"),a("OutboundLink")],1)])])])}),[],!1,null,null,null);a.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/39.b76a2ad0.js b/assets/js/39.089a397e.js similarity index 99% rename from assets/js/39.b76a2ad0.js rename to assets/js/39.089a397e.js index 64bd78a0b4..4612598e26 100644 --- a/assets/js/39.b76a2ad0.js +++ b/assets/js/39.089a397e.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{385:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("BDK wallet developer library can be used to easily deploy wallets with various kinds of blockchain backend support, like "),s("a",{attrs:{href:"https://github.com/romanz/electrs",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("electrum")]),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("esplora")]),s("OutboundLink")],1),t._v(", "),s("code",[t._v("compact-filters")]),t._v(" ("),s("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[t._v("BIP157"),s("OutboundLink")],1),t._v(") etc. With the latest release of BDK "),s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk/releases/tag/v0.10.0",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("v0.10.0")]),s("OutboundLink")],1),t._v(", BDK now supports Bitcoin Core as a blockchain backend. BDK talks with Bitcoin Core using rust-bitcoin's "),s("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-bitcoincore-rpc",target:"_blank",rel:"noopener noreferrer"}},[t._v("bitcoincore-rpc"),s("OutboundLink")],1),t._v(" library.")]),t._v(" "),s("p",[t._v("This allows wallet devs to quickly deploy their wallet that can talk to a bitcoin full node (home raspi nodes) out of the box. Wallet devs don't need to worry about connecting to a full node with correct RPC calls, all of that is handled by BDK under the hood. All they need is to identify the full node's RPC IP address and the correct RPC credentials.")]),t._v(" "),s("p",[t._v("In this tutorial we will see how to write a very simplistic wallet code that can connect to a bitcoin core node and maintain its balance and make transactions.")]),t._v(" "),s("p",[t._v("Unlike other tutorials, we will not use "),s("code",[t._v("bdk-cli")]),t._v(" tools, but instead write rust code directly using "),s("code",[t._v("BDK")]),t._v(" devkit. In the end we will end up with our own simple bitcoin wallet.")]),t._v(" "),s("h2",{attrs:{id:"prerequisite"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#prerequisite"}},[t._v("#")]),t._v(" Prerequisite")]),t._v(" "),s("p",[t._v("To run with this tutorial you would need to have a bitcoin core node running in regtest mode. Get the bitcoin core binary either from the "),s("a",{attrs:{href:"https://bitcoincore.org/bin/bitcoin-core-0.21.1/",target:"_blank",rel:"noopener noreferrer"}},[t._v("bitcoin core repo"),s("OutboundLink")],1),t._v(" or "),s("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/v0.21.1/doc/build-unix.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("build from source"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("Then configure the node with a following "),s("code",[t._v("bitcoin.conf")]),t._v(" file")]),t._v(" "),s("div",{staticClass:"language-txt extra-class"},[s("pre",{pre:!0,attrs:{class:"language-txt"}},[s("code",[t._v("regtest=1\nfallbackfee=0.0001\nserver=1\ntxindex=1\nrpcuser=admin\nrpcpassword=password\n")])])]),s("p",[t._v("Apart from that, you would need to install rust in your system. Grab the installation one-liner from "),s("a",{attrs:{href:"https://www.rust-lang.org/tools/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"setting-up"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-up"}},[t._v("#")]),t._v(" Setting Up")]),t._v(" "),s("p",[t._v("Create a new cargo binary repository.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mkdir")]),t._v(" ~/tutorial\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" tutorial\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" new bdk-example\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" bdk-example\n")])])]),s("p",[t._v("This will create a new project folder named "),s("code",[t._v("bdk-example")]),t._v(" with "),s("code",[t._v("src/main.rs")]),t._v(" and a "),s("code",[t._v("cargo.toml")]),t._v(".")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ tree "),s("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-L")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(".")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(".")]),t._v("\n├── Cargo.toml\n└── src\n └── main.rs\n\n"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" directory, "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" files\n")])])]),s("p",[t._v("Opening "),s("code",[t._v("main.rs")]),t._v(" you will see some predefined code like this")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, world!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Try running "),s("code",[t._v("cargo run")]),t._v(' and if everything is set, you should see "Hello, world!" printed in your terminal')]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Compiling bdk-example v0.1.0 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("/home/raj/github-repo/tutorial/bdk-example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(".95s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\nHello, world"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n")])])]),s("p",[t._v("Of course we will not use the given "),s("code",[t._v("println!()")]),t._v(" statement, but we will put our main code in the "),s("code",[t._v("main()")]),t._v(" function.")]),t._v(" "),s("p",[s("code",[t._v("cargo new")]),t._v(" will also produce a skeleton "),s("code",[t._v("Cargo.toml")]),t._v(" file like this")]),t._v(" "),s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("package")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("name")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk-example"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.1.0"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("edition")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2018"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),s("h2",{attrs:{id:"setting-dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-dependencies"}},[t._v("#")]),t._v(" Setting dependencies")]),t._v(" "),s("p",[t._v("Once the rust binary is compiled and running, we now need to specify the dependencies we need to work on our library.")]),t._v(" "),s("p",[t._v("Remember that BDK provides almost everything we would need to build a wallet out of the box. So we don't need any more dependencies apart from BDK. We will use another small rust crate called "),s("a",{attrs:{href:"https://crates.io/crates/dirs-next",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("dirs_next")]),s("OutboundLink")],1),t._v(" to find our home directory and store wallet files in a subfolder there.")]),t._v(" "),s("p",[t._v("Add the dependencies into "),s("code",[t._v("Cargo.toml")]),t._v(" like below")]),t._v(" "),s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("package")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("name")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk-example"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.1.0"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("edition")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2018"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("bdk")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"^0.10"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("default-features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"all-keys"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key-value-db"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rpc"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("dirs-next")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.0"')]),t._v("\n")])])]),s("p",[t._v("We disabled the default BDK feature (which specifies blockchain backend as an electrum server) and we requested the following features:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("all-keys")]),t._v(": Adds BIP39 key derivation capabilities")]),t._v(" "),s("li",[s("strong",[t._v("key-value-db")]),t._v(": Adds a persistence storage capability")]),t._v(" "),s("li",[s("strong",[t._v("rpc")]),t._v(": Adds the RPC blockchain backend capability.")])]),t._v(" "),s("p",[t._v("Now that we have the dependencies added, we can import them in the "),s("code",[t._v("main.rs")]),t._v(" file to use in our code.\nAdd the following imports at the start of "),s("code",[t._v("main.rs")])]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip32"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoincore_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcApi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet_name_from_descriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfigurableBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip39"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("With this we are now ready to add our wallet code.")]),t._v(" "),s("h2",{attrs:{id:"getting-descriptors"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-descriptors"}},[t._v("#")]),t._v(" Getting Descriptors")]),t._v(" "),s("p",[t._v("BDK is a descriptor based wallet library. That means when we specify our wallet key-chain we need to tell BDK about it in the format of a descriptor. You can read up on descriptors more "),s("a",{attrs:{href:"https://bitcoindevkit.org/descriptors/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(". A descriptor string looks like this\n"),s("code",[t._v("\"wpkh([b8b575c2/84'/1'/0'/0]tprv8icWtRzy9CWgFxpGMLSdAeE4wWyz39XGc6SwykeTo13tYm14JkVVQAf7jz8WDDarCgNJrG3aEPJEqchDWeJdiaWpS3FwbLB9SzsN57V7qxB/*)\"")]),t._v(".")]),t._v(" "),s("p",[t._v("This describes a SegwitV0 descriptor of a key derived at path "),s("code",[t._v("m/84'/1'/0'/0")]),t._v(". If you already have a descriptor from other sources, you can use that. Otherwise, BDK has your back. BDK can be used to generate a fresh master key with mnemonic, and then derive child keys from it given a specific path. Putting the key in a descriptor is as simple as wrapping it with a "),s("code",[t._v("wpkh()")]),t._v(" string.")]),t._v(" "),s("p",[t._v("We will use a dedicated function that will create fresh receive and change descriptors from BDK for our purpose. It will also generate the mnemonic word list for later regenerating the wallet. But we will ignore that for our scope.")]),t._v(" "),s("p",[t._v("Add a function named "),s("code",[t._v("get-descriptor()")]),t._v(" below the "),s("code",[t._v("main()")]),t._v(" function as shown")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generate fresh descriptor strings and return them via (receive, change) tuple")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a new secp context")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can also set a password to unlock the mnemonic")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"random password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate a fresh mnemonic, and from there a privatekey")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Words12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_extended_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_xprv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create derived privkey from the above master privkey")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We use the following derivation paths for receive and change keys")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// receive: "m/84h/1h/0h/0"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// change: "m/84h/1h/0h/1" ')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" keys "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fingerprint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv_desc_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n derived_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_descriptor_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wrap the derived key with the wpkh() string to produce a descriptor string")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" derived_xprv_desc_key "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wpkh("')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('")"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Return the keys as a tuple")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("To check that the above added function is working as expected, call it in the main function and print the descriptors")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"recv: {:#?}, \\nchng: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Running the binary should produce the following result")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\nrecv: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"wpkh([89df6a67/84'/1'/0'/0]tprv8iSRXyLtTKJN9qt1jyPVqwhDMEaYztXunPaRQznaH1z8gj8e2g7RnF2ZoHP56VEXwMn76AiV1Je6nJmZbFistwAQCrRGmSrsoKfdqfTDNA1/*)\"")]),t._v(", \nchng: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"wpkh([89df6a67/84'/1'/0'/1]tprv8iSRXyLtTKJNCECQxBJ19cgx2ueS7mC7GNq7VqTWY3RNPMBY7DfTb9HUnXpJqa14jCJNRmi4yGxfoTVS4WLBXDkvTLq4vujeAD9NfDtSxGP/*)\"")]),t._v("\n")])])]),s("p",[t._v("Voila! Now we have nice descriptors strings handy to use for our BDK wallet construction.")]),t._v(" "),s("h2",{attrs:{id:"talking-to-bitcoin-core-programmatically"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#talking-to-bitcoin-core-programmatically"}},[t._v("#")]),t._v(" Talking to Bitcoin Core Programmatically")]),t._v(" "),s("p",[t._v("Like all other tutorials we will use two wallets to send coins back and forth. A Bitcoin Core wallet accessible via "),s("code",[t._v("bitcoin-cli")]),t._v(" command line tools, and a BDK wallet maintained by BDK library.")]),t._v(" "),s("p",[t._v("But unlike other tutorials, we won't be using "),s("code",[t._v("bitcoin-cli")]),t._v(" to talk to the Core wallet (we can, but let's spice things up). Instead, we will use the "),s("code",[t._v("bitcoin-rpc")]),t._v(" library, to talk with our core node listening at "),s("code",[t._v("127.0.0.1:18443")]),t._v(", from inside our main function. This will allow us to write code, that will handle both the core and BDK wallet, from inside of the same function, and we won't have to switch terminals!")]),t._v(" "),s("p",[t._v("Remember we imported "),s("code",[t._v("use bdk::bitcoincore_rpc::{Auth as rpc_auth, Client, RpcApi};")]),t._v("? Thats exactly for this purpose.")]),t._v(" "),s("p",[t._v("Start the "),s("code",[t._v("bitcoind")]),t._v(" node.")]),t._v(" "),s("p",[t._v("you should see bitcoind listening at port 18443")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sudo")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("netstat")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-nptl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("grep")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18443")]),t._v(" \ntcp "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),t._v(".0.0:18443 "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),t._v(".0.0:* LISTEN "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("135532")]),t._v("/bitcoind \n")])])]),s("p",[t._v("Lets create a core rpc interface in our main function.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a RPC interface")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_rpc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://127.0.0.1:18443/wallet/test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_blockchain_info")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We have provided our RPC authentication "),s("code",[t._v("username")]),t._v(" and "),s("code",[t._v("password")]),t._v(" (same as provided in "),s("code",[t._v("bitcoin.conf")]),t._v(" file).\nWe have provided the RPC address of our local bitcoin node, with the path to a wallet file, named "),s("code",[t._v("test")]),t._v(". And then asked the rpc client to give us the current blockchain info.\nIf everything goes well, running "),s("code",[t._v("cargo run")]),t._v(" you should see an output like below:")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\nGetBlockchainInfoResult "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"regtest"')]),t._v(",\n blocks: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(",\n headers: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(",\n best_block_hash: 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206,\n difficulty: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.00000000046565423739069247")]),t._v(",\n median_time: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1296688602")]),t._v(",\n verification_progress: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),t._v(",\n initial_block_download: true,\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\n")])])]),s("p",[t._v("Thats it. Now we can programmatically talk to our core node.")]),t._v(" "),s("h2",{attrs:{id:"get-some-balance-in-core-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#get-some-balance-in-core-wallet"}},[t._v("#")]),t._v(" Get some balance in core wallet.")]),t._v(" "),s("p",[t._v("We have told our rpc client that we would use a wallet named "),s("code",[t._v("test")]),t._v(". But currently, our core node doesn't have such a wallet. So let's create the wallet and fund it with some test coins.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the test wallet ")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get a new address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_new_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate 101 blocks and use the above address as coinbase")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("101")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// fetch the new balance")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Show balance")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("This will create a wallet in bitcoin core named "),s("code",[t._v("test")]),t._v(". generate 101 blocks and use a new address from the wallet as coinbase wallet. Because required coinbase maturity in bitcoin is 100 blocks, by generating 101 blocks, we will have the balance of the first coinbase block reward available for use.\nThe last "),s("code",[t._v("println!()")]),t._v(" statement will show the new updated balance as 50 BTC.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\ncore balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("50.00000000")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),s("p",[t._v("Great! We now have 50 regtest BTC to play with.")]),t._v(" "),s("h2",{attrs:{id:"setup-the-bdk-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setup-the-bdk-wallet"}},[t._v("#")]),t._v(" Setup the BDK wallet")]),t._v(" "),s("p",[t._v("Now that we are done setting up the core wallet. The last remaining step is to setup the BDK wallet. For this we will use the previous descriptor generation function and write code as below.")]),t._v(" "),s("p",[s("strong",[t._v("Note")]),t._v(": You might want to comment out the previous code in "),s("code",[t._v("main()")]),t._v(", as running them again will create more coins in core, which isn't an issue, but might be confusing.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get receive and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use deterministic wallet name derived from descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("wallet_name_from_descriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the datadir to store wallet data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" datadir "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("dirs_next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("home_dir")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('".bdk-example"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" database "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" db_tree "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open_tree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC username, password and url")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n username"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" rpc_url "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1:18443"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Setup the RPC configuration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n skip_blocks"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the above configuration to create a RPC blockchain backend")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_config")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("rpc_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Combine everything and finally create the BDK wallet structure")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" db_tree"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk address: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("That's a lot of code. They are divided into logical sections. Let's discuss each step one by one.")]),t._v(" "),s("ul",[s("li",[t._v("First we used our previous "),s("code",[t._v("get_descriptors()")]),t._v(" function to generate two descriptor strings. One for generating receive addresses and one for change addresses.")]),t._v(" "),s("li",[t._v("Then we used a special function from BDK called "),s("code",[t._v("wallet_name_from_descriptor()")]),t._v(" to derive a name of the wallet from our descriptors. This allows us to have wallet names deterministically linked with descriptors. So in future if we use a different descriptor, the wallet will automatically have a different name. This allows us to not mix wallet names with same descriptor, and given the descriptors we can always determine what was the name we used. It is recommended to derive wallet names like this while using a core backend. Note that this wallet will be created inside the core node. So just like we accessed the "),s("code",[t._v("test")]),t._v(" wallet, we could also access this wallet.")]),t._v(" "),s("li",[t._v("Then we created a data directory at path "),s("code",[t._v("/home/username/.bdk-example")]),t._v(". We use "),s("code",[t._v("dirs_next")]),t._v(" to find our home path, and then appended that with "),s("code",[t._v(".bdk-example")]),t._v(". All the BDK wallet files will be created and maintained in that directory. In the Database we instructed BDK to create a new "),s("code",[t._v("Tree")]),t._v(" with "),s("code",[t._v("wallet_name")]),t._v(", so given a descriptor, BDK will always know which DB Tree to refer ("),s("code",[t._v("Tree")]),t._v(" is a "),s("code",[t._v("sled")]),t._v(" specific term).")]),t._v(" "),s("li",[t._v("Then like we did previously, we created the rpc username/password authentication, and specified the rpc url. Note that we cannot use the same "),s("code",[t._v("rpc_auth")]),t._v(" we used before for "),s("code",[t._v("core_rpc")]),t._v(" as BDK auth and bitcoin-rpc auth are slightly separate structures.")]),t._v(" "),s("li",[t._v("We combined all this information and created an "),s("code",[t._v("RpcConfig")]),t._v(" structure.")]),t._v(" "),s("li",[t._v("We used the rpc configuration to create a "),s("code",[t._v("RpcBlockchain")]),t._v(" structure.")]),t._v(" "),s("li",[t._v("Finally we used the Descriptors, Database, and Blockchain to create our final BDK "),s("code",[t._v("wallet")]),t._v(" structure.")])]),t._v(" "),s("p",[t._v("Now that we have our wallet cooked, in the end, we instructed it to sync with the bitcoin core backend, and fetch us a new address.")]),t._v(" "),s("p",[t._v("If all goes well, you should see an address printed in the terminal.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(".99s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\nbdk address: bcrt1q9vkmujggvzs0rd4z6069v3v0jucje7ua7ap308\n")])])]),s("h2",{attrs:{id:"sending-sats-around"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sending-sats-around"}},[t._v("#")]),t._v(" Sending Sats Around")]),t._v(" "),s("p",[t._v("Now that we have covered all the groundwork, we have all we need to send coins back and forth between core and BDK wallet.")]),t._v(" "),s("p",[t._v("We will keep things simple here and make the following actions")]),t._v(" "),s("ul",[s("li",[t._v("Send 10 BTC from Core to BDK")]),t._v(" "),s("li",[t._v("Send back 5 BTC from BDK to Core")]),t._v(" "),s("li",[t._v("Display balance of two wallets")])]),t._v(" "),s("p",[t._v("In the last line of previous section we got a new address from BDK wallet. We will start from there. Without further discussion lets jump straight into code.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Send 10 BTC from Core to BDK")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_btc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a transaction builder")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" tx_builder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set recipient of the transaction")]),t._v("\n tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_recipients")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500000000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finalise the transaction and extract PSBT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set signing option")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signopt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n assume_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sign the above psbt with signing option")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signopt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Extract the final transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Broadcast the transaction")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch and display wallet balances")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bdk_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_sat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"BDK wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bdk_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The above code segment is mostly straightforward. The only new thing added is "),s("code",[t._v("wallet.build_tx()")]),t._v(" which returns a "),s("code",[t._v("TxBuilder")]),t._v(". BDK allows us to have very fine grained control of cooking up transactions. Almost everything that is possible to do with a Bitcoin transaction can be done in BDK. Here we have a very simple vanilla transaction with no added magic. To get full list of capabilities that "),s("code",[t._v("TxBuilder")]),t._v(" supports scour its implementation "),s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk/blob/38d1d0b0e29d38cd370c740d798d96a3c9fcaa1f/src/wallet/tx_builder.rs#L123-L153",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("Finally to step through what we did above:")]),t._v(" "),s("ul",[s("li",[t._v("We asked core wallet to send 10 BTC to bdk wallet address.")]),t._v(" "),s("li",[t._v("We confirmed the transaction, and synced the wallet.")]),t._v(" "),s("li",[t._v("We asked BDK to create a transaction sending 5 BTC to core wallet address.")]),t._v(" "),s("li",[t._v("We signed and broadcast the transaction. BDK will use the same core node to broadcast the transaction to network.")]),t._v(" "),s("li",[t._v("We confirmed the transaction by mining a block, and synced the wallet.")]),t._v(" "),s("li",[t._v("We fetched and displayed balance of both core and BDK wallet.")])]),t._v(" "),s("p",[t._v("If all goes well, you should see the final updated balance as below:")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Compiling bdk-example v0.1.0 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("/home/raj/github-repo/bdk-example/bdk-example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(".57s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\ncore wallet balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("144.99998590")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nBDK wallet balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.99999859")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Voila! We have ~145 BTC (150 - 5) in core wallet and 5 BTC (10 - 5) in BDK wallet. The slight deficiency in the amount are due to transaction fees. Because we are using regtest, the fee is some standard value hardcoded in core node.")]),t._v(" "),s("p",[t._v("Check out the data directory where BDK has created the wallet data files.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ls")]),t._v(" ~/.bdk-example/\nblobs conf db snap.0000000000023CAB\n")])])]),s("p",[t._v("And finally, this is what the final "),s("code",[t._v("main.rs")]),t._v(" file looks like.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip32"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoincore_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcApi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet_name_from_descriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfigurableBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip39"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a RPC interface")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_rpc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://127.0.0.1:18443/wallet/test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the test wallet ")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get a new address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_new_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate 101 blocks and use the above address as coinbase")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("101")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get receive and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use deterministic wallet name derived from descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("wallet_name_from_descriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the datadir to store wallet data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" datadir "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("dirs_next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("home_dir")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('".bdk-example"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" database "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" db_tree "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open_tree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC username and password")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n username"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC url")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" rpc_url "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1:18443"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Setup the RPC configuration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n skip_blocks"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the above configuration to create a RPC blockchain backend")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_config")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("rpc_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Combine everything and finally create the BDK wallet structure")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" db_tree"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Send 10 BTC from Core to BDK")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_btc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a transaction builder")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" tx_builder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set recipient of the transaction")]),t._v("\n tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_recipients")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500000000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finalise the transaction and extract PSBT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set signing option")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signopt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n assume_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sign the above psbt with signing option")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signopt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Extract the final transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Broadcast the transaction")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch and display wallet balances")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bdk_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_sat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"BDK wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bdk_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generate fresh descriptor strings and return them via (receive, change) tupple ")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a new secp context")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can also set a password to unlock the mnemonic")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"random password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate a fresh menmonic, and from their, a fresh private key xprv")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Words12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_extended_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_xprv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Derive our descriptors to use")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We use the following paths for recieve and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// recieve: "m/84h/1h/0h/0"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// change: "m/84h/1h/0h/1" ')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" keys "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fingerprint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv_desc_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n derived_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_descriptor_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wrap the derived key with the wpkh() string to produce a descriptor string")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" derived_xprv_desc_key "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wpkh("')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('")"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Return the keys as a tupple")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"conclusion"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[t._v("#")]),t._v(" Conclusion")]),t._v(" "),s("p",[t._v("In this tutorial we saw some very basic BDK wallet functionality with a bitcoin core backend as the source and sync of blockchain data. This is just tip of the iceberg of BDK capabilities. BDK allows flexibility in all the dimensions of a bitcoin wallet, that is key chain, blockchain backend and database management. With all that power, we just implemented a trustless, non-custodial, private bitcoin wallet, backed by a bitcoin full node, with less than 200 lines of code (including lots of comments).")]),t._v(" "),s("p",[t._v("BDK thus allows wallet devs, to only focus on stuff that they care about, writing wallet logic. All the backend stuff like blockchain, key management, and databases are abstracted away under the hood.")]),t._v(" "),s("p",[t._v("To find and explore more about the BDK capabilities and how it can fit your development need refer the following resources.")]),t._v(" "),s("ul",[s("li",[s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[t._v("source code"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://docs.rs/bdk/latest/bdk/",target:"_blank",rel:"noopener noreferrer"}},[t._v("dev docs"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://discord.com/invite/d7NkDKm",target:"_blank",rel:"noopener noreferrer"}},[t._v("community"),s("OutboundLink")],1)])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{388:function(t,s,a){"use strict";a.r(s);var n=a(7),e=Object(n.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h2",{attrs:{id:"introduction"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),s("p",[t._v("BDK wallet developer library can be used to easily deploy wallets with various kinds of blockchain backend support, like "),s("a",{attrs:{href:"https://github.com/romanz/electrs",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("electrum")]),s("OutboundLink")],1),t._v(", "),s("a",{attrs:{href:"https://github.com/Blockstream/esplora",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("esplora")]),s("OutboundLink")],1),t._v(", "),s("code",[t._v("compact-filters")]),t._v(" ("),s("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[t._v("BIP157"),s("OutboundLink")],1),t._v(") etc. With the latest release of BDK "),s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk/releases/tag/v0.10.0",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("v0.10.0")]),s("OutboundLink")],1),t._v(", BDK now supports Bitcoin Core as a blockchain backend. BDK talks with Bitcoin Core using rust-bitcoin's "),s("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-bitcoincore-rpc",target:"_blank",rel:"noopener noreferrer"}},[t._v("bitcoincore-rpc"),s("OutboundLink")],1),t._v(" library.")]),t._v(" "),s("p",[t._v("This allows wallet devs to quickly deploy their wallet that can talk to a bitcoin full node (home raspi nodes) out of the box. Wallet devs don't need to worry about connecting to a full node with correct RPC calls, all of that is handled by BDK under the hood. All they need is to identify the full node's RPC IP address and the correct RPC credentials.")]),t._v(" "),s("p",[t._v("In this tutorial we will see how to write a very simplistic wallet code that can connect to a bitcoin core node and maintain its balance and make transactions.")]),t._v(" "),s("p",[t._v("Unlike other tutorials, we will not use "),s("code",[t._v("bdk-cli")]),t._v(" tools, but instead write rust code directly using "),s("code",[t._v("BDK")]),t._v(" devkit. In the end we will end up with our own simple bitcoin wallet.")]),t._v(" "),s("h2",{attrs:{id:"prerequisite"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#prerequisite"}},[t._v("#")]),t._v(" Prerequisite")]),t._v(" "),s("p",[t._v("To run with this tutorial you would need to have a bitcoin core node running in regtest mode. Get the bitcoin core binary either from the "),s("a",{attrs:{href:"https://bitcoincore.org/bin/bitcoin-core-0.21.1/",target:"_blank",rel:"noopener noreferrer"}},[t._v("bitcoin core repo"),s("OutboundLink")],1),t._v(" or "),s("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/v0.21.1/doc/build-unix.md",target:"_blank",rel:"noopener noreferrer"}},[t._v("build from source"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("Then configure the node with a following "),s("code",[t._v("bitcoin.conf")]),t._v(" file")]),t._v(" "),s("div",{staticClass:"language-txt extra-class"},[s("pre",{pre:!0,attrs:{class:"language-txt"}},[s("code",[t._v("regtest=1\nfallbackfee=0.0001\nserver=1\ntxindex=1\nrpcuser=admin\nrpcpassword=password\n")])])]),s("p",[t._v("Apart from that, you would need to install rust in your system. Grab the installation one-liner from "),s("a",{attrs:{href:"https://www.rust-lang.org/tools/install",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"setting-up"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-up"}},[t._v("#")]),t._v(" Setting Up")]),t._v(" "),s("p",[t._v("Create a new cargo binary repository.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("mkdir")]),t._v(" ~/tutorial\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" tutorial\n"),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" new bdk-example\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" bdk-example\n")])])]),s("p",[t._v("This will create a new project folder named "),s("code",[t._v("bdk-example")]),t._v(" with "),s("code",[t._v("src/main.rs")]),t._v(" and a "),s("code",[t._v("cargo.toml")]),t._v(".")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ tree "),s("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-L")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(".")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(".")]),t._v("\n├── Cargo.toml\n└── src\n └── main.rs\n\n"),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),t._v(" directory, "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" files\n")])])]),s("p",[t._v("Opening "),s("code",[t._v("main.rs")]),t._v(" you will see some predefined code like this")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Hello, world!"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Try running "),s("code",[t._v("cargo run")]),t._v(' and if everything is set, you should see "Hello, world!" printed in your terminal')]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Compiling bdk-example v0.1.0 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("/home/raj/github-repo/tutorial/bdk-example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(".95s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\nHello, world"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v("\n")])])]),s("p",[t._v("Of course we will not use the given "),s("code",[t._v("println!()")]),t._v(" statement, but we will put our main code in the "),s("code",[t._v("main()")]),t._v(" function.")]),t._v(" "),s("p",[s("code",[t._v("cargo new")]),t._v(" will also produce a skeleton "),s("code",[t._v("Cargo.toml")]),t._v(" file like this")]),t._v(" "),s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("package")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("name")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk-example"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.1.0"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("edition")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2018"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n")])])]),s("h2",{attrs:{id:"setting-dependencies"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setting-dependencies"}},[t._v("#")]),t._v(" Setting dependencies")]),t._v(" "),s("p",[t._v("Once the rust binary is compiled and running, we now need to specify the dependencies we need to work on our library.")]),t._v(" "),s("p",[t._v("Remember that BDK provides almost everything we would need to build a wallet out of the box. So we don't need any more dependencies apart from BDK. We will use another small rust crate called "),s("a",{attrs:{href:"https://crates.io/crates/dirs-next",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("dirs_next")]),s("OutboundLink")],1),t._v(" to find our home directory and store wallet files in a subfolder there.")]),t._v(" "),s("p",[t._v("Add the dependencies into "),s("code",[t._v("Cargo.toml")]),t._v(" like below")]),t._v(" "),s("div",{staticClass:"language-toml extra-class"},[s("pre",{pre:!0,attrs:{class:"language-toml"}},[s("code",[s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("package")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("name")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk-example"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0.1.0"')]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("edition")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2018"')]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token table class-name"}},[t._v("dependencies")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("bdk")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("version")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"^0.10"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("default-features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token boolean"}},[t._v("false")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("features")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"all-keys"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"key-value-db"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"rpc"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token key property"}},[t._v("dirs-next")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"2.0"')]),t._v("\n")])])]),s("p",[t._v("We disabled the default BDK feature (which specifies blockchain backend as an electrum server) and we requested the following features:")]),t._v(" "),s("ul",[s("li",[s("strong",[t._v("all-keys")]),t._v(": Adds BIP39 key derivation capabilities")]),t._v(" "),s("li",[s("strong",[t._v("key-value-db")]),t._v(": Adds a persistence storage capability")]),t._v(" "),s("li",[s("strong",[t._v("rpc")]),t._v(": Adds the RPC blockchain backend capability.")])]),t._v(" "),s("p",[t._v("Now that we have the dependencies added, we can import them in the "),s("code",[t._v("main.rs")]),t._v(" file to use in our code.\nAdd the following imports at the start of "),s("code",[t._v("main.rs")])]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip32"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoincore_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcApi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet_name_from_descriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfigurableBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip39"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n")])])]),s("p",[t._v("With this we are now ready to add our wallet code.")]),t._v(" "),s("h2",{attrs:{id:"getting-descriptors"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#getting-descriptors"}},[t._v("#")]),t._v(" Getting Descriptors")]),t._v(" "),s("p",[t._v("BDK is a descriptor based wallet library. That means when we specify our wallet key-chain we need to tell BDK about it in the format of a descriptor. You can read up on descriptors more "),s("a",{attrs:{href:"https://bitcoindevkit.org/descriptors/",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(". A descriptor string looks like this\n"),s("code",[t._v("\"wpkh([b8b575c2/84'/1'/0'/0]tprv8icWtRzy9CWgFxpGMLSdAeE4wWyz39XGc6SwykeTo13tYm14JkVVQAf7jz8WDDarCgNJrG3aEPJEqchDWeJdiaWpS3FwbLB9SzsN57V7qxB/*)\"")]),t._v(".")]),t._v(" "),s("p",[t._v("This describes a SegwitV0 descriptor of a key derived at path "),s("code",[t._v("m/84'/1'/0'/0")]),t._v(". If you already have a descriptor from other sources, you can use that. Otherwise, BDK has your back. BDK can be used to generate a fresh master key with mnemonic, and then derive child keys from it given a specific path. Putting the key in a descriptor is as simple as wrapping it with a "),s("code",[t._v("wpkh()")]),t._v(" string.")]),t._v(" "),s("p",[t._v("We will use a dedicated function that will create fresh receive and change descriptors from BDK for our purpose. It will also generate the mnemonic word list for later regenerating the wallet. But we will ignore that for our scope.")]),t._v(" "),s("p",[t._v("Add a function named "),s("code",[t._v("get-descriptor()")]),t._v(" below the "),s("code",[t._v("main()")]),t._v(" function as shown")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generate fresh descriptor strings and return them via (receive, change) tuple")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a new secp context")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can also set a password to unlock the mnemonic")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"random password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate a fresh mnemonic, and from there a privatekey")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Words12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_extended_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_xprv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create derived privkey from the above master privkey")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We use the following derivation paths for receive and change keys")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// receive: "m/84h/1h/0h/0"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// change: "m/84h/1h/0h/1" ')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" keys "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fingerprint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv_desc_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n derived_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_descriptor_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wrap the derived key with the wpkh() string to produce a descriptor string")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" derived_xprv_desc_key "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wpkh("')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('")"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Return the keys as a tuple")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("To check that the above added function is working as expected, call it in the main function and print the descriptors")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"recv: {:#?}, \\nchng: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("Running the binary should produce the following result")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\nrecv: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"wpkh([89df6a67/84'/1'/0'/0]tprv8iSRXyLtTKJN9qt1jyPVqwhDMEaYztXunPaRQznaH1z8gj8e2g7RnF2ZoHP56VEXwMn76AiV1Je6nJmZbFistwAQCrRGmSrsoKfdqfTDNA1/*)\"")]),t._v(", \nchng: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v("\"wpkh([89df6a67/84'/1'/0'/1]tprv8iSRXyLtTKJNCECQxBJ19cgx2ueS7mC7GNq7VqTWY3RNPMBY7DfTb9HUnXpJqa14jCJNRmi4yGxfoTVS4WLBXDkvTLq4vujeAD9NfDtSxGP/*)\"")]),t._v("\n")])])]),s("p",[t._v("Voila! Now we have nice descriptors strings handy to use for our BDK wallet construction.")]),t._v(" "),s("h2",{attrs:{id:"talking-to-bitcoin-core-programmatically"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#talking-to-bitcoin-core-programmatically"}},[t._v("#")]),t._v(" Talking to Bitcoin Core Programmatically")]),t._v(" "),s("p",[t._v("Like all other tutorials we will use two wallets to send coins back and forth. A Bitcoin Core wallet accessible via "),s("code",[t._v("bitcoin-cli")]),t._v(" command line tools, and a BDK wallet maintained by BDK library.")]),t._v(" "),s("p",[t._v("But unlike other tutorials, we won't be using "),s("code",[t._v("bitcoin-cli")]),t._v(" to talk to the Core wallet (we can, but let's spice things up). Instead, we will use the "),s("code",[t._v("bitcoin-rpc")]),t._v(" library, to talk with our core node listening at "),s("code",[t._v("127.0.0.1:18443")]),t._v(", from inside our main function. This will allow us to write code, that will handle both the core and BDK wallet, from inside of the same function, and we won't have to switch terminals!")]),t._v(" "),s("p",[t._v("Remember we imported "),s("code",[t._v("use bdk::bitcoincore_rpc::{Auth as rpc_auth, Client, RpcApi};")]),t._v("? Thats exactly for this purpose.")]),t._v(" "),s("p",[t._v("Start the "),s("code",[t._v("bitcoind")]),t._v(" node.")]),t._v(" "),s("p",[t._v("you should see bitcoind listening at port 18443")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sudo")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("netstat")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-nptl")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("grep")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("18443")]),t._v(" \ntcp "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),t._v(".0.0:18443 "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.0")]),t._v(".0.0:* LISTEN "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("135532")]),t._v("/bitcoind \n")])])]),s("p",[t._v("Lets create a core rpc interface in our main function.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a RPC interface")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_rpc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://127.0.0.1:18443/wallet/test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_blockchain_info")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("We have provided our RPC authentication "),s("code",[t._v("username")]),t._v(" and "),s("code",[t._v("password")]),t._v(" (same as provided in "),s("code",[t._v("bitcoin.conf")]),t._v(" file).\nWe have provided the RPC address of our local bitcoin node, with the path to a wallet file, named "),s("code",[t._v("test")]),t._v(". And then asked the rpc client to give us the current blockchain info.\nIf everything goes well, running "),s("code",[t._v("cargo run")]),t._v(" you should see an output like below:")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\nGetBlockchainInfoResult "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n chain: "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"regtest"')]),t._v(",\n blocks: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(",\n headers: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(",\n best_block_hash: 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206,\n difficulty: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0.00000000046565423739069247")]),t._v(",\n median_time: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1296688602")]),t._v(",\n verification_progress: "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1.0")]),t._v(",\n initial_block_download: true,\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\n")])])]),s("p",[t._v("Thats it. Now we can programmatically talk to our core node.")]),t._v(" "),s("h2",{attrs:{id:"get-some-balance-in-core-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#get-some-balance-in-core-wallet"}},[t._v("#")]),t._v(" Get some balance in core wallet.")]),t._v(" "),s("p",[t._v("We have told our rpc client that we would use a wallet named "),s("code",[t._v("test")]),t._v(". But currently, our core node doesn't have such a wallet. So let's create the wallet and fund it with some test coins.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the test wallet ")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get a new address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_new_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate 101 blocks and use the above address as coinbase")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("101")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// fetch the new balance")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Show balance")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("This will create a wallet in bitcoin core named "),s("code",[t._v("test")]),t._v(". generate 101 blocks and use a new address from the wallet as coinbase wallet. Because required coinbase maturity in bitcoin is 100 blocks, by generating 101 blocks, we will have the balance of the first coinbase block reward available for use.\nThe last "),s("code",[t._v("println!()")]),t._v(" statement will show the new updated balance as 50 BTC.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),t._v(".\ncore balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("50.00000000")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" \n")])])]),s("p",[t._v("Great! We now have 50 regtest BTC to play with.")]),t._v(" "),s("h2",{attrs:{id:"setup-the-bdk-wallet"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#setup-the-bdk-wallet"}},[t._v("#")]),t._v(" Setup the BDK wallet")]),t._v(" "),s("p",[t._v("Now that we are done setting up the core wallet. The last remaining step is to setup the BDK wallet. For this we will use the previous descriptor generation function and write code as below.")]),t._v(" "),s("p",[s("strong",[t._v("Note")]),t._v(": You might want to comment out the previous code in "),s("code",[t._v("main()")]),t._v(", as running them again will create more coins in core, which isn't an issue, but might be confusing.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get receive and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use deterministic wallet name derived from descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("wallet_name_from_descriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the datadir to store wallet data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" datadir "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("dirs_next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("home_dir")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('".bdk-example"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" database "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" db_tree "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open_tree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC username, password and url")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n username"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" rpc_url "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1:18443"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Setup the RPC configuration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n skip_blocks"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the above configuration to create a RPC blockchain backend")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_config")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("rpc_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Combine everything and finally create the BDK wallet structure")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" db_tree"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"bdk address: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("That's a lot of code. They are divided into logical sections. Let's discuss each step one by one.")]),t._v(" "),s("ul",[s("li",[t._v("First we used our previous "),s("code",[t._v("get_descriptors()")]),t._v(" function to generate two descriptor strings. One for generating receive addresses and one for change addresses.")]),t._v(" "),s("li",[t._v("Then we used a special function from BDK called "),s("code",[t._v("wallet_name_from_descriptor()")]),t._v(" to derive a name of the wallet from our descriptors. This allows us to have wallet names deterministically linked with descriptors. So in future if we use a different descriptor, the wallet will automatically have a different name. This allows us to not mix wallet names with same descriptor, and given the descriptors we can always determine what was the name we used. It is recommended to derive wallet names like this while using a core backend. Note that this wallet will be created inside the core node. So just like we accessed the "),s("code",[t._v("test")]),t._v(" wallet, we could also access this wallet.")]),t._v(" "),s("li",[t._v("Then we created a data directory at path "),s("code",[t._v("/home/username/.bdk-example")]),t._v(". We use "),s("code",[t._v("dirs_next")]),t._v(" to find our home path, and then appended that with "),s("code",[t._v(".bdk-example")]),t._v(". All the BDK wallet files will be created and maintained in that directory. In the Database we instructed BDK to create a new "),s("code",[t._v("Tree")]),t._v(" with "),s("code",[t._v("wallet_name")]),t._v(", so given a descriptor, BDK will always know which DB Tree to refer ("),s("code",[t._v("Tree")]),t._v(" is a "),s("code",[t._v("sled")]),t._v(" specific term).")]),t._v(" "),s("li",[t._v("Then like we did previously, we created the rpc username/password authentication, and specified the rpc url. Note that we cannot use the same "),s("code",[t._v("rpc_auth")]),t._v(" we used before for "),s("code",[t._v("core_rpc")]),t._v(" as BDK auth and bitcoin-rpc auth are slightly separate structures.")]),t._v(" "),s("li",[t._v("We combined all this information and created an "),s("code",[t._v("RpcConfig")]),t._v(" structure.")]),t._v(" "),s("li",[t._v("We used the rpc configuration to create a "),s("code",[t._v("RpcBlockchain")]),t._v(" structure.")]),t._v(" "),s("li",[t._v("Finally we used the Descriptors, Database, and Blockchain to create our final BDK "),s("code",[t._v("wallet")]),t._v(" structure.")])]),t._v(" "),s("p",[t._v("Now that we have our wallet cooked, in the end, we instructed it to sync with the bitcoin core backend, and fetch us a new address.")]),t._v(" "),s("p",[t._v("If all goes well, you should see an address printed in the terminal.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(".99s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\nbdk address: bcrt1q9vkmujggvzs0rd4z6069v3v0jucje7ua7ap308\n")])])]),s("h2",{attrs:{id:"sending-sats-around"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#sending-sats-around"}},[t._v("#")]),t._v(" Sending Sats Around")]),t._v(" "),s("p",[t._v("Now that we have covered all the groundwork, we have all we need to send coins back and forth between core and BDK wallet.")]),t._v(" "),s("p",[t._v("We will keep things simple here and make the following actions")]),t._v(" "),s("ul",[s("li",[t._v("Send 10 BTC from Core to BDK")]),t._v(" "),s("li",[t._v("Send back 5 BTC from BDK to Core")]),t._v(" "),s("li",[t._v("Display balance of two wallets")])]),t._v(" "),s("p",[t._v("In the last line of previous section we got a new address from BDK wallet. We will start from there. Without further discussion lets jump straight into code.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("...")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Send 10 BTC from Core to BDK")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_btc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a transaction builder")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" tx_builder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set recipient of the transaction")]),t._v("\n tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_recipients")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500000000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finalise the transaction and extract PSBT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set signing option")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signopt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n assume_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sign the above psbt with signing option")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signopt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Extract the final transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Broadcast the transaction")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch and display wallet balances")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bdk_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_sat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"BDK wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bdk_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v("The above code segment is mostly straightforward. The only new thing added is "),s("code",[t._v("wallet.build_tx()")]),t._v(" which returns a "),s("code",[t._v("TxBuilder")]),t._v(". BDK allows us to have very fine grained control of cooking up transactions. Almost everything that is possible to do with a Bitcoin transaction can be done in BDK. Here we have a very simple vanilla transaction with no added magic. To get full list of capabilities that "),s("code",[t._v("TxBuilder")]),t._v(" supports scour its implementation "),s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk/blob/38d1d0b0e29d38cd370c740d798d96a3c9fcaa1f/src/wallet/tx_builder.rs#L123-L153",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),s("OutboundLink")],1),t._v(".")]),t._v(" "),s("p",[t._v("Finally to step through what we did above:")]),t._v(" "),s("ul",[s("li",[t._v("We asked core wallet to send 10 BTC to bdk wallet address.")]),t._v(" "),s("li",[t._v("We confirmed the transaction, and synced the wallet.")]),t._v(" "),s("li",[t._v("We asked BDK to create a transaction sending 5 BTC to core wallet address.")]),t._v(" "),s("li",[t._v("We signed and broadcast the transaction. BDK will use the same core node to broadcast the transaction to network.")]),t._v(" "),s("li",[t._v("We confirmed the transaction by mining a block, and synced the wallet.")]),t._v(" "),s("li",[t._v("We fetched and displayed balance of both core and BDK wallet.")])]),t._v(" "),s("p",[t._v("If all goes well, you should see the final updated balance as below:")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" run\n Compiling bdk-example v0.1.0 "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("/home/raj/github-repo/bdk-example/bdk-example"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n Finished dev "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("unoptimized + debuginfo"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" target"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("s"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(".57s\n Running "),s("span",{pre:!0,attrs:{class:"token variable"}},[s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")]),t._v("target/debug/bdk-example"),s("span",{pre:!0,attrs:{class:"token variable"}},[t._v("`")])]),t._v("\ncore wallet balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("144.99998590")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\nBDK wallet balance: Amount"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("4.99999859")]),t._v(" BTC"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),s("p",[t._v("Voila! We have ~145 BTC (150 - 5) in core wallet and 5 BTC (10 - 5) in BDK wallet. The slight deficiency in the amount are due to transaction fees. Because we are using regtest, the fee is some standard value hardcoded in core node.")]),t._v(" "),s("p",[t._v("Check out the data directory where BDK has created the wallet data files.")]),t._v(" "),s("div",{staticClass:"language-shell extra-class"},[s("pre",{pre:!0,attrs:{class:"language-shell"}},[s("code",[t._v("$ "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("ls")]),t._v(" ~/.bdk-example/\nblobs conf db snap.0000000000023CAB\n")])])]),s("p",[t._v("And finally, this is what the final "),s("code",[t._v("main.rs")]),t._v(" file looks like.")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("secp256k1"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("util"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip32"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bitcoincore_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("as")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcApi")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" wallet_name_from_descriptor"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ConfigurableBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("bip39"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivableKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("miniscript"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("signer"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("bdk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("use")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("std"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("FromStr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("main")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a RPC interface")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v(" \n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_rpc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Client")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://127.0.0.1:18443/wallet/test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" rpc_auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the test wallet ")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("create_wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"test"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get a new address")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_new_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate 101 blocks and use the above address as coinbase")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("101")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Get receive and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use deterministic wallet name derived from descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet_name "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("wallet_name_from_descriptor")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create the datadir to store wallet data")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" datadir "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("dirs_next"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("home_dir")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('".bdk-example"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" database "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sled"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("datadir"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" db_tree "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" database"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("open_tree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC username and password")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" auth "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Auth")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("UserPass")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n username"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"admin"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set RPC url")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" rpc_url "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"http://"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"127.0.0.1:18443"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Setup the RPC configuration")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" rpc_config "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcConfig")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" rpc_url"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n auth"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n network"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n wallet_name"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n skip_blocks"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Use the above configuration to create a RPC blockchain backend")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" blockchain "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("RpcBlockchain")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_config")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("rpc_config"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Combine everything and finally create the BDK wallet structure")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" wallet "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Wallet")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("receive_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("change_desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" db_tree"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" blockchain"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch a fresh address to receive coins")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" address "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("AddressIndex")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("New")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Send 10 BTC from Core to BDK")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("send_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_btc")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10.0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a transaction builder")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" tx_builder "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("build_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set recipient of the transaction")]),t._v("\n tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("set_recipients")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("vec!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("500000000")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Finalise the transaction and extract PSBT")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" tx_builder"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("finish")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Set signing option")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" signopt "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("SignOptions")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n assume_height"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sign the above psbt with signing option")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sign")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" signopt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Extract the final transaction")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" tx "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" psbt"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("extract_tx")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Broadcast the transaction")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("broadcast")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("tx"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Confirm transaction by generating some blocks")]),t._v("\n core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate_to_address")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("core_address"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Sync the BDK wallet")]),t._v("\n wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("sync")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NoopProgress")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Fetch and display wallet balances")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" core_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" core_rpc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("None")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" bdk_balance "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Amount")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_sat")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("wallet"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("get_balance")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"core wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" core_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token macro property"}},[t._v("println!")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"BDK wallet balance: {:#?}"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" bdk_balance"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// generate fresh descriptor strings and return them via (receive, change) tupple ")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("get_descriptors")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("String")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Create a new secp context")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" secp "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secp256k1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// You can also set a password to unlock the mnemonic")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" password "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"random password"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Generate a fresh menmonic, and from their, a fresh private key xprv")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("GeneratedKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("_"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Mnemonic")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("generate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("MnemonicType")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Words12")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Language")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("English")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" mnemonic "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ExtendedKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("mnemonic"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" password"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_extended_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" xkey"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_xprv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Network")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Regtest")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Derive our descriptors to use")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// We use the following paths for recieve and change descriptor")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// recieve: "m/84h/1h/0h/0"')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v('// change: "m/84h/1h/0h/1" ')]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" keys "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Vec")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" path "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("in")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/0"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m/84h/1h/0h/1"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("derive_priv")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("KeySource")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fingerprint")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("secp"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" deriv_path"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" derived_xprv_desc_key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DescriptorKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Segwitv0")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n derived_xprv"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_descriptor_key")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Some")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("origin"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivationPath")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("default")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("unwrap")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Wrap the derived key with the wpkh() string to produce a descriptor string")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("if")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Secret")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" _"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" derived_xprv_desc_key "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("let")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("mut")]),t._v(" desc "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"wpkh("')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("key"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_string")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push_str")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('")"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("push")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("desc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n \n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("// Return the keys as a tupple")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" keys"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("clone")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"conclusion"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[t._v("#")]),t._v(" Conclusion")]),t._v(" "),s("p",[t._v("In this tutorial we saw some very basic BDK wallet functionality with a bitcoin core backend as the source and sync of blockchain data. This is just tip of the iceberg of BDK capabilities. BDK allows flexibility in all the dimensions of a bitcoin wallet, that is key chain, blockchain backend and database management. With all that power, we just implemented a trustless, non-custodial, private bitcoin wallet, backed by a bitcoin full node, with less than 200 lines of code (including lots of comments).")]),t._v(" "),s("p",[t._v("BDK thus allows wallet devs, to only focus on stuff that they care about, writing wallet logic. All the backend stuff like blockchain, key management, and databases are abstracted away under the hood.")]),t._v(" "),s("p",[t._v("To find and explore more about the BDK capabilities and how it can fit your development need refer the following resources.")]),t._v(" "),s("ul",[s("li",[s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[t._v("source code"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://docs.rs/bdk/latest/bdk/",target:"_blank",rel:"noopener noreferrer"}},[t._v("dev docs"),s("OutboundLink")],1)]),t._v(" "),s("li",[s("a",{attrs:{href:"https://discord.com/invite/d7NkDKm",target:"_blank",rel:"noopener noreferrer"}},[t._v("community"),s("OutboundLink")],1)])])])}),[],!1,null,null,null);s.default=e.exports}}]); \ No newline at end of file diff --git a/assets/js/40.578db781.js b/assets/js/40.40d30668.js similarity index 99% rename from assets/js/40.578db781.js rename to assets/js/40.40d30668.js index 0051d28d33..9e2c066643 100644 --- a/assets/js/40.578db781.js +++ b/assets/js/40.40d30668.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{388:function(t,e,s){"use strict";s.r(e);var a=s(7),r=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h2",{attrs:{id:"2-of-3-multi-signature-descriptor-wallet-using-bdk-cli"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2-of-3-multi-signature-descriptor-wallet-using-bdk-cli"}},[t._v("#")]),t._v(" 2-of-3 Multi-Signature Descriptor Wallet using bdk-cli")]),t._v(" "),e("h2",{attrs:{id:"overview-of-the-tutorial"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#overview-of-the-tutorial"}},[t._v("#")]),t._v(" Overview of the tutorial")]),t._v(" "),e("ul",[e("li",[t._v("The purpose of this tutorial is to continue learning "),e("code",[t._v("bdk-cli")]),t._v(" as our tool to manage a 2 of 3 multi-signature wallet.")]),t._v(" "),e("li",[t._v("Generate a receive address with a spending Policy of 2 out of 3 escrow aka multi-signature.")]),t._v(" "),e("li",[t._v("Intro to more complex but standard policies to create custom encumberances aka custom spending conditions for transactions.")])]),t._v(" "),e("p",[t._v("Note that to complete this tutorial, you'll need to enable the "),e("code",[t._v("compiler")]),t._v(" and "),e("code",[t._v("electrum")]),t._v(" flags when installing or building bdk-cli, for example by installing using:")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" bdk-cli "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--features")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("compiler,electrum\n")])])]),e("h2",{attrs:{id:"step-1-generate-the-xprvs-extended-keys-and-save-to-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-1-generate-the-xprvs-extended-keys-and-save-to-environment-variables"}},[t._v("#")]),t._v(" Step 1: Generate the XPRVs (Extended-Keys) and Save to environment variables")]),t._v(" "),e("blockquote",[e("p",[t._v("Create three private keys and each in their own environment variable")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_00=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_01=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_02=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/FwgUdwK.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"1a-verify-xprv-environment-variables-are-active"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#1a-verify-xprv-environment-variables-are-active"}},[t._v("#")]),t._v(" 1a: Verify XPRV environment variables are Active")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep XPRV")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/ZerGPbO.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-2-generate-xpubs-extended-public-keys-save-to-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-2-generate-xpubs-extended-public-keys-save-to-environment-variables"}},[t._v("#")]),t._v(" Step 2: Generate XPUBs (Extended Public Keys) & Save to environment variables")]),t._v(" "),e("blockquote",[e("p",[t._v("Generate the three individual Public Keys aka XPUBs using our Private key and descriptor path.")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_00=$(bdk-cli key derive --xprv $XPRV_00 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_01=$(bdk-cli key derive --xprv $XPRV_01 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_02=$(bdk-cli key derive --xprv $XPRV_02 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/xT3KRh4.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"2a-verify-xpub-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2a-verify-xpub-environment-variables"}},[t._v("#")]),t._v(" 2a: Verify XPUB environment variables")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep XPUB")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/SzAip9E.gif",alt:""}})]),t._v(" "),e("hr"),t._v(" "),e("h2",{attrs:{id:"step-3-create-single-wallet-descriptors"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-3-create-single-wallet-descriptors"}},[t._v("#")]),t._v(" Step 3: Create Single-Wallet Descriptors")]),t._v(" "),e("blockquote",[e("p",[t._v("Create the wallet Descriptor for each wallet")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_00="$XPRV_00/84h/1h/0h/0/*"')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_01="$XPRV_01/84h/1h/0h/0/*"')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_02="$XPRV_02/84h/1h/0h/0/*"')])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/mFrWt6b.png",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-4-create-multi-sig-descriptor-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-4-create-multi-sig-descriptor-wallets"}},[t._v("#")]),t._v(" Step 4: Create Multi-Sig-Descriptor Wallets")]),t._v(" "),e("blockquote",[e("p",[t._v("This is how you create the 2-of-3 multi-sig output descriptor. You will need (one PrivateKey and two Xpubs) It consists of using the "),e("code",[t._v("compiler")]),t._v(" function to parse "),e("code",[t._v("policy")]),t._v(" to "),e("code",[t._v("mini-script")]),t._v(" .")])]),t._v(" "),e("ul",[e("li",[t._v("When creating the descriptor the order matters so be aware of that when following tutorial if you are for any reason changing the order of the policy.")])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-0"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-0"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 0")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_00=$(bdk-cli compile \"thresh(2,pk($DESCRIPTOR_00),pk($XPUB_01),pk($XPUB_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-1"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 1")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_01=$(bdk-cli compile \"thresh(2,pk($XPUB_00),pk($DESCRIPTOR_01),pk($XPUB_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-2"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 2")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_02=$(bdk-cli compile \"thresh(2,pk($XPUB_00),pk($XPUB_01),pk($DESCRIPTOR_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/Yb8RmFS.gif",alt:""}})]),t._v(" "),e("h4",{attrs:{id:"multi-sig-2-of-3-policy-gets-compiled-to-miniscript"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-2-of-3-policy-gets-compiled-to-miniscript"}},[t._v("#")]),t._v(" multi-sig 2 of 3 policy gets compiled to miniscript")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# policy")]),t._v("\nthresh"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPRV_A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPUB_B"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPUB_C"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("))")]),t._v(" \n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# miniscript")]),t._v("\nwsh"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("multi"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",XPRV_KEY,PUBKEY_B,XPUB_C"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("))")]),t._v("\n")])])]),e("hr"),t._v(" "),e("h3",{attrs:{id:"4a-verify-multi-sig-descriptor-environment-variables-are-active"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#4a-verify-multi-sig-descriptor-environment-variables-are-active"}},[t._v("#")]),t._v(" 4a: Verify Multi-Sig-Descriptor environment variables are active")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep MULTI")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/aAgtlsi.gif",alt:""}})]),t._v(" "),e("hr"),t._v(" "),e("h2",{attrs:{id:"step-5-generate-receive-address-by-using-multi-sig-descriptor-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-5-generate-receive-address-by-using-multi-sig-descriptor-wallets"}},[t._v("#")]),t._v(" Step 5: Generate Receive Address by using Multi-Sig-Descriptor Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 get_new_address")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 get_new_address")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd02 --descriptor $MULTI_DESCRIPTOR_02 get_new_address")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/w1fxPSn.gif",alt:""}})]),t._v(" "),e("p",[t._v("🔴 Did you generate the same address for all three? Good! Else, something might be incorrect.")]),t._v(" "),e("h2",{attrs:{id:"step-6-send-testnet-bitcoin-to-the-newly-created-receive-address"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-6-send-testnet-bitcoin-to-the-newly-created-receive-address"}},[t._v("#")]),t._v(" Step 6: Send Testnet Bitcoin to the newly created receive-address")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://testnet-faucet.mempool.co",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Testnet Faucet link:1"),e("OutboundLink")],1),t._v(" "),e("a",{attrs:{href:"https://bitcoinfaucet.uo1.net",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Testnet Faucet link:2"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"step-7-sync-one-of-the-multi-sig-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-7-sync-one-of-the-multi-sig-wallets"}},[t._v("#")]),t._v(" Step 7: Sync one of the Multi-Sig Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sync")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/GuefgeI.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-8-check-balance-multi-sig-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-8-check-balance-multi-sig-wallets"}},[t._v("#")]),t._v(" Step 8: Check Balance Multi-Sig Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 get_balance")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/zNciCqF.gif",alt:""}})]),t._v(" "),e("ul",[e("li",[t._v("Every wallet has access to sync and view balance.")])]),t._v(" "),e("h2",{attrs:{id:"step-9-check-multi-sig-policies-on-descriptor-wallet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-9-check-multi-sig-policies-on-descriptor-wallet"}},[t._v("#")]),t._v(" Step 9: Check Multi-Sig Policies on Descriptor Wallet")]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 policies")])]),t._v(" "),e("p",[t._v("The output below confirms the command was successful.")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"external"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"contribution"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"conditions"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"items"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"n"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sorted"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" false,\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARTIAL"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"seaxtqqn"')]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"keys"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"7cdf2d46"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fc7870cd"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"26b03333"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"satisfaction"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"items"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"n"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sorted"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" false,\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARTIAL"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"threshold"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"MULTISIG"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"internal"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" null\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n")])])]),e("h3",{attrs:{id:"spendingpolicyrequired-for-complex-descriptors"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#spendingpolicyrequired-for-complex-descriptors"}},[t._v("#")]),t._v(" SpendingPolicyRequired for complex descriptors")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--external_policy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{'),e("span",{pre:!0,attrs:{class:"token entity",title:'\\"'}},[t._v('\\"')]),t._v("seaxtqqn"),e("span",{pre:!0,attrs:{class:"token entity",title:'\\"'}},[t._v('\\"')]),t._v(': [0,1]}"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("-rootnode-"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("children "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#0 and #1 of root node>")]),t._v("\n")])])]),e("blockquote",[e("p",[t._v("Save the \"id\": We will need to use this ''id'' later.")])]),t._v(" "),e("p",[t._v("More info on "),e("a",{attrs:{href:"https://bitcoindevkit.org/bdk-cli/interface/",target:"_blank",rel:"noopener noreferrer"}},[t._v("external policies here"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"step-10-create-a-transaction-psbt"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-10-create-a-transaction-psbt"}},[t._v("#")]),t._v(" Step 10: Create a Transaction (PSBT)")]),t._v(" "),e("ul",[e("li",[t._v("1st Create a PSBT using the first wallet")]),t._v(" "),e("li",[t._v("2nd Sign the PSBT with the first wallet")]),t._v(" "),e("li",[t._v("3rd Sign PSBT with the second wallet")]),t._v(" "),e("li",[t._v("Broadcast PSBT")])]),t._v(" "),e("h3",{attrs:{id:"export-unsigned-psbt-to-environment-variable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#export-unsigned-psbt-to-environment-variable"}},[t._v("#")]),t._v(" Export UNSIGNED_PSBT to environment variable")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export UNSIGNED_PSBT=$(bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 create_tx --send_all --to mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt:0 --external_policy "{\\"CHANGE_ID_HERE\\": [0,1]}" | jq -r \'.psbt\')')])]),t._v(" "),e("h3",{attrs:{id:"verify-unsigned-psbt-environment-variable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#verify-unsigned-psbt-environment-variable"}},[t._v("#")]),t._v(" Verify UNSIGNED_PSBT environment variable")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep UNSIGNED")]),t._v(" "),e("img",{attrs:{src:"https://i.imgur.com/djHaRDq.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-11-sign-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-11-sign-the-transaction"}},[t._v("#")]),t._v(" Step 11: SIGN the Transaction")]),t._v(" "),e("h3",{attrs:{id:"1st-wallet-signs-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#1st-wallet-signs-the-transaction"}},[t._v("#")]),t._v(" 1st Wallet Signs the transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sign --psbt $UNSIGNED_PSBT")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export ONESIG_PSBT=$(bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sign --psbt $UNSIGNED_PSBT | jq -r '.psbt')")])]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("env | grep ONESIG")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "is_finalized": false,\n "psbt": "cHNidP8BAFUBAAAAAdYCtva/7Rkt+fgFu3mxAdaPh4uTbgBL3HmYZgcEKWygAAAAAAD/////AQqGAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA6gIAAAAAAQFLyGFJFK884DGBM1WgskRZ6gKp/7oZ+Z30u0+wF3pZYAEAAAAA/v///wKghgEAAAAAACIAINHcOQLE6GpJ3J+FOzn/be+HApxW8sZtGqfA3TBW+NYX91hoOAAAAAAWABTPQDZx2wYYIn+ug2pZBmWBn0Tu/gJHMEQCIHu6GmRMDgPZyTx+klFMA9VujR3qDA/Y08kSkRvOaChjAiBAtExtGAYLuQ/DDJzCqLlNZ1bMB3MV+nxsLfTdI9YcYwEhA0b8lz+kt0xHfR/tjUKOc2Nt2L61pDd5vJ/lsKi8pw9MmFUjAAEBK6CGAQAAAAAAIgAg0dw5AsToakncn4U7Of9t74cCnFbyxm0ap8DdMFb41hciAgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDUgwRQIhAJdILr7G3UzYylyr2fA13MFsz/jG4+iZlKeEkX79d082AiA99UF0/uFyXBVNUmuGaxdHL7wlhzqfbgGLMREN0z/O6QEBBWlSIQIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDSEDzsDXexRPSxeXiLJoS0i2fQlOoOGHmo+Dhaeaq3oHV6YhAjGKA2Dqg+QeMICBAifYslQF2WrehLEQ0iEOpp/+eQ0NU64iBgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDRh83y1GVAAAgAEAAIAAAACAAAAAAAAAAAAiBgIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDRgmsDMzVAAAgAEAAIAAAACAAAAAAAAAAAAiBgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXphj8eHDNVAAAgAEAAIAAAACAAAAAAAAAAAAAAA=="\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/0w4sK5y.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"2nd-wallet-signs-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2nd-wallet-signs-the-transaction"}},[t._v("#")]),t._v(" 2nd Wallet Signs the transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 sign --psbt $ONESIG_PSBT")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export SECONDSIG_PSBT=$(bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 sign --psbt $ONESIG_PSBT | jq -r '.psbt')")])]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("env | grep SECONDSIG")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "is_finalized": true,\n "psbt": "cHNidP8BAFUBAAAAAdYCtva/7Rkt+fgFu3mxAdaPh4uTbgBL3HmYZgcEKWygAAAAAAD/////AQqGAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA6gIAAAAAAQFLyGFJFK884DGBM1WgskRZ6gKp/7oZ+Z30u0+wF3pZYAEAAAAA/v///wKghgEAAAAAACIAINHcOQLE6GpJ3J+FOzn/be+HApxW8sZtGqfA3TBW+NYX91hoOAAAAAAWABTPQDZx2wYYIn+ug2pZBmWBn0Tu/gJHMEQCIHu6GmRMDgPZyTx+klFMA9VujR3qDA/Y08kSkRvOaChjAiBAtExtGAYLuQ/DDJzCqLlNZ1bMB3MV+nxsLfTdI9YcYwEhA0b8lz+kt0xHfR/tjUKOc2Nt2L61pDd5vJ/lsKi8pw9MmFUjAAEBK6CGAQAAAAAAIgAg0dw5AsToakncn4U7Of9t74cCnFbyxm0ap8DdMFb41hciAgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDUgwRQIhAJdILr7G3UzYylyr2fA13MFsz/jG4+iZlKeEkX79d082AiA99UF0/uFyXBVNUmuGaxdHL7wlhzqfbgGLMREN0z/O6QEiAgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXpkgwRQIhAO2aRERcublhAzToshkZRMg2I8GaE7mM2ECr0vYyuscmAiB5KK4ETlvrLqL0QbcRbGqrSwIa9lVuOqP3f5qCnGRMaQEBBWlSIQIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDSEDzsDXexRPSxeXiLJoS0i2fQlOoOGHmo+Dhaeaq3oHV6YhAjGKA2Dqg+QeMICBAifYslQF2WrehLEQ0iEOpp/+eQ0NU64iBgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDRh83y1GVAAAgAEAAIAAAACAAAAAAAAAAAAiBgIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDRgmsDMzVAAAgAEAAIAAAACAAAAAAAAAAAAiBgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXphj8eHDNVAAAgAEAAIAAAACAAAAAAAAAAAABBwABCP3+AAQASDBFAiEAl0guvsbdTNjKXKvZ8DXcwWzP+Mbj6JmUp4SRfv13TzYCID31QXT+4XJcFU1Sa4ZrF0cvvCWHOp9uAYsxEQ3TP87pAUgwRQIhAO2aRERcublhAzToshkZRMg2I8GaE7mM2ECr0vYyuscmAiB5KK4ETlvrLqL0QbcRbGqrSwIa9lVuOqP3f5qCnGRMaQFpUiECI1AiHZ8q+qw7bjYVTbeGQQ3L2C2sH6CW82z8sXP1jQ0hA87A13sUT0sXl4iyaEtItn0JTqDhh5qPg4Wnmqt6B1emIQIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDVOuAAA="\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/OdLHnJ3.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-12-broadcast-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-12-broadcast-transaction"}},[t._v("#")]),t._v(" Step 12: Broadcast Transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 broadcast --psbt $SECONDSIG_PSBT")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "txid": "61da2451874a483aa8d1d0787c7680d157639f284840de8885098cac43f6cc2f"\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/M7s0Fd6.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"verify-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#verify-transaction"}},[t._v("#")]),t._v(" Verify Transaction")]),t._v(" "),e("p",[t._v("Verify transcation in the memory pool on testnet "),e("a",{attrs:{href:"https://mempool.space/testnet",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mempool-testnet!"),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{385:function(t,e,s){"use strict";s.r(e);var a=s(7),r=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h2",{attrs:{id:"2-of-3-multi-signature-descriptor-wallet-using-bdk-cli"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2-of-3-multi-signature-descriptor-wallet-using-bdk-cli"}},[t._v("#")]),t._v(" 2-of-3 Multi-Signature Descriptor Wallet using bdk-cli")]),t._v(" "),e("h2",{attrs:{id:"overview-of-the-tutorial"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#overview-of-the-tutorial"}},[t._v("#")]),t._v(" Overview of the tutorial")]),t._v(" "),e("ul",[e("li",[t._v("The purpose of this tutorial is to continue learning "),e("code",[t._v("bdk-cli")]),t._v(" as our tool to manage a 2 of 3 multi-signature wallet.")]),t._v(" "),e("li",[t._v("Generate a receive address with a spending Policy of 2 out of 3 escrow aka multi-signature.")]),t._v(" "),e("li",[t._v("Intro to more complex but standard policies to create custom encumberances aka custom spending conditions for transactions.")])]),t._v(" "),e("p",[t._v("Note that to complete this tutorial, you'll need to enable the "),e("code",[t._v("compiler")]),t._v(" and "),e("code",[t._v("electrum")]),t._v(" flags when installing or building bdk-cli, for example by installing using:")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token function"}},[t._v("cargo")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" bdk-cli "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--features")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("compiler,electrum\n")])])]),e("h2",{attrs:{id:"step-1-generate-the-xprvs-extended-keys-and-save-to-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-1-generate-the-xprvs-extended-keys-and-save-to-environment-variables"}},[t._v("#")]),t._v(" Step 1: Generate the XPRVs (Extended-Keys) and Save to environment variables")]),t._v(" "),e("blockquote",[e("p",[t._v("Create three private keys and each in their own environment variable")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_00=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_01=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export XPRV_02=$(bdk-cli key generate | jq -r '.xprv')")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/FwgUdwK.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"1a-verify-xprv-environment-variables-are-active"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#1a-verify-xprv-environment-variables-are-active"}},[t._v("#")]),t._v(" 1a: Verify XPRV environment variables are Active")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep XPRV")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/ZerGPbO.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-2-generate-xpubs-extended-public-keys-save-to-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-2-generate-xpubs-extended-public-keys-save-to-environment-variables"}},[t._v("#")]),t._v(" Step 2: Generate XPUBs (Extended Public Keys) & Save to environment variables")]),t._v(" "),e("blockquote",[e("p",[t._v("Generate the three individual Public Keys aka XPUBs using our Private key and descriptor path.")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_00=$(bdk-cli key derive --xprv $XPRV_00 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_01=$(bdk-cli key derive --xprv $XPRV_01 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export XPUB_02=$(bdk-cli key derive --xprv $XPRV_02 --path "m/84\'/1\'/0\'/0" | jq -r ".xpub")')])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/xT3KRh4.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"2a-verify-xpub-environment-variables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2a-verify-xpub-environment-variables"}},[t._v("#")]),t._v(" 2a: Verify XPUB environment variables")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep XPUB")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/SzAip9E.gif",alt:""}})]),t._v(" "),e("hr"),t._v(" "),e("h2",{attrs:{id:"step-3-create-single-wallet-descriptors"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-3-create-single-wallet-descriptors"}},[t._v("#")]),t._v(" Step 3: Create Single-Wallet Descriptors")]),t._v(" "),e("blockquote",[e("p",[t._v("Create the wallet Descriptor for each wallet")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_00="$XPRV_00/84h/1h/0h/0/*"')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_01="$XPRV_01/84h/1h/0h/0/*"')])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export DESCRIPTOR_02="$XPRV_02/84h/1h/0h/0/*"')])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/mFrWt6b.png",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-4-create-multi-sig-descriptor-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-4-create-multi-sig-descriptor-wallets"}},[t._v("#")]),t._v(" Step 4: Create Multi-Sig-Descriptor Wallets")]),t._v(" "),e("blockquote",[e("p",[t._v("This is how you create the 2-of-3 multi-sig output descriptor. You will need (one PrivateKey and two Xpubs) It consists of using the "),e("code",[t._v("compiler")]),t._v(" function to parse "),e("code",[t._v("policy")]),t._v(" to "),e("code",[t._v("mini-script")]),t._v(" .")])]),t._v(" "),e("ul",[e("li",[t._v("When creating the descriptor the order matters so be aware of that when following tutorial if you are for any reason changing the order of the policy.")])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-0"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-0"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 0")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_00=$(bdk-cli compile \"thresh(2,pk($DESCRIPTOR_00),pk($XPUB_01),pk($XPUB_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-1"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 1")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_01=$(bdk-cli compile \"thresh(2,pk($XPUB_00),pk($DESCRIPTOR_01),pk($XPUB_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("h4",{attrs:{id:"multi-sig-wallet-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-wallet-2"}},[t._v("#")]),t._v(" Multi-Sig-Wallet 2")]),t._v(" "),e("ul",[e("li",[t._v("[ ] ▶️ "),e("code",[t._v("export MULTI_DESCRIPTOR_02=$(bdk-cli compile \"thresh(2,pk($XPUB_00),pk($XPUB_01),pk($DESCRIPTOR_02))\" | jq -r '.descriptor')")])])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/Yb8RmFS.gif",alt:""}})]),t._v(" "),e("h4",{attrs:{id:"multi-sig-2-of-3-policy-gets-compiled-to-miniscript"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#multi-sig-2-of-3-policy-gets-compiled-to-miniscript"}},[t._v("#")]),t._v(" multi-sig 2 of 3 policy gets compiled to miniscript")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# policy")]),t._v("\nthresh"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPRV_A"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPUB_B"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(",pk"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("XPUB_C"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("))")]),t._v(" \n\n"),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("# miniscript")]),t._v("\nwsh"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("multi"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",XPRV_KEY,PUBKEY_B,XPUB_C"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("))")]),t._v("\n")])])]),e("hr"),t._v(" "),e("h3",{attrs:{id:"4a-verify-multi-sig-descriptor-environment-variables-are-active"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#4a-verify-multi-sig-descriptor-environment-variables-are-active"}},[t._v("#")]),t._v(" 4a: Verify Multi-Sig-Descriptor environment variables are active")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep MULTI")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/aAgtlsi.gif",alt:""}})]),t._v(" "),e("hr"),t._v(" "),e("h2",{attrs:{id:"step-5-generate-receive-address-by-using-multi-sig-descriptor-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-5-generate-receive-address-by-using-multi-sig-descriptor-wallets"}},[t._v("#")]),t._v(" Step 5: Generate Receive Address by using Multi-Sig-Descriptor Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 get_new_address")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 get_new_address")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd02 --descriptor $MULTI_DESCRIPTOR_02 get_new_address")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/w1fxPSn.gif",alt:""}})]),t._v(" "),e("p",[t._v("🔴 Did you generate the same address for all three? Good! Else, something might be incorrect.")]),t._v(" "),e("h2",{attrs:{id:"step-6-send-testnet-bitcoin-to-the-newly-created-receive-address"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-6-send-testnet-bitcoin-to-the-newly-created-receive-address"}},[t._v("#")]),t._v(" Step 6: Send Testnet Bitcoin to the newly created receive-address")]),t._v(" "),e("p",[e("a",{attrs:{href:"https://testnet-faucet.mempool.co",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Testnet Faucet link:1"),e("OutboundLink")],1),t._v(" "),e("a",{attrs:{href:"https://bitcoinfaucet.uo1.net",target:"_blank",rel:"noopener noreferrer"}},[t._v("Bitcoin Testnet Faucet link:2"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"step-7-sync-one-of-the-multi-sig-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-7-sync-one-of-the-multi-sig-wallets"}},[t._v("#")]),t._v(" Step 7: Sync one of the Multi-Sig Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sync")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/GuefgeI.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-8-check-balance-multi-sig-wallets"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-8-check-balance-multi-sig-wallets"}},[t._v("#")]),t._v(" Step 8: Check Balance Multi-Sig Wallets")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 get_balance")])]),t._v(" "),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/zNciCqF.gif",alt:""}})]),t._v(" "),e("ul",[e("li",[t._v("Every wallet has access to sync and view balance.")])]),t._v(" "),e("h2",{attrs:{id:"step-9-check-multi-sig-policies-on-descriptor-wallet"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-9-check-multi-sig-policies-on-descriptor-wallet"}},[t._v("#")]),t._v(" Step 9: Check Multi-Sig Policies on Descriptor Wallet")]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 policies")])]),t._v(" "),e("p",[t._v("The output below confirms the command was successful.")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"external"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"contribution"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"conditions"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"0"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"items"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"n"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sorted"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" false,\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARTIAL"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"id"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"seaxtqqn"')]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"keys"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"7cdf2d46"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fc7870cd"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"fingerprint"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"26b03333"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"satisfaction"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"items"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"m"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"n"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"sorted"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" false,\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"PARTIAL"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"threshold"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"type"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"MULTISIG"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v(",\n "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"internal"')]),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(":")]),t._v(" null\n"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n\n")])])]),e("h3",{attrs:{id:"spendingpolicyrequired-for-complex-descriptors"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#spendingpolicyrequired-for-complex-descriptors"}},[t._v("#")]),t._v(" SpendingPolicyRequired for complex descriptors")]),t._v(" "),e("div",{staticClass:"language-shell extra-class"},[e("pre",{pre:!0,attrs:{class:"language-shell"}},[e("code",[e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("--external_policy")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"{'),e("span",{pre:!0,attrs:{class:"token entity",title:'\\"'}},[t._v('\\"')]),t._v("seaxtqqn"),e("span",{pre:!0,attrs:{class:"token entity",title:'\\"'}},[t._v('\\"')]),t._v(': [0,1]}"')]),t._v("\n "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("-rootnode-"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("children "),e("span",{pre:!0,attrs:{class:"token comment"}},[t._v("#0 and #1 of root node>")]),t._v("\n")])])]),e("blockquote",[e("p",[t._v("Save the \"id\": We will need to use this ''id'' later.")])]),t._v(" "),e("p",[t._v("More info on "),e("a",{attrs:{href:"https://bitcoindevkit.org/bdk-cli/interface/",target:"_blank",rel:"noopener noreferrer"}},[t._v("external policies here"),e("OutboundLink")],1)]),t._v(" "),e("h2",{attrs:{id:"step-10-create-a-transaction-psbt"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-10-create-a-transaction-psbt"}},[t._v("#")]),t._v(" Step 10: Create a Transaction (PSBT)")]),t._v(" "),e("ul",[e("li",[t._v("1st Create a PSBT using the first wallet")]),t._v(" "),e("li",[t._v("2nd Sign the PSBT with the first wallet")]),t._v(" "),e("li",[t._v("3rd Sign PSBT with the second wallet")]),t._v(" "),e("li",[t._v("Broadcast PSBT")])]),t._v(" "),e("h3",{attrs:{id:"export-unsigned-psbt-to-environment-variable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#export-unsigned-psbt-to-environment-variable"}},[t._v("#")]),t._v(" Export UNSIGNED_PSBT to environment variable")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v('export UNSIGNED_PSBT=$(bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 create_tx --send_all --to mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt:0 --external_policy "{\\"CHANGE_ID_HERE\\": [0,1]}" | jq -r \'.psbt\')')])]),t._v(" "),e("h3",{attrs:{id:"verify-unsigned-psbt-environment-variable"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#verify-unsigned-psbt-environment-variable"}},[t._v("#")]),t._v(" Verify UNSIGNED_PSBT environment variable")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("env | grep UNSIGNED")]),t._v(" "),e("img",{attrs:{src:"https://i.imgur.com/djHaRDq.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-11-sign-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-11-sign-the-transaction"}},[t._v("#")]),t._v(" Step 11: SIGN the Transaction")]),t._v(" "),e("h3",{attrs:{id:"1st-wallet-signs-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#1st-wallet-signs-the-transaction"}},[t._v("#")]),t._v(" 1st Wallet Signs the transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sign --psbt $UNSIGNED_PSBT")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export ONESIG_PSBT=$(bdk-cli wallet --wallet wallet_name_msd00 --descriptor $MULTI_DESCRIPTOR_00 sign --psbt $UNSIGNED_PSBT | jq -r '.psbt')")])]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("env | grep ONESIG")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "is_finalized": false,\n "psbt": "cHNidP8BAFUBAAAAAdYCtva/7Rkt+fgFu3mxAdaPh4uTbgBL3HmYZgcEKWygAAAAAAD/////AQqGAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA6gIAAAAAAQFLyGFJFK884DGBM1WgskRZ6gKp/7oZ+Z30u0+wF3pZYAEAAAAA/v///wKghgEAAAAAACIAINHcOQLE6GpJ3J+FOzn/be+HApxW8sZtGqfA3TBW+NYX91hoOAAAAAAWABTPQDZx2wYYIn+ug2pZBmWBn0Tu/gJHMEQCIHu6GmRMDgPZyTx+klFMA9VujR3qDA/Y08kSkRvOaChjAiBAtExtGAYLuQ/DDJzCqLlNZ1bMB3MV+nxsLfTdI9YcYwEhA0b8lz+kt0xHfR/tjUKOc2Nt2L61pDd5vJ/lsKi8pw9MmFUjAAEBK6CGAQAAAAAAIgAg0dw5AsToakncn4U7Of9t74cCnFbyxm0ap8DdMFb41hciAgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDUgwRQIhAJdILr7G3UzYylyr2fA13MFsz/jG4+iZlKeEkX79d082AiA99UF0/uFyXBVNUmuGaxdHL7wlhzqfbgGLMREN0z/O6QEBBWlSIQIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDSEDzsDXexRPSxeXiLJoS0i2fQlOoOGHmo+Dhaeaq3oHV6YhAjGKA2Dqg+QeMICBAifYslQF2WrehLEQ0iEOpp/+eQ0NU64iBgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDRh83y1GVAAAgAEAAIAAAACAAAAAAAAAAAAiBgIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDRgmsDMzVAAAgAEAAIAAAACAAAAAAAAAAAAiBgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXphj8eHDNVAAAgAEAAIAAAACAAAAAAAAAAAAAAA=="\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/0w4sK5y.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"2nd-wallet-signs-the-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#2nd-wallet-signs-the-transaction"}},[t._v("#")]),t._v(" 2nd Wallet Signs the transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 sign --psbt $ONESIG_PSBT")])]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("export SECONDSIG_PSBT=$(bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 sign --psbt $ONESIG_PSBT | jq -r '.psbt')")])]),t._v(" "),e("p",[t._v("▶️"),e("code",[t._v("env | grep SECONDSIG")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "is_finalized": true,\n "psbt": "cHNidP8BAFUBAAAAAdYCtva/7Rkt+fgFu3mxAdaPh4uTbgBL3HmYZgcEKWygAAAAAAD/////AQqGAQAAAAAAGXapFDRKD0jKFQ7CuQOBdmC5tosTpnAmiKwAAAAAAAEA6gIAAAAAAQFLyGFJFK884DGBM1WgskRZ6gKp/7oZ+Z30u0+wF3pZYAEAAAAA/v///wKghgEAAAAAACIAINHcOQLE6GpJ3J+FOzn/be+HApxW8sZtGqfA3TBW+NYX91hoOAAAAAAWABTPQDZx2wYYIn+ug2pZBmWBn0Tu/gJHMEQCIHu6GmRMDgPZyTx+klFMA9VujR3qDA/Y08kSkRvOaChjAiBAtExtGAYLuQ/DDJzCqLlNZ1bMB3MV+nxsLfTdI9YcYwEhA0b8lz+kt0xHfR/tjUKOc2Nt2L61pDd5vJ/lsKi8pw9MmFUjAAEBK6CGAQAAAAAAIgAg0dw5AsToakncn4U7Of9t74cCnFbyxm0ap8DdMFb41hciAgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDUgwRQIhAJdILr7G3UzYylyr2fA13MFsz/jG4+iZlKeEkX79d082AiA99UF0/uFyXBVNUmuGaxdHL7wlhzqfbgGLMREN0z/O6QEiAgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXpkgwRQIhAO2aRERcublhAzToshkZRMg2I8GaE7mM2ECr0vYyuscmAiB5KK4ETlvrLqL0QbcRbGqrSwIa9lVuOqP3f5qCnGRMaQEBBWlSIQIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDSEDzsDXexRPSxeXiLJoS0i2fQlOoOGHmo+Dhaeaq3oHV6YhAjGKA2Dqg+QeMICBAifYslQF2WrehLEQ0iEOpp/+eQ0NU64iBgIjUCIdnyr6rDtuNhVNt4ZBDcvYLawfoJbzbPyxc/WNDRh83y1GVAAAgAEAAIAAAACAAAAAAAAAAAAiBgIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDRgmsDMzVAAAgAEAAIAAAACAAAAAAAAAAAAiBgPOwNd7FE9LF5eIsmhLSLZ9CU6g4Yeaj4OFp5qregdXphj8eHDNVAAAgAEAAIAAAACAAAAAAAAAAAABBwABCP3+AAQASDBFAiEAl0guvsbdTNjKXKvZ8DXcwWzP+Mbj6JmUp4SRfv13TzYCID31QXT+4XJcFU1Sa4ZrF0cvvCWHOp9uAYsxEQ3TP87pAUgwRQIhAO2aRERcublhAzToshkZRMg2I8GaE7mM2ECr0vYyuscmAiB5KK4ETlvrLqL0QbcRbGqrSwIa9lVuOqP3f5qCnGRMaQFpUiECI1AiHZ8q+qw7bjYVTbeGQQ3L2C2sH6CW82z8sXP1jQ0hA87A13sUT0sXl4iyaEtItn0JTqDhh5qPg4Wnmqt6B1emIQIxigNg6oPkHjCAgQIn2LJUBdlq3oSxENIhDqaf/nkNDVOuAAA="\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/OdLHnJ3.gif",alt:""}})]),t._v(" "),e("h2",{attrs:{id:"step-12-broadcast-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#step-12-broadcast-transaction"}},[t._v("#")]),t._v(" Step 12: Broadcast Transaction")]),t._v(" "),e("p",[t._v("▶️ "),e("code",[t._v("bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 broadcast --psbt $SECONDSIG_PSBT")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v('{\n "txid": "61da2451874a483aa8d1d0787c7680d157639f284840de8885098cac43f6cc2f"\n}\n')])])]),e("figure",[e("img",{attrs:{src:"https://i.imgur.com/M7s0Fd6.gif",alt:""}})]),t._v(" "),e("h3",{attrs:{id:"verify-transaction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#verify-transaction"}},[t._v("#")]),t._v(" Verify Transaction")]),t._v(" "),e("p",[t._v("Verify transcation in the memory pool on testnet "),e("a",{attrs:{href:"https://mempool.space/testnet",target:"_blank",rel:"noopener noreferrer"}},[t._v("Mempool-testnet!"),e("OutboundLink")],1)])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/45.251f6700.js b/assets/js/45.41387e37.js similarity index 99% rename from assets/js/45.251f6700.js rename to assets/js/45.41387e37.js index 9be704531f..04e953750d 100644 --- a/assets/js/45.251f6700.js +++ b/assets/js/45.41387e37.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{393:function(e,t,a){"use strict";a.r(t);var s=a(7),r=Object(s.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[e._v("In this post, we will use the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" tool to create a multi-owned descriptor-based paper wallet. We will use "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" via the "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" tool to test our descriptor and to be able to sweep the funds from our paper wallet to a new address.")]),e._v(" "),t("h2",{attrs:{id:"about-paper-wallets"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#about-paper-wallets"}},[e._v("#")]),e._v(" About paper wallets")]),e._v(" "),t("p",[e._v("Paper wallets have a lot of drawbacks, as explained in the "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/Paper_wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("paper wallet Wiki article"),t("OutboundLink")],1),e._v(", as always, do your own research before deciding to use it with mainnet bitcoins. In this post we will\nonly be using testnet coins.")]),e._v(" "),t("h2",{attrs:{id:"descriptors"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#descriptors"}},[e._v("#")]),e._v(" Descriptors")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet/tree/339fa4418d94f6fdd96f3d0301cab8a0bc09e8bd",target:"_blank",rel:"noopener noreferrer"}},[e._v("previous version"),t("OutboundLink")],1),e._v(" of the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" followed the original paper wallet design: WIF"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" as secret part with the option to generate a different kind of addresses (legacy, nested segwit, and segwit).")]),e._v(" "),t("p",[e._v("There were plans to "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet/issues/5",target:"_blank",rel:"noopener noreferrer"}},[e._v("support mnemonic"),t("OutboundLink")],1),e._v(" instead of WIF keys because it may"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(" save the sweep transaction"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(" and there are more wallets capable of importing a mnemonic instead of a WIF.")]),e._v(" "),t("p",[e._v("However, choosing a single address type or having wallet support for a specific format is the kind of problem "),t("a",{attrs:{href:"/descriptors"}},[e._v("descriptors")]),e._v(" solve perfectly, so the latest "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" version now accepts a descriptor and the network as parameters.")]),e._v(" "),t("h2",{attrs:{id:"example-use-case"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#example-use-case"}},[e._v("#")]),e._v(" Example use case")]),e._v(" "),t("p",[e._v("So let's say your grandma wants to buy bitcoin and asked for your help.")]),e._v(" "),t("p",[e._v("You are a little afraid she may lose the private key. At the same time, you don't want to duplicate the keys and give those to her daughters Alice and Barbara, because both of them could spend and accuse the other of having done so.")]),e._v(" "),t("p",[e._v("Even though we trust everyone in the family it is better to play it safe and divide the responsibility of protecting Grandma's bitcoin.")]),e._v(" "),t("p",[e._v("This is a perfect case for a 2 of 3 multi-signature paper wallet. This way also protects the participants from having their copy of the wallet stolen. To compromise Grandma's wallet a thief would need to find and steal at least two of them.")]),e._v(" "),t("p",[e._v("Note that you as the wallet creator are still the single point of trust because you are going to generate the keys for everyone. Setups combining self generated keys from the participants is possible future work.")]),e._v(" "),t("h2",{attrs:{id:"creating-the-paper-wallet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#creating-the-paper-wallet"}},[e._v("#")]),e._v(" Creating the paper wallet")]),e._v(" "),t("p",[e._v("For this example the spending descriptor would be:")]),e._v(" "),t("p",[t("code",[e._v("wsh(multi(2,Grandma,Alice,Barbara))")])]),e._v(" "),t("p",[e._v("You need "),t("a",{attrs:{href:"https://www.rust-lang.org/tools/install",target:"_blank",rel:"noopener noreferrer"}},[e._v("rust"),t("OutboundLink")],1),e._v(" installed to use "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(". The -n option below explicitly selects\ngenerating "),t("code",[e._v("testnet")]),e._v(" keys. Use "),t("code",[e._v("rusty-paper-wallet --help")]),e._v(" to see usage instructions and other\noptions.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("cargo")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("install")]),e._v(" rusty-paper-wallet\n$ rusty-paper-wallet "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,Grandma,Alice,Barbara))"')]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-n")]),e._v(" testnet\ndata:text/html"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("base64,PCFET0N"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("..")]),e._v(".\n")])])]),t("p",[e._v("The "),t("a",{attrs:{href:"/descriptor-based-paper-wallets/data-url.txt"}},[e._v("output")]),e._v(" of the command is very long and has been shortened. The string is a "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Data_URI_scheme",target:"_blank",rel:"noopener noreferrer"}},[e._v("data URI scheme"),t("OutboundLink")],1),e._v(" paste-able in the address bar of a browser. By using a data URI no files are written on the hard disk, leaving less trace of secret material on the computer.\nIt's also a good idea to use incognito mode in the browser to prevent it from saving the page in the history.")]),e._v(" "),t("p",[e._v("The following is the result:")]),e._v(" "),t("iframe",{staticClass:"example",attrs:{src:"/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html"}}),e._v(" "),t("p",[e._v("Under the hood, the command created a key pair randomly for every alias present in the descriptor, then replaced the aliases with the created keys and generated the corresponding address. This address is the same for every paper wallet and it is shown in the upper part of the paper wallet (the public part) along with the alias, linking the paper wallet to the owner.")]),e._v(" "),t("p",[e._v("The lower part is the secret part, the written part is the descriptor with the aliases, followed by a legend linking the aliases with the keys. In the legend, all the keys are public but the one of the owner which is a private WIF. The secret QR code instead contains the descriptor already with the keys.")]),e._v(" "),t("p",[e._v("The paper wallet must then be printed, and it is better to use a printer without wifi and also to be aware that some sensitive data may remain in the printer's cache.")]),e._v(" "),t("p",[e._v("Then the paper wallet must be cut along the dotted lines, the secret part should be folded twice over the black zone"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(". The black zone helps to avoid showing the secret parts in the presence of back-light. Once the folding is done the paper wallet should be plasticized to prevent being damaged by water.")]),e._v(" "),t("h2",{attrs:{id:"bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bdk"}},[e._v("#")]),e._v(" BDK")]),e._v(" "),t("p",[e._v("Any descriptor based wallet can be used to check the balance of and sweep the funds from\nGrandma's paper wallet. For this post we'll demonstrate using the "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" tool to do these steps.\nAnother area where "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" could be used with "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" is to compile a more\ncomplicated miniscript spending policy into a descriptor, as we have done in the "),t("RouterLink",{attrs:{to:"/blog/2021/02/spending-policy-demo/#step-4-create-wallet-descriptors-for-each-participant"}},[e._v("spending policy demo")]),e._v(" post.")],1),e._v(" "),t("h2",{attrs:{id:"funding-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#funding-tx"}},[e._v("#")]),e._v(" Funding tx")]),e._v(" "),t("p",[e._v("Since Grandma's wallet was created as a "),t("code",[e._v("wsh")]),e._v(" descriptor, bitcoin can be sent to it from any\nsegwit capable wallet, we'll use a public "),t("a",{attrs:{href:"https://bitcoinfaucet.uo1.net/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitcoin testnet faucet"),t("OutboundLink")],1),e._v(". Once the funds are sent the\ndeposit address "),t("code",[e._v("tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw")]),e._v(" we can also use this\naddress and a testnet explorer to "),t("a",{attrs:{href:"https://mempool.space/testnet/address/tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw",target:"_blank",rel:"noopener noreferrer"}},[e._v("confirm the funds were received"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"sweep-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sweep-tx"}},[e._v("#")]),e._v(" Sweep tx")]),e._v(" "),t("p",[e._v("Now that Grandma's paper wallet is funded it's time to demonstrate how to use "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" to sweep these\nfunds to a new address. Let's assume Grandma lost her original paper wallet and has asked\nher daughters to sweep them to a new single signature wallet so she can spend them.")]),e._v(" "),t("h3",{attrs:{id:"step-1-alice-creates-and-signs-a-psbt"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#step-1-alice-creates-and-signs-a-psbt"}},[e._v("#")]),e._v(" Step 1: Alice creates and signs a PSBT")]),e._v(" "),t("p",[e._v("Alice uses the private text or QR code from her paper wallet to find her private key and the\npublic keys for Grandma and Barbara. With this info she creates a PSBT to sweep Grandma's funds\nto a new address (in this example we'll send them back to our "),t("a",{attrs:{href:"https://bitcoinfaucet.uo1.net/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitcoin testnet faucet"),t("OutboundLink")],1),e._v("). Notice how Alice\nincludes her wallet's descriptor checksum '#em3q73l5', this "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums",target:"_blank",rel:"noopener noreferrer"}},[e._v("guarantees"),t("OutboundLink")],1),e._v(" she has entered her descriptor correctly.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("SWEEP_TO_ADDR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_WIF")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("GRANDMA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_DESCRIPTOR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,'),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$GRANDMA_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_WIF")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_PUBKEY")]),e._v('))#em3q73l5"')]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# confirm descriptor creates the expected deposit address")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" get_new_address\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"address"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# sync the wallet and show the balance")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("sync")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" get_balance\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"satoshi"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("10000")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# create and sign PSBT")]),e._v("\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("UNSIGNED_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $ALICE_DESCRIPTOR create_tx "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--send_all")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--to")]),e._v(" $SWEEP_TO_ADDR:0 "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_SIGNED_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $ALICE_DESCRIPTOR sign "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" $UNSIGNED_PSBT "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n")])])]),t("h3",{attrs:{id:"step-2-barbara-signs-alices-signed-psbt-and-broadcasts-the-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#step-2-barbara-signs-alices-signed-psbt-and-broadcasts-the-tx"}},[e._v("#")]),e._v(" Step 2: Barbara signs Alice's signed PSBT and broadcasts the tx")]),e._v(" "),t("p",[e._v("Now it's Barbara's turn to use the private text or QR code from her paper wallet to get her private\nkey and the public keys for Grandma and Alice. With this info plus Alice's signed PSBT she can\ncreate a fully signed PSBT to broadcast and complete the sweep of Grandma's funds.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_WIF")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("GRANDMA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_DESCRIPTOR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,'),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$GRANDMA_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_WIF")]),e._v('))#nxfa5n0z"')]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# confirm descriptor creates the expected deposit address")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" get_new_address\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"address"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# sync the wallet and show the balance")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("sync")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" get_balance\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"satoshi"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("10000")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("FINAL_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $BARBARA_DESCRIPTOR sign "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" $ALICE_SIGNED_PSBT "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" broadcast "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$FINAL_PSBT")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"txid"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),t("p",[e._v("And finally we verify that Alice and Barbara successfully created and broadcast Grandma's "),t("a",{attrs:{href:"https://mempool.space/testnet/tx/9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59",target:"_blank",rel:"noopener noreferrer"}},[e._v("sweep tx"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("In this post we showed how to create a multi-sig descriptor based paper wallet using\n"),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" and then sweep the funds from our example paper wallet to a new address. If you\nfound this post interesting please comment below. Or give it a try yourself and if you run into any\nproblems or would like to suggest improvements leave an issue in the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" or\n"),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" github repos. Thanks!")]),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("Wallet Input Format, a string encoding a ECDSA private key https://en.bitcoin.it/wiki/Wallet_import_format "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("Unless the user import the WIF directly into bitcoin core "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("Some wallets refers to sweep as the action to create a transaction taking all the funds from the paper wallet and sending those to the wallet itself. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("Ideally, the black zone should be twice as long as the secret part to cover it back and front, long descriptor may leave a shorter black zone, ensure to have you printer set with vertical layout for best results. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{394:function(e,t,a){"use strict";a.r(t);var s=a(7),r=Object(s.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[e._v("In this post, we will use the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" tool to create a multi-owned descriptor-based paper wallet. We will use "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" via the "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" tool to test our descriptor and to be able to sweep the funds from our paper wallet to a new address.")]),e._v(" "),t("h2",{attrs:{id:"about-paper-wallets"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#about-paper-wallets"}},[e._v("#")]),e._v(" About paper wallets")]),e._v(" "),t("p",[e._v("Paper wallets have a lot of drawbacks, as explained in the "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/Paper_wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("paper wallet Wiki article"),t("OutboundLink")],1),e._v(", as always, do your own research before deciding to use it with mainnet bitcoins. In this post we will\nonly be using testnet coins.")]),e._v(" "),t("h2",{attrs:{id:"descriptors"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#descriptors"}},[e._v("#")]),e._v(" Descriptors")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet/tree/339fa4418d94f6fdd96f3d0301cab8a0bc09e8bd",target:"_blank",rel:"noopener noreferrer"}},[e._v("previous version"),t("OutboundLink")],1),e._v(" of the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" followed the original paper wallet design: WIF"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" as secret part with the option to generate a different kind of addresses (legacy, nested segwit, and segwit).")]),e._v(" "),t("p",[e._v("There were plans to "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet/issues/5",target:"_blank",rel:"noopener noreferrer"}},[e._v("support mnemonic"),t("OutboundLink")],1),e._v(" instead of WIF keys because it may"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(" save the sweep transaction"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(" and there are more wallets capable of importing a mnemonic instead of a WIF.")]),e._v(" "),t("p",[e._v("However, choosing a single address type or having wallet support for a specific format is the kind of problem "),t("a",{attrs:{href:"/descriptors"}},[e._v("descriptors")]),e._v(" solve perfectly, so the latest "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" version now accepts a descriptor and the network as parameters.")]),e._v(" "),t("h2",{attrs:{id:"example-use-case"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#example-use-case"}},[e._v("#")]),e._v(" Example use case")]),e._v(" "),t("p",[e._v("So let's say your grandma wants to buy bitcoin and asked for your help.")]),e._v(" "),t("p",[e._v("You are a little afraid she may lose the private key. At the same time, you don't want to duplicate the keys and give those to her daughters Alice and Barbara, because both of them could spend and accuse the other of having done so.")]),e._v(" "),t("p",[e._v("Even though we trust everyone in the family it is better to play it safe and divide the responsibility of protecting Grandma's bitcoin.")]),e._v(" "),t("p",[e._v("This is a perfect case for a 2 of 3 multi-signature paper wallet. This way also protects the participants from having their copy of the wallet stolen. To compromise Grandma's wallet a thief would need to find and steal at least two of them.")]),e._v(" "),t("p",[e._v("Note that you as the wallet creator are still the single point of trust because you are going to generate the keys for everyone. Setups combining self generated keys from the participants is possible future work.")]),e._v(" "),t("h2",{attrs:{id:"creating-the-paper-wallet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#creating-the-paper-wallet"}},[e._v("#")]),e._v(" Creating the paper wallet")]),e._v(" "),t("p",[e._v("For this example the spending descriptor would be:")]),e._v(" "),t("p",[t("code",[e._v("wsh(multi(2,Grandma,Alice,Barbara))")])]),e._v(" "),t("p",[e._v("You need "),t("a",{attrs:{href:"https://www.rust-lang.org/tools/install",target:"_blank",rel:"noopener noreferrer"}},[e._v("rust"),t("OutboundLink")],1),e._v(" installed to use "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(". The -n option below explicitly selects\ngenerating "),t("code",[e._v("testnet")]),e._v(" keys. Use "),t("code",[e._v("rusty-paper-wallet --help")]),e._v(" to see usage instructions and other\noptions.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("cargo")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("install")]),e._v(" rusty-paper-wallet\n$ rusty-paper-wallet "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,Grandma,Alice,Barbara))"')]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-n")]),e._v(" testnet\ndata:text/html"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(";")]),e._v("base64,PCFET0N"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("..")]),e._v(".\n")])])]),t("p",[e._v("The "),t("a",{attrs:{href:"/descriptor-based-paper-wallets/data-url.txt"}},[e._v("output")]),e._v(" of the command is very long and has been shortened. The string is a "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Data_URI_scheme",target:"_blank",rel:"noopener noreferrer"}},[e._v("data URI scheme"),t("OutboundLink")],1),e._v(" paste-able in the address bar of a browser. By using a data URI no files are written on the hard disk, leaving less trace of secret material on the computer.\nIt's also a good idea to use incognito mode in the browser to prevent it from saving the page in the history.")]),e._v(" "),t("p",[e._v("The following is the result:")]),e._v(" "),t("iframe",{staticClass:"example",attrs:{src:"/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html"}}),e._v(" "),t("p",[e._v("Under the hood, the command created a key pair randomly for every alias present in the descriptor, then replaced the aliases with the created keys and generated the corresponding address. This address is the same for every paper wallet and it is shown in the upper part of the paper wallet (the public part) along with the alias, linking the paper wallet to the owner.")]),e._v(" "),t("p",[e._v("The lower part is the secret part, the written part is the descriptor with the aliases, followed by a legend linking the aliases with the keys. In the legend, all the keys are public but the one of the owner which is a private WIF. The secret QR code instead contains the descriptor already with the keys.")]),e._v(" "),t("p",[e._v("The paper wallet must then be printed, and it is better to use a printer without wifi and also to be aware that some sensitive data may remain in the printer's cache.")]),e._v(" "),t("p",[e._v("Then the paper wallet must be cut along the dotted lines, the secret part should be folded twice over the black zone"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(". The black zone helps to avoid showing the secret parts in the presence of back-light. Once the folding is done the paper wallet should be plasticized to prevent being damaged by water.")]),e._v(" "),t("h2",{attrs:{id:"bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bdk"}},[e._v("#")]),e._v(" BDK")]),e._v(" "),t("p",[e._v("Any descriptor based wallet can be used to check the balance of and sweep the funds from\nGrandma's paper wallet. For this post we'll demonstrate using the "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" tool to do these steps.\nAnother area where "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" could be used with "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" is to compile a more\ncomplicated miniscript spending policy into a descriptor, as we have done in the "),t("RouterLink",{attrs:{to:"/blog/2021/02/spending-policy-demo/#step-4-create-wallet-descriptors-for-each-participant"}},[e._v("spending policy demo")]),e._v(" post.")],1),e._v(" "),t("h2",{attrs:{id:"funding-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#funding-tx"}},[e._v("#")]),e._v(" Funding tx")]),e._v(" "),t("p",[e._v("Since Grandma's wallet was created as a "),t("code",[e._v("wsh")]),e._v(" descriptor, bitcoin can be sent to it from any\nsegwit capable wallet, we'll use a public "),t("a",{attrs:{href:"https://bitcoinfaucet.uo1.net/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitcoin testnet faucet"),t("OutboundLink")],1),e._v(". Once the funds are sent the\ndeposit address "),t("code",[e._v("tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw")]),e._v(" we can also use this\naddress and a testnet explorer to "),t("a",{attrs:{href:"https://mempool.space/testnet/address/tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw",target:"_blank",rel:"noopener noreferrer"}},[e._v("confirm the funds were received"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"sweep-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#sweep-tx"}},[e._v("#")]),e._v(" Sweep tx")]),e._v(" "),t("p",[e._v("Now that Grandma's paper wallet is funded it's time to demonstrate how to use "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" to sweep these\nfunds to a new address. Let's assume Grandma lost her original paper wallet and has asked\nher daughters to sweep them to a new single signature wallet so she can spend them.")]),e._v(" "),t("h3",{attrs:{id:"step-1-alice-creates-and-signs-a-psbt"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#step-1-alice-creates-and-signs-a-psbt"}},[e._v("#")]),e._v(" Step 1: Alice creates and signs a PSBT")]),e._v(" "),t("p",[e._v("Alice uses the private text or QR code from her paper wallet to find her private key and the\npublic keys for Grandma and Barbara. With this info she creates a PSBT to sweep Grandma's funds\nto a new address (in this example we'll send them back to our "),t("a",{attrs:{href:"https://bitcoinfaucet.uo1.net/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitcoin testnet faucet"),t("OutboundLink")],1),e._v("). Notice how Alice\nincludes her wallet's descriptor checksum '#em3q73l5', this "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums",target:"_blank",rel:"noopener noreferrer"}},[e._v("guarantees"),t("OutboundLink")],1),e._v(" she has entered her descriptor correctly.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("SWEEP_TO_ADDR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_WIF")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("GRANDMA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_DESCRIPTOR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,'),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$GRANDMA_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_WIF")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_PUBKEY")]),e._v('))#em3q73l5"')]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# confirm descriptor creates the expected deposit address")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" get_new_address\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"address"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# sync the wallet and show the balance")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("sync")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_DESCRIPTOR")]),e._v(" get_balance\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"satoshi"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("10000")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# create and sign PSBT")]),e._v("\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("UNSIGNED_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $ALICE_DESCRIPTOR create_tx "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--send_all")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--to")]),e._v(" $SWEEP_TO_ADDR:0 "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_SIGNED_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" alice "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $ALICE_DESCRIPTOR sign "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" $UNSIGNED_PSBT "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n")])])]),t("h3",{attrs:{id:"step-2-barbara-signs-alices-signed-psbt-and-broadcasts-the-tx"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#step-2-barbara-signs-alices-signed-psbt-and-broadcasts-the-tx"}},[e._v("#")]),e._v(" Step 2: Barbara signs Alice's signed PSBT and broadcasts the tx")]),e._v(" "),t("p",[e._v("Now it's Barbara's turn to use the private text or QR code from her paper wallet to get her private\nkey and the public keys for Grandma and Alice. With this info plus Alice's signed PSBT she can\ncreate a fully signed PSBT to broadcast and complete the sweep of Grandma's funds.")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[e._v("$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("ALICE_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_WIF")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("GRANDMA_PUBKEY")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("BARBARA_DESCRIPTOR")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"wsh(multi(2,'),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$GRANDMA_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$ALICE_PUBKEY")]),e._v(","),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_WIF")]),e._v('))#nxfa5n0z"')]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# confirm descriptor creates the expected deposit address")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" get_new_address\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"address"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token comment"}},[e._v("# sync the wallet and show the balance")]),e._v("\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token function"}},[e._v("sync")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" get_balance\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"satoshi"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("10000")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n\n$ "),t("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e._v("FINAL_PSBT")]),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token variable"}},[t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$(")]),e._v("bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" $BARBARA_DESCRIPTOR sign "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" $ALICE_SIGNED_PSBT "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("|")]),e._v(" jq "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-r")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('".psbt"')]),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v(")")])]),e._v("\n\n$ bdk-cli wallet "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-w")]),e._v(" barbara "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("-d")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$BARBARA_DESCRIPTOR")]),e._v(" broadcast "),t("span",{pre:!0,attrs:{class:"token parameter variable"}},[e._v("--psbt")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token variable"}},[e._v("$FINAL_PSBT")]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("{")]),e._v("\n "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"txid"')]),t("span",{pre:!0,attrs:{class:"token builtin class-name"}},[e._v(":")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59"')]),e._v("\n"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("}")]),e._v("\n")])])]),t("p",[e._v("And finally we verify that Alice and Barbara successfully created and broadcast Grandma's "),t("a",{attrs:{href:"https://mempool.space/testnet/tx/9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59",target:"_blank",rel:"noopener noreferrer"}},[e._v("sweep tx"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("In this post we showed how to create a multi-sig descriptor based paper wallet using\n"),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" and then sweep the funds from our example paper wallet to a new address. If you\nfound this post interesting please comment below. Or give it a try yourself and if you run into any\nproblems or would like to suggest improvements leave an issue in the "),t("a",{attrs:{href:"https://github.com/RCasatta/rusty-paper-wallet",target:"_blank",rel:"noopener noreferrer"}},[e._v("Rusty Paper Wallet"),t("OutboundLink")],1),e._v(" or\n"),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk-cli",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk-cli"),t("OutboundLink")],1),e._v(" github repos. Thanks!")]),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("Wallet Input Format, a string encoding a ECDSA private key https://en.bitcoin.it/wiki/Wallet_import_format "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("Unless the user import the WIF directly into bitcoin core "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("Some wallets refers to sweep as the action to create a transaction taking all the funds from the paper wallet and sending those to the wallet itself. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("Ideally, the black zone should be twice as long as the secret part to cover it back and front, long descriptor may leave a shorter black zone, ensure to have you printer set with vertical layout for best results. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/46.5ebccb0a.js b/assets/js/46.883464d4.js similarity index 99% rename from assets/js/46.5ebccb0a.js rename to assets/js/46.883464d4.js index 693f2472cc..3340e76c61 100644 --- a/assets/js/46.5ebccb0a.js +++ b/assets/js/46.883464d4.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{401:function(e,t,r){"use strict";r.r(t);var a=r(7),s=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[e._v("I have tried to setup a 2 of 2 multi signature infrastructure with two\ndifferent wallets, which know nothing about each other, but are compliant with\ntwo very important protocols: "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("Partially Signed\nBitcoin Transactions"),t("OutboundLink")],1),e._v(" described in BIP 174.")]),e._v(" "),t("p",[e._v("Before these two protocols came into existence, making a multi signature setup\nand spending from it was possible only if the involved parties were using the\nsame wallet (eg. Electrum Desktop Wallet). This limitation was due to the fact\nthat the two parties had to agree:")]),e._v(" "),t("ul",[t("li",[e._v("on the particular type of script and address to use")]),e._v(" "),t("li",[e._v("on the way the transaction would be shared composed and signed with all the\ninvolved parties.")])]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" are a way to express which kind scriptPubKey and\naddresses to produce with a key or a series of keys.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("PSBT"),t("OutboundLink")],1),e._v(" is instead the standard protocol used to create a transaction and to enrich\nit with the necessary signatures and other components, to make it valid and complete.")]),e._v(" "),t("p",[e._v("Together they provide a common ground to create and use a multi signature\ninfrastructure in a heterogeneous environment, and this is what I have put\nto test.")]),e._v(" "),t("h2",{attrs:{id:"the-use-case"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-use-case"}},[e._v("#")]),e._v(" The use case")]),e._v(" "),t("p",[e._v("Imagine Alice and Bob owning a company and being willing to put the corporate cash\nin a 2of2 multi signature setup, so that each one of them have to agree and sign each\ntransaction.")]),e._v(" "),t("h2",{attrs:{id:"the-role-of-descriptors"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-role-of-descriptors"}},[e._v("#")]),e._v(" The role of Descriptors")]),e._v(" "),t("p",[e._v("If Alice and Bob cannot agree on the software to use, to monitor the same financial\nsituation, the two software must control and produce exactly the same series\nof multisignature addresses.")]),e._v(" "),t("p",[e._v("To make two different software produce the same addresses in a deterministic way\nwe must ensure that they:")]),e._v(" "),t("ul",[t("li",[e._v("produce the same pair of public keys")]),e._v(" "),t("li",[e._v("combine them in the same order")]),e._v(" "),t("li",[e._v("put them inside the same scriptPubKey to produce the same address")])]),e._v(" "),t("p",[e._v("Here is where the "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" come into play. They describe:")]),e._v(" "),t("ul",[t("li",[e._v("the sequence of public keys each extended key (xpub) will produce")]),e._v(" "),t("li",[e._v("the sequence in which the new public keys of various parties will enter into\nthe script")]),e._v(" "),t("li",[e._v("the type of script the wallet will prepare with that group keys and so the type\nof address the group of keys will produce.")])]),e._v(" "),t("p",[t("strong",[e._v("By sharing the same Descriptor, every compliant wallet will derive\ndeterministically the same series of multisig addresses")]),e._v(".")]),e._v(" "),t("p",[e._v("Imagine Alice using Bitcoin Core (from now on "),t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v('"Core"'),t("OutboundLink")],1),e._v(') as a\nWallet and Bob using a "Last generation" wallet, Bitcoin Development Kit\n(from now on '),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v('"BDK"'),t("OutboundLink")],1),e._v("), which uses descriptors and miniscript natively.")]),e._v(" "),t("p",[e._v("Each of these two software wallets should be able to:")]),e._v(" "),t("ul",[t("li",[e._v("Create a new address which is seen as belonging to the multi signature\nwallet in both software")]),e._v(" "),t("li",[e._v("Express the consent of each party by partially signing the transaction in a way\nthe other wallet can understand and complete it with its own signature.")])]),e._v(" "),t("p",[e._v("The infrastructure of multiple Extended keys combined toghether to produce\nmultiple multisignature addresses is often referred as\n"),t("em",[t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("Hierarchical Deterministic"),t("OutboundLink")],1),e._v(" multi signature wallet or HDM")]),e._v(".")]),e._v(" "),t("p",[e._v("What follows are the steps to create the HDM usable both in Core and\nin BDK.")]),e._v(" "),t("p",[t("em",[e._v("Note: In Core, "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/pull/16528",target:"_blank",rel:"noopener noreferrer"}},[e._v("Descriptor wallets"),t("OutboundLink")],1),e._v(" are still experimental and in general,\nboth wallets should be tested for descriptor capabilities only in testnet.")])]),e._v(" "),t("h2",{attrs:{id:"our-playground"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#our-playground"}},[e._v("#")]),e._v(" Our playground")]),e._v(" "),t("p",[e._v("We will build a 2of2 key set up that will be used cooperatively by Bitcoin Core\nand Bitcoin Development Kit.\nThe steps Alice and Bob will do are:")]),e._v(" "),t("ol",[t("li",[e._v("creation of the seed and the derived Extended Master Public and send it to\nthe other party")]),e._v(" "),t("li",[e._v("Create the multi signature descriptor for each wallet")]),e._v(" "),t("li",[e._v("Use each other's software to receive testnet coins from a faucet")]),e._v(" "),t("li",[e._v("return part of the coins to the faucet signing the transaction with both\nwallets.")])]),e._v(" "),t("p",[e._v("We need:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Dev Kit"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Core"),t("OutboundLink")],1),e._v(" (v0.21.0 or later)")])]),e._v(" "),t("h3",{attrs:{id:"1-creating-the-seeds-and-the-derived-extended-public-keys"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#1-creating-the-seeds-and-the-derived-extended-public-keys"}},[e._v("#")]),e._v(" 1. Creating the seeds and the derived Extended Public keys")]),e._v(" "),t("h4",{attrs:{id:"seeds-and-extended-master-public"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#seeds-and-extended-master-public"}},[e._v("#")]),e._v(" Seeds and Extended Master Public")]),e._v(" "),t("p",[e._v("We build an Extended Private Master Key for both wallet and derive a BIP84\nExtended Master Public for Bitcoin Core and then for BDK.")]),e._v(" "),t("p",[e._v("For Bitcoin Core (Alice):")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("# new Extended wallet data\nexport core_key=$(bdk-cli key generate)\n\n# New Extended Master Private\n\nexport core_xprv=$(echo $core_key | jq -r '.xprv')\n\n# Now I derive the xpubs (one for receiving and one for the change)\n# together with informations about the derivation path to be communicated\n# to BDK wallet's owner (Bob).\n\nexport core_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $core_xprv | jq -r '.xpub')\nexport core_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $core_xprv | jq -r '.xpub')\n")])])]),t("p",[e._v("For BDK (Bob) we do the same:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("# new Extended wallet data\n\nexport BDK_key=$(bdk-cli key generate)\n\n# New Extended Master Private\n\nexport BDK_xprv=$(echo $BDK_key | jq -r '.xprv')\n\n# Now I build the derived xpubs to be communicated (to Alice).\n\nexport BDK_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $BDK_xprv | jq -r '.xpub')\nexport BDK_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $BDK_xprv | jq -r '.xpub')\n")])])]),t("h3",{attrs:{id:"2-creation-of-the-multi-signature-descriptor-for-each-wallet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#2-creation-of-the-multi-signature-descriptor-for-each-wallet"}},[e._v("#")]),e._v(" 2. Creation of the multi signature descriptor for each wallet")]),e._v(" "),t("p",[e._v("To build a multisig wallet, each wallet owner must compose the descriptor\nadding:")]),e._v(" "),t("ul",[t("li",[e._v("his derived extended "),t("strong",[e._v("private")]),e._v(" key AND")]),e._v(" "),t("li",[e._v("all the extended "),t("strong",[e._v("public")]),e._v(" keys of the other wallets involved in the\nmulti signature setup")])]),e._v(" "),t("p",[t("em",[e._v("The different nature of the two keys (one is private and one is public) is\ndue to the fact that each wallet, to be able to partially sign the transaction,\n"),t("strong",[e._v("must manage the private key of the wallet's owner")])]),e._v(" AND have the other\nparty's public key. Otherwise, if we put both public keys, we would obtain\na watch-only wallet unable to sign the transactions. If we\nhad both extended private keys inside the descriptor, we would allow each party\nto finalize the transactions autonomously.")]),e._v(" "),t("h4",{attrs:{id:"in-bitcoin-core"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bitcoin-core"}},[e._v("#")]),e._v(" In Bitcoin Core:")]),e._v(" "),t("p",[e._v("In our case, the multi signature descriptor for Bitcoin Core will be composed\nwith:")]),e._v(" "),t("ul",[t("li",[e._v("The BIP84 derived Extended "),t("strong",[e._v("Public")]),e._v(" Key from BDK")]),e._v(" "),t("li",[e._v("The BIP84 derived Extended "),t("strong",[e._v("Private")]),e._v(" Key from Core.")])]),e._v(" "),t("p",[e._v("BDK wallet's owner will send to Core's owner the derived xpub for this purpose.\nThis is how the Core's multisig descriptor will be created and put into an\nenvironment variable:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_rec_desc=\"wsh(multi(2,$BDK_xpub_84_for_rec_desc,$core_xprv/84'/0'/0'/0/*))\"\n")])])]),t("p",[e._v("Where of course "),t("code",[e._v("$BDK_xpub_84_for_rec_desc")]),e._v("is the derived master public created\nin BDK and received by Core's owner.")]),e._v(" "),t("p",[e._v("The meaning of what is before and after is illustrated in the doc that explain\nthe use of "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors in Bitcoin Core"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We add the necessary checksum using the specific "),t("code",[e._v("bitcoin-cli")]),e._v(" call.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_rec_desc_chksum=$core_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_rec_desc | jq -r '.checksum')\n")])])]),t("p",[e._v("We repeat the same to build the descriptor to receive the change.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_chg_desc=\"wsh(multi(2,$BDK_xpub_84_for_chg_desc,$core_xprv/84'/0'/0'/1/*))\"\nexport core_chg_desc_chksum=$core_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_chg_desc|jq -r '.checksum')\n")])])]),t("h4",{attrs:{id:"in-bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bdk"}},[e._v("#")]),e._v(" In BDK:")]),e._v(" "),t("p",[e._v("For BDK we set the derivation for receiving addresses and change addresses\nin the command line (maybe setting an alias)")]),e._v(" "),t("p",[e._v("Building the descriptor:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export BDK_rec_desc=\"wsh(multi(2,$BDK_xprv/84'/0'/0'/0/*,$core_xpub_84_for_rec_desc))\"`\n")])])]),t("p",[e._v("Please note that the order of the extended key in the descriptor MUST be the\nsame in the 2 wallets.")]),e._v(" "),t("p",[t("em",[e._v("We have chosen to put BDK first and in each software wallet, the public key\nderived from BDK will always come first. In alternative, we could have chosen to\nproduce the descriptor, "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/pull/17056?ref=tokendaily",target:"_blank",rel:"noopener noreferrer"}},[e._v("chosing a "),t("code",[e._v("soretedmulti")]),e._v(" multisignature setup"),t("OutboundLink")],1)]),e._v(".")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export BDK_rec_desc_chksum=$BDK_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_rec_desc | jq -r '.checksum')\nexport BDK_chg_desc=\"wsh(multi(2,$BDK_xprv/84'/0'/0'/1/*,$core_xpub_84_for_chg_desc))\"\nexport BDK_chg_desc_chksum=$BDK_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_chg_desc | jq -r '.checksum')\n")])])]),t("p",[e._v("To take a look at the variables we have produced so far:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("env | grep 'core_'\nenv | grep 'BDK_'\n")])])]),t("p",[e._v("Now we will use the multisig descriptor wallet to receive testnet coins with\nAlice and Bob's software")]),e._v(" "),t("h3",{attrs:{id:"3-use-each-others-software-to-receive-testnet-coins-from-a-faucet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#3-use-each-others-software-to-receive-testnet-coins-from-a-faucet"}},[e._v("#")]),e._v(" 3. Use each other's software to receive testnet coins from a faucet")]),e._v(" "),t("h4",{attrs:{id:"in-bitcoin-core-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bitcoin-core-2"}},[e._v("#")]),e._v(" In Bitcoin Core")]),e._v(" "),t("p",[e._v('Alice must create an empty, experimental new "descriptors wallet" in Core and\nto import the multisig Output Descriptor.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('bitcoin-cli -testnet createwallet "multisig2of2withBDK" false true "" false true false\n')])])]),t("p",[e._v("The flag are to:")]),e._v(" "),t("ul",[t("li",[e._v("use the private keys")]),e._v(" "),t("li",[e._v("make it empty")]),e._v(" "),t("li",[e._v("no password provided to the wallet")]),e._v(" "),t("li",[e._v("reusing of addresses not allowed")]),e._v(" "),t("li",[e._v('"new experimental descriptors wallet"')]),e._v(" "),t("li",[e._v("don't load it on start up")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK importdescriptors "[{\\"desc\\":\\"$core_rec_desc_chksum\\",\\"timestamp\\":\\"now\\",\\"active\\":true,\\"internal\\":false},{\\"desc\\":\\"$core_chg_desc_chksum\\",\\"timestamp\\":\\"now\\",\\"active\\":true,\\"internal\\":true}]"\n')])])]),t("p",[e._v("Now Alice asks for her first receiving multisignature address.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export first_address=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getnewaddress)\necho $first_address\n")])])]),t("h4",{attrs:{id:"bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bdk"}},[e._v("#")]),e._v(" BDK")]),e._v(" "),t("p",[e._v("In BDK Bob can specify directly the descriptors on the command line to produce\nthe multisig address, because BDK is descriptors aware natively.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_new_address`\n')])])]),t("p",[e._v('Et voilà: if we have done everything correctly, the newly created address in\nCore is the same of the newly created address in BDK. this is part of the\n"miracle" of descriptors\' interoperability.')]),e._v(" "),t("h4",{attrs:{id:"we-ask-for-testnet-coins-giving-the-first-created-address"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#we-ask-for-testnet-coins-giving-the-first-created-address"}},[e._v("#")]),e._v(" We ask for testnet coins giving the first created address.")]),e._v(" "),t("p",[e._v('To find testnet coins for free, you can just google "testnet faucet" and you\nshould find some satoshis to play with. Just give to the site your first\ngenerated address and, in twenty minutes, you will find the satoshis in\nyour balance both in Core and in BDK.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('# to check it in Core:\n\nbitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getbalance\n\n# In BDK:\n\n# Sync with the blockchain\nrepl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sync\n# Get the balance\nrepl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_balance\n')])])]),t("p",[e._v("Some testnet faucets have an address to send back the unused satoshi after\nthe use. Take note of that because we will use it in the next step.")]),e._v(" "),t("h3",{attrs:{id:"4-we-return-part-of-the-satoshis-received-back-to-the-faucet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#4-we-return-part-of-the-satoshis-received-back-to-the-faucet"}},[e._v("#")]),e._v(" 4. we return part of the satoshis received back to the faucet")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletcreatefundedpsbt "[]" "[{\\"tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a\\":0.000012}]" | jq -r \'.psbt\')\n\nexport psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletprocesspsbt $psbt | jq -r \'.psbt\')\n{\n "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAQEFR1IhArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvIQNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfVKuIgYCufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8YNEw2cFQAAIAAAACAAAAAgAAAAAAAAAAAIgYDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH0YO/laXFQAAIAAAACAAAAAgAAAAAAAAAAAAAEBR1IhAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcIQLHKhjmPuCQjyS77ZfaMN2tdgNKcf/+57VXGZhz/UWTl1KuIgICpxy8DesvXcPUrgZ5aNxqEOw7c/yhpU0G22TgyUIpchwYNEw2cFQAAIAAAACAAAAAgAEAAAADAAAAIgICxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5cYO/laXFQAAIAAAACAAAAAgAEAAAADAAAAAAA=",\n "complete": false\n}\n')])])]),t("p",[e._v("Exactly! Note the "),t("code",[e._v('"complete": false')]),e._v(". We have processed the transaction with\nCore but we miss one of the necessary key of the multisig 2of2 setup (The one\ncontained inside BDK).")]),e._v(" "),t("p",[t("code",[e._v("tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a")]),e._v(" is the address\nwe got from the faucet site to return the satoshis.")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("PSBT"),t("OutboundLink")],1),e._v(" is sent over to the BDK wallet owner who tries to sign the\ntransaction:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sign --psbt $psbt\n{\n "is_finalized": true,\n "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA"\n}\n')])])]),t("p",[e._v('The signature has succeded (note the "is_finalized": true,) and now we can\nbroadcast the transction.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint broadcast --psbt "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA"\n{\n "txid": "a0b082e3b0579822d4a0b0fa95a4c4662f6b128ffd43fdcfe53c37473ce85dee"\n}\n')])])]),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("We have built an HDM and we have used it with two indipendent wallets, which\nare compatible with "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("BIP 174"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(". Hopefully we\nwill see many other compatible wallets beyound "),t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Core"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(",\nwith which we will be able to easily set up multi signature schemes.")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{393:function(e,t,r){"use strict";r.r(t);var a=r(7),s=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h2",{attrs:{id:"introduction"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[e._v("#")]),e._v(" Introduction")]),e._v(" "),t("p",[e._v("I have tried to setup a 2 of 2 multi signature infrastructure with two\ndifferent wallets, which know nothing about each other, but are compliant with\ntwo very important protocols: "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("Partially Signed\nBitcoin Transactions"),t("OutboundLink")],1),e._v(" described in BIP 174.")]),e._v(" "),t("p",[e._v("Before these two protocols came into existence, making a multi signature setup\nand spending from it was possible only if the involved parties were using the\nsame wallet (eg. Electrum Desktop Wallet). This limitation was due to the fact\nthat the two parties had to agree:")]),e._v(" "),t("ul",[t("li",[e._v("on the particular type of script and address to use")]),e._v(" "),t("li",[e._v("on the way the transaction would be shared composed and signed with all the\ninvolved parties.")])]),e._v(" "),t("p",[t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" are a way to express which kind scriptPubKey and\naddresses to produce with a key or a series of keys.")]),e._v(" "),t("p",[t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("PSBT"),t("OutboundLink")],1),e._v(" is instead the standard protocol used to create a transaction and to enrich\nit with the necessary signatures and other components, to make it valid and complete.")]),e._v(" "),t("p",[e._v("Together they provide a common ground to create and use a multi signature\ninfrastructure in a heterogeneous environment, and this is what I have put\nto test.")]),e._v(" "),t("h2",{attrs:{id:"the-use-case"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-use-case"}},[e._v("#")]),e._v(" The use case")]),e._v(" "),t("p",[e._v("Imagine Alice and Bob owning a company and being willing to put the corporate cash\nin a 2of2 multi signature setup, so that each one of them have to agree and sign each\ntransaction.")]),e._v(" "),t("h2",{attrs:{id:"the-role-of-descriptors"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-role-of-descriptors"}},[e._v("#")]),e._v(" The role of Descriptors")]),e._v(" "),t("p",[e._v("If Alice and Bob cannot agree on the software to use, to monitor the same financial\nsituation, the two software must control and produce exactly the same series\nof multisignature addresses.")]),e._v(" "),t("p",[e._v("To make two different software produce the same addresses in a deterministic way\nwe must ensure that they:")]),e._v(" "),t("ul",[t("li",[e._v("produce the same pair of public keys")]),e._v(" "),t("li",[e._v("combine them in the same order")]),e._v(" "),t("li",[e._v("put them inside the same scriptPubKey to produce the same address")])]),e._v(" "),t("p",[e._v("Here is where the "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(" come into play. They describe:")]),e._v(" "),t("ul",[t("li",[e._v("the sequence of public keys each extended key (xpub) will produce")]),e._v(" "),t("li",[e._v("the sequence in which the new public keys of various parties will enter into\nthe script")]),e._v(" "),t("li",[e._v("the type of script the wallet will prepare with that group keys and so the type\nof address the group of keys will produce.")])]),e._v(" "),t("p",[t("strong",[e._v("By sharing the same Descriptor, every compliant wallet will derive\ndeterministically the same series of multisig addresses")]),e._v(".")]),e._v(" "),t("p",[e._v("Imagine Alice using Bitcoin Core (from now on "),t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v('"Core"'),t("OutboundLink")],1),e._v(') as a\nWallet and Bob using a "Last generation" wallet, Bitcoin Development Kit\n(from now on '),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v('"BDK"'),t("OutboundLink")],1),e._v("), which uses descriptors and miniscript natively.")]),e._v(" "),t("p",[e._v("Each of these two software wallets should be able to:")]),e._v(" "),t("ul",[t("li",[e._v("Create a new address which is seen as belonging to the multi signature\nwallet in both software")]),e._v(" "),t("li",[e._v("Express the consent of each party by partially signing the transaction in a way\nthe other wallet can understand and complete it with its own signature.")])]),e._v(" "),t("p",[e._v("The infrastructure of multiple Extended keys combined toghether to produce\nmultiple multisignature addresses is often referred as\n"),t("em",[t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("Hierarchical Deterministic"),t("OutboundLink")],1),e._v(" multi signature wallet or HDM")]),e._v(".")]),e._v(" "),t("p",[e._v("What follows are the steps to create the HDM usable both in Core and\nin BDK.")]),e._v(" "),t("p",[t("em",[e._v("Note: In Core, "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/pull/16528",target:"_blank",rel:"noopener noreferrer"}},[e._v("Descriptor wallets"),t("OutboundLink")],1),e._v(" are still experimental and in general,\nboth wallets should be tested for descriptor capabilities only in testnet.")])]),e._v(" "),t("h2",{attrs:{id:"our-playground"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#our-playground"}},[e._v("#")]),e._v(" Our playground")]),e._v(" "),t("p",[e._v("We will build a 2of2 key set up that will be used cooperatively by Bitcoin Core\nand Bitcoin Development Kit.\nThe steps Alice and Bob will do are:")]),e._v(" "),t("ol",[t("li",[e._v("creation of the seed and the derived Extended Master Public and send it to\nthe other party")]),e._v(" "),t("li",[e._v("Create the multi signature descriptor for each wallet")]),e._v(" "),t("li",[e._v("Use each other's software to receive testnet coins from a faucet")]),e._v(" "),t("li",[e._v("return part of the coins to the faucet signing the transaction with both\nwallets.")])]),e._v(" "),t("p",[e._v("We need:")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Dev Kit"),t("OutboundLink")],1)]),e._v(" "),t("li",[t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Core"),t("OutboundLink")],1),e._v(" (v0.21.0 or later)")])]),e._v(" "),t("h3",{attrs:{id:"1-creating-the-seeds-and-the-derived-extended-public-keys"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#1-creating-the-seeds-and-the-derived-extended-public-keys"}},[e._v("#")]),e._v(" 1. Creating the seeds and the derived Extended Public keys")]),e._v(" "),t("h4",{attrs:{id:"seeds-and-extended-master-public"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#seeds-and-extended-master-public"}},[e._v("#")]),e._v(" Seeds and Extended Master Public")]),e._v(" "),t("p",[e._v("We build an Extended Private Master Key for both wallet and derive a BIP84\nExtended Master Public for Bitcoin Core and then for BDK.")]),e._v(" "),t("p",[e._v("For Bitcoin Core (Alice):")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("# new Extended wallet data\nexport core_key=$(bdk-cli key generate)\n\n# New Extended Master Private\n\nexport core_xprv=$(echo $core_key | jq -r '.xprv')\n\n# Now I derive the xpubs (one for receiving and one for the change)\n# together with informations about the derivation path to be communicated\n# to BDK wallet's owner (Bob).\n\nexport core_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $core_xprv | jq -r '.xpub')\nexport core_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $core_xprv | jq -r '.xpub')\n")])])]),t("p",[e._v("For BDK (Bob) we do the same:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("# new Extended wallet data\n\nexport BDK_key=$(bdk-cli key generate)\n\n# New Extended Master Private\n\nexport BDK_xprv=$(echo $BDK_key | jq -r '.xprv')\n\n# Now I build the derived xpubs to be communicated (to Alice).\n\nexport BDK_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $BDK_xprv | jq -r '.xpub')\nexport BDK_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $BDK_xprv | jq -r '.xpub')\n")])])]),t("h3",{attrs:{id:"2-creation-of-the-multi-signature-descriptor-for-each-wallet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#2-creation-of-the-multi-signature-descriptor-for-each-wallet"}},[e._v("#")]),e._v(" 2. Creation of the multi signature descriptor for each wallet")]),e._v(" "),t("p",[e._v("To build a multisig wallet, each wallet owner must compose the descriptor\nadding:")]),e._v(" "),t("ul",[t("li",[e._v("his derived extended "),t("strong",[e._v("private")]),e._v(" key AND")]),e._v(" "),t("li",[e._v("all the extended "),t("strong",[e._v("public")]),e._v(" keys of the other wallets involved in the\nmulti signature setup")])]),e._v(" "),t("p",[t("em",[e._v("The different nature of the two keys (one is private and one is public) is\ndue to the fact that each wallet, to be able to partially sign the transaction,\n"),t("strong",[e._v("must manage the private key of the wallet's owner")])]),e._v(" AND have the other\nparty's public key. Otherwise, if we put both public keys, we would obtain\na watch-only wallet unable to sign the transactions. If we\nhad both extended private keys inside the descriptor, we would allow each party\nto finalize the transactions autonomously.")]),e._v(" "),t("h4",{attrs:{id:"in-bitcoin-core"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bitcoin-core"}},[e._v("#")]),e._v(" In Bitcoin Core:")]),e._v(" "),t("p",[e._v("In our case, the multi signature descriptor for Bitcoin Core will be composed\nwith:")]),e._v(" "),t("ul",[t("li",[e._v("The BIP84 derived Extended "),t("strong",[e._v("Public")]),e._v(" Key from BDK")]),e._v(" "),t("li",[e._v("The BIP84 derived Extended "),t("strong",[e._v("Private")]),e._v(" Key from Core.")])]),e._v(" "),t("p",[e._v("BDK wallet's owner will send to Core's owner the derived xpub for this purpose.\nThis is how the Core's multisig descriptor will be created and put into an\nenvironment variable:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_rec_desc=\"wsh(multi(2,$BDK_xpub_84_for_rec_desc,$core_xprv/84'/0'/0'/0/*))\"\n")])])]),t("p",[e._v("Where of course "),t("code",[e._v("$BDK_xpub_84_for_rec_desc")]),e._v("is the derived master public created\nin BDK and received by Core's owner.")]),e._v(" "),t("p",[e._v("The meaning of what is before and after is illustrated in the doc that explain\nthe use of "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors in Bitcoin Core"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("We add the necessary checksum using the specific "),t("code",[e._v("bitcoin-cli")]),e._v(" call.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_rec_desc_chksum=$core_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_rec_desc | jq -r '.checksum')\n")])])]),t("p",[e._v("We repeat the same to build the descriptor to receive the change.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export core_chg_desc=\"wsh(multi(2,$BDK_xpub_84_for_chg_desc,$core_xprv/84'/0'/0'/1/*))\"\nexport core_chg_desc_chksum=$core_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_chg_desc|jq -r '.checksum')\n")])])]),t("h4",{attrs:{id:"in-bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bdk"}},[e._v("#")]),e._v(" In BDK:")]),e._v(" "),t("p",[e._v("For BDK we set the derivation for receiving addresses and change addresses\nin the command line (maybe setting an alias)")]),e._v(" "),t("p",[e._v("Building the descriptor:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export BDK_rec_desc=\"wsh(multi(2,$BDK_xprv/84'/0'/0'/0/*,$core_xpub_84_for_rec_desc))\"`\n")])])]),t("p",[e._v("Please note that the order of the extended key in the descriptor MUST be the\nsame in the 2 wallets.")]),e._v(" "),t("p",[t("em",[e._v("We have chosen to put BDK first and in each software wallet, the public key\nderived from BDK will always come first. In alternative, we could have chosen to\nproduce the descriptor, "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/pull/17056?ref=tokendaily",target:"_blank",rel:"noopener noreferrer"}},[e._v("chosing a "),t("code",[e._v("soretedmulti")]),e._v(" multisignature setup"),t("OutboundLink")],1)]),e._v(".")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export BDK_rec_desc_chksum=$BDK_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_rec_desc | jq -r '.checksum')\nexport BDK_chg_desc=\"wsh(multi(2,$BDK_xprv/84'/0'/0'/1/*,$core_xpub_84_for_chg_desc))\"\nexport BDK_chg_desc_chksum=$BDK_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_chg_desc | jq -r '.checksum')\n")])])]),t("p",[e._v("To take a look at the variables we have produced so far:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("env | grep 'core_'\nenv | grep 'BDK_'\n")])])]),t("p",[e._v("Now we will use the multisig descriptor wallet to receive testnet coins with\nAlice and Bob's software")]),e._v(" "),t("h3",{attrs:{id:"3-use-each-others-software-to-receive-testnet-coins-from-a-faucet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#3-use-each-others-software-to-receive-testnet-coins-from-a-faucet"}},[e._v("#")]),e._v(" 3. Use each other's software to receive testnet coins from a faucet")]),e._v(" "),t("h4",{attrs:{id:"in-bitcoin-core-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#in-bitcoin-core-2"}},[e._v("#")]),e._v(" In Bitcoin Core")]),e._v(" "),t("p",[e._v('Alice must create an empty, experimental new "descriptors wallet" in Core and\nto import the multisig Output Descriptor.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('bitcoin-cli -testnet createwallet "multisig2of2withBDK" false true "" false true false\n')])])]),t("p",[e._v("The flag are to:")]),e._v(" "),t("ul",[t("li",[e._v("use the private keys")]),e._v(" "),t("li",[e._v("make it empty")]),e._v(" "),t("li",[e._v("no password provided to the wallet")]),e._v(" "),t("li",[e._v("reusing of addresses not allowed")]),e._v(" "),t("li",[e._v('"new experimental descriptors wallet"')]),e._v(" "),t("li",[e._v("don't load it on start up")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK importdescriptors "[{\\"desc\\":\\"$core_rec_desc_chksum\\",\\"timestamp\\":\\"now\\",\\"active\\":true,\\"internal\\":false},{\\"desc\\":\\"$core_chg_desc_chksum\\",\\"timestamp\\":\\"now\\",\\"active\\":true,\\"internal\\":true}]"\n')])])]),t("p",[e._v("Now Alice asks for her first receiving multisignature address.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("export first_address=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getnewaddress)\necho $first_address\n")])])]),t("h4",{attrs:{id:"bdk"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#bdk"}},[e._v("#")]),e._v(" BDK")]),e._v(" "),t("p",[e._v("In BDK Bob can specify directly the descriptors on the command line to produce\nthe multisig address, because BDK is descriptors aware natively.")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_new_address`\n')])])]),t("p",[e._v('Et voilà: if we have done everything correctly, the newly created address in\nCore is the same of the newly created address in BDK. this is part of the\n"miracle" of descriptors\' interoperability.')]),e._v(" "),t("h4",{attrs:{id:"we-ask-for-testnet-coins-giving-the-first-created-address"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#we-ask-for-testnet-coins-giving-the-first-created-address"}},[e._v("#")]),e._v(" We ask for testnet coins giving the first created address.")]),e._v(" "),t("p",[e._v('To find testnet coins for free, you can just google "testnet faucet" and you\nshould find some satoshis to play with. Just give to the site your first\ngenerated address and, in twenty minutes, you will find the satoshis in\nyour balance both in Core and in BDK.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('# to check it in Core:\n\nbitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getbalance\n\n# In BDK:\n\n# Sync with the blockchain\nrepl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sync\n# Get the balance\nrepl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_balance\n')])])]),t("p",[e._v("Some testnet faucets have an address to send back the unused satoshi after\nthe use. Take note of that because we will use it in the next step.")]),e._v(" "),t("h3",{attrs:{id:"4-we-return-part-of-the-satoshis-received-back-to-the-faucet"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#4-we-return-part-of-the-satoshis-received-back-to-the-faucet"}},[e._v("#")]),e._v(" 4. we return part of the satoshis received back to the faucet")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletcreatefundedpsbt "[]" "[{\\"tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a\\":0.000012}]" | jq -r \'.psbt\')\n\nexport psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletprocesspsbt $psbt | jq -r \'.psbt\')\n{\n "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAQEFR1IhArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvIQNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfVKuIgYCufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8YNEw2cFQAAIAAAACAAAAAgAAAAAAAAAAAIgYDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH0YO/laXFQAAIAAAACAAAAAgAAAAAAAAAAAAAEBR1IhAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcIQLHKhjmPuCQjyS77ZfaMN2tdgNKcf/+57VXGZhz/UWTl1KuIgICpxy8DesvXcPUrgZ5aNxqEOw7c/yhpU0G22TgyUIpchwYNEw2cFQAAIAAAACAAAAAgAEAAAADAAAAIgICxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5cYO/laXFQAAIAAAACAAAAAgAEAAAADAAAAAAA=",\n "complete": false\n}\n')])])]),t("p",[e._v("Exactly! Note the "),t("code",[e._v('"complete": false')]),e._v(". We have processed the transaction with\nCore but we miss one of the necessary key of the multisig 2of2 setup (The one\ncontained inside BDK).")]),e._v(" "),t("p",[t("code",[e._v("tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a")]),e._v(" is the address\nwe got from the faucet site to return the satoshis.")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("PSBT"),t("OutboundLink")],1),e._v(" is sent over to the BDK wallet owner who tries to sign the\ntransaction:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sign --psbt $psbt\n{\n "is_finalized": true,\n "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA"\n}\n')])])]),t("p",[e._v('The signature has succeded (note the "is_finalized": true,) and now we can\nbroadcast the transction.')]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint broadcast --psbt "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA"\n{\n "txid": "a0b082e3b0579822d4a0b0fa95a4c4662f6b128ffd43fdcfe53c37473ce85dee"\n}\n')])])]),t("h2",{attrs:{id:"conclusion"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion"}},[e._v("#")]),e._v(" Conclusion")]),e._v(" "),t("p",[e._v("We have built an HDM and we have used it with two indipendent wallets, which\nare compatible with "),t("a",{attrs:{href:"https://en.bitcoin.it/wiki/BIP_0174",target:"_blank",rel:"noopener noreferrer"}},[e._v("BIP 174"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://bitcoinops.org/en/topics/output-script-descriptors/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Output Descriptors"),t("OutboundLink")],1),e._v(". Hopefully we\nwill see many other compatible wallets beyound "),t("a",{attrs:{href:"https://bitcoincore.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Bitcoin Core"),t("OutboundLink")],1),e._v(" and "),t("a",{attrs:{href:"https://bitcoindevkit.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("BDK"),t("OutboundLink")],1),e._v(",\nwith which we will be able to easily set up multi signature schemes.")])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/47.95bbbc17.js b/assets/js/47.a9e58080.js similarity index 99% rename from assets/js/47.95bbbc17.js rename to assets/js/47.a9e58080.js index c1e622d567..bc732699c8 100644 --- a/assets/js/47.95bbbc17.js +++ b/assets/js/47.a9e58080.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{395:function(e,t,a){"use strict";a.r(t);var o=a(7),n=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 1 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#introduction-what-is-fee-estimation"}},[e._v("Introduction: what is fee estimation?")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-problem"}},[e._v("The problem")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-challenges-and-the-solution"}},[e._v("The challenges and the solution")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-question"}},[e._v("The question")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-data-logger"}},[e._v("The data logger")])])])])]),e._v(" "),t("h2",{attrs:{id:"introduction-what-is-fee-estimation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction-what-is-fee-estimation"}},[e._v("#")]),e._v(" Introduction: what is fee estimation?")]),e._v(" "),t("p",[e._v("Fee estimation is the process of selecting the fee rate"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" for a bitcoin transaction being created, according to two main factors:")]),e._v(" "),t("ul",[t("li",[e._v("The current congestion of the Bitcoin network.")]),e._v(" "),t("li",[e._v("The urgency, or lack thereof, for the transaction confirmation, i.e, its inclusion in a block.")])]),e._v(" "),t("p",[e._v("A fee rate should be adequate to the above factors: a fee too high would be a waste of money, because the same result could have been achieved with a lower expense. On the other hand, a fee rate too low would wait for a confirmation longer than planned or, even worse, the transaction could not be confirmed at all.")]),e._v(" "),t("h2",{attrs:{id:"the-problem"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-problem"}},[e._v("#")]),e._v(" The problem")]),e._v(" "),t("p",[e._v("Bitcoin Core offers fee estimation through the "),t("a",{attrs:{href:"https://bitcoincore.org/en/doc/0.20.0/rpc/util/estimatesmartfee/",target:"_blank",rel:"noopener noreferrer"}},[t("code",[e._v("estimatesmartfee")]),t("OutboundLink")],1),e._v(" RPC method, and there are also a lot of third-party "),t("a",{attrs:{href:"https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/",target:"_blank",rel:"noopener noreferrer"}},[e._v("fee estimators"),t("OutboundLink")],1),e._v(" online, so do we need yet another estimator?")]),e._v(" "),t("p",[e._v("The model used by Bitcoin Core is not well suited for light-clients such as mobile wallets, even when running in pruned mode. Online estimators are lacking in terms of:")]),e._v(" "),t("ul",[t("li",[e._v("Privacy: Contacting the server leaks your IP (unless you are using Tor or a VPN), and the request timing may be used to correlate the request to a transaction broadcasted to the network soon thereafter.")]),e._v(" "),t("li",[e._v("Security: A malicious estimator could provide a high fee rate leading to a waste of money, or a low fee rate hampering the transaction confirmation.")])]),e._v(" "),t("p",[e._v("Replace By Fee (RBF) and Child Pays For Parent (CPFP) are techniques that can somewhat minimize the fee estimation problem, because one could simply underestimate the fee rate and then raise it when necessary, however:")]),e._v(" "),t("ul",[t("li",[e._v("RBF and CPFP may leak more information, such as patterns that may allow to detect the kind of wallet used, or which one of the transaction outputs is the change.")]),e._v(" "),t("li",[e._v('Requires additional interaction: the client must come back "online" to perform the fee bump. Sometimes this might be impractical or risky, for instance when using an offline signer or a multisignature with geographically distributed keys.')])]),e._v(" "),t("p",[e._v("Thus, this work is an effort to build a "),t("strong",[e._v("good fee estimator for purely peer to peer light clients")]),e._v(" such as "),t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("neutrino"),t("OutboundLink")],1),e._v(" based ones, or at least determine whether the approach we take is infeasible and open the discussion\nfor other, better, models.")]),e._v(" "),t("p",[e._v("In the meantime, another sub-goal is pursued: attract the interest of data scientists; Indeed the initial step for this analysis consists in constructing a data set, which could also also help kickstart other studies on fee estimation or, more broadly, on the Bitcoin mempool.")]),e._v(" "),t("h4",{attrs:{id:"the-challenges-and-the-solution"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-challenges-and-the-solution"}},[e._v("#")]),e._v(" The challenges and the solution")]),e._v(" "),t("p",[e._v("The hardest part of doing fee estimation on a light client is the lack of information: for example, Bitcoin Core's "),t("code",[e._v("estimatesmartfee")]),e._v(" uses up to the last 1008 blocks and knows everything about the mempool"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(", such as the fee rate of every transaction it contains, but a light-client does not.")]),e._v(" "),t("p",[e._v("Also, there are other factors that may help doing fee estimation, such as the day of the week (the mempool usually empties during the "),t("a",{attrs:{href:"https://www.blockchainresearchlab.org/2020/03/30/a-week-with-bitcoin-transaction-timing-and-transaction-fees/",target:"_blank",rel:"noopener noreferrer"}},[e._v("weekend"),t("OutboundLink")],1),e._v(") or the time of the day to anticipate recurring daily events\n(such as the batch of "),t("a",{attrs:{href:"https://b10c.me/mempool-observations/2-bitmex-broadcast-13-utc/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitmex withdrawals"),t("OutboundLink")],1),e._v(").")]),e._v(" "),t("p",[e._v("The idea is to apply Machine Learning (ML) techniques"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(" to discover patterns over what a light-client knows and see if they are enough to achieve consistently good estimations.")]),e._v(" "),t("h4",{attrs:{id:"the-question"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-question"}},[e._v("#")]),e._v(" The question")]),e._v(" "),t("p",[e._v('We are going to use a DNN (Deep Neural Network), a ML technique in the supervised learning branch. The "ELI5" is: give a lot of example inputs and the desired output to a black box; if there are correlations between inputs and outputs,\nand there are enough examples, the black box will eventually start predicting the correct output even with inputs it has never seen before.')]),e._v(" "),t("p",[e._v("To define our inputs and outputs, we need to start from the question we want to answer. For a fee estimator this is:")]),e._v(" "),t("p",[t("em",[e._v('"Which minimum fee rate should I use if I want this transaction to be confirmed in at most '),t("code",[e._v("n")]),e._v(' blocks?"')])]),e._v(" "),t("p",[e._v("This can be translated to a table with many rows like:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("confirms_in")]),e._v(" "),t("th",[e._v("other_information")]),e._v(" "),t("th",[e._v("fee_rate")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("1")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("100.34")])]),e._v(" "),t("tr",[t("td",[e._v("2")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("84.33")])]),e._v(" "),t("tr",[t("td",[e._v("10")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("44.44")])])])]),e._v(" "),t("p",[e._v("where the "),t("code",[e._v("fee_rate")]),e._v(' column is the output we want, also called the "'),t("em",[e._v("target")]),e._v('" or "'),t("em",[e._v("label")]),e._v('" in ML terminology, and the other columns are our inputs.')]),e._v(" "),t("p",[e._v("Can we build this table just by looking at the Bitcoin blockchain? Unfortunately, we can't:\nThe main thing that's missing is an indication of when the node first saw a transaction that has been later confirmed in a block. With that knowledge we can say that the fee rate of that transaction was the exact value required to confirm\nwithin the number of blocks it actually took to be confirmed. For instance, if we see transaction "),t("code",[e._v("t")]),e._v(" when the blockchain is at height "),t("code",[e._v("1000")]),e._v(" and then we notice that "),t("code",[e._v("t")]),e._v(" has been included in block "),t("code",[e._v("1006")]),e._v(", we can deduce that the\nfee rate paid by "),t("code",[e._v("t")]),e._v(" was the exact value required to get confirmed within the next "),t("code",[e._v("6")]),e._v(" blocks.")]),e._v(" "),t("p",[e._v("So to build our model, we first need to gather these data, and machine learning needs a "),t("em",[e._v("lot")]),e._v(" of data to work well.")]),e._v(" "),t("h4",{attrs:{id:"the-data-logger"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-data-logger"}},[e._v("#")]),e._v(" The data logger")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger",target:"_blank",rel:"noopener noreferrer"}},[e._v("data logger"),t("OutboundLink")],1),e._v(" is built with the purpose of collecting all the data we need, and it's MIT licensed open source software written in Rust.")]),e._v(" "),t("p",[e._v("We need to register the moment in time when transactions enter in the node's mempool; to be efficient and precise we should not only call the RPC endpoints but listen to "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("ZMQ"),t("OutboundLink")],1),e._v(" events. Luckily, the just released bitcoin core 0.21.0 added a new "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("ZMQ"),t("OutboundLink")],1),e._v(" topic "),t("code",[e._v("zmqpubsequence")]),e._v(" notifying mempool events (and block events). The logger is also listening to "),t("code",[e._v("zmqpubrawtx")]),e._v(" and "),t("code",[e._v("zmqpubrawblock")]),e._v(" topics, to make less RPC calls.")]),e._v(" "),t("p",[e._v("We are not only interested in the timestamp of the transaction entering the mempool, but also how many blocks it will take until the same transaction is confirmed.\nIn the final dataset this field is called "),t("code",[e._v("confirms_in")]),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v("; if "),t("code",[e._v("confirms_in = 1")]),e._v(" it means the transaction is confirmed in the first block created after it has been seen for the first time.")]),e._v(" "),t("p",[e._v("Another critical piece of information logged by the data logger is the "),t("code",[e._v("fee_rate")]),e._v(" of the transaction, since the absolute fee value paid by a bitcoin transaction is not available nor derivable given only the transaction itself, as the inputs don't have explicit amounts.")]),e._v(" "),t("p",[e._v("All these data (apart from the time of the transaction entering in the mempool) can actually be reconstructed simply by looking at the blockchain. However, querying the bitcoin node can be fairly slow, and during the model training iterations we want to recreate the ML dataset rapidly"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn5",id:"fnref5"}},[e._v("[5]")])]),e._v(", for example whenever we need to modify or add a new field.")]),e._v(" "),t("p",[e._v("For these reasons, the logger is split into two parts: a process listening to the events sent by our node, which creates raw logs, and then a second process that uses these logs to create the final CSV dataset.\nRaw logs are self-contained: for example, they contain all the previous transaction output values for every relevant transaction. This causes some redundancy, but in this case it's better to trade some efficiency for more performance\nwhen recreating the dataset.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/high-level-graph.svg",alt:"High level graph"}})]),e._v(" "),t("p",[e._v("My logger instance started collecting data on the 18th of December 2020, and as of today (25th January 2020), the raw logs are about 16GB.")]),e._v(" "),t("p",[e._v("I expect (or at least hope) the raw logs, the CSV dataset, or the data logger will be useful also for other projects as well, like monitoring the propagation of transactions or other works involving raw mempool data. We will share raw logs data through torrent soon.")]),e._v(" "),t("p",[e._v("In the following "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(" we are going to talk about the dataset.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("The transaction fee rate is the ratio between the absolute fee expressed in satoshi, over the weight of the transaction measured in virtual bytes. The weight of the transaction is similar to the byte size, however a part of the transaction (the segwit part) is discounted, their byte size is considered less because it creates less burden for the network. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("mempool is the set of transactions that are valid by consensus rules (for example, they are spending existing bitcoin), broadcasted in the bitcoin peer to peer network, but they are not yet part of the blockchain. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("DISCLAIMER: I am not an expert data-scientist! "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("Conceptually similar to bitcoin core "),t("code",[e._v("estimatesmartfee")]),e._v(' parameter called "blocks target", however, '),t("code",[e._v("confirms_in")]),e._v(" is the real value not the desired target. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn5"}},[t("p",[e._v("16GB of compressed raw logs are processed and a compressed CSV produced in about 5 minutes. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref5"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{397:function(e,t,a){"use strict";a.r(t);var o=a(7),n=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 1 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#introduction-what-is-fee-estimation"}},[e._v("Introduction: what is fee estimation?")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-problem"}},[e._v("The problem")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-challenges-and-the-solution"}},[e._v("The challenges and the solution")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-question"}},[e._v("The question")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-data-logger"}},[e._v("The data logger")])])])])]),e._v(" "),t("h2",{attrs:{id:"introduction-what-is-fee-estimation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#introduction-what-is-fee-estimation"}},[e._v("#")]),e._v(" Introduction: what is fee estimation?")]),e._v(" "),t("p",[e._v("Fee estimation is the process of selecting the fee rate"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" for a bitcoin transaction being created, according to two main factors:")]),e._v(" "),t("ul",[t("li",[e._v("The current congestion of the Bitcoin network.")]),e._v(" "),t("li",[e._v("The urgency, or lack thereof, for the transaction confirmation, i.e, its inclusion in a block.")])]),e._v(" "),t("p",[e._v("A fee rate should be adequate to the above factors: a fee too high would be a waste of money, because the same result could have been achieved with a lower expense. On the other hand, a fee rate too low would wait for a confirmation longer than planned or, even worse, the transaction could not be confirmed at all.")]),e._v(" "),t("h2",{attrs:{id:"the-problem"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-problem"}},[e._v("#")]),e._v(" The problem")]),e._v(" "),t("p",[e._v("Bitcoin Core offers fee estimation through the "),t("a",{attrs:{href:"https://bitcoincore.org/en/doc/0.20.0/rpc/util/estimatesmartfee/",target:"_blank",rel:"noopener noreferrer"}},[t("code",[e._v("estimatesmartfee")]),t("OutboundLink")],1),e._v(" RPC method, and there are also a lot of third-party "),t("a",{attrs:{href:"https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/",target:"_blank",rel:"noopener noreferrer"}},[e._v("fee estimators"),t("OutboundLink")],1),e._v(" online, so do we need yet another estimator?")]),e._v(" "),t("p",[e._v("The model used by Bitcoin Core is not well suited for light-clients such as mobile wallets, even when running in pruned mode. Online estimators are lacking in terms of:")]),e._v(" "),t("ul",[t("li",[e._v("Privacy: Contacting the server leaks your IP (unless you are using Tor or a VPN), and the request timing may be used to correlate the request to a transaction broadcasted to the network soon thereafter.")]),e._v(" "),t("li",[e._v("Security: A malicious estimator could provide a high fee rate leading to a waste of money, or a low fee rate hampering the transaction confirmation.")])]),e._v(" "),t("p",[e._v("Replace By Fee (RBF) and Child Pays For Parent (CPFP) are techniques that can somewhat minimize the fee estimation problem, because one could simply underestimate the fee rate and then raise it when necessary, however:")]),e._v(" "),t("ul",[t("li",[e._v("RBF and CPFP may leak more information, such as patterns that may allow to detect the kind of wallet used, or which one of the transaction outputs is the change.")]),e._v(" "),t("li",[e._v('Requires additional interaction: the client must come back "online" to perform the fee bump. Sometimes this might be impractical or risky, for instance when using an offline signer or a multisignature with geographically distributed keys.')])]),e._v(" "),t("p",[e._v("Thus, this work is an effort to build a "),t("strong",[e._v("good fee estimator for purely peer to peer light clients")]),e._v(" such as "),t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("neutrino"),t("OutboundLink")],1),e._v(" based ones, or at least determine whether the approach we take is infeasible and open the discussion\nfor other, better, models.")]),e._v(" "),t("p",[e._v("In the meantime, another sub-goal is pursued: attract the interest of data scientists; Indeed the initial step for this analysis consists in constructing a data set, which could also also help kickstart other studies on fee estimation or, more broadly, on the Bitcoin mempool.")]),e._v(" "),t("h4",{attrs:{id:"the-challenges-and-the-solution"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-challenges-and-the-solution"}},[e._v("#")]),e._v(" The challenges and the solution")]),e._v(" "),t("p",[e._v("The hardest part of doing fee estimation on a light client is the lack of information: for example, Bitcoin Core's "),t("code",[e._v("estimatesmartfee")]),e._v(" uses up to the last 1008 blocks and knows everything about the mempool"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(", such as the fee rate of every transaction it contains, but a light-client does not.")]),e._v(" "),t("p",[e._v("Also, there are other factors that may help doing fee estimation, such as the day of the week (the mempool usually empties during the "),t("a",{attrs:{href:"https://www.blockchainresearchlab.org/2020/03/30/a-week-with-bitcoin-transaction-timing-and-transaction-fees/",target:"_blank",rel:"noopener noreferrer"}},[e._v("weekend"),t("OutboundLink")],1),e._v(") or the time of the day to anticipate recurring daily events\n(such as the batch of "),t("a",{attrs:{href:"https://b10c.me/mempool-observations/2-bitmex-broadcast-13-utc/",target:"_blank",rel:"noopener noreferrer"}},[e._v("bitmex withdrawals"),t("OutboundLink")],1),e._v(").")]),e._v(" "),t("p",[e._v("The idea is to apply Machine Learning (ML) techniques"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(" to discover patterns over what a light-client knows and see if they are enough to achieve consistently good estimations.")]),e._v(" "),t("h4",{attrs:{id:"the-question"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-question"}},[e._v("#")]),e._v(" The question")]),e._v(" "),t("p",[e._v('We are going to use a DNN (Deep Neural Network), a ML technique in the supervised learning branch. The "ELI5" is: give a lot of example inputs and the desired output to a black box; if there are correlations between inputs and outputs,\nand there are enough examples, the black box will eventually start predicting the correct output even with inputs it has never seen before.')]),e._v(" "),t("p",[e._v("To define our inputs and outputs, we need to start from the question we want to answer. For a fee estimator this is:")]),e._v(" "),t("p",[t("em",[e._v('"Which minimum fee rate should I use if I want this transaction to be confirmed in at most '),t("code",[e._v("n")]),e._v(' blocks?"')])]),e._v(" "),t("p",[e._v("This can be translated to a table with many rows like:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("confirms_in")]),e._v(" "),t("th",[e._v("other_information")]),e._v(" "),t("th",[e._v("fee_rate")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("1")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("100.34")])]),e._v(" "),t("tr",[t("td",[e._v("2")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("84.33")])]),e._v(" "),t("tr",[t("td",[e._v("10")]),e._v(" "),t("td",[e._v("...")]),e._v(" "),t("td",[e._v("44.44")])])])]),e._v(" "),t("p",[e._v("where the "),t("code",[e._v("fee_rate")]),e._v(' column is the output we want, also called the "'),t("em",[e._v("target")]),e._v('" or "'),t("em",[e._v("label")]),e._v('" in ML terminology, and the other columns are our inputs.')]),e._v(" "),t("p",[e._v("Can we build this table just by looking at the Bitcoin blockchain? Unfortunately, we can't:\nThe main thing that's missing is an indication of when the node first saw a transaction that has been later confirmed in a block. With that knowledge we can say that the fee rate of that transaction was the exact value required to confirm\nwithin the number of blocks it actually took to be confirmed. For instance, if we see transaction "),t("code",[e._v("t")]),e._v(" when the blockchain is at height "),t("code",[e._v("1000")]),e._v(" and then we notice that "),t("code",[e._v("t")]),e._v(" has been included in block "),t("code",[e._v("1006")]),e._v(", we can deduce that the\nfee rate paid by "),t("code",[e._v("t")]),e._v(" was the exact value required to get confirmed within the next "),t("code",[e._v("6")]),e._v(" blocks.")]),e._v(" "),t("p",[e._v("So to build our model, we first need to gather these data, and machine learning needs a "),t("em",[e._v("lot")]),e._v(" of data to work well.")]),e._v(" "),t("h4",{attrs:{id:"the-data-logger"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-data-logger"}},[e._v("#")]),e._v(" The data logger")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger",target:"_blank",rel:"noopener noreferrer"}},[e._v("data logger"),t("OutboundLink")],1),e._v(" is built with the purpose of collecting all the data we need, and it's MIT licensed open source software written in Rust.")]),e._v(" "),t("p",[e._v("We need to register the moment in time when transactions enter in the node's mempool; to be efficient and precise we should not only call the RPC endpoints but listen to "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("ZMQ"),t("OutboundLink")],1),e._v(" events. Luckily, the just released bitcoin core 0.21.0 added a new "),t("a",{attrs:{href:"https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("ZMQ"),t("OutboundLink")],1),e._v(" topic "),t("code",[e._v("zmqpubsequence")]),e._v(" notifying mempool events (and block events). The logger is also listening to "),t("code",[e._v("zmqpubrawtx")]),e._v(" and "),t("code",[e._v("zmqpubrawblock")]),e._v(" topics, to make less RPC calls.")]),e._v(" "),t("p",[e._v("We are not only interested in the timestamp of the transaction entering the mempool, but also how many blocks it will take until the same transaction is confirmed.\nIn the final dataset this field is called "),t("code",[e._v("confirms_in")]),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v("; if "),t("code",[e._v("confirms_in = 1")]),e._v(" it means the transaction is confirmed in the first block created after it has been seen for the first time.")]),e._v(" "),t("p",[e._v("Another critical piece of information logged by the data logger is the "),t("code",[e._v("fee_rate")]),e._v(" of the transaction, since the absolute fee value paid by a bitcoin transaction is not available nor derivable given only the transaction itself, as the inputs don't have explicit amounts.")]),e._v(" "),t("p",[e._v("All these data (apart from the time of the transaction entering in the mempool) can actually be reconstructed simply by looking at the blockchain. However, querying the bitcoin node can be fairly slow, and during the model training iterations we want to recreate the ML dataset rapidly"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn5",id:"fnref5"}},[e._v("[5]")])]),e._v(", for example whenever we need to modify or add a new field.")]),e._v(" "),t("p",[e._v("For these reasons, the logger is split into two parts: a process listening to the events sent by our node, which creates raw logs, and then a second process that uses these logs to create the final CSV dataset.\nRaw logs are self-contained: for example, they contain all the previous transaction output values for every relevant transaction. This causes some redundancy, but in this case it's better to trade some efficiency for more performance\nwhen recreating the dataset.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/high-level-graph.svg",alt:"High level graph"}})]),e._v(" "),t("p",[e._v("My logger instance started collecting data on the 18th of December 2020, and as of today (25th January 2020), the raw logs are about 16GB.")]),e._v(" "),t("p",[e._v("I expect (or at least hope) the raw logs, the CSV dataset, or the data logger will be useful also for other projects as well, like monitoring the propagation of transactions or other works involving raw mempool data. We will share raw logs data through torrent soon.")]),e._v(" "),t("p",[e._v("In the following "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(" we are going to talk about the dataset.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("The transaction fee rate is the ratio between the absolute fee expressed in satoshi, over the weight of the transaction measured in virtual bytes. The weight of the transaction is similar to the byte size, however a part of the transaction (the segwit part) is discounted, their byte size is considered less because it creates less burden for the network. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("mempool is the set of transactions that are valid by consensus rules (for example, they are spending existing bitcoin), broadcasted in the bitcoin peer to peer network, but they are not yet part of the blockchain. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("DISCLAIMER: I am not an expert data-scientist! "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("Conceptually similar to bitcoin core "),t("code",[e._v("estimatesmartfee")]),e._v(' parameter called "blocks target", however, '),t("code",[e._v("confirms_in")]),e._v(" is the real value not the desired target. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn5"}},[t("p",[e._v("16GB of compressed raw logs are processed and a compressed CSV produced in about 5 minutes. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref5"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/48.f74437f6.js b/assets/js/48.9a448976.js similarity index 99% rename from assets/js/48.f74437f6.js rename to assets/js/48.9a448976.js index fc72b1b1ab..57f33f52d7 100644 --- a/assets/js/48.f74437f6.js +++ b/assets/js/48.9a448976.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{398:function(e,t,a){"use strict";a.r(t);var o=a(7),n=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 2 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-dataset"}},[e._v("The dataset")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-mempool"}},[e._v("The mempool")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-outliers"}},[e._v("The outliers")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#recap"}},[e._v("Recap")])])])])]),e._v(" "),t("h2",{attrs:{id:"the-dataset"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-dataset"}},[e._v("#")]),e._v(" The dataset")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz",target:"_blank",rel:"noopener noreferrer"}},[e._v("dataset"),t("OutboundLink")],1),e._v(" is publicly available (~500MB gzip compressed, ~2GB as plain CSV).")]),e._v(" "),t("p",[e._v("The output of the model is the fee rate, expressed in "),t("code",[e._v("[satoshi/vbytes]")]),e._v(".")]),e._v(" "),t("p",[e._v("What about the inputs? Generally speaking, we have two main requirements for what can be included as input for our model:")]),e._v(" "),t("ul",[t("li",[e._v("It must be correlated to the output, even with a non-linear relation.")]),e._v(" "),t("li",[e._v("It must be available to a light client: for instance, assuming to have knowledge and an index of the last 1000 blocks is considered too much.")])]),e._v(" "),t("p",[e._v("To evaluate the approach we are taking, we also want to compare our model's results with another available estimation: for this reason the dataset includes data to compute the error agains Bitcoin Core's "),t("code",[e._v("estimatesmartfee")]),e._v(" results, even though we are not going to use it for this model.")]),e._v(" "),t("p",[e._v("The dataset will contain only transactions that spend already confirmed inputs. If we wanted to include transactions with unconfirmed inputs as well, the fee rate would have to be computed as a whole;\nfor example if transaction "),t("code",[e._v("t2")]),e._v(" spends an unconfirmed input from "),t("code",[e._v("t1")]),e._v(" (while "),t("code",[e._v("t1")]),e._v(" only spends confirmed inputs, and all its other outputs are unspent), the aggregated fee rate would have to be used.\nSupposing "),t("code",[e._v("f()")]),e._v(" is extracts the absolute fee and "),t("code",[e._v("w()")]),e._v(" the transaction weight, the aggregated fee rate would be "),t("code",[e._v("(f(t1) + f(t2)) / (w(t1) + w(t2))")]),e._v(". Thus, as already said previously, to keep things simple the model simply discards all the transaction\nthat would need to perform this computation.")]),e._v(" "),t("p",[e._v("For the same reason the dataset has the "),t("code",[e._v("parent_in_cpfp")]),e._v(" flag. When a transaction has inputs confirmed (so it's not excluded by the previous rule) but one or more of its output have been spent by a transaction confirmed in the same block, "),t("code",[e._v("parent_in_cpfp")]),e._v(" is "),t("code",[e._v("1")]),e._v(".\nTransactions with "),t("code",[e._v("parent_in_cpfp = 1")]),e._v(" are included in the dataset but excluded by the current model, since the miner probably considered an aggregated fee rate while picking the transactions to build a block.")]),e._v(" "),t("h4",{attrs:{id:"the-mempool"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-mempool"}},[e._v("#")]),e._v(" The mempool")]),e._v(" "),t("p",[e._v("The most important input of our model is the current "),t("em",[e._v("status")]),e._v(' of the mempool itself. However, we cannot feed the model with a list of the fee rate of every unconfirmed transaction, because this array would have a variable length.\nTo overcome this, the transaction contained in the mempool are grouped in "buckets" which are basically subsets of the mempool where all the transactions contained in a bucket have a similar fee rate. In particular we only care about the\n'),t("em",[e._v("number")]),e._v(" of transaction in every "),t("em",[e._v("bucket")]),e._v(", not which transactions it contains.")]),e._v(" "),t("p",[e._v("The mempool buckets array is defined by two parameters, the "),t("code",[e._v("percentage_increment")]),e._v(" and the "),t("code",[e._v("array_max")]),e._v(" value.\nStarting from the minimum fee rate value "),t("code",[e._v("min_relay_fee=1.0")]),e._v(", the "),t("code",[e._v("ith")]),e._v(" element is: "),t("code",[e._v("a_i=min_relay_fee * (1+percentage_increment)^(i+1)")])]),e._v(" "),t("p",[e._v("For instance, choosing the mempool buckets array to have parameters "),t("code",[e._v("percentage_increment = 50%")]),e._v(" and "),t("code",[e._v("array_max = 500.0 sat/vbytes")]),e._v(" the buckets would be constructed like so:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("bucket")]),e._v(" "),t("th",[e._v("bucket min fee rate")]),e._v(" "),t("th",[e._v("bucket max fee rate")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("a_0")]),e._v(" "),t("td",[e._v("1.0")]),e._v(" "),t("td",[e._v("1.5")])]),e._v(" "),t("tr",[t("td",[e._v("a_1")]),e._v(" "),t("td",[e._v("1.5")]),e._v(" "),t("td",[e._v("2.25")])]),e._v(" "),t("tr",[t("td",[e._v("a_2")]),e._v(" "),t("td",[e._v("2.25")]),e._v(" "),t("td",[e._v("3.375")])]),e._v(" "),t("tr",[t("td",[e._v("a_15")]),e._v(" "),t("td",[e._v("437.89")]),e._v(" "),t("td",[e._v("inf")])])])]),e._v(" "),t("p",[e._v("The array stops at "),t("code",[e._v("a15")]),e._v(" because "),t("code",[e._v("a16")]),e._v(" would have a bucket min greater than "),t("code",[e._v("array_max")]),e._v(".")]),e._v(" "),t("p",[e._v("The model is for light-client such as "),t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("neutrino"),t("OutboundLink")],1),e._v(" based ones. In these clients the mempool is already available (it's needed to check for received transactions) but we can't compute fee rates of this transactions because previous confirmed inputs are not in the mempool!")]),e._v(" "),t("p",[e._v("Luckily, "),t("strong",[e._v("thanks to temporal locality "),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(", an important part of mempool transactions spend outputs created very recently")]),e._v(", for example in the last 6 blocks.\nThe blocks are available through the p2p network, and downloading the last 6 is considered a good compromise between resource consumption and accurate prediction. We need the model to be built with the same data available in the prediction phase, as a consequence "),t("em",[e._v("the mempool data in the dataset refers only to transactions having their inputs in the last 6 blocks")]),e._v(". However the "),t("code",[e._v("bitcoin-csv")]),e._v(" tool inside the "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger",target:"_blank",rel:"noopener noreferrer"}},[e._v("data logger"),t("OutboundLink")],1),e._v(" allows to configure this parameter.")]),e._v(" "),t("h4",{attrs:{id:"the-outliers"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-outliers"}},[e._v("#")]),e._v(" The outliers")]),e._v(" "),t("p",[e._v("The dataset also contains the block percentile fee rate "),t("code",[e._v("q_k")]),e._v(", considering "),t("code",[e._v("r_i")]),e._v(" to be the rate of the "),t("code",[e._v("ith")]),e._v(" transaction in a block, "),t("code",[e._v("q_k")]),e._v(" is the fee rate value such that for each transaction in a block "),t("code",[e._v("r_i")]),e._v(" < "),t("code",[e._v("q_k")]),e._v(" returns the "),t("code",[e._v("k%")]),e._v(" transactions in the block that are paying lower fees.")]),e._v(" "),t("p",[e._v("Percentiles are not used to feed the model but to filter some outliers tx.\nRemoving this observations is controversial at best and considered cheating at worse. However, it should be considered that Bitcoin Core "),t("code",[e._v("estimatesmartfee")]),e._v(" doesn't even bother to give estimation for the next block, we think this is due to the fact that many transactions that are confirming in the next block are huge overestimation, or clearly errors like "),t("a",{attrs:{href:"https://blockstream.info/tx/33291156ab79e9b4a1019b618b0acfa18cbdf8fa6b71c43a9eed62a849b86f9a",target:"_blank",rel:"noopener noreferrer"}},[e._v("this one"),t("OutboundLink")],1),e._v(" we found when we started logging data.\nThese outliers are several for transactions confirming in the next block ("),t("code",[e._v("confirms_in=1")]),e._v("), less so for "),t("code",[e._v("confirms_in=2")]),e._v(", mostly disappeared for "),t("code",[e._v("confirms_in=3")]),e._v(" or more. It's counterintuitive that overestimation exists for "),t("code",[e._v("confirms_in>1")]),e._v(", by definition an overestimation is a fee rate way higher than needed, so how is possible that an overestimation doesn't enter the very next block? There are a couple of reasons why a block is discovered without containing a transaction with high fee rate:")]),e._v(" "),t("ul",[t("li",[e._v("network latency: my node saw the transaction but the miner didn't see that transaction yet,")]),e._v(" "),t("li",[e._v("block building latency: the miner saw the transaction, but didn't finish to rebuild the block template or decided it's more efficient to finish a cycle on the older block template.")])]),e._v(" "),t("p",[e._v("To keep the model balanced, when overestimation is filtered out, underestimation are filtered out as well. This also has the effect to remove some of the transactions possibly included because a fee is payed out-of-band.\nAnother reason to filter transactions is that the dataset is over-represented by transactions with low "),t("code",[e._v("confirms_in")]),e._v(": more than 50% of transactions get confirmed in the next block, so we think it's good to filter some of these transactions.")]),e._v(" "),t("p",[e._v("The applied filters are the following:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("confirms_in")]),e._v(" "),t("th",[e._v("lower")]),e._v(" "),t("th",[e._v("higher")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("1")]),e._v(" "),t("td",[e._v("q45")]),e._v(" "),t("td",[e._v("q55")])]),e._v(" "),t("tr",[t("td",[e._v("2")]),e._v(" "),t("td",[e._v("q30")]),e._v(" "),t("td",[e._v("q70")])]),e._v(" "),t("tr",[t("td",[e._v("3")]),e._v(" "),t("td",[e._v("q1")]),e._v(" "),t("td",[e._v("q99")])])])]),e._v(" "),t("p",[e._v("Not yet convinced by the removal of these outliers? The "),t("a",{attrs:{href:"https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz",target:"_blank",rel:"noopener noreferrer"}},[e._v("dataset"),t("OutboundLink")],1),e._v(" contains all the observations, make your model 😃")]),e._v(" "),t("h4",{attrs:{id:"recap"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#recap"}},[e._v("#")]),e._v(" Recap")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("column")]),e._v(" "),t("th",[e._v("used in the model")]),e._v(" "),t("th",[e._v("description")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("txid")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Transaction hash, useful for debugging")])]),e._v(" "),t("tr",[t("td",[e._v("timestamp")]),e._v(" "),t("td",[e._v("converted")]),e._v(" "),t("td",[e._v("The time when the transaction has been added in the mempool, in the model is used in the form "),t("code",[e._v("day_of_week")]),e._v(" and "),t("code",[e._v("hour")])])]),e._v(" "),t("tr",[t("td",[e._v("current_height")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("The blockchain height seen by the node in this moment")])]),e._v(" "),t("tr",[t("td",[e._v("confirms_in")]),e._v(" "),t("td",[e._v("yes")]),e._v(" "),t("td",[e._v("This transaction confirmed at block height "),t("code",[e._v("current_height+confirms_in")])])]),e._v(" "),t("tr",[t("td",[e._v("fee_rate")]),e._v(" "),t("td",[e._v("target")]),e._v(" "),t("td",[e._v("This transaction fee rate measured in "),t("code",[e._v("[sat/vbytes]")])])]),e._v(" "),t("tr",[t("td",[e._v("fee_rate_bytes")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("fee rate in satoshi / bytes, used to check Bitcoin Core "),t("code",[e._v("estimatesmartfee")]),e._v(" predictions")])]),e._v(" "),t("tr",[t("td",[e._v("block_avg_fee")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("block average fee rate "),t("code",[e._v("[sat/vbytes]")]),e._v(" of block "),t("code",[e._v("current_height+confirms_in")])])]),e._v(" "),t("tr",[t("td",[e._v("core_econ")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("bitcoin "),t("code",[e._v("estimatesmartfee")]),e._v(" result for "),t("code",[e._v("confirms_in")]),e._v(" block target and in economic mode. Could be not available "),t("code",[e._v("?")]),e._v(" when a block is connected more recently than the estimation has been requested, estimation are requested every 10 secs.")])]),e._v(" "),t("tr",[t("td",[e._v("core_cons")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Same as above but with conservative mode")])]),e._v(" "),t("tr",[t("td",[e._v("mempool_len")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Sum of the mempool transactions with fee rate available (sum of every "),t("code",[e._v("a*")]),e._v(" field)")])]),e._v(" "),t("tr",[t("td",[e._v("parent_in_cpfp")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("It's 1 when the transaction has outputs that are spent in the same block in which the transaction is confirmed (they are parent in a CPFP relations).")])]),e._v(" "),t("tr",[t("td",[e._v("q1-q30-...")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Transaction confirming fast could be outliers, usually paying a lot more than required, this percentiles are used to filter those transactions,")])]),e._v(" "),t("tr",[t("td",[e._v("a1-a2-...")]),e._v(" "),t("td",[e._v("yes")]),e._v(" "),t("td",[e._v("Contains the number of transaction in the mempool with known fee rate in the ith bucket.")])])])]),e._v(" "),t("p",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg",alt:"The good, the bad and the ugly"}})]),t("div",{attrs:{align:"center"}},[e._v('My biological neural network fired this, I think it\'s because a lot of chapters start with "The"')]),e._v(" "),t("br"),t("br"),t("p"),e._v(" "),t("p",[e._v("In the previous "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(" we talked about the problem.")],1),e._v(" "),t("p",[e._v("In the following "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(" we are going to talk about the model.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("In computer science temporal locality refers to the tendency to access recent data more often than older data. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{399:function(e,t,a){"use strict";a.r(t);var o=a(7),n=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 2 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-dataset"}},[e._v("The dataset")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-mempool"}},[e._v("The mempool")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-outliers"}},[e._v("The outliers")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#recap"}},[e._v("Recap")])])])])]),e._v(" "),t("h2",{attrs:{id:"the-dataset"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-dataset"}},[e._v("#")]),e._v(" The dataset")]),e._v(" "),t("p",[e._v("The "),t("a",{attrs:{href:"https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz",target:"_blank",rel:"noopener noreferrer"}},[e._v("dataset"),t("OutboundLink")],1),e._v(" is publicly available (~500MB gzip compressed, ~2GB as plain CSV).")]),e._v(" "),t("p",[e._v("The output of the model is the fee rate, expressed in "),t("code",[e._v("[satoshi/vbytes]")]),e._v(".")]),e._v(" "),t("p",[e._v("What about the inputs? Generally speaking, we have two main requirements for what can be included as input for our model:")]),e._v(" "),t("ul",[t("li",[e._v("It must be correlated to the output, even with a non-linear relation.")]),e._v(" "),t("li",[e._v("It must be available to a light client: for instance, assuming to have knowledge and an index of the last 1000 blocks is considered too much.")])]),e._v(" "),t("p",[e._v("To evaluate the approach we are taking, we also want to compare our model's results with another available estimation: for this reason the dataset includes data to compute the error agains Bitcoin Core's "),t("code",[e._v("estimatesmartfee")]),e._v(" results, even though we are not going to use it for this model.")]),e._v(" "),t("p",[e._v("The dataset will contain only transactions that spend already confirmed inputs. If we wanted to include transactions with unconfirmed inputs as well, the fee rate would have to be computed as a whole;\nfor example if transaction "),t("code",[e._v("t2")]),e._v(" spends an unconfirmed input from "),t("code",[e._v("t1")]),e._v(" (while "),t("code",[e._v("t1")]),e._v(" only spends confirmed inputs, and all its other outputs are unspent), the aggregated fee rate would have to be used.\nSupposing "),t("code",[e._v("f()")]),e._v(" is extracts the absolute fee and "),t("code",[e._v("w()")]),e._v(" the transaction weight, the aggregated fee rate would be "),t("code",[e._v("(f(t1) + f(t2)) / (w(t1) + w(t2))")]),e._v(". Thus, as already said previously, to keep things simple the model simply discards all the transaction\nthat would need to perform this computation.")]),e._v(" "),t("p",[e._v("For the same reason the dataset has the "),t("code",[e._v("parent_in_cpfp")]),e._v(" flag. When a transaction has inputs confirmed (so it's not excluded by the previous rule) but one or more of its output have been spent by a transaction confirmed in the same block, "),t("code",[e._v("parent_in_cpfp")]),e._v(" is "),t("code",[e._v("1")]),e._v(".\nTransactions with "),t("code",[e._v("parent_in_cpfp = 1")]),e._v(" are included in the dataset but excluded by the current model, since the miner probably considered an aggregated fee rate while picking the transactions to build a block.")]),e._v(" "),t("h4",{attrs:{id:"the-mempool"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-mempool"}},[e._v("#")]),e._v(" The mempool")]),e._v(" "),t("p",[e._v("The most important input of our model is the current "),t("em",[e._v("status")]),e._v(' of the mempool itself. However, we cannot feed the model with a list of the fee rate of every unconfirmed transaction, because this array would have a variable length.\nTo overcome this, the transaction contained in the mempool are grouped in "buckets" which are basically subsets of the mempool where all the transactions contained in a bucket have a similar fee rate. In particular we only care about the\n'),t("em",[e._v("number")]),e._v(" of transaction in every "),t("em",[e._v("bucket")]),e._v(", not which transactions it contains.")]),e._v(" "),t("p",[e._v("The mempool buckets array is defined by two parameters, the "),t("code",[e._v("percentage_increment")]),e._v(" and the "),t("code",[e._v("array_max")]),e._v(" value.\nStarting from the minimum fee rate value "),t("code",[e._v("min_relay_fee=1.0")]),e._v(", the "),t("code",[e._v("ith")]),e._v(" element is: "),t("code",[e._v("a_i=min_relay_fee * (1+percentage_increment)^(i+1)")])]),e._v(" "),t("p",[e._v("For instance, choosing the mempool buckets array to have parameters "),t("code",[e._v("percentage_increment = 50%")]),e._v(" and "),t("code",[e._v("array_max = 500.0 sat/vbytes")]),e._v(" the buckets would be constructed like so:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("bucket")]),e._v(" "),t("th",[e._v("bucket min fee rate")]),e._v(" "),t("th",[e._v("bucket max fee rate")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("a_0")]),e._v(" "),t("td",[e._v("1.0")]),e._v(" "),t("td",[e._v("1.5")])]),e._v(" "),t("tr",[t("td",[e._v("a_1")]),e._v(" "),t("td",[e._v("1.5")]),e._v(" "),t("td",[e._v("2.25")])]),e._v(" "),t("tr",[t("td",[e._v("a_2")]),e._v(" "),t("td",[e._v("2.25")]),e._v(" "),t("td",[e._v("3.375")])]),e._v(" "),t("tr",[t("td",[e._v("a_15")]),e._v(" "),t("td",[e._v("437.89")]),e._v(" "),t("td",[e._v("inf")])])])]),e._v(" "),t("p",[e._v("The array stops at "),t("code",[e._v("a15")]),e._v(" because "),t("code",[e._v("a16")]),e._v(" would have a bucket min greater than "),t("code",[e._v("array_max")]),e._v(".")]),e._v(" "),t("p",[e._v("The model is for light-client such as "),t("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[e._v("neutrino"),t("OutboundLink")],1),e._v(" based ones. In these clients the mempool is already available (it's needed to check for received transactions) but we can't compute fee rates of this transactions because previous confirmed inputs are not in the mempool!")]),e._v(" "),t("p",[e._v("Luckily, "),t("strong",[e._v("thanks to temporal locality "),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(", an important part of mempool transactions spend outputs created very recently")]),e._v(", for example in the last 6 blocks.\nThe blocks are available through the p2p network, and downloading the last 6 is considered a good compromise between resource consumption and accurate prediction. We need the model to be built with the same data available in the prediction phase, as a consequence "),t("em",[e._v("the mempool data in the dataset refers only to transactions having their inputs in the last 6 blocks")]),e._v(". However the "),t("code",[e._v("bitcoin-csv")]),e._v(" tool inside the "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger",target:"_blank",rel:"noopener noreferrer"}},[e._v("data logger"),t("OutboundLink")],1),e._v(" allows to configure this parameter.")]),e._v(" "),t("h4",{attrs:{id:"the-outliers"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-outliers"}},[e._v("#")]),e._v(" The outliers")]),e._v(" "),t("p",[e._v("The dataset also contains the block percentile fee rate "),t("code",[e._v("q_k")]),e._v(", considering "),t("code",[e._v("r_i")]),e._v(" to be the rate of the "),t("code",[e._v("ith")]),e._v(" transaction in a block, "),t("code",[e._v("q_k")]),e._v(" is the fee rate value such that for each transaction in a block "),t("code",[e._v("r_i")]),e._v(" < "),t("code",[e._v("q_k")]),e._v(" returns the "),t("code",[e._v("k%")]),e._v(" transactions in the block that are paying lower fees.")]),e._v(" "),t("p",[e._v("Percentiles are not used to feed the model but to filter some outliers tx.\nRemoving this observations is controversial at best and considered cheating at worse. However, it should be considered that Bitcoin Core "),t("code",[e._v("estimatesmartfee")]),e._v(" doesn't even bother to give estimation for the next block, we think this is due to the fact that many transactions that are confirming in the next block are huge overestimation, or clearly errors like "),t("a",{attrs:{href:"https://blockstream.info/tx/33291156ab79e9b4a1019b618b0acfa18cbdf8fa6b71c43a9eed62a849b86f9a",target:"_blank",rel:"noopener noreferrer"}},[e._v("this one"),t("OutboundLink")],1),e._v(" we found when we started logging data.\nThese outliers are several for transactions confirming in the next block ("),t("code",[e._v("confirms_in=1")]),e._v("), less so for "),t("code",[e._v("confirms_in=2")]),e._v(", mostly disappeared for "),t("code",[e._v("confirms_in=3")]),e._v(" or more. It's counterintuitive that overestimation exists for "),t("code",[e._v("confirms_in>1")]),e._v(", by definition an overestimation is a fee rate way higher than needed, so how is possible that an overestimation doesn't enter the very next block? There are a couple of reasons why a block is discovered without containing a transaction with high fee rate:")]),e._v(" "),t("ul",[t("li",[e._v("network latency: my node saw the transaction but the miner didn't see that transaction yet,")]),e._v(" "),t("li",[e._v("block building latency: the miner saw the transaction, but didn't finish to rebuild the block template or decided it's more efficient to finish a cycle on the older block template.")])]),e._v(" "),t("p",[e._v("To keep the model balanced, when overestimation is filtered out, underestimation are filtered out as well. This also has the effect to remove some of the transactions possibly included because a fee is payed out-of-band.\nAnother reason to filter transactions is that the dataset is over-represented by transactions with low "),t("code",[e._v("confirms_in")]),e._v(": more than 50% of transactions get confirmed in the next block, so we think it's good to filter some of these transactions.")]),e._v(" "),t("p",[e._v("The applied filters are the following:")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("confirms_in")]),e._v(" "),t("th",[e._v("lower")]),e._v(" "),t("th",[e._v("higher")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("1")]),e._v(" "),t("td",[e._v("q45")]),e._v(" "),t("td",[e._v("q55")])]),e._v(" "),t("tr",[t("td",[e._v("2")]),e._v(" "),t("td",[e._v("q30")]),e._v(" "),t("td",[e._v("q70")])]),e._v(" "),t("tr",[t("td",[e._v("3")]),e._v(" "),t("td",[e._v("q1")]),e._v(" "),t("td",[e._v("q99")])])])]),e._v(" "),t("p",[e._v("Not yet convinced by the removal of these outliers? The "),t("a",{attrs:{href:"https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz",target:"_blank",rel:"noopener noreferrer"}},[e._v("dataset"),t("OutboundLink")],1),e._v(" contains all the observations, make your model 😃")]),e._v(" "),t("h4",{attrs:{id:"recap"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#recap"}},[e._v("#")]),e._v(" Recap")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("column")]),e._v(" "),t("th",[e._v("used in the model")]),e._v(" "),t("th",[e._v("description")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("txid")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Transaction hash, useful for debugging")])]),e._v(" "),t("tr",[t("td",[e._v("timestamp")]),e._v(" "),t("td",[e._v("converted")]),e._v(" "),t("td",[e._v("The time when the transaction has been added in the mempool, in the model is used in the form "),t("code",[e._v("day_of_week")]),e._v(" and "),t("code",[e._v("hour")])])]),e._v(" "),t("tr",[t("td",[e._v("current_height")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("The blockchain height seen by the node in this moment")])]),e._v(" "),t("tr",[t("td",[e._v("confirms_in")]),e._v(" "),t("td",[e._v("yes")]),e._v(" "),t("td",[e._v("This transaction confirmed at block height "),t("code",[e._v("current_height+confirms_in")])])]),e._v(" "),t("tr",[t("td",[e._v("fee_rate")]),e._v(" "),t("td",[e._v("target")]),e._v(" "),t("td",[e._v("This transaction fee rate measured in "),t("code",[e._v("[sat/vbytes]")])])]),e._v(" "),t("tr",[t("td",[e._v("fee_rate_bytes")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("fee rate in satoshi / bytes, used to check Bitcoin Core "),t("code",[e._v("estimatesmartfee")]),e._v(" predictions")])]),e._v(" "),t("tr",[t("td",[e._v("block_avg_fee")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("block average fee rate "),t("code",[e._v("[sat/vbytes]")]),e._v(" of block "),t("code",[e._v("current_height+confirms_in")])])]),e._v(" "),t("tr",[t("td",[e._v("core_econ")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("bitcoin "),t("code",[e._v("estimatesmartfee")]),e._v(" result for "),t("code",[e._v("confirms_in")]),e._v(" block target and in economic mode. Could be not available "),t("code",[e._v("?")]),e._v(" when a block is connected more recently than the estimation has been requested, estimation are requested every 10 secs.")])]),e._v(" "),t("tr",[t("td",[e._v("core_cons")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Same as above but with conservative mode")])]),e._v(" "),t("tr",[t("td",[e._v("mempool_len")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Sum of the mempool transactions with fee rate available (sum of every "),t("code",[e._v("a*")]),e._v(" field)")])]),e._v(" "),t("tr",[t("td",[e._v("parent_in_cpfp")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("It's 1 when the transaction has outputs that are spent in the same block in which the transaction is confirmed (they are parent in a CPFP relations).")])]),e._v(" "),t("tr",[t("td",[e._v("q1-q30-...")]),e._v(" "),t("td",[e._v("no")]),e._v(" "),t("td",[e._v("Transaction confirming fast could be outliers, usually paying a lot more than required, this percentiles are used to filter those transactions,")])]),e._v(" "),t("tr",[t("td",[e._v("a1-a2-...")]),e._v(" "),t("td",[e._v("yes")]),e._v(" "),t("td",[e._v("Contains the number of transaction in the mempool with known fee rate in the ith bucket.")])])])]),e._v(" "),t("p",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg",alt:"The good, the bad and the ugly"}})]),t("div",{attrs:{align:"center"}},[e._v('My biological neural network fired this, I think it\'s because a lot of chapters start with "The"')]),e._v(" "),t("br"),t("br"),t("p"),e._v(" "),t("p",[e._v("In the previous "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(" we talked about the problem.")],1),e._v(" "),t("p",[e._v("In the following "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-3/"}},[e._v("Part 3")]),e._v(" we are going to talk about the model.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("In computer science temporal locality refers to the tendency to access recent data more often than older data. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/49.fd2860a9.js b/assets/js/49.17ce6e83.js similarity index 99% rename from assets/js/49.fd2860a9.js rename to assets/js/49.17ce6e83.js index 9ce7757fab..63014e7a93 100644 --- a/assets/js/49.fd2860a9.js +++ b/assets/js/49.17ce6e83.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{397:function(e,t,a){"use strict";a.r(t);var n=a(7),s=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 3 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-model"}},[e._v("The model")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#splitting"}},[e._v("Splitting")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#preprocessing"}},[e._v("Preprocessing")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#build"}},[e._v("Build")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#finally--training"}},[e._v("Finally, training")])])])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-prediction-phase"}},[e._v("The prediction phase")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#conclusion-and-future-development"}},[e._v("Conclusion and future development")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#acknowledgements"}},[e._v("Acknowledgements")])])]),e._v(" "),t("h2",{attrs:{id:"the-model"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-model"}},[e._v("#")]),e._v(" The model")]),e._v(" "),t("p",[e._v("The code building and training the model with "),t("a",{attrs:{href:"https://www.tensorflow.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("tensorflow"),t("OutboundLink")],1),e._v(" is available in "),t("a",{attrs:{href:"https://colab.research.google.com/drive/1yamwh8nE4NhmGButep-pfUT-1uRKs49a?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("google colab notebook"),t("OutboundLink")],1),e._v(" (jupyter notebook); you can also download the file as plain python and run it locally. At least 1 hour is needed to train the full model, but it heavily depends on the hardware available.")]),e._v(" "),t("p",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png",alt:"graph confirm_in blocks vs fee_rate"}})]),t("div",{attrs:{align:"center"}},[e._v("Do you want to choose the fee without a model? In the last 5 weeks a ~50 sat/vbyte transaction never took more than a day to confirm and a ~10 sat/vbyte never took more than a week")]),t("br"),t("p"),e._v(" "),t("p",[e._v("As a reference, in the code we have a calculation of the bitcoin core "),t("code",[e._v("estimatesmartfee")]),e._v(" MAE"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" and drift"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(".\nMAE is computed as "),t("code",[e._v("avg(abs(fee_rate - core_econ))")]),e._v(" when "),t("code",[e._v("core_econ")]),e._v(" is available (about 1.2M observations, sometime the value is not available when considered too old).")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("estimatesmartfee mode")]),e._v(" "),t("th",[e._v("MAE [satoshi/vbytes]")]),e._v(" "),t("th",[e._v("drift")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("economic")]),e._v(" "),t("td",[e._v("28.77")]),e._v(" "),t("td",[e._v("20.79")])]),e._v(" "),t("tr",[t("td",[e._v("conservative")]),e._v(" "),t("td",[e._v("46.49")]),e._v(" "),t("td",[e._v("44.73")])])])]),e._v(" "),t("p",[e._v("As seen from the table, the error is quite high, but the positive drift suggests "),t("code",[e._v("estimatesmartfee")]),e._v(" prefers to overestimate to avoid transactions not confirming.")]),e._v(" "),t("p",[e._v('As we said in the introduction, network traffic is correlated with time and we have the timestamp of when the transaction has been first seen, however a ML model doesn\'t like plain numbers too much, but it behaves better with "number that repeats", like categories, so we are converting the timestamp in '),t("code",[e._v("day_of_week")]),e._v(" a number from 0 to 6, and "),t("code",[e._v("hours")]),e._v(" a number from 0 to 24.")]),e._v(" "),t("h4",{attrs:{id:"splitting"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#splitting"}},[e._v("#")]),e._v(" Splitting")]),e._v(" "),t("p",[e._v("The dataset is splitted in training and test data with a 80/20 proportion. As the name suggest the training part is used to train the model, the test is composed of other observations to test if the model is good with observations that has never seen (proving the model can generalize, not just memorizing the answer).")]),e._v(" "),t("p",[e._v("During the training the data is splitted again in 80/20 for training and validation respectively, validation is basically testing during training.")]),e._v(" "),t("p",[e._v("During splitting, the dataset is converted from a pandas data frame to tensorflow dataset, decreasing training times.")]),e._v(" "),t("h4",{attrs:{id:"preprocessing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#preprocessing"}},[e._v("#")]),e._v(" Preprocessing")]),e._v(" "),t("p",[e._v("The preprocessing phase is part of the model however it contains transformations without parameters trained by the model.\nThis transformations are useful because model trains better if data are in some format, and having this phase inside the model helps to avoid to prepare the data before feeding the model at prediction phase.")]),e._v(" "),t("p",[e._v("Our model performs 2 kind of preprocessing:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Normalization: model trains faster if numerical features have mean 0 and standard deviation equal to 1, so this layer is built by computing the "),t("code",[e._v("mean")]),e._v(" and "),t("code",[e._v("std")]),e._v(" from the series of a feature before training, and the model is feed with "),t("code",[e._v("(feature - mean)/std")]),e._v(". Our model normalize "),t("code",[e._v("confirms_in")]),e._v(" feature and all the buckets "),t("code",[e._v("a*")])])]),e._v(" "),t("li",[t("p",[e._v("one-hot vector: Numerical categories having a small number of different unique values like our "),t("code",[e._v("day_of_week")]),e._v(" and "),t("code",[e._v("hours")]),e._v(" could be trained better/faster by being converted in one hot vector. For example "),t("code",[e._v("day_of_week=6")]),e._v(" (Sunday) is converted in a vector "),t("code",[e._v("['0', '0', '0', '0', '0', '0', '1']")]),e._v(" while "),t("code",[e._v("day_of_week=5")]),e._v(" (Saturday) is converted in the vector "),t("code",[e._v("['0', '0', '0', '0', '0', '1', '0']")])])])]),e._v(" "),t("h4",{attrs:{id:"build"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#build"}},[e._v("#")]),e._v(" Build")]),e._v(" "),t("div",{staticClass:"language-python extra-class"},[t("pre",{pre:!0,attrs:{class:"language-python"}},[t("code",[e._v("all_features "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("concatenate"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("encoded_features"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nx "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"relu"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("all_features"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nx "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"relu"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("x"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\noutput "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("clip"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("x"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nmodel "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Model"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("all_inputs"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" output"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\noptimizer "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("optimizers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Adam"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("learning_rate"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("0.01")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nmodel"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),t("span",{pre:!0,attrs:{class:"token builtin"}},[e._v("compile")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("loss"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mse'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n optimizer"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("optimizer"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n metrics"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mae'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mse'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-model.png",alt:"model graph"}})]),e._v(" "),t("p",[e._v("The model is fed with the "),t("code",[e._v("encoded_features")]),e._v(" coming from the processing phase, then there are 2 layers with 64 neurons each followed by one neuron giving the "),t("code",[e._v("fee_rate")]),e._v(" as output.")]),e._v(" "),t("p",[e._v("With this configurations the model has:")]),e._v(" "),t("ul",[t("li",[e._v("Total params: "),t("code",[e._v("7,412")])]),e._v(" "),t("li",[e._v("Trainable params: "),t("code",[e._v("7,361")])]),e._v(" "),t("li",[e._v("Non-trainable params: "),t("code",[e._v("51")])])]),e._v(" "),t("p",[e._v("Non-trainable params comes from the normalization layer and are computed in the pre-processing phase (it contains, for example, the mean of a series). Trainable parameters are values initialized randomly and changed during the training phase. The trainable parameters are "),t("code",[e._v("7,361")]),e._v(", this number comes from the following, every neuron has an associated bias and a weight for every element in the inputs, thus:")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("48")]),e._v(" input_values_weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" * "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" first_layer_neurons"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n+ "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" input_values_weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" * "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" second layer neurons"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n+ "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" input values weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("49")]),e._v("*64+65*64+65 "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("7361")]),e._v("\n")])])]),t("p",[e._v("Honestly, neural network parameters are mostly the one taken from this tensorflow "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/regression",target:"_blank",rel:"noopener noreferrer"}},[e._v("example"),t("OutboundLink")],1),e._v(", we even tried to "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/keras_tuner",target:"_blank",rel:"noopener noreferrer"}},[e._v("tune hyperparameters"),t("OutboundLink")],1),e._v(", however, we decided to follow this "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#demonstrate_overfitting",target:"_blank",rel:"noopener noreferrer"}},[e._v("advice"),t("OutboundLink")],1),e._v(": "),t("em",[e._v('"The simplest way to prevent overfitting is to start with a small model:"')]),e._v(". We hope this work will attract other data scientists to this bitcoin problem, improving the model. We also think that a longer time for the data collection is needed to capture various situations.")]),e._v(" "),t("p",[e._v("A significant part of a ML model are the activation functions, "),t("code",[e._v("relu")]),e._v(" (Rectified Linear Unit) is one of the most used lately, because it's simple and works well as we learned in this "),t("a",{attrs:{href:"https://youtu.be/aircAruvnKk?t=1035",target:"_blank",rel:"noopener noreferrer"}},[e._v("introducing neural network video"),t("OutboundLink")],1),e._v(". "),t("code",[e._v("relu")]),e._v(" it's equal to zero for negative values and equal to the input for positive values. Being non-linear allows the whole model to be non-linear.")]),e._v(" "),t("p",[e._v("For the last layer it is different: we want to enforce a minimum for the output, which is the minimum relay fee "),t("code",[e._v("1.0")]),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(". One could not simply cut the output of the model after prediction because all the training would not consider this constraint. So we need to build a custom activation function that the model training will be able to use for the "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Gradient_descent#:~:text=Gradient%20descent%20is%20a%20first,the%20direction%20of%20steepest%20descent.",target:"_blank",rel:"noopener noreferrer"}},[e._v("gradient descent"),t("OutboundLink")],1),e._v(" optimization step. Luckily this is very simple using tensorflow primitives:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("def clip(x):\n min = tf.constant(1.0)\n return tf.where(tf.less(x, min), min, x)\n")])])]),t("p",[e._v("Another important part is the optimizer, when we first read the aforementioned "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/regression",target:"_blank",rel:"noopener noreferrer"}},[e._v("example"),t("OutboundLink")],1),e._v(" the optimizer used was "),t("code",[e._v("RMSProp")]),e._v(" however the example updated lately and we noticed the optimizer changed in favor of "),t("code",[e._v("Adam")]),e._v(" which we read is the "),t("a",{attrs:{href:"https://towardsdatascience.com/adam-latest-trends-in-deep-learning-optimization-6be9a291375c",target:"_blank",rel:"noopener noreferrer"}},[e._v("latest trend"),t("OutboundLink")],1),e._v(" in data science. We changed the model to use "),t("code",[e._v("Adam")]),e._v(" and effectively the training is faster with "),t("code",[e._v("Adam")]),e._v(" and even slightly lower error is achieved.\nAnother important parameter is the learning rate, which we set to "),t("code",[e._v("0.01")]),e._v(" after manual trials; however there might be space for improvements such as using "),t("a",{attrs:{href:"https://www.tensorflow.org/api_docs/python/tf/compat/v1/train/exponential_decay",target:"_blank",rel:"noopener noreferrer"}},[e._v("exponential decay"),t("OutboundLink")],1),e._v(", starting with an high learning rate and decreasing it through training epochs.")]),e._v(" "),t("p",[e._v('The last part of the model configuration is the loss function: the objective of the training is to find the minimum of this function. Usually for regression problem (the ones having a number as output, not a category) the most used is the Mean squared error (MSE). MSE is measured as the average of squared difference between predictions and actual observations, giving larger penalties to large difference because of the square. An interesting property is that the bigger the error the faster the changes is good at the beginning of the training, while slowing down when the model predicts better is desirable to avoid "jumping out" the local minimum.')]),e._v(" "),t("h4",{attrs:{id:"finally-the-model-training"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#finally-the-model-training"}},[e._v("#")]),e._v(" Finally, the model training")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("PATIENCE = 20\nMAX_EPOCHS = 200\n\ndef train():\n early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=PATIENCE)\n history = model.fit(train_ds, epochs=MAX_EPOCHS, validation_data=val_ds, verbose=1, callbacks=[early_stop])\n return history\n\nhistory = train()\n")])])]),t("p",[e._v("This steps is the core of the neural network, it takes a while, let's analyze the output:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Epoch 1/200\n7559/7559 [==============================] - 34s 3ms/step - loss: 547.8023 - mae: 16.9547 - mse: 547.8023 - val_loss: 300.5965 - val_ma\ne: 11.9202 - val_mse: 300.5965\n...\nEpoch 158/200\n7559/7559 [==============================] - 31s 3ms/step - loss: 163.2548 - mae: 8.3126 - mse: 163.2548 - val_loss: 164.8296 - val_mae: 8.3402 - val_mse: 164.8296\n")])])]),t("p",[e._v("Training is done in epochs, under every epoch all the training data is iterated and model parameters updated to minimize the loss function.")]),e._v(" "),t("p",[e._v("The number "),t("code",[e._v("7559")]),e._v(" represent the number of steps. Theoretically the whole training data should be processed at once and parameters updated accordingly, however in practice this is infeasible for example for memory resource, thus the training happens in batch. In our case we have "),t("code",[e._v("1,934,999")]),e._v(" observations in the training set and our batch size is "),t("code",[e._v("256")]),e._v(", thus we have "),t("code",[e._v("1,437,841/256=7,558.58")]),e._v(" which by excess result in "),t("code",[e._v("7559")]),e._v(" steps.")]),e._v(" "),t("p",[e._v("The "),t("code",[e._v("~31s")]),e._v(" is the time it takes to process the epoch on a threadripper CPU but GPU or TPU could do better.")]),e._v(" "),t("p",[e._v("The value "),t("code",[e._v("loss")]),e._v(" is the MSE on the training data while "),t("code",[e._v("val_loss")]),e._v(" is the MSE value on the validation data. As far as we understand the separated validation data helps to detect the machine learning enemy, overfitting. Because in case of overfitting the value "),t("code",[e._v("loss")]),e._v(" continue to improve (almost indefinitely) while "),t("code",[e._v("val_loss")]),e._v(" start improving with the loss but a certain point diverge, indicating the network is memorizing the training data to improve "),t("code",[e._v("loss")]),e._v(" but in doing so losing generalizing capabilities.")]),e._v(" "),t("p",[e._v("Our model doesn't look to suffer overfitting cause "),t("code",[e._v("loss")]),e._v(" and "),t("code",[e._v("val_loss")]),e._v(" doesn't diverge during training")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-train-history.png",alt:"train history"}})]),e._v(" "),t("p",[e._v("While we told the training to do 200 epochs, the training stopped at 158 because we added an "),t("code",[e._v("early_stop")]),e._v(" call back with "),t("code",[e._v("20")]),e._v(" as "),t("code",[e._v("PATIENCE")]),e._v(", meaning that after 20 epoch and no improvement in "),t("code",[e._v("val_loss")]),e._v(" the training is halted, saving time and potentially avoiding overfitting.")]),e._v(" "),t("h2",{attrs:{id:"the-prediction-phase"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-prediction-phase"}},[e._v("#")]),e._v(" The prediction phase")]),e._v(" "),t("p",[e._v("A "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" is available on github. At the moment it uses a bitcoin core node to provide network data for simplicity, but it queries it only for the mempool and the last 6 blocks, so it's something that also a light-client could do"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(".")]),e._v(" "),t("p",[e._v("The following chart is probably the best visualization to evaluate the model, on the x axis there is the real fee rate while on the y axis there is the prediction, the more the points are centered on the bisection, the more the model is good.\nWe can see the model is doing quite well, the MAE is 8 which is way lower than "),t("code",[e._v("estimatesmartfee")]),e._v(". However, there are big errors some times, in particular for prediction for fast confirmation ("),t("code",[e._v("confirms_in=1 or confirms_in=2")]),e._v(") as shown by the orange points. Creating a model only for blocks target greater than 2 instead of simply remove some observations may be an option.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png",alt:"prediction results"}})]),e._v(" "),t("p",[e._v("The following chart is instead a distribution of the errors, which for good model should resemble the normal distribution centered in 0, and it loooks like the model is respecting that.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png",alt:"error distribution"}})]),e._v(" "),t("h2",{attrs:{id:"conclusion-and-future-development"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion-and-future-development"}},[e._v("#")]),e._v(" Conclusion and future development")]),e._v(" "),t("p",[e._v("The results have shown deep neural network are a tool capable of good bitcoin transaction fee estimations; this suggests that further ML research in this area might be promising.")]),e._v(" "),t("p",[e._v("This is just a starting point, there are many future improvements such as:")]),e._v(" "),t("ul",[t("li",[e._v("Build a separate model with full knowledge, thus for full, always-connected nodes could be interesting and improve network resource allocation with respect to current estimators.")]),e._v(" "),t("li",[e._v("Tensorflow is a huge dependency, and since it contains all the feature to build and train a model, most of the feature are not needed in the prediction phase. In fact tensorflow lite exists which is specifically created for embedded and mobile devices; the "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" and the final integration in "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" should use it.")]),e._v(" "),t("li",[e._v("Explore other fields to improve model predictions such as:\n"),t("ul",[t("li",[e._v("A bucket array of the transactions in the last 6 blocks with known fee rates. This should in particular help estimations with almost empty mempool.")]),e._v(" "),t("li",[e._v("Transaction weight")]),e._v(" "),t("li",[e._v("Time from last block")])])]),e._v(" "),t("li",[e._v("Some fields are very important and could benefit from pre-processing expansion, for instance applying "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/structured_data/feature_columns#hashed_feature_columns",target:"_blank",rel:"noopener noreferrer"}},[e._v("hashed feature columns"),t("OutboundLink")],1),e._v(" to "),t("code",[e._v("confirms_in")]),e._v(".")]),e._v(" "),t("li",[e._v("Bitcoin logger could be improved by a merge command to unify raw logs files, reducing redundancy and consequently disk occupation.")]),e._v(" "),t("li",[e._v("The dataset could be created in multiple files to allow more parallelism and use less memory during training.")]),e._v(" "),t("li",[e._v("Saving the dataset in "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/load_data/tfrecord",target:"_blank",rel:"noopener noreferrer"}},[e._v("TFRecord format"),t("OutboundLink")],1),e._v(" instead of CSV")]),e._v(" "),t("li",[e._v("At the moment we are training the model on a threadripper CPU, training the code on GPU or even TPU will be needed to decrease training time, especially because input data will grow.")]),e._v(" "),t("li",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" should estimate only using the p2p bitcoin network, without requiring a node. This work would be propedeutic for "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" integration")]),e._v(" "),t("li",[e._v("At the moment mempool buckets are multiple inputs "),t("code",[e._v("a*")]),e._v(" as show in the model graph; since they are related, is it possible to merge them in one TensorArray?")]),e._v(" "),t("li",[e._v("Sometimes the model does not learn and "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("gets stuck"),t("OutboundLink")],1),e._v(". The reason is the "),t("code",[e._v("clip")]),e._v(" function applied in the last layer is constant for a value lower than 1. In this case, the derivative is 0 and the gradient descent doesn't know where to go. Instead of using the "),t("code",[e._v("clip")]),e._v(" function apply penalties to the loss function for values lower than 1.")]),e._v(" "),t("li",[e._v("There are issues regarding dead neurons (going to 0) or neurons with big weight, weight results should be monitored for this events, and also weight decay and L2 regularization should be explored.")]),e._v(" "),t("li",[e._v("Tune hyper-parameters technique should be re-tested.")]),e._v(" "),t("li",[e._v("Predictions should be monotonic decreasing for growing "),t("code",[e._v("confirms_in")]),e._v(" parameter; for obvious reason it doesn't make sense that an higher fee rate will result in a higher confirmation time. But since this is not enforced anywhere in the model, at the moment this could happen.")]),e._v(" "),t("li",[e._v("Since nodes with bloom filter disabled doesn't serve the mempool anymore, a model based only on last blocks should be evaluated.")])]),e._v(" "),t("h2",{attrs:{id:"acknowledgements"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#acknowledgements"}},[e._v("#")]),e._v(" Acknowledgements")]),e._v(" "),t("p",[e._v("Thanks to "),t("a",{attrs:{href:"https://squarecrypto.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Square crypto"),t("OutboundLink")],1),e._v(" for sponsoring this work and thanks to the reviewers: "),t("a",{attrs:{href:"https://twitter.com/LeoComandini",target:"_blank",rel:"noopener noreferrer"}},[e._v("Leonardo Comandini"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/domegabri",target:"_blank",rel:"noopener noreferrer"}},[e._v("Domenico Gabriele"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/afilini",target:"_blank",rel:"noopener noreferrer"}},[e._v("Alekos Filini"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/Ferdinando1970",target:"_blank",rel:"noopener noreferrer"}},[e._v("Ferdinando Ametrano"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("And also this tweet that remembered me "),t("a",{attrs:{href:"https://twitter.com/RCasatta",target:"_blank",rel:"noopener noreferrer"}},[e._v("I"),t("OutboundLink")],1),e._v(" had this work in my TODO list")]),e._v(" "),t("blockquote",{staticClass:"twitter-tweet"},[t("p",{attrs:{lang:"en",dir:"ltr"}},[e._v("I don't understand Machine Learning(ML), but is it horrible to use ML to predict bitcoin fees? "),t("br"),t("br"),e._v('I have heard tales of this "Deep Learning" thing where you throw a bunch of data at it and it gives you good results with high accuracy.')]),e._v("— sanket1729 (@sanket1729) "),t("a",{attrs:{href:"https://twitter.com/sanket1729/status/1336624662365822977?ref_src=twsrc%5Etfw"}},[e._v("December 9, 2020")])]),e._v(" "),t("script",{attrs:{async:"",src:"https://platform.twitter.com/widgets.js",charset:"utf-8"}}),e._v(" "),t("p",[e._v("This is the final part of the series. In the previous "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(" we talked about the problem and in "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(" we talked about the dataset.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("MAE is Mean Absolute Error, which is the average of the series built by the absolute difference between the real value and the estimation. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("drift like MAE, but without the absolute value "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("Most node won't relay transactions with fee lower than the min relay fee, which has a default of "),t("code",[e._v("1.0")]),e._v(" "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("An important issue emerged after the article came out, a bitcoin core client with bloom filter disabled (default as of 0.21) doesn't serve the mempool via p2p. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{398:function(e,t,a){"use strict";a.r(t);var n=a(7),s=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("p",[e._v("This post is part 3 of 3 of a series. ("),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(", "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(")")],1),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#the-model"}},[e._v("The model")]),e._v(" "),t("ul",[t("li",[t("a",{attrs:{href:"#splitting"}},[e._v("Splitting")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#preprocessing"}},[e._v("Preprocessing")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#build"}},[e._v("Build")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#finally--training"}},[e._v("Finally, training")])])])]),e._v(" "),t("li",[t("a",{attrs:{href:"#the-prediction-phase"}},[e._v("The prediction phase")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#conclusion-and-future-development"}},[e._v("Conclusion and future development")])]),e._v(" "),t("li",[t("a",{attrs:{href:"#acknowledgements"}},[e._v("Acknowledgements")])])]),e._v(" "),t("h2",{attrs:{id:"the-model"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-model"}},[e._v("#")]),e._v(" The model")]),e._v(" "),t("p",[e._v("The code building and training the model with "),t("a",{attrs:{href:"https://www.tensorflow.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("tensorflow"),t("OutboundLink")],1),e._v(" is available in "),t("a",{attrs:{href:"https://colab.research.google.com/drive/1yamwh8nE4NhmGButep-pfUT-1uRKs49a?usp=sharing",target:"_blank",rel:"noopener noreferrer"}},[e._v("google colab notebook"),t("OutboundLink")],1),e._v(" (jupyter notebook); you can also download the file as plain python and run it locally. At least 1 hour is needed to train the full model, but it heavily depends on the hardware available.")]),e._v(" "),t("p",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png",alt:"graph confirm_in blocks vs fee_rate"}})]),t("div",{attrs:{align:"center"}},[e._v("Do you want to choose the fee without a model? In the last 5 weeks a ~50 sat/vbyte transaction never took more than a day to confirm and a ~10 sat/vbyte never took more than a week")]),t("br"),t("p"),e._v(" "),t("p",[e._v("As a reference, in the code we have a calculation of the bitcoin core "),t("code",[e._v("estimatesmartfee")]),e._v(" MAE"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn1",id:"fnref1"}},[e._v("[1]")])]),e._v(" and drift"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn2",id:"fnref2"}},[e._v("[2]")])]),e._v(".\nMAE is computed as "),t("code",[e._v("avg(abs(fee_rate - core_econ))")]),e._v(" when "),t("code",[e._v("core_econ")]),e._v(" is available (about 1.2M observations, sometime the value is not available when considered too old).")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("estimatesmartfee mode")]),e._v(" "),t("th",[e._v("MAE [satoshi/vbytes]")]),e._v(" "),t("th",[e._v("drift")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("economic")]),e._v(" "),t("td",[e._v("28.77")]),e._v(" "),t("td",[e._v("20.79")])]),e._v(" "),t("tr",[t("td",[e._v("conservative")]),e._v(" "),t("td",[e._v("46.49")]),e._v(" "),t("td",[e._v("44.73")])])])]),e._v(" "),t("p",[e._v("As seen from the table, the error is quite high, but the positive drift suggests "),t("code",[e._v("estimatesmartfee")]),e._v(" prefers to overestimate to avoid transactions not confirming.")]),e._v(" "),t("p",[e._v('As we said in the introduction, network traffic is correlated with time and we have the timestamp of when the transaction has been first seen, however a ML model doesn\'t like plain numbers too much, but it behaves better with "number that repeats", like categories, so we are converting the timestamp in '),t("code",[e._v("day_of_week")]),e._v(" a number from 0 to 6, and "),t("code",[e._v("hours")]),e._v(" a number from 0 to 24.")]),e._v(" "),t("h4",{attrs:{id:"splitting"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#splitting"}},[e._v("#")]),e._v(" Splitting")]),e._v(" "),t("p",[e._v("The dataset is splitted in training and test data with a 80/20 proportion. As the name suggest the training part is used to train the model, the test is composed of other observations to test if the model is good with observations that has never seen (proving the model can generalize, not just memorizing the answer).")]),e._v(" "),t("p",[e._v("During the training the data is splitted again in 80/20 for training and validation respectively, validation is basically testing during training.")]),e._v(" "),t("p",[e._v("During splitting, the dataset is converted from a pandas data frame to tensorflow dataset, decreasing training times.")]),e._v(" "),t("h4",{attrs:{id:"preprocessing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#preprocessing"}},[e._v("#")]),e._v(" Preprocessing")]),e._v(" "),t("p",[e._v("The preprocessing phase is part of the model however it contains transformations without parameters trained by the model.\nThis transformations are useful because model trains better if data are in some format, and having this phase inside the model helps to avoid to prepare the data before feeding the model at prediction phase.")]),e._v(" "),t("p",[e._v("Our model performs 2 kind of preprocessing:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Normalization: model trains faster if numerical features have mean 0 and standard deviation equal to 1, so this layer is built by computing the "),t("code",[e._v("mean")]),e._v(" and "),t("code",[e._v("std")]),e._v(" from the series of a feature before training, and the model is feed with "),t("code",[e._v("(feature - mean)/std")]),e._v(". Our model normalize "),t("code",[e._v("confirms_in")]),e._v(" feature and all the buckets "),t("code",[e._v("a*")])])]),e._v(" "),t("li",[t("p",[e._v("one-hot vector: Numerical categories having a small number of different unique values like our "),t("code",[e._v("day_of_week")]),e._v(" and "),t("code",[e._v("hours")]),e._v(" could be trained better/faster by being converted in one hot vector. For example "),t("code",[e._v("day_of_week=6")]),e._v(" (Sunday) is converted in a vector "),t("code",[e._v("['0', '0', '0', '0', '0', '0', '1']")]),e._v(" while "),t("code",[e._v("day_of_week=5")]),e._v(" (Saturday) is converted in the vector "),t("code",[e._v("['0', '0', '0', '0', '0', '1', '0']")])])])]),e._v(" "),t("h4",{attrs:{id:"build"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#build"}},[e._v("#")]),e._v(" Build")]),e._v(" "),t("div",{staticClass:"language-python extra-class"},[t("pre",{pre:!0,attrs:{class:"language-python"}},[t("code",[e._v("all_features "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("concatenate"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("encoded_features"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nx "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"relu"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("all_features"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nx "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v('"relu"')]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("x"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\noutput "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("layers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Dense"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" activation"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("clip"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("x"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nmodel "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("keras"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Model"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("all_inputs"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" output"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\noptimizer "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" tf"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("optimizers"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),e._v("Adam"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("learning_rate"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("0.01")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\nmodel"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(".")]),t("span",{pre:!0,attrs:{class:"token builtin"}},[e._v("compile")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),e._v("loss"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mse'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n optimizer"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v("optimizer"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v("\n metrics"),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("[")]),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mae'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(",")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token string"}},[e._v("'mse'")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("]")]),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n")])])]),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-model.png",alt:"model graph"}})]),e._v(" "),t("p",[e._v("The model is fed with the "),t("code",[e._v("encoded_features")]),e._v(" coming from the processing phase, then there are 2 layers with 64 neurons each followed by one neuron giving the "),t("code",[e._v("fee_rate")]),e._v(" as output.")]),e._v(" "),t("p",[e._v("With this configurations the model has:")]),e._v(" "),t("ul",[t("li",[e._v("Total params: "),t("code",[e._v("7,412")])]),e._v(" "),t("li",[e._v("Trainable params: "),t("code",[e._v("7,361")])]),e._v(" "),t("li",[e._v("Non-trainable params: "),t("code",[e._v("51")])])]),e._v(" "),t("p",[e._v("Non-trainable params comes from the normalization layer and are computed in the pre-processing phase (it contains, for example, the mean of a series). Trainable parameters are values initialized randomly and changed during the training phase. The trainable parameters are "),t("code",[e._v("7,361")]),e._v(", this number comes from the following, every neuron has an associated bias and a weight for every element in the inputs, thus:")]),e._v(" "),t("div",{staticClass:"language-shell extra-class"},[t("pre",{pre:!0,attrs:{class:"language-shell"}},[t("code",[t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("48")]),e._v(" input_values_weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" * "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" first_layer_neurons"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n+ "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" input_values_weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v(" * "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" second layer neurons"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n+ "),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v("(")]),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("64")]),e._v(" input values weights + "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("1")]),e._v(" bias"),t("span",{pre:!0,attrs:{class:"token punctuation"}},[e._v(")")]),e._v("\n\n"),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("49")]),e._v("*64+65*64+65 "),t("span",{pre:!0,attrs:{class:"token operator"}},[e._v("=")]),e._v(" "),t("span",{pre:!0,attrs:{class:"token number"}},[e._v("7361")]),e._v("\n")])])]),t("p",[e._v("Honestly, neural network parameters are mostly the one taken from this tensorflow "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/regression",target:"_blank",rel:"noopener noreferrer"}},[e._v("example"),t("OutboundLink")],1),e._v(", we even tried to "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/keras_tuner",target:"_blank",rel:"noopener noreferrer"}},[e._v("tune hyperparameters"),t("OutboundLink")],1),e._v(", however, we decided to follow this "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#demonstrate_overfitting",target:"_blank",rel:"noopener noreferrer"}},[e._v("advice"),t("OutboundLink")],1),e._v(": "),t("em",[e._v('"The simplest way to prevent overfitting is to start with a small model:"')]),e._v(". We hope this work will attract other data scientists to this bitcoin problem, improving the model. We also think that a longer time for the data collection is needed to capture various situations.")]),e._v(" "),t("p",[e._v("A significant part of a ML model are the activation functions, "),t("code",[e._v("relu")]),e._v(" (Rectified Linear Unit) is one of the most used lately, because it's simple and works well as we learned in this "),t("a",{attrs:{href:"https://youtu.be/aircAruvnKk?t=1035",target:"_blank",rel:"noopener noreferrer"}},[e._v("introducing neural network video"),t("OutboundLink")],1),e._v(". "),t("code",[e._v("relu")]),e._v(" it's equal to zero for negative values and equal to the input for positive values. Being non-linear allows the whole model to be non-linear.")]),e._v(" "),t("p",[e._v("For the last layer it is different: we want to enforce a minimum for the output, which is the minimum relay fee "),t("code",[e._v("1.0")]),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn3",id:"fnref3"}},[e._v("[3]")])]),e._v(". One could not simply cut the output of the model after prediction because all the training would not consider this constraint. So we need to build a custom activation function that the model training will be able to use for the "),t("a",{attrs:{href:"https://en.wikipedia.org/wiki/Gradient_descent#:~:text=Gradient%20descent%20is%20a%20first,the%20direction%20of%20steepest%20descent.",target:"_blank",rel:"noopener noreferrer"}},[e._v("gradient descent"),t("OutboundLink")],1),e._v(" optimization step. Luckily this is very simple using tensorflow primitives:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("def clip(x):\n min = tf.constant(1.0)\n return tf.where(tf.less(x, min), min, x)\n")])])]),t("p",[e._v("Another important part is the optimizer, when we first read the aforementioned "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/keras/regression",target:"_blank",rel:"noopener noreferrer"}},[e._v("example"),t("OutboundLink")],1),e._v(" the optimizer used was "),t("code",[e._v("RMSProp")]),e._v(" however the example updated lately and we noticed the optimizer changed in favor of "),t("code",[e._v("Adam")]),e._v(" which we read is the "),t("a",{attrs:{href:"https://towardsdatascience.com/adam-latest-trends-in-deep-learning-optimization-6be9a291375c",target:"_blank",rel:"noopener noreferrer"}},[e._v("latest trend"),t("OutboundLink")],1),e._v(" in data science. We changed the model to use "),t("code",[e._v("Adam")]),e._v(" and effectively the training is faster with "),t("code",[e._v("Adam")]),e._v(" and even slightly lower error is achieved.\nAnother important parameter is the learning rate, which we set to "),t("code",[e._v("0.01")]),e._v(" after manual trials; however there might be space for improvements such as using "),t("a",{attrs:{href:"https://www.tensorflow.org/api_docs/python/tf/compat/v1/train/exponential_decay",target:"_blank",rel:"noopener noreferrer"}},[e._v("exponential decay"),t("OutboundLink")],1),e._v(", starting with an high learning rate and decreasing it through training epochs.")]),e._v(" "),t("p",[e._v('The last part of the model configuration is the loss function: the objective of the training is to find the minimum of this function. Usually for regression problem (the ones having a number as output, not a category) the most used is the Mean squared error (MSE). MSE is measured as the average of squared difference between predictions and actual observations, giving larger penalties to large difference because of the square. An interesting property is that the bigger the error the faster the changes is good at the beginning of the training, while slowing down when the model predicts better is desirable to avoid "jumping out" the local minimum.')]),e._v(" "),t("h4",{attrs:{id:"finally-the-model-training"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#finally-the-model-training"}},[e._v("#")]),e._v(" Finally, the model training")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("PATIENCE = 20\nMAX_EPOCHS = 200\n\ndef train():\n early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=PATIENCE)\n history = model.fit(train_ds, epochs=MAX_EPOCHS, validation_data=val_ds, verbose=1, callbacks=[early_stop])\n return history\n\nhistory = train()\n")])])]),t("p",[e._v("This steps is the core of the neural network, it takes a while, let's analyze the output:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Epoch 1/200\n7559/7559 [==============================] - 34s 3ms/step - loss: 547.8023 - mae: 16.9547 - mse: 547.8023 - val_loss: 300.5965 - val_ma\ne: 11.9202 - val_mse: 300.5965\n...\nEpoch 158/200\n7559/7559 [==============================] - 31s 3ms/step - loss: 163.2548 - mae: 8.3126 - mse: 163.2548 - val_loss: 164.8296 - val_mae: 8.3402 - val_mse: 164.8296\n")])])]),t("p",[e._v("Training is done in epochs, under every epoch all the training data is iterated and model parameters updated to minimize the loss function.")]),e._v(" "),t("p",[e._v("The number "),t("code",[e._v("7559")]),e._v(" represent the number of steps. Theoretically the whole training data should be processed at once and parameters updated accordingly, however in practice this is infeasible for example for memory resource, thus the training happens in batch. In our case we have "),t("code",[e._v("1,934,999")]),e._v(" observations in the training set and our batch size is "),t("code",[e._v("256")]),e._v(", thus we have "),t("code",[e._v("1,437,841/256=7,558.58")]),e._v(" which by excess result in "),t("code",[e._v("7559")]),e._v(" steps.")]),e._v(" "),t("p",[e._v("The "),t("code",[e._v("~31s")]),e._v(" is the time it takes to process the epoch on a threadripper CPU but GPU or TPU could do better.")]),e._v(" "),t("p",[e._v("The value "),t("code",[e._v("loss")]),e._v(" is the MSE on the training data while "),t("code",[e._v("val_loss")]),e._v(" is the MSE value on the validation data. As far as we understand the separated validation data helps to detect the machine learning enemy, overfitting. Because in case of overfitting the value "),t("code",[e._v("loss")]),e._v(" continue to improve (almost indefinitely) while "),t("code",[e._v("val_loss")]),e._v(" start improving with the loss but a certain point diverge, indicating the network is memorizing the training data to improve "),t("code",[e._v("loss")]),e._v(" but in doing so losing generalizing capabilities.")]),e._v(" "),t("p",[e._v("Our model doesn't look to suffer overfitting cause "),t("code",[e._v("loss")]),e._v(" and "),t("code",[e._v("val_loss")]),e._v(" doesn't diverge during training")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-train-history.png",alt:"train history"}})]),e._v(" "),t("p",[e._v("While we told the training to do 200 epochs, the training stopped at 158 because we added an "),t("code",[e._v("early_stop")]),e._v(" call back with "),t("code",[e._v("20")]),e._v(" as "),t("code",[e._v("PATIENCE")]),e._v(", meaning that after 20 epoch and no improvement in "),t("code",[e._v("val_loss")]),e._v(" the training is halted, saving time and potentially avoiding overfitting.")]),e._v(" "),t("h2",{attrs:{id:"the-prediction-phase"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#the-prediction-phase"}},[e._v("#")]),e._v(" The prediction phase")]),e._v(" "),t("p",[e._v("A "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" is available on github. At the moment it uses a bitcoin core node to provide network data for simplicity, but it queries it only for the mempool and the last 6 blocks, so it's something that also a light-client could do"),t("sup",{staticClass:"footnote-ref"},[t("a",{attrs:{href:"#fn4",id:"fnref4"}},[e._v("[4]")])]),e._v(".")]),e._v(" "),t("p",[e._v("The following chart is probably the best visualization to evaluate the model, on the x axis there is the real fee rate while on the y axis there is the prediction, the more the points are centered on the bisection, the more the model is good.\nWe can see the model is doing quite well, the MAE is 8 which is way lower than "),t("code",[e._v("estimatesmartfee")]),e._v(". However, there are big errors some times, in particular for prediction for fast confirmation ("),t("code",[e._v("confirms_in=1 or confirms_in=2")]),e._v(") as shown by the orange points. Creating a model only for blocks target greater than 2 instead of simply remove some observations may be an option.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png",alt:"prediction results"}})]),e._v(" "),t("p",[e._v("The following chart is instead a distribution of the errors, which for good model should resemble the normal distribution centered in 0, and it loooks like the model is respecting that.")]),e._v(" "),t("figure",[t("img",{attrs:{src:"/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png",alt:"error distribution"}})]),e._v(" "),t("h2",{attrs:{id:"conclusion-and-future-development"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#conclusion-and-future-development"}},[e._v("#")]),e._v(" Conclusion and future development")]),e._v(" "),t("p",[e._v("The results have shown deep neural network are a tool capable of good bitcoin transaction fee estimations; this suggests that further ML research in this area might be promising.")]),e._v(" "),t("p",[e._v("This is just a starting point, there are many future improvements such as:")]),e._v(" "),t("ul",[t("li",[e._v("Build a separate model with full knowledge, thus for full, always-connected nodes could be interesting and improve network resource allocation with respect to current estimators.")]),e._v(" "),t("li",[e._v("Tensorflow is a huge dependency, and since it contains all the feature to build and train a model, most of the feature are not needed in the prediction phase. In fact tensorflow lite exists which is specifically created for embedded and mobile devices; the "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" and the final integration in "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" should use it.")]),e._v(" "),t("li",[e._v("Explore other fields to improve model predictions such as:\n"),t("ul",[t("li",[e._v("A bucket array of the transactions in the last 6 blocks with known fee rates. This should in particular help estimations with almost empty mempool.")]),e._v(" "),t("li",[e._v("Transaction weight")]),e._v(" "),t("li",[e._v("Time from last block")])])]),e._v(" "),t("li",[e._v("Some fields are very important and could benefit from pre-processing expansion, for instance applying "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/structured_data/feature_columns#hashed_feature_columns",target:"_blank",rel:"noopener noreferrer"}},[e._v("hashed feature columns"),t("OutboundLink")],1),e._v(" to "),t("code",[e._v("confirms_in")]),e._v(".")]),e._v(" "),t("li",[e._v("Bitcoin logger could be improved by a merge command to unify raw logs files, reducing redundancy and consequently disk occupation.")]),e._v(" "),t("li",[e._v("The dataset could be created in multiple files to allow more parallelism and use less memory during training.")]),e._v(" "),t("li",[e._v("Saving the dataset in "),t("a",{attrs:{href:"https://www.tensorflow.org/tutorials/load_data/tfrecord",target:"_blank",rel:"noopener noreferrer"}},[e._v("TFRecord format"),t("OutboundLink")],1),e._v(" instead of CSV")]),e._v(" "),t("li",[e._v("At the moment we are training the model on a threadripper CPU, training the code on GPU or even TPU will be needed to decrease training time, especially because input data will grow.")]),e._v(" "),t("li",[e._v("The "),t("a",{attrs:{href:"https://github.com/RCasatta/estimate_ml_fee",target:"_blank",rel:"noopener noreferrer"}},[e._v("prediction test tool"),t("OutboundLink")],1),e._v(" should estimate only using the p2p bitcoin network, without requiring a node. This work would be propedeutic for "),t("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk",target:"_blank",rel:"noopener noreferrer"}},[e._v("bdk"),t("OutboundLink")],1),e._v(" integration")]),e._v(" "),t("li",[e._v("At the moment mempool buckets are multiple inputs "),t("code",[e._v("a*")]),e._v(" as show in the model graph; since they are related, is it possible to merge them in one TensorArray?")]),e._v(" "),t("li",[e._v("Sometimes the model does not learn and "),t("a",{attrs:{href:"https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("gets stuck"),t("OutboundLink")],1),e._v(". The reason is the "),t("code",[e._v("clip")]),e._v(" function applied in the last layer is constant for a value lower than 1. In this case, the derivative is 0 and the gradient descent doesn't know where to go. Instead of using the "),t("code",[e._v("clip")]),e._v(" function apply penalties to the loss function for values lower than 1.")]),e._v(" "),t("li",[e._v("There are issues regarding dead neurons (going to 0) or neurons with big weight, weight results should be monitored for this events, and also weight decay and L2 regularization should be explored.")]),e._v(" "),t("li",[e._v("Tune hyper-parameters technique should be re-tested.")]),e._v(" "),t("li",[e._v("Predictions should be monotonic decreasing for growing "),t("code",[e._v("confirms_in")]),e._v(" parameter; for obvious reason it doesn't make sense that an higher fee rate will result in a higher confirmation time. But since this is not enforced anywhere in the model, at the moment this could happen.")]),e._v(" "),t("li",[e._v("Since nodes with bloom filter disabled doesn't serve the mempool anymore, a model based only on last blocks should be evaluated.")])]),e._v(" "),t("h2",{attrs:{id:"acknowledgements"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#acknowledgements"}},[e._v("#")]),e._v(" Acknowledgements")]),e._v(" "),t("p",[e._v("Thanks to "),t("a",{attrs:{href:"https://squarecrypto.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("Square crypto"),t("OutboundLink")],1),e._v(" for sponsoring this work and thanks to the reviewers: "),t("a",{attrs:{href:"https://twitter.com/LeoComandini",target:"_blank",rel:"noopener noreferrer"}},[e._v("Leonardo Comandini"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/domegabri",target:"_blank",rel:"noopener noreferrer"}},[e._v("Domenico Gabriele"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/afilini",target:"_blank",rel:"noopener noreferrer"}},[e._v("Alekos Filini"),t("OutboundLink")],1),e._v(", "),t("a",{attrs:{href:"https://twitter.com/Ferdinando1970",target:"_blank",rel:"noopener noreferrer"}},[e._v("Ferdinando Ametrano"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("And also this tweet that remembered me "),t("a",{attrs:{href:"https://twitter.com/RCasatta",target:"_blank",rel:"noopener noreferrer"}},[e._v("I"),t("OutboundLink")],1),e._v(" had this work in my TODO list")]),e._v(" "),t("blockquote",{staticClass:"twitter-tweet"},[t("p",{attrs:{lang:"en",dir:"ltr"}},[e._v("I don't understand Machine Learning(ML), but is it horrible to use ML to predict bitcoin fees? "),t("br"),t("br"),e._v('I have heard tales of this "Deep Learning" thing where you throw a bunch of data at it and it gives you good results with high accuracy.')]),e._v("— sanket1729 (@sanket1729) "),t("a",{attrs:{href:"https://twitter.com/sanket1729/status/1336624662365822977?ref_src=twsrc%5Etfw"}},[e._v("December 9, 2020")])]),e._v(" "),t("script",{attrs:{async:"",src:"https://platform.twitter.com/widgets.js",charset:"utf-8"}}),e._v(" "),t("p",[e._v("This is the final part of the series. In the previous "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-1/"}},[e._v("Part 1")]),e._v(" we talked about the problem and in "),t("RouterLink",{attrs:{to:"/blog/2021/01/fee-estimation-for-light-clients-part-2/"}},[e._v("Part 2")]),e._v(" we talked about the dataset.")],1),e._v(" "),t("hr",{staticClass:"footnotes-sep"}),e._v(" "),t("section",{staticClass:"footnotes"},[t("ol",{staticClass:"footnotes-list"},[t("li",{staticClass:"footnote-item",attrs:{id:"fn1"}},[t("p",[e._v("MAE is Mean Absolute Error, which is the average of the series built by the absolute difference between the real value and the estimation. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref1"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn2"}},[t("p",[e._v("drift like MAE, but without the absolute value "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref2"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn3"}},[t("p",[e._v("Most node won't relay transactions with fee lower than the min relay fee, which has a default of "),t("code",[e._v("1.0")]),e._v(" "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref3"}},[e._v("↩︎")])])]),e._v(" "),t("li",{staticClass:"footnote-item",attrs:{id:"fn4"}},[t("p",[e._v("An important issue emerged after the article came out, a bitcoin core client with bloom filter disabled (default as of 0.21) doesn't serve the mempool via p2p. "),t("a",{staticClass:"footnote-backref",attrs:{href:"#fnref4"}},[e._v("↩︎")])])])])])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/51.1ead12c8.js b/assets/js/51.29907970.js similarity index 99% rename from assets/js/51.1ead12c8.js rename to assets/js/51.29907970.js index f1dcc6d6c6..2f2802e1b6 100644 --- a/assets/js/51.1ead12c8.js +++ b/assets/js/51.29907970.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{399:function(t,s,e){"use strict";e.r(s);var a=e(7),n=Object(a.a)({},(function(){var t=this,s=t._self._c;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("p",[t._v("This is the second part of a two-part blog series in which I talk through the changes made to BDK to make a Taproot transaction. If you haven't read it yet, check out "),s("a",{attrs:{href:"/blog/2021/11/first-bdk-taproot-tx-look-at-the-code-part-1"}},[t._v("Part 1")]),t._v(".")]),t._v(" "),s("p",[t._v("While in the first part I managed to show full raw commits, in this case I will only focus on the relevant changes, otherwise the post would get very long. You can always find the "),s("a",{attrs:{href:"https://github.com/bitcoindevkit/bdk/compare/aa075f0...afilini:taproot-testing",target:"_blank",rel:"noopener noreferrer"}},[t._v("full diff"),s("OutboundLink")],1),t._v(" here, if you are interested\nin that.")]),t._v(" "),s("h2",{attrs:{id:"shortcuts"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#shortcuts"}},[t._v("#")]),t._v(" Shortcuts")]),t._v(" "),s("p",[t._v("As mentioned previously, the main goal of this journey for me was to find out what it really takes to support Taproot in BDK. The code shown here wasn't written to be readable and/or maintainable, so\nsome shortcuts were taken, in particular:")]),t._v(" "),s("ul",[s("li",[t._v('No support for BIP32 extended keys: this is probably very quick to add, but in the first "proof of concept" I decided to only work with WIF keys for simplicity')]),t._v(" "),s("li",[t._v("No support for "),s("a",{attrs:{href:"https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki",target:"_blank",rel:"noopener noreferrer"}},[s("code",[t._v("SIGHASH_DEFAULT")]),s("OutboundLink")],1),t._v(': this would require some minor changes to a few traits in BDK that still use the "legacy" '),s("code",[t._v("SigHashType")]),t._v(" enum from "),s("a",{attrs:{href:"https://github.com/rust-bitcoin/rust-bitcoin",target:"_blank",rel:"noopener noreferrer"}},[t._v("rust-bitcoin"),s("OutboundLink")],1)])]),t._v(" "),s("h2",{attrs:{id:"utilities"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#utilities"}},[t._v("#")]),t._v(" Utilities")]),t._v(" "),s("p",[t._v("Let's start with some utilities:")]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("ecdsa_to_schnorr")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("pk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("ecdsa"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("schnorr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("schnorr"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("PublicKey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_slice")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),t._v("pk"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("to_bytes")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Key conversion failure"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("compute_merkle_root")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n leaf_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TapLeafHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n control_block"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(":")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("ControlBlock")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TapBranchHash")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("TapBranchHash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n control_block\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("merkle_branch\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("iter")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("fold")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NodeInfo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_hidden")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("sha256"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("from_slice")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("leaf_hash"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("as_inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Invalid TapLeafHash"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token closure-params"}},[s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")]),t._v("acc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" branch"),s("span",{pre:!0,attrs:{class:"token closure-punctuation punctuation"}},[t._v("|")])]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NodeInfo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("combine")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),t._v("acc"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token namespace"}},[t._v("taproot"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")])]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("NodeInfo")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("::")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("new_hidden")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v("branch"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"Invalid tree"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("hash")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("into_inner")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("p",[t._v('The first function "converts" an ECDSA key to a Schnorr key by dropping the first byte that encodes the key parity, since Schnorr keys are "x-only".')]),t._v(" "),s("p",[t._v("The second one constructs the merkle root of a taptree given a leaf hash and the corresponding control block.")]),t._v(" "),s("h2",{attrs:{id:"wrap-fallible-methods"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#wrap-fallible-methods"}},[t._v("#")]),t._v(" Wrap Fallible Methods")]),t._v(" "),s("p",[t._v("Many of the methods exposed by a "),s("code",[t._v("Descriptor")]),t._v(' struct used to be infallible: for instance, it was always possible to "encode" a descriptor into a Bitcoin script by calling the '),s("code",[t._v("script_pubkey()")]),t._v(" method.")]),t._v(" "),s("p",[t._v("Unfortunately, taproot descriptors need some extra metadata to do that: they can be computed by calling the "),s("code",[t._v("spend_info()")]),t._v(" method, and they will be cached inside the descriptor, but since it's not guaranteed by the\ncompiler that the method will be called before trying to encode it, the infallible methods had to be changed to return a "),s("code",[t._v("Result")]),t._v(", so that they can fail if the spend info is not present.")]),t._v(" "),s("p",[t._v("In BDK we call the "),s("code",[t._v("spend_info()")]),t._v(' method right after "deriving" the descriptor, so it\'s guaranteed that we will never encounter that error: for this reason, we wrap those methods and call '),s("code",[t._v("expect()")]),t._v(" on them, to keep\nthe original code mostly unchanged.")]),t._v(" "),s("p",[t._v("Here we call "),s("code",[t._v("spend_info()")]),t._v(" right after deriving the descriptor, if it's a "),s("code",[t._v("Tr")]),t._v(" variant:")]),t._v(" "),s("div",{staticClass:"language-diff extra-class"},[s("pre",{pre:!0,attrs:{class:"language-diff"}},[s("code",[t._v("@@ -136,10 +133,16 @@ impl AsDerived for Descriptor {\n"),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" index: u32,\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" secp: &'s SecpCtx,\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" ) -> Descriptor> {\n")])]),s("span",{pre:!0,attrs:{class:"token deleted-sign deleted"}},[s("span",{pre:!0,attrs:{class:"token prefix deleted"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" self.derive(index).translate_pk_infallible(\n")])]),s("span",{pre:!0,attrs:{class:"token inserted-sign inserted"}},[s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" let mut derived = self.derive(index).translate_pk_infallible(\n")])]),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" |key| DerivedDescriptorKey::new(key.clone(), secp),\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" |key| DerivedDescriptorKey::new(key.clone(), secp),\n")])]),s("span",{pre:!0,attrs:{class:"token deleted-sign deleted"}},[s("span",{pre:!0,attrs:{class:"token prefix deleted"}},[t._v("-")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" )\n")])]),s("span",{pre:!0,attrs:{class:"token inserted-sign inserted"}},[s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" );\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v("\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" if let Descriptor::Tr(tr) = &mut derived {\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" tr.spend_info(secp);\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" }\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v("\n")]),s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" derived\n")])]),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" }\n")])])])])]),s("p",[t._v("And here we wrap the "),s("code",[t._v("script_pubkey()")]),t._v(" method and call "),s("code",[t._v("expect()")]),t._v(" on it. Note that we only implement it on "),s("code",[t._v("DerivedDescriptor")]),t._v(', because it\'s not guaranteed that "extended descriptors" will have the cached metadata inside.')]),t._v(" "),s("div",{staticClass:"language-rust extra-class"},[s("pre",{pre:!0,attrs:{class:"language-rust"}},[s("code",[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("pub")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("crate")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("trait")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token type-definition class-name"}},[t._v("DerivedDescriptorSafeOps")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// The [`Descriptor::script_pubkey`] method can fail on `Tr` descriptors that don't have the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// `spend_info` inside. Since we generate those upon derivation, it's guaranteed that the")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("/// method will not fail on `DerivedDescriptor`s.")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("script_pubkey_derived")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(";")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("impl")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'s")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivedDescriptorSafeOps")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("for")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Descriptor")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("DerivedDescriptorKey")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),s("span",{pre:!0,attrs:{class:"token lifetime-annotation symbol"}},[t._v("'s")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("fn")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token function-definition function"}},[t._v("script_pubkey_derived")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("&")]),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token class-name"}},[t._v("Script")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("self")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("script_pubkey")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token function"}},[t._v("expect")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token string"}},[t._v('"`spend_info` is always present in `DerivedDescriptor`s"')]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),t._v("\n")])])]),s("h2",{attrs:{id:"descriptor-metadata"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#descriptor-metadata"}},[t._v("#")]),t._v(" Descriptor Metadata")]),t._v(" "),s("p",[t._v('In BDK we have a few traits that in a way "unify" the interface of a descriptor: things like the '),s("code",[t._v("redeem_script")]),t._v(" of an input has to be computed differently depending on the type of descriptor. The traits we define\nare implemented on the "),s("code",[t._v("DerivedDescriptor")]),t._v(" or "),s("code",[t._v("ExtendedDescriptor")]),t._v(" structs and allow us to quickly get what we need without having to check the descriptor type manually.")]),t._v(" "),s("p",[t._v("Internally, they are essentially large "),s("code",[t._v("match")]),t._v("es that return different things depending on the descriptor variant. Due to some renaming that had been done recently in "),s("code",[t._v("miniscript")]),t._v(" (not necessarily related to taproot)\nwe have to update them:")]),t._v(" "),s("div",{staticClass:"language-diff extra-class"},[s("pre",{pre:!0,attrs:{class:"language-diff"}},[s("code",[t._v("@@ -337,6 +339,7 @@ pub(crate) trait DerivedDescriptorMeta {\n\n"),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v("pub(crate) trait DescriptorMeta {\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" fn is_witness(&self) -> bool;\n")])]),s("span",{pre:!0,attrs:{class:"token inserted-sign inserted"}},[s("span",{pre:!0,attrs:{class:"token prefix inserted"}},[t._v("+")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" fn is_tap(&self) -> bool;\n")])]),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" fn get_extended_keys(&self) -> Result>, DescriptorError>;\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" fn derive_from_hd_keypaths<'s>(\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" &self,\n")])]),t._v("@@ -358,23 +361,29 @@ pub(crate) trait DescriptorScripts {\n\n"),s("span",{pre:!0,attrs:{class:"token unchanged"}},[s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v("impl<'s> DescriptorScripts for DerivedDescriptor<'s> {\n")]),s("span",{pre:!0,attrs:{class:"token prefix unchanged"}},[t._v(" ")]),s("span",{pre:!0,attrs:{class:"token line"}},[t._v(" fn psbt_redeem_script(&self) -> Option + diff --git a/bdk-cli/concept/index.html b/bdk-cli/concept/index.html index 6c6f3507be..e2ad124371 100644 --- a/bdk-cli/concept/index.html +++ b/bdk-cli/concept/index.html @@ -31,7 +31,7 @@ - + @@ -62,7 +62,7 @@ will never contain any data that can't be recreated purely by looking at the blockchain. Keys, descriptors, Electrum endpoints are not stored in the database. This explains why you'll have to specify them every time in the command line. It can be seen more like a cache and can be safely deleted without risking funds.
  • BDK doesn't automatically "monitor" the blockchain, instead there's a sync command that has to be called by the user.
  • When you create a transaction and then sign it, it's not automatically broadcast to the network. There's a broadcast command that does this. Moreover, the command doesn't accept a normal Bitcoin raw transaction, but instead a PSBT. That's because internally transactions are always moved as PSBTs, and again, the broadcast command is just a very thin wrapper over the raw library call.
  • There are probably more of these examples, but hopefully by this point you'll have more or less understood the gist of it. If you are not a developer, some parts of this will feel weird, inefficient, hard -to understand, and that's absolutely normal. Just try to survive through the pain and you'll be rewarded!

    - + diff --git a/bdk-cli/index.html b/bdk-cli/index.html index 1401b30461..d3ef26160a 100644 --- a/bdk-cli/index.html +++ b/bdk-cli/index.html @@ -33,7 +33,7 @@ - + @@ -59,7 +59,7 @@ GitHub (opens new window)

    # BDK-CLI

    The bdk-cli (opens new window) repo has an example interactive shell built using the bdk library called bdk-cli that acts both as a reference implementation of a wallet -and a tool to quickly experiment with descriptors and transactions.

    - + diff --git a/bdk-cli/installation/index.html b/bdk-cli/installation/index.html index f89518b49c..e8466a55a3 100644 --- a/bdk-cli/installation/index.html +++ b/bdk-cli/installation/index.html @@ -35,7 +35,7 @@ - + @@ -110,7 +110,7 @@ wallet Wallet Operations

    An example command to sync a testnet wallet to a default electrum server looks like this:

    bdk-cli wallet -w example --descriptor "wpkh(tprv8ZgxMBicQKsPexGYyaFwnAsCXCjmz2FaTm6LtesyyihjbQE3gRMfXqQBXKM43DvC1UgRVv1qom1qFxNMSqVAs88qx9PhgFnfGVUdiiDf6j4/0/*)" sync
    -
    BDK Foundation
    - + diff --git a/bdk-cli/interface/index.html b/bdk-cli/interface/index.html index e3ff42e236..34a35e150b 100644 --- a/bdk-cli/interface/index.html +++ b/bdk-cli/interface/index.html @@ -29,7 +29,7 @@ - + @@ -364,7 +364,7 @@ --psbt <BASE64_PSBT> Sets the PSBT to sign --assume_height <HEIGHT> Assume the blockchain has reached a specific height. This affects the transaction finalization, if there are timelocks in the descriptor --trust_witness_utxo <WITNESS> Whether the signer should trust the witness_utxo, if the non_witness_utxo hasn’t been provided -

    Adds to the PSBT all the signatures it can produce with the secrets embedded in the descriptor (xprv or WIF keys). Returns the signed PSBT and, if there are enough item to satisfy the script, also the extracted raw Bitcoin transaction.

    Optionally, the --assume_height option can be specified to let the wallet assume the blockchain has reached a specific height. This affects the finalization of the PSBT which is done right at the end of the signing process: the wallet tries to satisfy the spending condition of each input using the partial signatures collected. In case timelocks are present the wallet needs to know whether or not they have expired. This flag is particularly useful for offline wallets.

    # sync

    This subcommand has no extra flags. It connects to the chosen Electrum server and synchronizes the list of transactions received and available UTXOs.

    Adds to the PSBT all the signatures it can produce with the secrets embedded in the descriptor (xprv or WIF keys). Returns the signed PSBT and, if there are enough item to satisfy the script, also the extracted raw Bitcoin transaction.

    Optionally, the --assume_height option can be specified to let the wallet assume the blockchain has reached a specific height. This affects the finalization of the PSBT which is done right at the end of the signing process: the wallet tries to satisfy the spending condition of each input using the partial signatures collected. In case timelocks are present the wallet needs to know whether or not they have expired. This flag is particularly useful for offline wallets.

    # sync

    This subcommand has no extra flags. It connects to the chosen Electrum server and synchronizes the list of transactions received and available UTXOs.

    BDK Foundation
    - + diff --git a/bdk-cli/introduction/index.html b/bdk-cli/introduction/index.html index 3b6a2c7193..68cc07b4b4 100644 --- a/bdk-cli/introduction/index.html +++ b/bdk-cli/introduction/index.html @@ -29,7 +29,7 @@ - + @@ -53,7 +53,7 @@ Blog GitHub - (opens new window)

    # Introduction

    bdk-cli (opens new window) is a lightweight repl (opens new window) wrapper over bdk that comes as a command line application. It is useful for quick testing and prototyping of bdk functionalities.

    This can also be used as an example application to create your own command line bitcoin wallet tool using bdk.

    bdk-cli can interface with all the blockchain backends currently supported by bdk, like rpc, electrum, esplora and compact_filters.

    Check out project documentation (opens new window) for more details.

    The following sections goes into more details on the installation and usage of bdk-cli.

    - + diff --git a/bdk-cli/playground/index.html b/bdk-cli/playground/index.html index 043f507492..2681861e98 100644 --- a/bdk-cli/playground/index.html +++ b/bdk-cli/playground/index.html @@ -27,7 +27,7 @@ - + @@ -51,7 +51,7 @@ Blog GitHub - (opens new window)

    # Playground

    - + diff --git a/bdk-cli/regtest/index.html b/bdk-cli/regtest/index.html index b31395dcef..1f5193f008 100644 --- a/bdk-cli/regtest/index.html +++ b/bdk-cli/regtest/index.html @@ -31,7 +31,7 @@ - + @@ -60,7 +60,7 @@

    Just like before, this command will probably take a while to finish.

    Once it's done, assuming you have a regtest bitcoind running in background, you can launch a new terminal and run the following command to actually start electrs:

    electrs --log-filters INFO --timestamp --db-dir /tmp/electrs-db --electrum-rpc-addr="127.0.0.1:50001" --network=regtest --cookie-file=$HOME/.bitcoin/regtest/.cookie
     

    on macOS you should change the cookie-file to $HOME/Library/Application Support/Bitcoin/regtest/.cookie.

    This will start the Electrum server on port 50001. You can then add the -n regtest -s 127.0.0.1:50001 to the bdk-cli commands to switch to the local regtest.

    # Troubleshooting

    # Stuck with "wait until bitcoind is synced (i.e. initialblockdownload = false)"

    Just generate a few blocks with bitcoin-cli generatetoaddress 1 <address>

    # Bonus: Docker

    If you have already installed Docker on your machine, you can also use 🍣 Nigiri CLI (opens new window) to spin-up a complete development environment in regtest that includes a bitcoin node, an electrs explorer and the esplora (opens new window) web-app to visualize blocks and transactions in the browser.

    Install 🍣 Nigiri

    $ curl https://getnigiri.vulpem.com | bash
     

    Start Docker daemon and run Nigiri box

    $ nigiri start
    -

    This will start electrum RPC interface on port 51401, the REST interface on 3000 and the esplora UI on 5000 (You can visit with the browser and look for blocks, addresses and transactions)

    You can then add the -n regtest -s 127.0.0.1:51401 to the bdk-cli commands to switch to the local regtest.

    This will start electrum RPC interface on port 51401, the REST interface on 3000 and the esplora UI on 5000 (You can visit with the browser and look for blocks, addresses and transactions)

    You can then add the -n regtest -s 127.0.0.1:51401 to the bdk-cli commands to switch to the local regtest.

    BDK Foundation
    - + diff --git a/blog/2020/12/hello-world/index.html b/blog/2020/12/hello-world/index.html index 62249194da..4fb3bec2c3 100644 --- a/blog/2020/12/hello-world/index.html +++ b/blog/2020/12/hello-world/index.html @@ -30,7 +30,7 @@ - + @@ -147,7 +147,7 @@ txid = txid );

    # Custom Database and Blockchain types

    We briefly mentioned before that for our example we used the MemoryDatabase, but that it could also be swapped for a different one: this is one example of the modularity of BDK. By default, some database types are already implemented in the library, namely the MemoryDatabase (opens new window) which only keeps data in RAM, the Sled (opens new window) database that can store data on a filesystem, and the SqliteDatabase (opens new window) that can store data into a SQLite database. But since the Database trait is public, users of the library can also implement different database types more suitable for their use-case.

    The same is true for the Blockchain types: the library provides (through the use of opt-in features) implementations for the Electrum, Esplora, CompactFilters (Neutrino) and Bitcoin Core rpc backends. Those again can also be -swapped with custom types if the user desires to do so.

    # Conclusion

    Hopefully, this article will help you get started with BDK! This is just a very quick and gentle introduction to the library, and only barely scratches the surface of what's inside: we will keep publishing more articles in the future to explain some of the more advanced features of BDK, like key generation, using complex descriptors with multiple keys and/or timelocks, using external signers, etc.

    If you'd like to learn more about the library feel free to ask any questions in the comment section down below, or join our Discord Community (opens new window) to chat with us directly!

    - + diff --git a/blog/2020/12/release-v0.2.0/index.html b/blog/2020/12/release-v0.2.0/index.html index f9da51d8b2..d90147b6a2 100644 --- a/blog/2020/12/release-v0.2.0/index.html +++ b/blog/2020/12/release-v0.2.0/index.html @@ -30,7 +30,7 @@ - + @@ -128,7 +128,7 @@ .map_err(|e| KeyError::Message(e.to_string()))?) } } -

    # Support for sortedmulti()

    Thanks to the addition of sortedmulti() in rust-miniscript, we can now also support them in BDK, which means we are getting more and more compatible with other descriptor-based wallets out there like Bitcoin Core.

    # Contributors

    A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports.

    Since the 0.1.0-beta.1 release over three months ago, we've had 213 new commits made by 10 different contributors for a total of 9990 additions and 2993 deletions. Here's the full diff (opens new window).

    A special thanks to the 7 new contributors:

    - + diff --git a/blog/bdk-cli-basics-multisig-2of3/index.html b/blog/bdk-cli-basics-multisig-2of3/index.html index a004446c86..8837a2204d 100644 --- a/blog/bdk-cli-basics-multisig-2of3/index.html +++ b/blog/bdk-cli-basics-multisig-2of3/index.html @@ -30,7 +30,7 @@ - + @@ -126,7 +126,7 @@

    # Step 12: Broadcast Transaction

    ▶️ bdk-cli wallet --wallet wallet_name_msd01 --descriptor $MULTI_DESCRIPTOR_01 broadcast --psbt $SECONDSIG_PSBT

    {
       "txid": "61da2451874a483aa8d1d0787c7680d157639f284840de8885098cac43f6cc2f"
     }
    -

    # Verify Transaction

    Verify transcation in the memory pool on testnet Mempool-testnet! (opens new window)

    - + diff --git a/blog/tags/basics/index.html b/blog/tags/basics/index.html index 20057ef007..576309b446 100644 --- a/blog/tags/basics/index.html +++ b/blog/tags/basics/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bdk-cli/index.html b/blog/tags/bdk-cli/index.html index 1c1ce67e6f..75146471c5 100644 --- a/blog/tags/bdk-cli/index.html +++ b/blog/tags/bdk-cli/index.html @@ -25,7 +25,7 @@ - + @@ -114,6 +114,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bdk-rn/index.html b/blog/tags/bdk-rn/index.html index 7f3cb7d260..8111eff0ae 100644 --- a/blog/tags/bdk-rn/index.html +++ b/blog/tags/bdk-rn/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bdk/index.html b/blog/tags/bdk/index.html index 16c3c90ff6..2431f2c8f7 100644 --- a/blog/tags/bdk/index.html +++ b/blog/tags/bdk/index.html @@ -25,7 +25,7 @@ - + @@ -169,6 +169,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bindings/index.html b/blog/tags/bindings/index.html index fd05d9c2ff..87165012dd 100644 --- a/blog/tags/bindings/index.html +++ b/blog/tags/bindings/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bitcoin-cli/index.html b/blog/tags/bitcoin-cli/index.html index 313724e11b..1d9973f138 100644 --- a/blog/tags/bitcoin-cli/index.html +++ b/blog/tags/bitcoin-cli/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/bitcoin/index.html b/blog/tags/bitcoin/index.html index e3ae94560e..b998e18ebf 100644 --- a/blog/tags/bitcoin/index.html +++ b/blog/tags/bitcoin/index.html @@ -25,7 +25,7 @@ - + @@ -92,6 +92,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/blockchain/index.html b/blog/tags/blockchain/index.html index c4462fa1c5..e9bdab1186 100644 --- a/blog/tags/blockchain/index.html +++ b/blog/tags/blockchain/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/coin selection/index.html b/blog/tags/coin selection/index.html index 7f2e0d52b1..78b40ce9f7 100644 --- a/blog/tags/coin selection/index.html +++ b/blog/tags/coin selection/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/compact_filters/index.html b/blog/tags/compact_filters/index.html index 685c1e4805..56f32baf6c 100644 --- a/blog/tags/compact_filters/index.html +++ b/blog/tags/compact_filters/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/descriptor/index.html b/blog/tags/descriptor/index.html index e6360ba3d6..7d369d5946 100644 --- a/blog/tags/descriptor/index.html +++ b/blog/tags/descriptor/index.html @@ -25,7 +25,7 @@ - + @@ -114,6 +114,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/development/index.html b/blog/tags/development/index.html index 4476fb19e0..f27375bc1a 100644 --- a/blog/tags/development/index.html +++ b/blog/tags/development/index.html @@ -25,7 +25,7 @@ - + @@ -103,6 +103,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/fee/index.html b/blog/tags/fee/index.html index fb3fc13870..efe8c481d5 100644 --- a/blog/tags/fee/index.html +++ b/blog/tags/fee/index.html @@ -25,7 +25,7 @@ - + @@ -103,6 +103,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/getting started/index.html b/blog/tags/getting started/index.html index 7476e38c9d..bddf880354 100644 --- a/blog/tags/getting started/index.html +++ b/blog/tags/getting started/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/guide/index.html b/blog/tags/guide/index.html index 158fc7abee..97b4c1fd40 100644 --- a/blog/tags/guide/index.html +++ b/blog/tags/guide/index.html @@ -25,7 +25,7 @@ - + @@ -125,6 +125,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/iOS/index.html b/blog/tags/iOS/index.html index 77a5c51a21..8714c29ccd 100644 --- a/blog/tags/iOS/index.html +++ b/blog/tags/iOS/index.html @@ -25,7 +25,7 @@ - + @@ -92,6 +92,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/index.html b/blog/tags/index.html index 41b69721e1..8abb35120f 100644 --- a/blog/tags/index.html +++ b/blog/tags/index.html @@ -25,7 +25,7 @@ - + @@ -49,7 +49,7 @@ Blog GitHub - (opens new window)
    - + diff --git a/blog/tags/miniscript/index.html b/blog/tags/miniscript/index.html index afe947988e..8821bf0f7e 100644 --- a/blog/tags/miniscript/index.html +++ b/blog/tags/miniscript/index.html @@ -25,7 +25,7 @@ - + @@ -114,6 +114,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/mobile/index.html b/blog/tags/mobile/index.html index a15b999760..cbee634375 100644 --- a/blog/tags/mobile/index.html +++ b/blog/tags/mobile/index.html @@ -25,7 +25,7 @@ - + @@ -92,6 +92,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/multi-sig/index.html b/blog/tags/multi-sig/index.html index 436abce7e4..b743526904 100644 --- a/blog/tags/multi-sig/index.html +++ b/blog/tags/multi-sig/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/novice/index.html b/blog/tags/novice/index.html index 62ff5db28e..70bb6abe1e 100644 --- a/blog/tags/novice/index.html +++ b/blog/tags/novice/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/paper wallets/index.html b/blog/tags/paper wallets/index.html index f18300c309..dcdb1a9786 100644 --- a/blog/tags/paper wallets/index.html +++ b/blog/tags/paper wallets/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/project/index.html b/blog/tags/project/index.html index 282c71b91b..3822393fe3 100644 --- a/blog/tags/project/index.html +++ b/blog/tags/project/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/release/index.html b/blog/tags/release/index.html index b5c7c5d82f..2833f59f53 100644 --- a/blog/tags/release/index.html +++ b/blog/tags/release/index.html @@ -25,7 +25,7 @@ - + @@ -158,6 +158,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/rust/index.html b/blog/tags/rust/index.html index b73d0183ec..f0e436b304 100644 --- a/blog/tags/rust/index.html +++ b/blog/tags/rust/index.html @@ -25,7 +25,7 @@ - + @@ -169,6 +169,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/security/index.html b/blog/tags/security/index.html index b596f9498b..363d3e07e9 100644 --- a/blog/tags/security/index.html +++ b/blog/tags/security/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/summer of bitcoin/index.html b/blog/tags/summer of bitcoin/index.html index 2a9e0518bd..a692f42648 100644 --- a/blog/tags/summer of bitcoin/index.html +++ b/blog/tags/summer of bitcoin/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/taproot/index.html b/blog/tags/taproot/index.html index 0fb19c6503..82a90274eb 100644 --- a/blog/tags/taproot/index.html +++ b/blog/tags/taproot/index.html @@ -25,7 +25,7 @@ - + @@ -92,6 +92,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/tor/index.html b/blog/tags/tor/index.html index aa5ffc9ed9..99495ef607 100644 --- a/blog/tags/tor/index.html +++ b/blog/tags/tor/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/tutorial/index.html b/blog/tags/tutorial/index.html index 325e325951..db08649146 100644 --- a/blog/tags/tutorial/index.html +++ b/blog/tags/tutorial/index.html @@ -25,7 +25,7 @@ - + @@ -147,6 +147,6 @@
    BDK Foundation
    - + diff --git a/blog/tags/wallet/index.html b/blog/tags/wallet/index.html index dc7824fb95..c33a93a6ea 100644 --- a/blog/tags/wallet/index.html +++ b/blog/tags/wallet/index.html @@ -25,7 +25,7 @@ - + @@ -81,6 +81,6 @@
    BDK Foundation
    - + diff --git a/blog/using-bdk-with-hardware-wallets/index.html b/blog/using-bdk-with-hardware-wallets/index.html index a4f4c2fef9..b4b74e2b95 100644 --- a/blog/using-bdk-with-hardware-wallets/index.html +++ b/blog/using-bdk-with-hardware-wallets/index.html @@ -30,7 +30,7 @@ - + @@ -181,7 +181,7 @@ blockchain.broadcast(&raw_transaction)?; println!("Transaction broadcasted! TXID: {txid}.\nExplorer URL: https://mempool.space/testnet/tx/{txid}", txid = txid); -

    # Conclusion

    We just received coins on a hardware wallet and spent from it - how cool is that?!

    See the hardware signer example (opens new window) for the full code, and, if you have any questions or suggestions, head to our Discord (opens new window). See you there!

    - + diff --git a/descriptors/index.html b/descriptors/index.html index 18c6efb7a2..e24329caca 100644 --- a/descriptors/index.html +++ b/descriptors/index.html @@ -33,7 +33,7 @@ - + @@ -63,7 +63,7 @@ aims to produce the first "Native Descriptor" Bitcoin library that can be used by developers to build their own "Native Descriptor Wallets" (opens new window).

    # Compatibility Matrix

    Below are some tables to highlight the differences between Bitcoin Core's descriptor support, rust-miniscript's one and BDK's.

    # Key Types

    Key Type BDK rust-miniscript Bitcoin Core
    Hex PublicKey
    WIF PrivateKey
    Extended Keys (xpub/xprv)

    # Script Types (top level)

    Script Type BDK rust-miniscript Bitcoin Core
    pk()
    pkh()
    wpkh()
    sh(wpkh())
    sh()
    wsh()
    sh(wsh())
    combo()
    addr()
    raw()
    Bare scripts

    # Operators

    Operator BDK rust-miniscript Bitcoin Core
    pk()
    pkh()
    older()
    after()
    sha256()
    hash256()
    ripemd160()
    hash160()
    andor()
    and_{v,b,n}()
    or_{b,c,d,i}()
    multi()
    thresh()
    sortedmulti()

    # Modifiers

    Script Type BDK rust-miniscript Bitcoin Core
    a:
    s:
    c:
    t:
    d:
    v:
    j:
    n:
    l:
    u:

    For a more thorough description of these operators and modifiers see Sipa's Miniscript Page (opens new window) and Bitcoin Core's (opens new window).

    # Examples

    Some examples of valid BDK descriptors are:

    Spending Policy Descriptor Address 0 Address 1
    Static P2PKH pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR) mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr
    Static P2PKH, watch-only pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c) mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr
    P2WSH 2-of-2 with one private key wsh(multi(2,tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*,tpubDBYDcH8P2PedrEN3HxWYJJJMZEdgnrqMsjeKpPNzwe7jmGwk5M3HRdSf5vudAXwrJPfUsfvUPFooKWmz79Lh111U51RNotagXiGNeJe3i6t/1/*)) tb1qqsat6c82fvdy73rfzye8f7nwxcz3xny7t56azl73g95mt3tmzvgs9a8vjs tb1q7sgx6gscgtau57jduend6a8l445ahpk3dt3u5zu58rx5qm27lhkqgfdjdr
    P2WSH-P2SH one key + 10 days timelock sh(wsh(and_v(vc:pk_h(tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*),older(1440)))) 2Mtk2nyS98MCi2P7TkoBGLaJviBy956XxB1 2MuEStKzYhqb5HCFgHz9153tZsL5sVqV5xC

    # Implementation Details

    BDK extends the capabilities of rust-miniscript (opens new window) by introducing the concept of an ExtendedDescriptor: it represents a descriptor that contains one or more "derivable keys" like xpubs or xprvs and can be "derived" from a normal Descriptor by deriving every single one of its keys. It is currently called "StringDescriptor" in the code, because it's implemented as a wrapped miniscript::Descriptor<String>.

    ExtendedDescriptors are derived using a single index instead of a full derivation path: this is because normally most of the path is fixed and can be represented right after the xpub/xprv itself, and only the final index changes for each address. This is what's normally called a DescriptorExtendedKey in the codebase, it is represented with a similar syntax to Bitcoin Core's, such as:

    [d34db33f/44'/0'/0']xpub6ERApfZwUNrhL.......rBGRjaDMzQLcgJvLJuZZvRcEL/0/*
    -
    BDK Foundation
    - + diff --git a/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html b/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html index f548b05c65..d86af3fcf2 100644 --- a/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html +++ b/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html @@ -173,10 +173,10 @@
    Examples
    assert_eq!(result.to_string(), "tr(03cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115)#6qm9h8ym");
    Errors

    This function will return an error if hardened derivation is attempted.

    -

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the minimum value (in satoshis) at which an output is broadcastable. -Panics if the descriptor wildcard is hardened. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    Extract the spending policy
    Run a predicate on every key in the descriptor, returning whether +

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the minimum value (in satoshis) at which an output is broadcastable. +Panics if the descriptor wildcard is hardened. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    Extract the spending policy
    Run a predicate on every key in the descriptor, returning whether the predicate returned true for every key Read more
    Run a predicate on every key in the descriptor, returning whether -the predicate returned true for any key Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more

    Parse an expression tree into a descriptor.

    +the predicate returned true for any key Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    Converts to this type from the input type.
    The associated error which can be returned from parsing.
    Parses a string s to return a value of this type. Read more

    Parse an expression tree into a descriptor.

    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    Converts this object into an abstract policy.
    This method returns an Ordering between self and other. Read more
    Compares and returns the maximum of two values. Read more
    Compares and returns the minimum of two values. Read more
    Restrict a value to a certain interval. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    This method returns an ordering between self and other values if one exists. Read more
    This method tests less than (for self and other) and is used by the < operator. Read more
    This method tests less than or equal to (for self and other) and is used by the <= diff --git a/docs-rs/bdk/nightly/latest/bdk/index.html b/docs-rs/bdk/nightly/latest/bdk/index.html index 7bfb11a3a0..42b7efb8ec 100644 --- a/docs-rs/bdk/nightly/latest/bdk/index.html +++ b/docs-rs/bdk/nightly/latest/bdk/index.html @@ -1,5 +1,5 @@ bdk - Rust

    Crate bdk

    source ·
    Expand description
    + logo

    Crate bdk

    Crate bdk

    source ·
    Expand description

    BDK

    @@ -167,4 +167,4 @@

    Contribution

    submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

    -

    Re-exports

    pub extern crate bitcoin;
    pub extern crate miniscript;
    pub use descriptor::template;
    pub use descriptor::HdKeyPaths;
    pub use wallet::signer;
    pub use wallet::signer::SignOptions;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::Wallet;
    pub use bdk_chain as chain;

    Modules

    Descriptors
    Key formats
    Additional functions on the rust-bitcoin Psbt structure.
    Wallet

    Macros

    Macro to write full descriptors with code
    Macro to write descriptor fragments with code

    Structs

    An unspent output owned by a Wallet.
    A Utxo with its satisfaction_weight.

    Enums

    Types of keychains
    An unspent transaction output (UTXO).

    Functions

    Get the version of BDK at runtime
    \ No newline at end of file +

    Re-exports

    pub extern crate bitcoin;
    pub extern crate miniscript;
    pub use descriptor::template;
    pub use descriptor::HdKeyPaths;
    pub use wallet::signer;
    pub use wallet::signer::SignOptions;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::Wallet;
    pub use bdk_chain as chain;

    Modules

    Descriptors
    Key formats
    Additional functions on the rust-bitcoin Psbt structure.
    Wallet

    Macros

    Macro to write full descriptors with code
    Macro to write descriptor fragments with code

    Structs

    An unspent output owned by a Wallet.
    A Utxo with its satisfaction_weight.

    Enums

    Types of keychains
    An unspent transaction output (UTXO).

    Functions

    Get the version of BDK at runtime
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html b/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html index f10c54b56f..4b6d906a78 100644 --- a/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html +++ b/docs-rs/bdk/nightly/latest/bdk/struct.LocalOutput.html @@ -5,14 +5,14 @@ pub keychain: KeychainKind, pub is_spent: bool, pub derivation_index: u32, - pub confirmation_time: ConfirmationTime, + pub confirmation_time: ConfirmationTime, }
    Expand description

    An unspent output owned by a Wallet.

    Fields§

    §outpoint: OutPoint

    Reference to a transaction output

    §txout: TxOut

    Transaction output

    §keychain: KeychainKind

    Type of keychain

    §is_spent: bool

    Whether this UTXO is spent or not

    §derivation_index: u32

    The derivation index for the script pubkey in the wallet

    -
    §confirmation_time: ConfirmationTime

    The confirmation time for transaction containing this utxo

    +
    §confirmation_time: ConfirmationTime

    The confirmation time for transaction containing this utxo

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Feeds this value into the given Hasher. Read more
    Feeds a slice of this type into the given Hasher. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html b/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html index 202c59861a..08c05e5ebd 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/enum.ApplyBlockError.html @@ -1,12 +1,12 @@ ApplyBlockError in bdk::wallet - Rust
    pub enum ApplyBlockError {
    -    CannotConnect(CannotConnectError),
    +    CannotConnect(CannotConnectError),
         UnexpectedConnectedToHash {
             connected_to_hash: BlockHash,
             expected_hash: BlockHash,
         },
     }
    Expand description

    An error that may occur when applying a block to Wallet.

    -

    Variants§

    §

    CannotConnect(CannotConnectError)

    Occurs when the update chain cannot connect with original chain.

    +

    Variants§

    §

    CannotConnect(CannotConnectError)

    Occurs when the update chain cannot connect with original chain.

    §

    UnexpectedConnectedToHash

    Fields

    §connected_to_hash: BlockHash

    Block hash of connected_to.

    §expected_hash: BlockHash

    Expected block hash of connected_to, as derived from block.

    Occurs when the connected_to hash does not match the hash derived from block.

    diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html index 412deea90d..5e3c1aaa12 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Balance.html @@ -1,5 +1,5 @@ Balance in bdk::wallet - Rust

    Struct bdk::wallet::Balance

    source ·
    pub struct Balance {
    +                    logo

    Balance

    Struct bdk::wallet::Balance

    pub struct Balance {
         pub immature: u64,
         pub trusted_pending: u64,
         pub untrusted_pending: u64,
    @@ -9,13 +9,13 @@
     
    §trusted_pending: u64

    Unconfirmed UTXOs generated by a wallet tx

    §untrusted_pending: u64

    Unconfirmed UTXOs received from an external wallet

    §confirmed: u64

    Confirmed and immediately spendable balance

    -

    Implementations§

    Get sum of trusted_pending and confirmed coins.

    +

    Implementations§

    Get sum of trusted_pending and confirmed coins.

    This is the balance you can spend right now that shouldn’t get cancelled via another party double spending it.

    -

    Get the whole balance visible to the wallet.

    -

    Trait Implementations§

    The resulting type after applying the + operator.
    Performs the + operation. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used +

    Get the whole balance visible to the wallet.

    +

    Trait Implementations§

    The resulting type after applying the + operator.
    Performs the + operation. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Formats the value using the given formatter. Read more
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html index f5962751ed..9baea2aba8 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.ChangeSet.html @@ -1,13 +1,13 @@ ChangeSet in bdk::wallet - Rust

    Struct bdk::wallet::ChangeSet

    source ·
    pub struct ChangeSet {
    -    pub chain: ChangeSet,
    -    pub indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>,
    +    pub chain: ChangeSet,
    +    pub indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>,
         pub network: Option<Network>,
     }
    Expand description

    The changes made to a wallet by applying an Update.

    -

    Fields§

    §chain: ChangeSet

    Changes to the LocalChain.

    -
    §indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>

    Changes to IndexedTxGraph.

    +

    Fields§

    §chain: ChangeSet

    Changes to the LocalChain.

    +
    §indexed_tx_graph: ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>

    Changes to IndexedTxGraph.

    §network: Option<Network>

    Stores the network type of the wallet.

    -

    Trait Implementations§

    Append another object of the same type onto self.
    Returns whether the structure is considered empty.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used +

    Trait Implementations§

    Append another object of the same type onto self.
    Returns whether the structure is considered empty.
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more
    Deserialize this value from the given Serde deserializer. Read more
    Converts to this type from the input type.
    Converts to this type from the input type.
    This method tests for self and other values to be equal, and is used by ==. Read more
    This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason. Read more
    Serialize this value into the given Serde serializer. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html index 36b90e7b75..acc4c3b32d 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Update.html @@ -1,14 +1,14 @@ Update in bdk::wallet - Rust

    Struct bdk::wallet::Update

    source ·
    pub struct Update {
         pub last_active_indices: BTreeMap<KeychainKind, u32>,
    -    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
    -    pub chain: Option<Update>,
    +    pub graph: TxGraph<ConfirmationTimeHeightAnchor>,
    +    pub chain: Option<Update>,
     }
    Expand description

    An update to Wallet.

    -

    It updates bdk_chain::keychain::KeychainTxOutIndex, bdk_chain::TxGraph and local_chain::LocalChain atomically.

    +

    It updates [bdk_chain::keychain::KeychainTxOutIndex], [bdk_chain::TxGraph] and [local_chain::LocalChain] atomically.

    Fields§

    §last_active_indices: BTreeMap<KeychainKind, u32>

    Contains the last active derivation indices per keychain (K), which is used to update the -KeychainTxOutIndex.

    -
    §graph: TxGraph<ConfirmationTimeHeightAnchor>

    Update for the wallet’s internal TxGraph.

    -
    §chain: Option<Update>

    Update for the wallet’s internal LocalChain.

    +[KeychainTxOutIndex].

    +
    §graph: TxGraph<ConfirmationTimeHeightAnchor>

    Update for the wallet’s internal [TxGraph].

    +
    §chain: Option<Update>

    Update for the wallet’s internal LocalChain.

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html index f483cb9ecb..3565a89a7f 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html @@ -8,7 +8,7 @@

    Implementations§

    Creates a wallet that does not persist data.

    Creates a wallet that does not persist data, with a custom genesis hash.

    -

    Infallibly return a derived address using the external descriptor, see AddressIndex for +

    Infallibly return a derived address using the external descriptor, see AddressIndex for available address index selection strategies. If none of the keys in the descriptor are derivable (i.e. does not end with /*) then the same address will always be returned for any AddressIndex.

    Panics
    @@ -22,21 +22,21 @@
    Panics
    Panics

    This panics when the caller requests for an address of derivation index greater than the BIP32 max index.

    -

    Initialize an empty Wallet.

    -

    Initialize an empty Wallet with a custom genesis hash.

    +

    Initialize an empty Wallet.

    +

    Initialize an empty Wallet with a custom genesis hash.

    This is like Wallet::new with an additional genesis_hash parameter. This is useful for syncing from alternative networks.

    -

    Load Wallet from the given persistence backend.

    -

    Either loads Wallet from persistence, or initializes it if it does not exist.

    +

    Load Wallet from the given persistence backend.

    +

    Either loads Wallet from persistence, or initializes it if it does not exist.

    This method will fail if the loaded Wallet has different parameters to those provided.

    -

    Either loads Wallet from persistence, or initializes it if it does not exist (with a +

    Either loads Wallet from persistence, or initializes it if it does not exist (with a custom genesis hash).

    This method will fail if the loaded Wallet has different parameters to those provided. This is like Wallet::new_or_load with an additional genesis_hash parameter. This is useful for syncing from alternative networks.

    Get the Bitcoin network the wallet is using.

    Iterator over all keychains in this wallet

    -

    Return a derived address using the external descriptor, see AddressIndex for +

    Return a derived address using the external descriptor, see AddressIndex for available address index selection strategies. If none of the keys in the descriptor are derivable (i.e. does not end with /*) then the same address will always be returned for any AddressIndex.

    A PersistBackend<ChangeSet>::WriteError will result if unable to persist the new address @@ -44,7 +44,7 @@

    Panics
    Panics

    This panics when the caller requests for an address of derivation index greater than the BIP32 max index.

    -

    Return a derived address using the internal (change) descriptor.

    +

    Return a derived address using the internal (change) descriptor.

    If the wallet doesn’t have an internal descriptor it will use the external descriptor.

    A PersistBackend<ChangeSet>::WriteError will result if unable to persist the new address to the PersistBackend.

    @@ -60,8 +60,8 @@
    Panics

    Return the list of unspent outputs of this wallet

    List all relevant outputs (includes both spent and unspent, confirmed and unconfirmed).

    To list only unspent outputs (UTXOs), use Wallet::list_unspent instead.

    -

    Get all the checkpoints the wallet is currently storing indexed by height.

    -

    Returns the latest checkpoint.

    +

    Get all the checkpoints the wallet is currently storing indexed by height.

    +

    Returns the latest checkpoint.

    Get unbounded script pubkey iterators for both Internal and External keychains.

    This is intended to be used when doing a full scan of your addresses (e.g. after restoring from seed words). You pass the BTreeMap of iterators to a blockchain data source (e.g. @@ -72,14 +72,14 @@

    Panics

    See all_unbounded_spk_iters for more documentation

    Returns the utxo owned by this wallet corresponding to outpoint if it exists in the wallet’s database.

    -

    Inserts a [TxOut] at [OutPoint] into the wallet’s transaction graph.

    +

    Inserts a [TxOut] at [OutPoint] into the wallet’s transaction graph.

    This is used for providing a previous output’s value so that we can use calculate_fee or calculate_fee_rate on a given transaction. Outputs inserted with this method will not be returned in list_unspent or list_output.

    Any inserted TxOuts are not persisted until commit is called.

    WARNING: This should only be used to add TxOuts that the wallet does not own. Only insert TxOuts that you trust the values for!

    -

    Calculates the fee of a given transaction. Returns 0 if tx is a coinbase transaction.

    +

    Calculates the fee of a given transaction. Returns 0 if tx is a coinbase transaction.

    To calculate the fee for a [Transaction] with inputs not owned by this wallet you must manually insert the TxOut(s) into the tx graph using the insert_txout function.

    Note tx does not have to be in the graph for this to work.

    @@ -89,7 +89,7 @@
    Examples
    let tx = &psbt.clone().extract_tx().expect("tx");
     let fee = wallet.calculate_fee(tx).expect("fee");
    -

    Calculate the [FeeRate] for a given transaction.

    +

    Calculate the [FeeRate] for a given transaction.

    To calculate the fee rate for a [Transaction] with inputs not owned by this wallet you must manually insert the TxOut(s) into the tx graph using the insert_txout function.

    Note tx does not have to be in the graph for this to work.

    @@ -109,12 +109,12 @@
    Examples
    let tx = &psbt.clone().extract_tx().expect("tx");
     let (sent, received) = wallet.sent_and_received(tx);
    -

    Get a single transaction from the wallet as a CanonicalTx (if the transaction exists).

    +

    Get a single transaction from the wallet as a [CanonicalTx] (if the transaction exists).

    CanonicalTx contains the full transaction alongside meta-data such as:

      -
    • Blocks that the transaction is Anchored in. These may or may not be blocks that exist +
    • Blocks that the transaction is Anchored in. These may or may not be blocks that exist in the best chain.
    • -
    • The ChainPosition of the transaction in the best chain - whether the transaction is +
    • The [ChainPosition] of the transaction in the best chain - whether the transaction is confirmed or unconfirmed. If the transaction is confirmed, the anchor which proves the confirmation is provided. If the transaction is unconfirmed, the unix timestamp of when the transaction was last seen in the mempool is provided.
    • @@ -147,11 +147,11 @@
      Examples
      last_seen, ), }
    -

    Add a new checkpoint to the wallet’s internal view of the chain. +

    Add a new checkpoint to the wallet’s internal view of the chain. This stages but does not commit the change.

    Returns whether anything changed with the insertion (e.g. false if checkpoint was already there).

    -

    Add a transaction to the wallet’s internal view of the chain. This stages but does not +

    Add a transaction to the wallet’s internal view of the chain. This stages but does not commit the change.

    Returns whether anything changed with the transaction insertion (e.g. false if the transaction was already inserted at the same position).

    @@ -161,7 +161,7 @@
    Examples

    WARNING: If position is confirmed, we anchor the tx to a the lowest checkpoint that is >= the position’s height. The caller is responsible for ensuring the tx exists in our local view of the best chain’s history.

    -

    Iterate over the transactions in the wallet.

    +

    Iterate over the transactions in the wallet.

    Return the balance, separated into available, trusted-pending, untrusted-pending and immature values.

    Add an external signer

    @@ -242,35 +242,35 @@
    Example

    The index of the next address that you would get if you were to ask the wallet for a new address

    Informs the wallet that you no longer intend to broadcast a tx that was built from it.

    This frees up the change address used when creating the tx for use in future transactions.

    -

    get the corresponding PSBT Input for a LocalUtxo

    +

    get the corresponding PSBT Input for a LocalUtxo

    Return the checksum of the public descriptor associated to keychain

    Internally calls Self::get_descriptor_for_keychain to fetch the right descriptor

    -

    Applies an update to the wallet and stages the changes (but does not commit them).

    +

    Applies an update to the wallet and stages the changes (but does not commit them).

    Usually you create an update by interacting with some blockchain data source and inserting transactions related to your wallet into it.

    -

    Commits all currently staged changed to the persistence backend returning and error when +

    Commits all currently staged changed to the persistence backend returning and error when this fails.

    This returns whether the update resulted in any changes.

    -

    Returns the changes that will be committed with the next call to commit.

    -

    Get a reference to the inner TxGraph.

    -

    Get a reference to the inner KeychainTxOutIndex.

    -

    Get a reference to the inner LocalChain.

    -

    Introduces a block of height to the wallet, and tries to connect it to the +

    Returns the changes that will be committed with the next call to commit.

    +

    Get a reference to the inner [TxGraph].

    +

    Get a reference to the inner [KeychainTxOutIndex].

    +

    Get a reference to the inner [LocalChain].

    +

    Introduces a block of height to the wallet, and tries to connect it to the prev_blockhash of the block’s header.

    This is a convenience method that is equivalent to calling apply_block_connected_to with prev_blockhash and height-1 as the connected_to parameter.

    -

    Applies relevant transactions from block of height to the wallet, and connects the +

    Applies relevant transactions from block of height to the wallet, and connects the block to the internal chain.

    The connected_to parameter informs the wallet how this block connects to the internal -LocalChain. Relevant transactions are filtered from the block and inserted into the -internal TxGraph.

    -

    Apply relevant unconfirmed transactions to the wallet.

    +[LocalChain]. Relevant transactions are filtered from the block and inserted into the +internal [TxGraph].

    +

    Apply relevant unconfirmed transactions to the wallet.

    Transactions that are not relevant are filtered out.

    This method takes in an iterator of (tx, last_seen) where last_seen is the timestamp of when the transaction was last seen in the mempool. This is used for conflict resolution when there is conflicting unconfirmed transactions. The transaction with the later last_seen is prioritized.

    -

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Converts this type into a shared reference of the (usually inferred) input type.
    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    diff --git a/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html b/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html index 501af9c524..7b89336676 100644 --- a/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html +++ b/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html @@ -196,7 +196,7 @@
    Errors

    In both cases, if you don’t provide a current height, we use the last sync height.

    Set whether or not the dust limit is checked.

    Note: by avoiding a dust limit check you may end up with a transaction that is non-standard.

    -

    Finish building the transaction.

    +

    Finish building the transaction.

    Returns a new [Psbt] per BIP174.

    Replace the recipients already added with a new list

    Add a recipient to the internal list

    diff --git a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/index.html b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/index.html index 29d415c662..6ad6c202bd 100644 --- a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/index.html @@ -1,4 +1,4 @@ -bdk_bitcoind_rpc - Rust

    Crate bdk_bitcoind_rpc

    source ·
    Expand description

    This crate is used for emitting blockchain data from the bitcoind RPC interface. It does not +bdk_bitcoind_rpc - Rust

    Crate bdk_bitcoind_rpc

    source ·
    Expand description

    This crate is used for emitting blockchain data from the bitcoind RPC interface. It does not use the wallet RPC API, so this crate can be used with wallet-disabled Bitcoin Core nodes.

    Emitter is the main structure which sources blockchain data from [bitcoincore_rpc::Client].

    To only get block updates (exclude mempool transactions), the caller can use diff --git a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html index 8c40bf3c0f..96fa8fd92c 100644 --- a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html +++ b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.BlockEvent.html @@ -1,18 +1,18 @@ BlockEvent in bdk_bitcoind_rpc - Rust

    pub struct BlockEvent<B> {
         pub block: B,
    -    pub checkpoint: CheckPoint,
    +    pub checkpoint: CheckPoint,
     }
    Expand description

    A newly emitted block from Emitter.

    Fields§

    §block: B

    Either a full [Block] or [Header] of the new block.

    -
    §checkpoint: CheckPoint

    The checkpoint of the new block.

    -

    A CheckPoint is a node of a linked list of BlockIds. This checkpoint is linked to -all BlockIds originally passed in Emitter::new as well as emitted blocks since then. +

    §checkpoint: CheckPoint

    The checkpoint of the new block.

    +

    A [CheckPoint] is a node of a linked list of [BlockId]s. This checkpoint is linked to +all [BlockId]s originally passed in Emitter::new as well as emitted blocks since then. These blocks are guaranteed to be of the same chain.

    This is important as BDK structures require block-to-apply to be connected with another block in the original chain.

    Implementations§

    The block height of this new block.

    The block hash of this new block.

    -

    The BlockId of a previous block that this block connects to.

    -

    This either returns a BlockId of a previously emitted block or from the chain we started +

    The [BlockId] of a previous block that this block connects to.

    +

    This either returns a [BlockId] of a previously emitted block or from the chain we started with (passed in as last_cp in Emitter::new).

    This value is derived from BlockEvent::checkpoint.

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    diff --git a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html index aec3eeb9e3..f18b7bc898 100644 --- a/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html +++ b/docs-rs/bdk/nightly/latest/bdk_bitcoind_rpc/struct.Emitter.html @@ -1,6 +1,6 @@ Emitter in bdk_bitcoind_rpc - Rust
    pub struct Emitter<'c, C> { /* private fields */ }
    Expand description

    The Emitter is used to emit data sourced from [bitcoincore_rpc::Client].

    Refer to module-level documentation for more.

    -

    Implementations§

    Construct a new Emitter.

    +

    Implementations§

    Construct a new Emitter.

    last_cp informs the emitter of the chain we are starting off with. This way, the emitter can start emission from a block that connects to the original chain.

    start_height starts emission from a given height (if there are no conflicts with the diff --git a/docs-rs/bdk/nightly/latest/bdk_chain/index.html b/docs-rs/bdk/nightly/latest/bdk_chain/index.html index 99b6502bbd..a876ce5845 100644 --- a/docs-rs/bdk/nightly/latest/bdk_chain/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_chain/index.html @@ -1,4 +1,4 @@ -bdk_chain - Rust

    Crate bdk_chain

    source ·
    Expand description

    This crate is a collection of core structures for Bitcoin Dev Kit.

    +bdk_chain - Rust

    Crate bdk_chain

    source ·
    Expand description

    This crate is a collection of core structures for Bitcoin Dev Kit.

    The goal of this crate is to give wallets the mechanisms needed to:

    1. Figure out what data they need to fetch.
    2. diff --git a/docs-rs/bdk/nightly/latest/bdk_electrum/index.html b/docs-rs/bdk/nightly/latest/bdk_electrum/index.html index f6b3ae8838..4ea608ac04 100644 --- a/docs-rs/bdk/nightly/latest/bdk_electrum/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_electrum/index.html @@ -1,4 +1,4 @@ -bdk_electrum - Rust

      Crate bdk_electrum

      source ·
      Expand description

      This crate is used for updating structures of bdk_chain with data from an Electrum server.

      +bdk_electrum - Rust

      Crate bdk_electrum

      source ·
      Expand description

      This crate is used for updating structures of [bdk_chain] with data from an Electrum server.

      The two primary methods are ElectrumExt::sync and ElectrumExt::full_scan. In most cases ElectrumExt::sync is used to sync the transaction histories of scripts that the application cares about, for example the scripts for all the receive addresses of a Wallet’s keychain that it @@ -6,9 +6,9 @@ keychain where the range of possibly used scripts is not known. In this case it is necessary to scan all keychain scripts until a number (the “stop gap”) of unused scripts is discovered. For a sync or full scan the user receives relevant blockchain data and output updates for -bdk_chain including RelevantTxids.

      +[bdk_chain] including RelevantTxids.

      The RelevantTxids only includes txids and not full transactions. The caller is responsible -for obtaining full transactions before applying new data to their bdk_chain. This can be +for obtaining full transactions before applying new data to their [bdk_chain]. This can be done with these steps:

      1. @@ -19,4 +19,4 @@

      Refer to example_electrum for a complete example.

      -

      Re-exports

      pub use bdk_chain;
      pub use electrum_client;

      Structs

      Combination of chain and transactions updates from electrum
      Represents updates fetched from an Electrum server, but excludes full transactions.

      Traits

      Trait to extend [Client] functionality.
      \ No newline at end of file +

      Re-exports

      pub use bdk_chain;
      pub use electrum_client;

      Structs

      Combination of chain and transactions updates from electrum
      Represents updates fetched from an Electrum server, but excludes full transactions.

      Traits

      Trait to extend [Client] functionality.
      \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html b/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html index 1a7f6a4080..3847723c9d 100644 --- a/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html +++ b/docs-rs/bdk/nightly/latest/bdk_electrum/struct.ElectrumUpdate.html @@ -1,10 +1,10 @@ ElectrumUpdate in bdk_electrum - Rust
      pub struct ElectrumUpdate {
      -    pub chain_update: Update,
      +    pub chain_update: Update,
           pub relevant_txids: RelevantTxids,
       }
      Expand description

      Combination of chain and transactions updates from electrum

      We have to update the chain and the txids at the same time since we anchor the txids to the same chain tip that we check before and after we gather the txids.

      -

      Fields§

      §chain_update: Update

      Chain update

      +

    Fields§

    §chain_update: Update

    Chain update

    §relevant_txids: RelevantTxids

    Transaction updates from electrum

    Trait Implementations§

    Formats the value using the given formatter. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    diff --git a/docs-rs/bdk/nightly/latest/bdk_electrum/struct.RelevantTxids.html b/docs-rs/bdk/nightly/latest/bdk_electrum/struct.RelevantTxids.html index 5931a1e64e..01393d6843 100644 --- a/docs-rs/bdk/nightly/latest/bdk_electrum/struct.RelevantTxids.html +++ b/docs-rs/bdk/nightly/latest/bdk_electrum/struct.RelevantTxids.html @@ -1,13 +1,13 @@ RelevantTxids in bdk_electrum - Rust
    pub struct RelevantTxids(_);
    Expand description

    Represents updates fetched from an Electrum server, but excludes full transactions.

    -

    To provide a complete update to TxGraph, you’ll need to call Self::missing_full_txs to -determine the full transactions missing from TxGraph. Then call Self::into_tx_graph to +

    To provide a complete update to [TxGraph], you’ll need to call Self::missing_full_txs to +determine the full transactions missing from [TxGraph]. Then call Self::into_tx_graph to fetch the full transactions from Electrum and finalize the update.

    -

    Implementations§

    Determine the full transactions that are missing from graph.

    +

    Implementations§

    Determine the full transactions that are missing from graph.

    Refer to RelevantTxids for more details.

    -

    Finalizes the TxGraph update by fetching missing txids from the client.

    +

    Finalizes the [TxGraph] update by fetching missing txids from the client.

    Refer to RelevantTxids for more details.

    -

    Finalizes the update by fetching missing txids from the client, where the -resulting TxGraph has anchors of type ConfirmationTimeHeightAnchor.

    +

    Finalizes the update by fetching missing txids from the client, where the +resulting [TxGraph] has anchors of type [ConfirmationTimeHeightAnchor].

    Refer to RelevantTxids for more details.

    Note: The confirmation time might not be precisely correct if there has been a reorg.

    Trait Implementations§

    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Formats the value using the given formatter. Read more
    Returns the “default value” for a type. Read more

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    diff --git a/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html b/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html index 9c0b023a42..3f306830db 100644 --- a/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html +++ b/docs-rs/bdk/nightly/latest/bdk_electrum/trait.ElectrumExt.html @@ -1,9 +1,9 @@ ElectrumExt in bdk_electrum - Rust
    pub trait ElectrumExt {
    -    fn full_scan<K: Ord + Clone>(
            &self,
            prev_tip: CheckPoint,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, ScriptBuf)>>,
            stop_gap: usize,
            batch_size: usize
        ) -> Result<(ElectrumUpdate, BTreeMap<K, u32>), Error>; - fn sync(
            &self,
            prev_tip: CheckPoint,
            misc_spks: impl IntoIterator<Item = ScriptBuf>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            batch_size: usize
        ) -> Result<ElectrumUpdate, Error>; + fn full_scan<K: Ord + Clone>(
            &self,
            prev_tip: CheckPoint,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, ScriptBuf)>>,
            stop_gap: usize,
            batch_size: usize
        ) -> Result<(ElectrumUpdate, BTreeMap<K, u32>), Error>; + fn sync(
            &self,
            prev_tip: CheckPoint,
            misc_spks: impl IntoIterator<Item = ScriptBuf>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            batch_size: usize
        ) -> Result<ElectrumUpdate, Error>; }
    Expand description

    Trait to extend [Client] functionality.

    -

    Required Methods§

    Full scan the keychain scripts specified with the blockchain (via an Electrum client) and -returns updates for bdk_chain data structures.

    +

    Required Methods§

    Full scan the keychain scripts specified with the blockchain (via an Electrum client) and +returns updates for [bdk_chain] data structures.

    • prev_tip: the most recent blockchain tip present locally
    • keychain_spks: keychains that we want to scan transactions for
    • @@ -11,12 +11,12 @@

      The full scan for each keychain stops after a gap of stop_gap script pubkeys with no associated transactions. batch_size specifies the max number of script pubkeys to request for in a single batch request.

      -

    Sync a set of scripts with the blockchain (via an Electrum client) for the data specified -and returns updates for bdk_chain data structures.

    +

    Sync a set of scripts with the blockchain (via an Electrum client) for the data specified +and returns updates for [bdk_chain] data structures.

    • prev_tip: the most recent blockchain tip present locally
    • misc_spks: an iterator of scripts we want to sync transactions for
    • -
    • txids: transactions for which we want updated Anchors
    • +
    • txids: transactions for which we want updated [Anchor]s
    • outpoints: transactions associated with these outpoints (residing, spending) that we want to include in the update
    diff --git a/docs-rs/bdk/nightly/latest/bdk_esplora/index.html b/docs-rs/bdk/nightly/latest/bdk_esplora/index.html index 47b4c8d0cf..5acf45464c 100644 --- a/docs-rs/bdk/nightly/latest/bdk_esplora/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_esplora/index.html @@ -1,4 +1,4 @@ -bdk_esplora - Rust

    Crate bdk_esplora

    source ·
    Expand description

    BDK Esplora

    +bdk_esplora - Rust

    Crate bdk_esplora

    source ·
    Expand description

    BDK Esplora

    BDK Esplora extends esplora-client to update bdk_chain structures from an Esplora server.

    Usage

    @@ -27,6 +27,6 @@

    Usage

    keychain where the range of possibly used scripts is not known. In this case it is necessary to scan all keychain scripts until a number (the “stop gap”) of unused scripts is discovered. For a sync or full scan the user receives relevant blockchain data and output updates for bdk_chain -via a new TxGraph to be appended to any existing TxGraph data.

    +via a new TxGraph to be appended to any existing TxGraph data.

    Refer to example_esplora for a complete example.

    Re-exports

    pub use esplora_client;

    Traits

    Trait to extend the functionality of [esplora_client::AsyncClient].
    Trait to extend the functionality of [esplora_client::BlockingClient].
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html b/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html index ccb70a88b3..711cfef08a 100644 --- a/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html +++ b/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraAsyncExt.html @@ -1,21 +1,21 @@ EsploraAsyncExt in bdk_esplora - Rust
    pub trait EsploraAsyncExt {
    -    fn update_local_chain<'life0, 'async_trait>(
            &'life0 self,
            local_tip: CheckPoint,
            request_heights: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = u32> + Send> + Send
        ) -> Pin<Box<dyn Future<Output = Result<Update, Box<Error>>> + Send + 'async_trait>>
        where
            Self: 'async_trait,
            'life0: 'async_trait
    ; - fn full_scan<'life0, 'async_trait, K>(
            &'life0 self,
            keychain_spks: BTreeMap<K, impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = (u32, ScriptBuf)> + Send> + Send>,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Box<Error>>> + Send + 'async_trait>>
        where
            K: 'async_trait + Ord + Clone + Send,
            Self: 'async_trait,
            'life0: 'async_trait
    ; - fn sync<'life0, 'async_trait>(
            &'life0 self,
            misc_spks: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = ScriptBuf> + Send> + Send,
            txids: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = Txid> + Send> + Send,
            outpoints: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = OutPoint> + Send> + Send,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<TxGraph<ConfirmationTimeHeightAnchor>, Box<Error>>> + Send + 'async_trait>>
        where
            Self: 'async_trait,
            'life0: 'async_trait
    ; + fn update_local_chain<'life0, 'async_trait>(
            &'life0 self,
            local_tip: CheckPoint,
            request_heights: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = u32> + Send> + Send
        ) -> Pin<Box<dyn Future<Output = Result<Update, Box<Error>>> + Send + 'async_trait>>
        where
            Self: 'async_trait,
            'life0: 'async_trait
    ; + fn full_scan<'life0, 'async_trait, K>(
            &'life0 self,
            keychain_spks: BTreeMap<K, impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = (u32, ScriptBuf)> + Send> + Send>,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Box<Error>>> + Send + 'async_trait>>
        where
            K: 'async_trait + Ord + Clone + Send,
            Self: 'async_trait,
            'life0: 'async_trait
    ; + fn sync<'life0, 'async_trait>(
            &'life0 self,
            misc_spks: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = ScriptBuf> + Send> + Send,
            txids: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = Txid> + Send> + Send,
            outpoints: impl 'async_trait + IntoIterator<IntoIter = impl 'async_trait + Iterator<Item = OutPoint> + Send> + Send,
            parallel_requests: usize
        ) -> Pin<Box<dyn Future<Output = Result<TxGraph<ConfirmationTimeHeightAnchor>, Box<Error>>> + Send + 'async_trait>>
        where
            Self: 'async_trait,
            'life0: 'async_trait
    ; }
    Expand description

    Trait to extend the functionality of [esplora_client::AsyncClient].

    Refer to crate-level documentation for more.

    -

    Required Methods§

    Prepare a LocalChain update with blocks fetched from Esplora.

    +

    Required Methods§

    Prepare a LocalChain update with blocks fetched from Esplora.

      -
    • local_tip is the previous tip of LocalChain::tip.
    • +
    • local_tip is the previous tip of LocalChain::tip.
    • request_heights is the block heights that we are interested in fetching from Esplora.
    -

    The result of this method can be applied to LocalChain::apply_update.

    +

    The result of this method can be applied to LocalChain::apply_update.

    Consistency

    The chain update returned is guaranteed to be consistent as long as there is not a large re-org during the call. The size of re-org we can tollerate is server dependent but will be at least 10.

    -

    Full scan the keychain scripts specified with the blockchain (via an Esplora client) and -returns a TxGraph and a map of last active indices.

    +

    Full scan the keychain scripts specified with the blockchain (via an Esplora client) and +returns a [TxGraph] and a map of last active indices.

    • keychain_spks: keychains that we want to scan transactions for
    @@ -31,14 +31,14 @@
    Note
    BTCPay Server, and Sparrow.

    A stop_gap of 0 will be treated as a stop_gap of 1.

    -

    Sync a set of scripts with the blockchain (via an Esplora client) for the data -specified and return a TxGraph.

    +

    Sync a set of scripts with the blockchain (via an Esplora client) for the data +specified and return a [TxGraph].

    • misc_spks: scripts that we want to sync transactions for
    • -
    • txids: transactions for which we want updated ConfirmationTimeHeightAnchors
    • +
    • txids: transactions for which we want updated [ConfirmationTimeHeightAnchor]s
    • outpoints: transactions associated with these outpoints (residing, spending) that we want to include in the update

    If the scripts to sync are unknown, such as when restoring or importing a keychain that may include scripts that have been used, use full_scan with the keychain.

    -

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html b/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html index 06b1a74bb6..b0aaf8513e 100644 --- a/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html +++ b/docs-rs/bdk/nightly/latest/bdk_esplora/trait.EsploraExt.html @@ -1,21 +1,21 @@ EsploraExt in bdk_esplora - Rust
    pub trait EsploraExt {
    -    fn update_local_chain(
            &self,
            local_tip: CheckPoint,
            request_heights: impl IntoIterator<Item = u32>
        ) -> Result<Update, Box<Error>>; - fn full_scan<K: Ord + Clone>(
            &self,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, ScriptBuf)>>,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Box<Error>>; - fn sync(
            &self,
            misc_spks: impl IntoIterator<Item = ScriptBuf>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            parallel_requests: usize
        ) -> Result<TxGraph<ConfirmationTimeHeightAnchor>, Box<Error>>; + fn update_local_chain(
            &self,
            local_tip: CheckPoint,
            request_heights: impl IntoIterator<Item = u32>
        ) -> Result<Update, Box<Error>>; + fn full_scan<K: Ord + Clone>(
            &self,
            keychain_spks: BTreeMap<K, impl IntoIterator<Item = (u32, ScriptBuf)>>,
            stop_gap: usize,
            parallel_requests: usize
        ) -> Result<(TxGraph<ConfirmationTimeHeightAnchor>, BTreeMap<K, u32>), Box<Error>>; + fn sync(
            &self,
            misc_spks: impl IntoIterator<Item = ScriptBuf>,
            txids: impl IntoIterator<Item = Txid>,
            outpoints: impl IntoIterator<Item = OutPoint>,
            parallel_requests: usize
        ) -> Result<TxGraph<ConfirmationTimeHeightAnchor>, Box<Error>>; }
    Expand description

    Trait to extend the functionality of [esplora_client::BlockingClient].

    Refer to crate-level documentation for more.

    -

    Required Methods§

    Prepare a LocalChain update with blocks fetched from Esplora.

    +

    Required Methods§

    Prepare a LocalChain update with blocks fetched from Esplora.

      -
    • local_tip is the previous tip of LocalChain::tip.
    • +
    • local_tip is the previous tip of LocalChain::tip.
    • request_heights is the block heights that we are interested in fetching from Esplora.
    -

    The result of this method can be applied to LocalChain::apply_update.

    +

    The result of this method can be applied to LocalChain::apply_update.

    Consistency

    The chain update returned is guaranteed to be consistent as long as there is not a large re-org during the call. The size of re-org we can tollerate is server dependent but will be at least 10.

    -

    Full scan the keychain scripts specified with the blockchain (via an Esplora client) and -returns a TxGraph and a map of last active indices.

    +

    Full scan the keychain scripts specified with the blockchain (via an Esplora client) and +returns a [TxGraph] and a map of last active indices.

    • keychain_spks: keychains that we want to scan transactions for
    @@ -31,14 +31,14 @@
    Note
    BTCPay Server, and Sparrow.

    A stop_gap of 0 will be treated as a stop_gap of 1.

    -

    Sync a set of scripts with the blockchain (via an Esplora client) for the data -specified and return a TxGraph.

    +

    Sync a set of scripts with the blockchain (via an Esplora client) for the data +specified and return a [TxGraph].

    • misc_spks: scripts that we want to sync transactions for
    • -
    • txids: transactions for which we want updated ConfirmationTimeHeightAnchors
    • +
    • txids: transactions for which we want updated [ConfirmationTimeHeightAnchor]s
    • outpoints: transactions associated with these outpoints (residing, spending) that we want to include in the update

    If the scripts to sync are unknown, such as when restoring or importing a keychain that may include scripts that have been used, use full_scan with the keychain.

    -

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file +

    Implementations on Foreign Types§

    Implementors§

    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_file_store/index.html b/docs-rs/bdk/nightly/latest/bdk_file_store/index.html index bcbc3630de..7f75e685df 100644 --- a/docs-rs/bdk/nightly/latest/bdk_file_store/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_file_store/index.html @@ -1,6 +1,6 @@ -bdk_file_store - Rust

    Crate bdk_file_store

    source ·
    Expand description

    BDK File Store

    +bdk_file_store - Rust

    Crate bdk_file_store

    source ·
    Expand description

    BDK File Store

    This is a simple append-only flat file implementation of -Persist.

    +Persist.

    The main structure is Store, which can be used with bdk’s Wallet to persist wallet data into a flat file.

    Structs

    Iterator over entries in a file store.
    Persists an append-only list of changesets (C) to a single file.

    Enums

    Error that occurs due to problems encountered with the file.
    Error type for EntryIter.
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html b/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html index 2e664f3be5..5199b27a9e 100644 --- a/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html +++ b/docs-rs/bdk/nightly/latest/bdk_file_store/struct.Store.html @@ -1,6 +1,6 @@ Store in bdk_file_store - Rust

    Struct bdk_file_store::Store

    source ·
    pub struct Store<C> { /* private fields */ }
    Expand description

    Persists an append-only list of changesets (C) to a single file.

    The changesets are the results of altering a tracker implementation (T).

    -

    Implementations§

    Create a new Store file in write-only mode; error if the file exists.

    +

    Implementations§

    Create a new Store file in write-only mode; error if the file exists.

    magic is the prefixed bytes to write to the new file. This will be checked when opening the Store in the future with open.

    Open an existing Store.

    @@ -30,7 +30,7 @@
    Errors
    changeset.

    The truncation is to avoid the possibility of having a valid but inconsistent changeset directly after the appended changeset.

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    The error the backend returns when it fails to write.
    The error the backend returns when it fails to load changesets C.
    Writes a changeset to the persistence backend. Read more
    Return the aggregate changeset C from persistence.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    The error the backend returns when it fails to write.
    The error the backend returns when it fails to load changesets C.
    Writes a changeset to the persistence backend. Read more
    Return the aggregate changeset C from persistence.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    diff --git a/docs-rs/bdk/nightly/latest/bdk_hwi/index.html b/docs-rs/bdk/nightly/latest/bdk_hwi/index.html index e8b9bcec10..86da9b7579 100644 --- a/docs-rs/bdk/nightly/latest/bdk_hwi/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_hwi/index.html @@ -1,5 +1,5 @@ bdk_hwi - Rust

    Crate bdk_hwi

    source ·
    Expand description

    HWI Signer

    -

    This crate contains HWISigner, an implementation of a TransactionSigner to be +

    This crate contains HWISigner, an implementation of a TransactionSigner to be used with hardware wallets.

    let mut devices = HWIClient::enumerate()?;
    diff --git a/docs-rs/bdk/nightly/latest/bdk_hwi/struct.HWISigner.html b/docs-rs/bdk/nightly/latest/bdk_hwi/struct.HWISigner.html
    index b18d2baff8..fb33bf59db 100644
    --- a/docs-rs/bdk/nightly/latest/bdk_hwi/struct.HWISigner.html
    +++ b/docs-rs/bdk/nightly/latest/bdk_hwi/struct.HWISigner.html
    @@ -1,7 +1,7 @@
     HWISigner in bdk_hwi - Rust

    Struct bdk_hwi::HWISigner

    source ·
    pub struct HWISigner { /* private fields */ }
    Expand description

    Custom signer for Hardware Wallets

    This ignores sign_options and leaves the decisions up to the hardware wallet.

    Implementations§

    Create a instance from the specified device and chain

    -

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Return the [SignerId] for this signer Read more
    Return the secret key for the signer Read more
    Sign all the inputs of the psbt

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +

    Trait Implementations§

    Formats the value using the given formatter. Read more
    Return the SignerId for this signer Read more
    Return the secret key for the signer Read more
    Sign all the inputs of the psbt

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    diff --git a/docs-rs/bdk/nightly/latest/bdk_testenv/index.html b/docs-rs/bdk/nightly/latest/bdk_testenv/index.html index 6f34844169..7641a6d56b 100644 --- a/docs-rs/bdk/nightly/latest/bdk_testenv/index.html +++ b/docs-rs/bdk/nightly/latest/bdk_testenv/index.html @@ -1,2 +1,2 @@ -bdk_testenv - Rust

    Crate bdk_testenv

    source ·

    Structs

    Struct for running a regtest environment with a single bitcoind node with an electrs +bdk_testenv - Rust

    Crate bdk_testenv

    source ·

    Structs

    Struct for running a regtest environment with a single bitcoind node with an electrs instance connected to it.
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/bdk_testenv/struct.TestEnv.html b/docs-rs/bdk/nightly/latest/bdk_testenv/struct.TestEnv.html index c68b46852a..769d97aaea 100644 --- a/docs-rs/bdk/nightly/latest/bdk_testenv/struct.TestEnv.html +++ b/docs-rs/bdk/nightly/latest/bdk_testenv/struct.TestEnv.html @@ -1,4 +1,4 @@ -TestEnv in bdk_testenv - Rust

    Struct bdk_testenv::TestEnv

    source ·
    pub struct TestEnv {
    +TestEnv in bdk_testenv - Rust

    Struct bdk_testenv::TestEnv

    source ·
    pub struct TestEnv {
         pub bitcoind: BitcoinD,
         pub electrsd: ElectrsD,
     }
    Expand description

    Struct for running a regtest environment with a single bitcoind node with an electrs @@ -19,4 +19,10 @@

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file +
    Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html b/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html index cacf4366b1..74f57a74be 100644 --- a/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html +++ b/docs-rs/bdk/nightly/latest/example_bitcoind_rpc_polling/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_bitcoind_rpc_polling - Rust
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file +ChangeSet in example_bitcoind_rpc_polling - Rust
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html b/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html index 190dd36f49..8d4ed7b0da 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html +++ b/docs-rs/bdk/nightly/latest/example_cli/fn.create_tx.html @@ -1 +1 @@ -create_tx in example_cli - Rust

    Function example_cli::create_tx

    source ·
    pub fn create_tx<A: Anchor, O: ChainOracle>(
        graph: &mut KeychainTxGraph<A>,
        chain: &O,
        keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
        cs_algorithm: CoinSelectionAlgo,
        address: Address,
        value: u64
    ) -> Result<(Transaction, Option<CreateTxChange>)>where
        O::Error: Error + Send + Sync + 'static,
    \ No newline at end of file +create_tx in example_cli - Rust

    Function example_cli::create_tx

    source ·
    pub fn create_tx<A: Anchor, O: ChainOracle>(
        graph: &mut KeychainTxGraph<A>,
        chain: &O,
        keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
        cs_algorithm: CoinSelectionAlgo,
        address: Address,
        value: u64
    ) -> Result<(Transaction, Option<CreateTxChange>)>where
        O::Error: Error + Send + Sync + 'static,
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html b/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html index daae353ae6..74aab9d2f0 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html +++ b/docs-rs/bdk/nightly/latest/example_cli/fn.handle_commands.html @@ -1 +1 @@ -handle_commands in example_cli - Rust
    pub fn handle_commands<CS: Subcommand, S: Args, A: Anchor, O: ChainOracle, C>(
        graph: &Mutex<KeychainTxGraph<A>>,
        db: &Mutex<Database<C>>,
        chain: &Mutex<O>,
        keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
        network: Network,
        broadcast: impl FnOnce(S, &Transaction) -> Result<()>,
        cmd: Commands<CS, S>
    ) -> Result<()>where
        O::Error: Error + Send + Sync + 'static,
        C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
    \ No newline at end of file +handle_commands in example_cli - Rust
    pub fn handle_commands<CS: Subcommand, S: Args, A: Anchor, O: ChainOracle, C>(
        graph: &Mutex<KeychainTxGraph<A>>,
        db: &Mutex<Database<C>>,
        chain: &Mutex<O>,
        keymap: &BTreeMap<DescriptorPublicKey, DescriptorSecretKey>,
        network: Network,
        broadcast: impl FnOnce(S, &Transaction) -> Result<()>,
        cmd: Commands<CS, S>
    ) -> Result<()>where
        O::Error: Error + Send + Sync + 'static,
        C: Default + Append + DeserializeOwned + Serialize + From<KeychainChangeSet<A>>,
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/fn.init.html b/docs-rs/bdk/nightly/latest/example_cli/fn.init.html index 3c326e8d73..40e7ae0f23 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/fn.init.html +++ b/docs-rs/bdk/nightly/latest/example_cli/fn.init.html @@ -1,3 +1,3 @@ -init in example_cli - Rust

    Function example_cli::init

    source ·
    pub fn init<CS: Subcommand, S: Args, C>(
        db_magic: &[u8],
        db_default_path: &str
    ) -> Result<Init<CS, S, C>>where
        C: Default + Append + Serialize + DeserializeOwned,
    Expand description

    Parses command line arguments and initializes all components, creating +init in example_cli - Rust

    Function example_cli::init

    source ·
    pub fn init<CS: Subcommand, S: Args, C>(
        db_magic: &[u8],
        db_default_path: &str
    ) -> Result<Init<CS, S, C>>where
        C: Default + Append + Serialize + DeserializeOwned,
    Expand description

    Parses command line arguments and initializes all components, creating a file store with the given parameters, or loading one if it exists.

    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html b/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html index bbeb908988..b71217a31c 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html +++ b/docs-rs/bdk/nightly/latest/example_cli/fn.planned_utxos.html @@ -1 +1 @@ -planned_utxos in example_cli - Rust

    Function example_cli::planned_utxos

    source ·
    pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + CanDerive>(
        graph: &KeychainTxGraph<A>,
        chain: &O,
        assets: &Assets<K>
    ) -> Result<Vec<PlannedUtxo<K, A>>, O::Error>
    \ No newline at end of file +planned_utxos in example_cli - Rust

    Function example_cli::planned_utxos

    source ·
    pub fn planned_utxos<A: Anchor, O: ChainOracle, K: Clone + CanDerive>(
        graph: &KeychainTxGraph<A>,
        chain: &O,
        assets: &Assets<K>
    ) -> Result<Vec<PlannedUtxo<K, A>>, O::Error>
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html b/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html index 69309dc374..4577b173ca 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html +++ b/docs-rs/bdk/nightly/latest/example_cli/struct.CreateTxChange.html @@ -1,8 +1,8 @@ CreateTxChange in example_cli - Rust
    pub struct CreateTxChange {
    -    pub index_changeset: ChangeSet<Keychain>,
    +    pub index_changeset: ChangeSet<Keychain>,
         pub change_keychain: Keychain,
         pub index: u32,
    -}

    Fields§

    §index_changeset: ChangeSet<Keychain>§change_keychain: Keychain§index: u32

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    +}

    Fields§

    §index_changeset: ChangeSet<Keychain>§change_keychain: Keychain§index: u32

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    diff --git a/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html b/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html index 07a6ef259c..ea55e4d1a8 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html +++ b/docs-rs/bdk/nightly/latest/example_cli/struct.Init.html @@ -1,13 +1,13 @@ Init in example_cli - Rust

    Struct example_cli::Init

    source ·
    pub struct Init<CS: Subcommand, S: Args, C> {
         pub args: Args<CS, S>,
         pub keymap: KeyMap,
    -    pub index: KeychainTxOutIndex<Keychain>,
    +    pub index: KeychainTxOutIndex<Keychain>,
         pub db: Mutex<Database<C>>,
         pub init_changeset: C,
     }
    Expand description

    The initial state returned by init.

    Fields§

    §args: Args<CS, S>

    Arguments parsed by the cli.

    §keymap: KeyMap

    Descriptor keymap.

    -
    §index: KeychainTxOutIndex<Keychain>

    Keychain-txout index.

    +
    §index: KeychainTxOutIndex<Keychain>

    Keychain-txout index.

    §db: Mutex<Database<C>>

    Persistence backend.

    §init_changeset: C

    Initial changeset.

    Auto Trait Implementations§

    Blanket Implementations§

    Gets the TypeId of self. Read more
    Immutably borrows from an owned value. Read more
    Mutably borrows from an owned value. Read more

    Returns the argument unchanged.

    diff --git a/docs-rs/bdk/nightly/latest/example_cli/type.Database.html b/docs-rs/bdk/nightly/latest/example_cli/type.Database.html index 70a890db01..961482e7b7 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/type.Database.html +++ b/docs-rs/bdk/nightly/latest/example_cli/type.Database.html @@ -1 +1 @@ -Database in example_cli - Rust

    Type Definition example_cli::Database

    source ·
    pub type Database<C> = Persist<Store<C>, C>;
    \ No newline at end of file +Database in example_cli - Rust

    Type Definition example_cli::Database

    source ·
    pub type Database<C> = Persist<Store<C>, C>;
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html b/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html index 2eb3cb6f36..a1dcf2b38a 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html +++ b/docs-rs/bdk/nightly/latest/example_cli/type.KeychainChangeSet.html @@ -1 +1 @@ -KeychainChangeSet in example_cli - Rust

    Type Definition example_cli::KeychainChangeSet

    source ·
    pub type KeychainChangeSet<A> = (ChangeSet, ChangeSet<A, ChangeSet<Keychain>>);
    \ No newline at end of file +KeychainChangeSet in example_cli - Rust

    Type Definition example_cli::KeychainChangeSet

    source ·
    pub type KeychainChangeSet<A> = (ChangeSet, ChangeSet<A, ChangeSet<Keychain>>);
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html b/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html index e9f67fd509..b2c7b94730 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html +++ b/docs-rs/bdk/nightly/latest/example_cli/type.KeychainTxGraph.html @@ -1 +1 @@ -KeychainTxGraph in example_cli - Rust

    Type Definition example_cli::KeychainTxGraph

    source ·
    pub type KeychainTxGraph<A> = IndexedTxGraph<A, KeychainTxOutIndex<Keychain>>;
    \ No newline at end of file +KeychainTxGraph in example_cli - Rust

    Type Definition example_cli::KeychainTxGraph

    source ·
    pub type KeychainTxGraph<A> = IndexedTxGraph<A, KeychainTxOutIndex<Keychain>>;
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html b/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html index 11ed4c16d7..50f27d3016 100644 --- a/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html +++ b/docs-rs/bdk/nightly/latest/example_cli/type.PlannedUtxo.html @@ -1 +1 @@ -PlannedUtxo in example_cli - Rust

    Type Definition example_cli::PlannedUtxo

    source ·
    pub type PlannedUtxo<K, A> = (Plan<K>, FullTxOut<A>);
    \ No newline at end of file +PlannedUtxo in example_cli - Rust

    Type Definition example_cli::PlannedUtxo

    source ·
    pub type PlannedUtxo<K, A> = (Plan<K>, FullTxOut<A>);
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html b/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html index b17942f23e..e4f850fe8f 100644 --- a/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html +++ b/docs-rs/bdk/nightly/latest/example_electrum/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_electrum - Rust

    Type Definition example_electrum::ChangeSet

    source ·
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file +ChangeSet in example_electrum - Rust

    Type Definition example_electrum::ChangeSet

    source ·
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_esplora/enum.EsploraCommands.html b/docs-rs/bdk/nightly/latest/example_esplora/enum.EsploraCommands.html index 4a2b134c1e..c135ae91de 100644 --- a/docs-rs/bdk/nightly/latest/example_esplora/enum.EsploraCommands.html +++ b/docs-rs/bdk/nightly/latest/example_esplora/enum.EsploraCommands.html @@ -1,4 +1,4 @@ -EsploraCommands in example_esplora - Rust

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a +
    Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_esplora/struct.EsploraArgs.html b/docs-rs/bdk/nightly/latest/example_esplora/struct.EsploraArgs.html index 6b6df3e09d..417bc087e4 100644 --- a/docs-rs/bdk/nightly/latest/example_esplora/struct.EsploraArgs.html +++ b/docs-rs/bdk/nightly/latest/example_esplora/struct.EsploraArgs.html @@ -1,4 +1,4 @@ -EsploraArgs in example_esplora - Rust
    pub struct EsploraArgs {
    +EsploraArgs in example_esplora - Rust
    pub struct EsploraArgs {
         pub(crate) esplora_url: Option<String>,
     }

    Fields§

    §esplora_url: Option<String>

    The esplora url endpoint to connect to e.g. <https://blockstream.info/api> If not provided it’ll be set to a default for the network provided

    @@ -8,6 +8,12 @@ Instrumented wrapper. Read more

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a +
    Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_esplora/struct.ScanOptions.html b/docs-rs/bdk/nightly/latest/example_esplora/struct.ScanOptions.html index 2cb29fb709..3bc2f68a3b 100644 --- a/docs-rs/bdk/nightly/latest/example_esplora/struct.ScanOptions.html +++ b/docs-rs/bdk/nightly/latest/example_esplora/struct.ScanOptions.html @@ -1,4 +1,4 @@ -ScanOptions in example_esplora - Rust
    pub struct ScanOptions {
    +ScanOptions in example_esplora - Rust
    pub struct ScanOptions {
         pub parallel_requests: usize,
     }

    Fields§

    §parallel_requests: usize

    Max number of concurrent esplora server requests.

    Trait Implementations§

    Append to [Command] so it can instantiate Self. Read more
    Append to [Command] so it can update self. Read more
    Returns a copy of the value. Read more
    Performs copy-assignment from source. Read more
    Deprecated, replaced with CommandFactory::command
    Deprecated, replaced with CommandFactory::command_for_update
    Build a [Command] that can instantiate Self. Read more
    Build a [Command] that can update self. Read more
    Formats the value using the given formatter. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Instantiate Self from [ArgMatches], parsing the arguments as needed. Read more
    Assign values from ArgMatches to self.
    Assign values from ArgMatches to self.
    Parse from std::env::args_os(), exit on error
    Parse from std::env::args_os(), return Err on error.
    Parse from iterator, exit on error
    Parse from iterator, return Err on error.
    Update from iterator, exit on error
    Update from iterator, return Err on error.
    This method tests for self and other values to be equal, and is used @@ -9,6 +9,12 @@ Instrumented wrapper. Read more

    Calls U::from(self).

    That is, this conversion is whatever the implementation of From<T> for U chooses to do.

    -
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a +
    Converts self into a Left variant of Either<Self, Self> +if into_left is true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    Converts self into a Left variant of Either<Self, Self> +if into_left(&self) returns true. +Converts self into a Right variant of Either<Self, Self> +otherwise. Read more
    The resulting type after obtaining ownership.
    Creates owned data from borrowed data, usually by cloning. Read more
    Uses borrowed data to replace owned data, usually by cloning. Read more
    The type returned in the event of a conversion error.
    Performs the conversion.
    The type returned in the event of a conversion error.
    Performs the conversion.
    Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html b/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html index a98214f7c6..17a9a772b4 100644 --- a/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html +++ b/docs-rs/bdk/nightly/latest/example_esplora/type.ChangeSet.html @@ -1 +1 @@ -ChangeSet in example_esplora - Rust

    Type Definition example_esplora::ChangeSet

    source ·
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file +ChangeSet in example_esplora - Rust

    Type Definition example_esplora::ChangeSet

    source ·
    pub(crate) type ChangeSet = (ChangeSet, ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<Keychain>>);
    \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js b/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js index fb042c4512..b008aa7a79 100644 --- a/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js +++ b/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.SignerCommon.js @@ -1,4 +1,4 @@ (function() {var implementors = { "bdk":[], -"bdk_hwi":[["impl SignerCommon for HWISigner"]] +"bdk_hwi":[["impl SignerCommon for HWISigner"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js b/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js index 68919d45f8..ea6c96cd81 100644 --- a/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js +++ b/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.TransactionSigner.js @@ -1,4 +1,4 @@ (function() {var implementors = { "bdk":[], -"bdk_hwi":[["impl TransactionSigner for HWISigner"]] +"bdk_hwi":[["impl TransactionSigner for HWISigner"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/bdk_chain/persist/trait.PersistBackend.js b/docs-rs/bdk/nightly/latest/implementors/bdk_chain/persist/trait.PersistBackend.js index 425e53ff1b..ddbe6660df 100644 --- a/docs-rs/bdk/nightly/latest/implementors/bdk_chain/persist/trait.PersistBackend.js +++ b/docs-rs/bdk/nightly/latest/implementors/bdk_chain/persist/trait.PersistBackend.js @@ -1,4 +1,4 @@ (function() {var implementors = { "bdk_chain":[], -"bdk_file_store":[["impl<C> PersistBackend<C> for Store<C>where
        C: Append + Serialize + DeserializeOwned,
    "]] +"bdk_file_store":[["impl<C> PersistBackend<C> for Store<C>where
        C: Append + Serialize + DeserializeOwned,
    "]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js b/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js index 7b3d82a242..2b650fa85a 100644 --- a/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js +++ b/docs-rs/bdk/nightly/latest/implementors/bdk_chain/tx_data_traits/trait.Append.js @@ -1,4 +1,4 @@ (function() {var implementors = { -"bdk":[["impl Append for ChangeSet"]], +"bdk":[["impl Append for ChangeSet"]], "bdk_chain":[] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js b/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js index 10305d41fc..8528302c07 100644 --- a/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js +++ b/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js @@ -1,4 +1,4 @@ (function() {var implementors = { -"bdk":[["impl AsRef<[u8]> for KeychainKind"],["impl<D> AsRef<TxGraph<ConfirmationTimeHeightAnchor>> for Wallet<D>"]], +"bdk":[["impl AsRef<[u8]> for KeychainKind"],["impl<D> AsRef<TxGraph<ConfirmationTimeHeightAnchor>> for Wallet<D>"]], "bdk_chain":[["impl<K> AsRef<BTreeMap<K, u32, Global>> for ChangeSet<K>"],["impl<A> AsRef<TxGraph<A>> for TxGraph<A>"]] };if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js b/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js index 9eaab63f21..8a4594a431 100644 --- a/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js +++ b/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js @@ -1,5 +1,5 @@ (function() {var implementors = { -"bdk":[["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<HexToBytesError> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<Xpub> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<Xpriv> for ExtendedKey<Ctx>"],["impl From<Error> for KeyError"],["impl From<Error> for KeyError"],["impl From<Hash> for SignerId"],["impl From<Fingerprint> for SignerId"],["impl From<Error> for SignerError"],["impl<P> From<Error> for CreateTxError<P>"],["impl<P> From<PolicyError> for CreateTxError<P>"],["impl<P> From<MiniscriptPsbtError> for CreateTxError<P>"],["impl<P> From<Error> for CreateTxError<P>"],["impl<P> From<Error> for CreateTxError<P>"],["impl From<BTreeMap<u32, Option<BlockHash>, Global>> for ChangeSet"],["impl From<ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>> for ChangeSet"]], +"bdk":[["impl From<KeyError> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<Error> for Error"],["impl From<HexToBytesError> for Error"],["impl From<PolicyError> for Error"],["impl From<bool> for Satisfaction"],["impl From<SatisfiableItem> for Policy"],["impl<Ctx: ScriptContext> From<Xpub> for ExtendedKey<Ctx>"],["impl<Ctx: ScriptContext> From<Xpriv> for ExtendedKey<Ctx>"],["impl From<Error> for KeyError"],["impl From<Error> for KeyError"],["impl From<Hash> for SignerId"],["impl From<Fingerprint> for SignerId"],["impl From<Error> for SignerError"],["impl<P> From<Error> for CreateTxError<P>"],["impl<P> From<PolicyError> for CreateTxError<P>"],["impl<P> From<MiniscriptPsbtError> for CreateTxError<P>"],["impl<P> From<Error> for CreateTxError<P>"],["impl<P> From<Error> for CreateTxError<P>"],["impl From<BTreeMap<u32, Option<BlockHash>, Global>> for ChangeSet"],["impl From<ChangeSet<ConfirmationTimeHeightAnchor, ChangeSet<KeychainKind>>> for ChangeSet"]], "bdk_chain":[["impl From<ChainPosition<ConfirmationTimeHeightAnchor>> for ConfirmationTime"],["impl From<(u32, BlockHash)> for BlockId"],["impl From<BlockId> for (u32, BlockHash)"],["impl From<(&u32, &BlockHash)> for BlockId"],["impl<A, IA: Default> From<ChangeSet<A>> for ChangeSet<A, IA>"],["impl<A, K> From<ChangeSet<K>> for ChangeSet<A, ChangeSet<K>>"]], "bdk_coin_select":[["impl From<usize> for BnbLimit"],["impl From<Duration> for BnbLimit"]], "bdk_file_store":[["impl From<Error> for IterError"],["impl From<Error> for FileError"]], diff --git a/docs-rs/bdk/nightly/latest/search-index.js b/docs-rs/bdk/nightly/latest/search-index.js index 7717a85a1a..3d71c3332d 100644 --- a/docs-rs/bdk/nightly/latest/search-index.js +++ b/docs-rs/bdk/nightly/latest/search-index.js @@ -1,5 +1,5 @@ var searchIndex = JSON.parse('{\ -"bdk":{"doc":"bdk","t":[13,13,2,13,4,13,3,2,2,4,2,3,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,12,12,0,14,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,12,12,0,11,12,11,0,12,11,11,11,2,2,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,12,5,11,11,11,11,0,12,12,12,13,6,4,2,4,6,8,6,8,16,4,3,13,13,2,8,4,13,13,6,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,10,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,5,5,13,13,4,13,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,4,13,3,6,13,13,6,13,13,13,13,13,13,13,13,13,13,13,4,3,4,13,13,13,13,13,4,4,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,3,3,8,6,3,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,13,13,13,16,13,3,13,8,4,13,13,13,3,3,4,3,13,6,13,13,13,5,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,11,12,12,11,11,11,11,11,11,10,12,11,11,11,11,11,10,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,8,10,10,10,4,3,4,3,13,3,13,13,13,13,4,8,13,13,13,4,13,13,13,13,13,4,4,13,13,13,13,13,3,3,13,13,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,12,11,12,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,12,12,12,13,13,3,13,8,3,6,4,4,13,3,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,5,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,4,13,13,13,4,13,13,13,13,13,13,13,13,4,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,3,6,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,13,13,13,13,13,13,13,8,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,4,3,3,3,13,4,8,13,11,12,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,10,11,11,11,10,11,12,11,12,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,4,4,4,13,3,13,13,4,3,13,13,13,13,13,13,3,8,4,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12],"n":["External","Foreign","HdKeyPaths","Internal","KeychainKind","Local","LocalOutput","SignOptions","TxBuilder","Utxo","Wallet","WeightedUtxo","as_byte","as_ref","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","confirmation_time","derivation_index","descriptor","descriptor","deserialize","deserialize","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fragment","from","from","from","from","hash","hash","into","into","into","into","is_spent","keychain","keys","outpoint","outpoint","partial_cmp","psbt","satisfaction_weight","sequence","serialize","serialize","signer","template","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","txout","txout","type_id","type_id","type_id","type_id","utxo","version","vzip","vzip","vzip","vzip","wallet","outpoint","psbt_input","sequence","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","Key","Legacy","Miniscript","MultiXPub","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","as_node","at_derivation_index","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","build_template","build_template_mall","calc_checksum","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_pk","check_pk","check_pk","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","contains_raw_pkh","derive","derived_descriptor","derived_descriptor","desc_type","deserialize","deserialize","dust_value","encode","eq","eq","eq","eq","error","explicit_script","ext","ext_check","extract_policy","extract_policy","extract_policy","find_derivation_index_for_spk","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from_ast","from_components_unchecked","from_str","from_str","from_str_ext","from_str_insane","from_tree","from_tree","get_nth_child","get_nth_pk","get_satisfaction","get_satisfaction_mall","has_mixed_timelocks","has_repeated_keys","has_wildcard","hash","hash","hash","hash","into","into","into","into","into_inner","into_single_descriptors","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_multipath","is_non_malleable","iter","iter_pk","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","max_weight_to_satisfy","name_str","name_str","name_str","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_with_wpkh","new_sh_with_wsh","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_tr","new_wpkh","new_wsh","new_wsh_sortedmulti","node","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","plan","plan_mall","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","sig_type","sig_type","sig_type","substitute_raw_pkh","template","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","within_resource_limits","calc_checksum","calc_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","MultiPath","Pk","Policy","borrow","borrow_mut","fmt","fmt","from","from","from","from","from","from","from","from","into","provide","to_string","try_from","try_into","type_id","vzip","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","EcdsaSignature","Fingerprint","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","Pubkey","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","SchnorrSignature","Sha256Preimage","Thresh","XOnlyPubkey","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","contribution","csv","default","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","hash","hash","id","id","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","partial_cmp","provide","requires_path","satisfaction","serialize","serialize","serialize","serialize","serialize","timelock","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","current_height","input_max_height","psbt","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","Bip86","Bip86Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2TR","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","build","build","build","from","from","from","from","from","from","from","from","from","from","from","from","into","into","into","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","MultiXPrv","MultiXPub","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","Single","Single","SinglePriv","SinglePub","SinglePubKey","SortedMultiVec","Tap","ValidNetworks","XOnly","XPrv","XPub","any_network","as_enum","at_derivation_index","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_template","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_pk","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","derive","deserialize","encode","eq","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_public","from_secret","from_str","from_str","from_tree","full_derivation_path","full_derivation_paths","generate","generate_default","generate_with_entropy","generate_with_entropy_default","has_secret","has_wildcard","hash","hash","hash","hash","into","into","into","into","into","into","into","into","into","into","into","into","into_assets","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_single_keys","into_single_keys","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_multipath","is_multipath","is_segwit_v0","is_segwit_v0","is_taproot","is_taproot","is_uncompressed","is_x_only_key","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","name_str","new","num_der_paths","origin","origin","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pks","provide","sanity_check","satisfy","script_size","serialize","sig_type","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_public","to_string","to_string","to_string","to_string","top_level_checks","top_level_type_check","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","PsbtUtils","fee_amount","fee_rate","get_utxo_for","AddressIndex","AddressInfo","ApplyBlockError","Balance","CannotConnect","ChangeSet","ConfirmationHeightCannotBeGreaterThanTip","Descriptor","Descriptor","Descriptor","InsertTxError","IsDust","LastUnused","Load","Load","LoadError","LoadedGenesisDoesNotMatch","LoadedNetworkDoesNotMatch","MissingGenesis","MissingNetwork","New","NewError","NewOrLoadError","NonEmptyDatabase","NotInitialized","NotInitialized","Peek","UnexpectedConnectedToHash","Update","Wallet","Write","Write","add","add_signer","address","all_unbounded_spk_iters","append","apply_block","apply_block_connected_to","apply_unconfirmed_txs","apply_update","as_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_fee_bump","build_tx","calculate_fee","calculate_fee_rate","cancel_tx","chain","chain","checkpoints","clone","clone","clone","clone_into","clone_into","clone_into","coin_selection","commit","confirmed","default","default","default","deref","derivation_index","derivation_of_spk","descriptor_checksum","deserialize","deserialize","eq","eq","eq","error","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_internal_address","get_psbt_input","get_signers","get_tx","get_utxo","graph","immature","index","indexed_tx_graph","insert_checkpoint","insert_tx","insert_txout","into","into","into","into","into","into","into","into","into","into","into","is_dust","is_empty","is_mine","keychain","keychains","last_active_indices","latest_checkpoint","list_output","list_unspent","load","local_chain","network","network","new","new_no_persist","new_no_persist_with_genesis_hash","new_or_load","new_or_load_with_genesis_hash","new_with_genesis_hash","next_derivation_index","policies","provide","provide","provide","provide","provide","public_descriptor","secp_ctx","sent_and_received","serialize","serialize","sign","signer","spk_index","staged","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","total","transactions","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_get_address","try_get_internal_address","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","tx_builder","tx_graph","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unbounded_spk_iter","untrusted_pending","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","connected_to_hash","expected_hash","tip_height","tx_height","expected","expected","got","got","BnBNoExactMatch","BnBTotalTriesExceeded","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Error","Excess","InsufficientFunds","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","coin_select","coin_select","coin_select","coin_select","decide_change","default","default","default","excess","fee_amount","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","into","into","into","into","into","into","local_selected_amount","new","provide","selected","selected_amount","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","available","needed","amount","change_fee","dust_threshold","fee","remaining_amount","BuildFeeBumpError","ChangePolicyDescriptor","CoinSelection","Conversion","CreateTxError","Descriptor","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","InsufficientFunds","IrreplaceableTransaction","LockTime","MiniscriptPsbt","MiniscriptPsbtError","MissingKeyOrigin","MissingNonWitnessUtxo","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","OutputUpdate","Persist","Policy","Psbt","RbfSequence","RbfSequenceCsv","SpendingPolicyRequired","TransactionConfirmed","TransactionNotFound","UnknownUtxo","UnknownUtxo","UtxoUpdate","Version0","Version1Csv","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","into","into","into","provide","provide","provide","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","available","csv","needed","rbf","requested","required","required","required","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","descriptor","deserialize","export_wallet","fmt","from","from_str","into","label","serialize","to_string","try_from","try_into","type_id","vzip","All","Dummy","Exclude","External","Fingerprint","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MiniscriptPsbt","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","None","PkHash","Segwitv0","SighashError","SignOptions","SignerCommon","SignerContext","SignerError","SignerId","SignerOrdering","SignerWrapper","SignersContainer","Tap","TapLeavesOptions","TransactionSigner","UserCanceled","add_external","allow_all_sighashes","allow_grinding","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","default","deref","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","eq","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","hash","id","id","id","id","ids","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","remove_taproot_extras","sign_input","sign_input","sign_input","sign_input","sign_transaction","sign_transaction","sign_with_tap_internal_key","signers","tap_leaves_options","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_finalize","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","is_internal_key","AddForeignUtxoError","AddUtxoError","AllowShrinkingError","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","InvalidOutpoint","InvalidTxid","MissingScriptPubKey","MissingUtxo","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","UnknownUtxo","Untouched","add_data","add_foreign_utxo","add_foreign_utxo_with_sequence","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","current_height","default","default","default","default","do_not_spend_change","drain_to","drain_wallet","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","include_output_redeem_witness_script","into","into","into","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","provide","provide","provide","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","foreign_utxo","input_txid"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Utxo","","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::checksum","","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::psbt","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::ApplyBlockError","","bdk::wallet::InsertTxError","","bdk::wallet::NewOrLoadError","","","","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection::Error","","bdk::wallet::coin_selection::Excess","","","","","bdk::wallet::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::error::CreateTxError","","","","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerContext","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::tx_builder::AddForeignUtxoError",""],"d":["External keychain, used for deriving recipient addresses.","A UTXO owned by another wallet.","","Internal keychain, used for deriving change addresses.","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","","","An unspent transaction output (UTXO).","","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","","","","","","","","","","","","","","","","","","The confirmation time for transaction containing this utxo","The derivation index for the script pubkey in the wallet","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","Macro to write descriptor fragments with code","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Whether this UTXO is spent or not","Type of keychain","Key formats","Get the location of the UTXO","Reference to a transaction output","","Additional functions on the rust-bitcoin Psbt structure.","The weight of the witness data and scriptSig expressed in …","Get the sequence number if an explicit sequence number has …","","","","","","","","","","","","","","","","","Get the TxOut of the UTXO","Transaction output","","","","","The UTXO","Get the version of BDK at runtime","","","","","Wallet","The location of the output.","The information about the input we require to add it to a …","The nSequence value to set for this input.","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Script descriptor","","The descriptor pubkey, either a single pubkey or an xpub.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","Alias for the type of maps that represent derivation paths …","Trait for types which can be converted into an …","The consensus key associated with the type. Must be a …","Legacy ScriptContext To be used as P2SH scripts For …","The top-level miniscript abstract syntax tree (AST).","Multiple extended public keys.","Pay-to-PubKey-Hash","","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Single public key.","Alias for the type of maps that represent taproot key …","Pay-to-Taproot","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Extended public key (xpub).","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","","Replaces all wildcards (i.e. /*) in the descriptor with a …","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","Attempt to produce a non-malleable witness template given …","Attempt to produce a malleable witness template given the …","","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Each context has slightly different rules on what Pks are …","","","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","Whether the given miniscript contains a raw pkh fragment","Deprecated name for Self::at_derivation_index.","Convert all the public keys in the descriptor to …","Convert all the public keys in the descriptor to …","Get the DescriptorType of Descriptor","","","","Encode as a Bitcoin script","","","","","Descriptor errors","Computes the the underlying script before any hashing is …","Additional information helpful for extra analysis.","Check whether the miniscript follows the given Extra …","Extract the spending policy","","","Utility method for deriving the descriptor at each index …","","","","","","","","","","","","Returns the argument unchanged.","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Add type information(Type and Extdata) to Miniscript based …","Create a new Miniscript from a Terminal node and a Type …","","Parse a Miniscript from string and perform sanity checks …","Attempt to parse an Miniscripts that don’t follow the …","Attempt to parse an insane(scripts don’t clear sanity …","Parse an expression tree into a descriptor.","Parse an expression tree into a Miniscript. As a general …","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns satisfying non-malleable witness and scriptSig to …","Returns a possilbly mallable satisfying non-malleable …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","Whether or not the descriptor has any wildcards i.e. /*.","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Extracts the AstElem representing the root of the …","Get as many descriptors as different paths in this …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether this descriptor contains a key that has multiple …","Whether the miniscript is malleable","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","","","Lifting corresponds to conversion of a miniscript into a …","Depending on script context, the size of a satifaction …","","","Maximum size, in bytes, of a satisfying witness. For …","Computes an upper bound on the weight of a satisfying …","Maximum number of witness elements used to satisfy the …","Computes an upper bound on the difference between a …","Local helper function to display error messages with …","","","Create a new bare descriptor from witness script Errors …","Create a new pk descriptor","Create a new PkH descriptor","Create a new sh for a given redeem script Errors when …","Create a new sh sortedmulti descriptor with threshold k …","Create a new sh wrapper for the given wpkh descriptor","Create a new sh wrapper for the given wsh descriptor","Create a new sh wrapped wpkh from Pk. Errors when …","Create a new sh wrapped wsh descriptor with witness script …","Create a new sh wrapped wsh sortedmulti descriptor from …","Create new tr descriptor Errors when miniscript exceeds …","Create a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the AST.","Other top level checks that are context specific","Attempt to parse a Script into Miniscript representation.","Parse a descriptor that may contain secret keys","Attempt to parse an insane(scripts don’t clear sanity …","Attempt to parse an miniscript with extra features that …","","","","","Get the len of public key when serialized based on context …","","","Returns a plan if the provided assets are sufficient to …","Returns a plan if the provided assets are sufficient to …","Descriptor policy","Whether all spend paths of miniscript require a signature","Checks whether the descriptor is safe.","Check whether the underlying Miniscript is safe under the …","Attempts to produce a non-malleable satisfying witness and …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Computes the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor.","Size, in bytes of the script-pubkey. If this Miniscript is …","","","The type of signature required for satisfaction","","","Substitutes raw public keys hashes with the public keys as …","Descriptor templates","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Converts a descriptor using abstract keys to one using …","Translates a struct from one generic to another where the …","","","","","","","","","The correctness and malleability type information for the …","","","","","Computes the scriptSig that will be in place for an …","","","","","Whether the miniscript can exceed the resource …","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","Error during base58 decoding","BIP32 error","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid byte found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","The descriptor contains multipath keys","Key-related error","Error while extracting and manipulating policies","","","","","","Returns the argument unchanged.","","","","","","","Calls U::from(self).","","","","","","","Absolute timeclock timestamp","Can not add to an item that is Satisfaction::None or …","Can not add to an item that is …","Options to build the satisfaction field in the policy","Can satisfy the policy item","An extra condition that must be satisfied but that is out …","Type for a map of sets of Condition items keyed by each set…","ECDSA Signature for a raw public key","An extended key fingerprint","Type for a map of folded sets of Condition items keyed by …","SHA256 then RIPEMD160 preimage hash","Double SHA256 preimage hash","Incompatible conditions (not currently used)","Index out of range for an item to satisfy a …","Can not merge CSV or timelock values unless both are less …","Multi-signature public keys with threshold count","Cannot satisfy or contribute to the policy item","Don’t generate satisfaction field","Not enough items are selected to satisfy a …","Only a partial satisfaction of some kind of threshold …","Can reach the threshold of some kind of threshold policy","A unique identifier for a key","Descriptor spending policy","Errors that can happen while extracting and manipulating …","Analyze the given PSBT to check for existing signatures","Like Psbt variant and also check for expired timelocks","A legacy public key","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","Schnorr Signature for a raw public key","SHA256 preimage hash","Threshold items with threshold count","A x-only public key","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the conditions that are set by the spending policy …","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the SatisfiableItem is a leaf item","Returns whether the Satisfaction is a leaf item","Returns true if there are no extra conditions to verify","Type of this policy node","","","Return whether or not a specific path in the policy tree …","How much a given PSBT already satisfies this policy node …","","","","","","Optional timelock condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Current blockchain height","The highest confirmation height between the inputs CSV …","Given PSBT","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","The items that can be satisfied by the descriptor or are …","The items that can be satisfied by the descriptor","Threshold","Threshold","Total number of items","Total number of items","Whether the items are sorted in lexicographic order (used …","Whether the items are sorted in lexicographic order (used …","The digest value","The digest value","The digest value","The digest value","The policy items","The raw public key or extended key fingerprint","The required threshold count","The required threshold count","The timelock value","The timelock value","BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to …","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)","BIP86 public template. Expands to tr(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2TR template. Expands to a descriptor tr(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The descriptor pubkey, either a single pubkey or an xpub.","The descriptor secret key, either a single private key or …","Type specifying the amount of entropy required e.g. [u8;32]","Returned error in case of failure","Trait that adds extra useful methods to ScriptContexts","Enum for extended keys that can be either xprv or xpub","A bitcoin public key (compressed or uncompressed).","Trait that allows generating a key with the default options","Trait for keys that can be generated","Output of a GeneratableKey key generation","Trait for objects that can be turned into a public or …","The key has an invalid checksum","The key is not valid for the given network","The key cannot exist in the given script context","The consensus key associated with the type. Must be a …","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Multiple extended private keys.","Multiple extended public keys.","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single public key.","Single private key.","A descriptor bitcoin::PrivateKey with optional origin …","A descriptor SinglePubKey with optional origin information.","Single public key without any origin or range information.","Contents of a “sortedmulti” descriptor","Taproot scripts","Set of valid networks for a key","An xonly public key.","Extended private key (xpriv).","Extended public key (xpub).","Create a set containing mainnet, testnet, signet, and …","Returns the ScriptContext as a ScriptContextEnum","Replaces any wildcard (i.e. /*) in the key with a …","","","","","","","","","","","","","","","","","","","","","","","","","Attempt to produce a witness template given the assets …","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Policy rules at the Miniscript satisfaction time. It is …","Check the consensus + policy(if not disabled) rules …","Each context has slightly different rules on what Pks are …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","Deprecated name for Self::at_derivation_index.","","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Returns a vector containing the full derivation paths from …","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","Return whether or not the key contains the private data","Whether or not the key has a wildcard","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Get as many keys as derivation paths in this key.","Get as many keys as derivation paths in this key.","Transform the ExtendedKey into an Xpriv for the given …","Transform the ExtendedKey into an Xpub for the given …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Whether or not this key has multiple derivation paths.","Whether or not this key has multiple derivation paths.","Returns whether the script context is Segwitv0","Returns whether the script context is …","Returns whether the script context is Tap, aka Taproot or …","Returns whether the script context is …","","","signatures required","The public key.","The private key.","","Create a set only containing mainnet","The fingerprint of the master key associated with this …","Depending on script context, the size of a satifaction …","Maximum size, in bytes, of a satisfying witness. In …","Maximum number of witness elements used to satisfy the …","Compute the intersection of two sets","Local helper function to display error messages with …","Create a new instance of SortedMultiVec given a list of …","","Origin information (fingerprint and derivation path).","Origin information (fingerprint and derivation path).","Other top level checks that are context specific","Override the computed set of valid networks","","","","","Get the len of public key when serialized based on context …","public keys inside sorted Multi","","utility function to sanity a sorted multi vec","Attempt to produce a satisfying witness for the witness …","Size, in bytes of the script-pubkey. If this Miniscript is …","","The type of signature required for satisfaction","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","","","Returns the public version of this key.","","","","","Check top level consensus rules.","Check whether the top-level is type B","This will panic if fpk returns an uncompressed key when …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Trait to add functions to extract utxos and calculate fees.","The total transaction fee amount, sum of input amounts …","The transaction’s fee rate. This value will only be …","Get the TxOut for the specified input index, if it doesn’…","The address index selection strategy to use to derived an …","A derived address and the index it was found at. For …","An error that may occur when applying a block to Wallet.","Balance, differentiated into various categories.","Occurs when the update chain cannot connect with original …","The changes made to a wallet by applying an Update.","The error variant that occurs when the caller attempts to …","There was problem with the passed-in descriptor(s).","There was a problem with the passed-in descriptor(s).","There is a problem with the passed-in descriptor.","An error that may occur when inserting a transaction into …","Trait to check if a value is below the dust limit. We are …","Return the address for the current descriptor index if it …","Loading data from the persistence backend failed.","Loading from the persistence backend failed.","The error type when loading a Wallet from persistence.","The loaded genesis hash does not match what was provided.","The loaded network type does not match what was provided.","Data loaded from persistence is missing genesis hash.","Data loaded from persistence is missing network type.","Return a new address after incrementing the current …","The error type when constructing a fresh Wallet.","Error type for when we try load a Wallet from persistence …","Database already has data.","Wallet not initialized, persistence backend is empty.","Wallet is not initialized, persistence backend is empty.","Return the address for a specific descriptor index. Does …","Occurs when the connected_to hash does not match the hash …","An update to Wallet.","A Bitcoin wallet","We were unable to write the wallet’s data to the …","Writing to the persistence backend failed.","","Add an external signer","Address","Get unbounded script pubkey iterators for both Internal …","","Introduces a block of height to the wallet, and tries to …","Applies relevant transactions from block of height to the …","Apply relevant unconfirmed transactions to the wallet.","Applies an update to the wallet and stages the changes …","","","","","","","","","","","","","","","","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Calculates the fee of a given transaction. Returns 0 if tx …","Calculate the FeeRate for a given transaction.","Informs the wallet that you no longer intend to broadcast …","Update for the wallet’s internal LocalChain.","Changes to the LocalChain.","Get all the checkpoints the wallet is currently storing …","","","","","","","Coin selection","Commits all currently staged changed to the persistence …","Confirmed and immediately spendable balance","","","","","The derivation index of this wallet. It will return None …","Finds how the wallet derived the script pubkey spk.","Return the checksum of the public descriptor associated to …","","","","","","Errors that can be thrown by the Wallet","Wallet export","Finalize a PSBT, i.e., for each input determine if …","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Infallibly return a derived address using the external …","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","Infallibly return a derived address using the internal …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Get a single transaction from the wallet as a CanonicalTx …","Returns the utxo owned by this wallet corresponding to …","Update for the wallet’s internal TxGraph.","All coinbase outputs not yet matured","Child index of this address","Changes to IndexedTxGraph.","Add a new checkpoint to the wallet’s internal view of …","Add a transaction to the wallet’s internal view of the …","Inserts a TxOut at OutPoint into the wallet’s …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Check whether or not a value is below dust limit","","Return whether or not a script is part of this wallet …","Type of keychain","Iterator over all keychains in this wallet","Contains the last active derivation indices per keychain (K…","Returns the latest checkpoint.","List all relevant outputs (includes both spent and …","Return the list of unspent outputs of this wallet","Load Wallet from the given persistence backend.","Get a reference to the inner LocalChain.","Get the Bitcoin network the wallet is using.","Stores the network type of the wallet.","Initialize an empty Wallet.","Creates a wallet that does not persist data.","Creates a wallet that does not persist data, with a custom …","Either loads Wallet from persistence, or initializes it if …","Either loads Wallet from persistence, or initializes it if …","Initialize an empty Wallet with a custom genesis hash.","The index of the next address that you would get if you …","Return the spending policies for the wallet’s descriptor","","","","","","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","Compute the tx’s sent and received amounts (in satoshis).","","","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Get a reference to the inner KeychainTxOutIndex.","Returns the changes that will be committed with the next …","","","","","","","","","","","Get the whole balance visible to the wallet.","Iterate over the transactions in the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","","Return a derived address using the external descriptor, …","Return a derived address using the internal (change) …","","","","","","","","","","","","Transaction builder","Get a reference to the inner TxGraph.","","","","","","","","","","","","Get an unbounded script pubkey iterator for the given …","Unconfirmed UTXOs received from an external wallet","","","","","","","","","","","","Deterministically generate a unique name given the …","Block hash of connected_to.","Expected block hash of connected_to, as derived from block.","The internal chain’s tip height.","The introduced transaction’s confirmation height.","The expected genesis block hash.","The expected network type.","The block hash loaded from persistence.","The network type loaded from persistence.","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Branch and bound coin selection","It’s possible to create spendable output from excess …","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Errors that can be thrown by the coin_selection module","Remaining amount after performing coin selection","Wallet’s UTXO set is not enough to cover recipient’s …","Simple and dumb coin selection","It’s not possible to create spendable output from excess …","OldestFirstCoinSelection always picks the utxo with the …","","","","","","","","","","","","","","","","","","","Perform the coin selection","","","","Decide if change can be created","","","","Remaining amount after deducing fees and outgoing outputs","Total fee amount for the selected utxos in satoshis","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The total value of the inputs selected from the local …","Create new instance with target size for change output","","List of outputs selected for use as inputs","The total value of the inputs selected.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","Sats needed for some transaction","Effective amount available to create change after …","The calculated fee for the drain TxOut with the selected …","Threshold to consider amount as dust for this particular …","The deducted change output fee","Exceeding amount of current selection over outgoing value …","Error returned from Wallet::build_fee_bump","The change_policy was set but the wallet does not have a …","There was an error with coin selection","Descriptor key conversion error","Error returned from TxBuilder::finish","There was a problem with the descriptors passed in","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","Wallet’s UTXO set is not enough to cover recipient’s …","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Requested LockTime is less than is required to spend from …","Miniscript PSBT error","Errors returned by miniscript when updating inconsistent …","In order to use the TxBuilder::add_global_xpubs option …","Missing non_witness_utxo on foreign utxo for given OutPoint","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Return error type for …","We were unable to write wallet data to the persistence …","There was a problem while extracting and manipulating …","Partially signed bitcoin transaction error","Cannot enable RBF with a Sequence >= 0xFFFFFFFE","Cannot enable RBF with Sequence given a required OP_CSV","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","Happens when trying to spend an UTXO that is not in the …","Return error type for PsbtExt::update_input_with_descriptor","Requested invalid transaction version ‘0’","Requested transaction version 1, but at least 2 is needed …","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","Returns the argument unchanged.","","","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","Sats available for spending","Required OP_CSV Sequence","Sats needed for some transaction","Given RBF Sequence","Requested LockTime","Required LockTime","Required fee absolute value (satoshi)","Required fee rate","Structure that contains the export of a wallet","Alias for FullyNodedExport","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","Return the external descriptor","","Export a wallet","","Returns the argument unchanged.","","Calls U::from(self).","Arbitrary label for the wallet","","","","","","","The signer will sign all the leaves it has a key for.","Dummy identifier","The signer won’t sign the specified leaves.","To be used only by external libraries implementing …","The fingerprint of a BIP32 extended key","The signer won’t sign leaves other than the ones …","Input index is out of range","PSBT Input signer","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","Invalid SIGHASH for the signing context in use","Legacy context","Miniscript PSBT error","The fingerprint and derivation path are missing from the …","The private key is missing for the required public key","The non_witness_utxo field of the transaction is required …","The witness_script field of the transaction is required to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","The signer won’t sign any leaf.","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Segwit v0 context (BIP 143)","Error while computing the hash to sign","Options for a software signer","Common signer methods","Signing context","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Wrapper to pair a signer with its context","Container for multiple signers","Taproot context (BIP 340)","Customize which taproot script-path leaves the signer …","PSBT signer","The user canceled the operation","Adds an external signer to the container for the specified …","Whether the signer should use the sighash_type set in the …","Whether we should grind ECDSA signature to ensure signing …","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","Build a new signer container from a KeyMap","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Return the SignerId for this signer","","","","Returns the list of identifiers of all the signers in the …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a wrapped signer from a signer and a context","Default constructor","","","","Removes a signer from the container and returns it","Whether to remove partial signatures from the PSBT inputs …","Whether to remove taproot specific fields from the PSBT on …","Sign a single psbt input","","","","Sign all the inputs of the psbt","","Whether we should try to sign a taproot transaction with …","Returns the list of signers in the container, sorted by …","Specifies which Taproot script-spend leaves we should sign …","","","","","","","","","Whether the signer should trust the witness_utxo, if the …","Whether to try finalizing the PSBT after the inputs are …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Whether the signer can sign for the internal key or not","Error returned from TxBuilder::add_foreign_utxo.","Error returned from TxBuilder::add_utxo and …","Error returned from TxBuilder::allow_shrinking","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Requested outpoint doesn’t exist in the tx (vout greater …","Foreign utxo outpoint txid does not match PSBT input txid","Script/PubKey was not in the original transaction","Foreign utxo missing witness_utxo or non_witness_utxo","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Happens when trying to spend an UTXO that is not in the …","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Same as add_foreign_utxo but allows to set the nSequence …","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Set whether or not the dust limit is checked.","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","Set the current blockchain height.","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee The fee_absolute method refers to the …","Set a custom fee rate.","Finish building the transaction.","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Fill-in the psbt::Output::redeem_script and …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","","","","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","","","","","","Foreign UTXO outpoint","PSBT input txid"],"i":[1,5,0,1,0,5,0,0,0,0,0,0,1,1,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,4,5,1,3,3,0,0,1,3,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,1,3,4,5,3,3,0,5,3,1,0,4,5,1,3,0,0,1,3,4,5,1,3,4,5,1,3,4,5,5,3,1,3,4,5,4,0,1,3,4,5,0,198,198,198,17,0,0,0,0,0,0,0,0,48,0,0,26,17,0,0,0,17,26,0,17,17,17,26,17,35,36,23,23,17,17,35,36,23,17,35,36,23,23,23,23,0,48,35,36,48,36,48,48,35,36,48,35,36,48,48,35,36,48,35,36,48,35,36,0,17,35,36,23,17,35,36,23,17,35,36,23,23,17,17,17,17,17,23,17,23,17,35,36,23,0,17,23,23,199,17,23,17,17,17,35,36,23,23,17,23,17,17,17,17,17,17,17,35,36,23,23,23,17,23,23,23,17,23,23,23,17,17,23,23,17,17,35,36,23,17,35,36,23,23,17,166,62,17,17,23,23,23,17,23,23,48,35,36,23,17,23,17,48,35,36,17,17,17,17,17,17,17,17,17,17,17,17,17,17,23,48,23,17,23,23,17,35,36,23,48,35,36,17,17,0,23,17,23,17,23,23,17,17,23,17,23,48,35,36,23,0,17,35,36,23,17,23,17,48,48,17,23,17,35,36,23,17,35,36,23,23,17,35,36,23,17,17,35,36,23,23,0,0,47,47,0,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,83,76,76,0,84,0,0,83,82,0,83,83,76,76,76,83,84,45,76,84,84,0,0,0,45,45,82,83,83,0,0,83,83,83,82,82,83,84,46,85,76,45,82,83,84,46,85,76,45,82,83,84,46,85,45,82,83,84,46,85,45,46,85,85,82,83,84,46,85,76,82,83,84,46,85,76,76,45,82,83,84,84,46,46,85,76,45,46,82,85,83,46,82,83,84,46,85,76,45,83,84,85,46,85,76,46,46,82,83,84,46,85,85,82,83,84,46,85,45,76,82,83,84,46,85,76,45,82,83,84,46,85,76,45,82,83,84,46,85,76,45,82,83,84,46,85,76,45,200,200,200,201,202,203,202,203,202,203,202,203,202,203,204,205,206,207,208,209,209,208,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,212,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,86,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,80,0,0,0,0,213,213,0,0,110,0,0,0,0,80,80,80,48,0,0,22,80,80,107,26,213,114,0,114,0,0,22,26,107,0,0,0,0,22,0,110,107,26,0,214,26,114,105,112,22,106,80,103,26,107,108,109,110,114,105,112,22,106,80,103,26,107,108,109,110,103,48,48,48,48,48,48,48,48,48,105,22,106,103,26,107,108,109,110,105,22,106,103,26,107,108,109,110,103,26,108,110,106,106,105,26,26,103,22,103,26,107,108,109,110,112,22,106,80,80,103,103,26,26,107,107,108,109,110,103,114,114,114,105,112,22,106,80,80,80,103,26,26,107,108,109,110,112,112,26,107,103,26,26,213,215,213,215,114,26,103,26,108,110,114,105,112,22,106,80,103,26,107,108,109,110,26,87,93,105,105,112,26,107,93,114,105,105,26,107,114,114,26,214,22,26,107,214,22,214,22,26,26,103,108,109,103,0,26,48,103,103,0,48,103,26,108,109,48,112,103,26,108,110,48,103,80,103,103,103,26,48,103,0,105,22,106,103,26,107,108,109,110,107,80,103,26,107,48,48,103,114,105,112,22,106,80,103,26,107,108,109,110,114,105,112,22,106,80,103,26,107,108,109,110,114,105,112,22,106,80,103,26,107,108,109,110,114,105,112,22,106,80,103,26,107,108,109,110,0,216,216,216,0,0,0,0,154,0,153,150,151,152,0,0,149,151,152,0,152,152,151,151,149,0,0,150,151,152,149,154,0,0,150,152,122,123,145,123,128,123,123,123,123,123,122,123,134,128,149,145,150,151,152,153,154,122,123,134,128,149,145,150,151,152,153,154,123,123,123,123,123,134,128,123,122,134,128,122,134,128,0,123,122,122,134,128,145,123,123,123,122,128,122,128,145,0,0,123,122,122,123,134,128,149,145,145,150,150,151,151,152,152,153,153,154,154,122,123,134,128,128,128,149,145,150,151,152,153,154,123,123,123,123,123,123,123,123,134,122,145,128,123,123,123,122,123,134,128,149,145,150,151,152,153,154,217,128,123,145,123,134,123,123,123,123,123,123,128,123,123,123,123,123,123,123,123,150,151,152,153,154,123,123,123,122,128,123,0,123,123,122,134,128,122,145,150,151,152,153,154,122,123,122,122,122,123,134,128,149,145,150,151,152,153,154,123,123,122,123,134,128,149,145,150,151,152,153,154,0,123,122,123,134,128,149,145,150,151,152,153,154,123,122,122,123,134,128,149,145,150,151,152,153,154,0,218,218,219,219,220,221,220,221,174,174,0,175,0,0,0,0,0,174,0,175,0,174,175,173,170,171,172,174,175,173,170,171,172,170,171,172,170,171,172,190,170,171,172,0,170,171,172,173,173,174,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,173,172,174,173,173,170,171,172,174,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,222,222,223,224,224,223,224,0,161,161,176,0,161,161,140,161,161,140,161,161,0,161,161,161,161,161,176,161,161,161,161,161,161,140,140,161,140,176,161,161,176,161,140,176,161,140,176,176,176,176,161,161,140,140,176,161,161,161,161,161,161,140,176,161,140,176,161,140,176,176,161,140,176,161,140,176,161,140,176,161,140,176,161,140,225,226,225,226,227,227,228,229,0,0,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,184,179,184,148,179,184,148,0,148,148,148,181,148,148,148,148,148,148,148,184,179,181,148,0,0,0,0,0,0,0,0,181,0,0,148,44,147,147,44,147,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,44,179,181,183,124,44,147,184,179,181,183,124,44,147,184,179,124,124,44,147,184,183,230,183,183,183,179,181,124,184,44,179,148,148,181,183,124,44,147,184,179,179,179,148,148,181,183,124,44,147,184,179,230,183,183,183,44,179,148,181,183,124,44,147,184,183,44,179,124,148,44,147,147,231,183,183,183,125,183,147,44,147,179,181,183,124,44,147,184,148,147,147,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,232,0,0,0,195,0,194,194,0,0,191,191,193,191,194,195,0,0,0,192,195,139,139,139,139,139,139,139,139,139,139,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,139,141,138,139,195,194,141,138,139,195,194,195,194,139,139,141,138,195,194,139,139,139,139,139,195,194,139,139,139,141,138,139,192,192,191,191,193,193,195,194,141,138,139,192,191,193,195,194,195,194,139,141,138,139,192,191,193,195,194,139,139,139,139,139,195,194,139,192,191,193,139,139,195,141,138,139,195,194,192,191,193,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,139,139,141,138,139,192,191,193,195,194,233,233],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[1,2],[1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[1,1],[3,3],[4,4],[5,5],[[]],[[]],[[]],[[]],[[1,1],6],0,0,0,0,[[],[[7,[1]]]],[[],[[7,[3]]]],[[1,1],8],[[3,3],8],[[4,4],8],[[5,5],8],[[1,9],10],[[3,9],10],[[4,9],10],[[5,9],10],0,[[]],[[]],[[]],[[]],[1],[3],[[]],[[]],[[]],[[]],0,0,0,[5,11],0,[[1,1],[[12,[6]]]],0,0,[5,[[12,[13]]]],[1,7],[3,7],0,0,[[]],[[]],[[]],[[]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[5,14],0,[[],15],[[],15],[[],15],[[],15],0,[[],16],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[17,18],[[7,[[20,[19]],21]]]],[[],22],[[],22],[23,24],[23,[[25,[23]]]],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[23,[[31,[23,30]]]],[23,[[33,[32]]]],[23,[[33,[32]]]],0,[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],0,[17,17],[35,35],[36,36],[23,23],[[]],[[]],[[]],[[]],[[17,17],6],[[35,35],6],[[36,36],6],[[23,23],6],[23,8],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[[17,[28]],37],[[7,[[17,[38]],29]]]],[[[17,[26]],37,27],[[7,[[17,[38]],29]]]],[17,39],[[],[[7,[17]]]],[[],[[7,[23]]]],[[[17,[26]]],40],[23,41],[[17,17],8],[[35,35],8],[[36,36],8],[[23,23],8],0,[17,[[7,[41,21]]]],0,[[23,42],[[7,[43]]]],[[44,45,37],[[7,[[12,[46]],47]]]],[[[17,[26]],44,45,37],[[7,[[12,[46]],47]]]],[[[23,[26,48]],44,45,37],[[7,[[12,[46]],47]]]],[[[17,[26]],37,49,[50,[27]]],[[7,[12,29]]]],[[17,9],[[7,[51]]]],[[17,9],[[7,[51]]]],[[35,9],[[7,[51]]]],[[36,9],[[7,[51]]]],[[23,9],[[7,[51]]]],[[23,9],[[7,[51]]]],[17,8],[23,8],[52,17],[53,17],[54,17],[[]],[55,17],[56,17],[57,17],[[]],[[]],[[]],[24,[[7,[23,21]]]],[[24,58,59],23],[16,[[7,[17,21]]]],[16,[[7,[23,21]]]],[[16,42],[[7,[23,21]]]],[16,[[7,[23,21]]]],[60,[[7,[17,21]]]],[60,[[7,[23,21]]]],[[23,61],[[12,[23]]]],[[23,61],12],[17,[[7,[21]]]],[17,[[7,[21]]]],[23,8],[23,8],[[[17,[26]]],8],[17],[35],[36],[23],[[]],[[]],[[]],[[]],[23,24],[[[17,[26]]],[[7,[[31,[[17,[26]],30]],21]]]],[[37,18],[[7,[47]]]],[[62,37,18],[[7,[47]]]],[[[17,[26]]],8],[[[17,[26]]],8],[23,8],[23,63],[23,64],[17,[[7,[65,21]]]],[23,[[7,[65,21]]]],[23,[[7,[66]]]],[23,[[12,[61]]]],[23,[[12,[61]]]],[23,[[12,[61]]]],[23,[[7,[61,21]]]],[17,[[7,[61,21]]]],[23,[[7,[61,21]]]],[17,[[7,[61,21]]]],[[],16],[[],16],[[],16],[[[23,[67]]],[[7,[17,21]]]],[[],17],[[],[[7,[17,21]]]],[[[23,[35]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],[55,17],[56,17],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],[[[12,[68]]],[[7,[17,21]]]],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],0,[23,[[7,[21]]]],[49,[[7,[23,21]]]],[[37,16],[[7,[21]]]],[49,[[7,[23,21]]]],[[49,42],[[7,[23,21]]]],[[17,17],[[12,[6]]]],[[35,35],[[12,[6]]]],[[36,36],[[12,[6]]]],[[23,23],[[12,[6]]]],[[],61],[[],61],[[],61],[[[17,[28]]],[[7,[69,[17,[28]]]]]],[[[17,[28]]],[[7,[69,[17,[28]]]]]],0,[23,8],[17,[[7,[21]]]],[23,[[7,[43]]]],[[17,70],[[7,[21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[17,[[7,[41,21]]]],[17,41],[23,61],[17,7],[23,7],[[],71],[[],71],[[],71],[[23,72],23],0,[[]],[[]],[[]],[[]],[[],73],[[],73],[[[17,[26]],72],73],[23,[[7,[21]]]],[23,[[7,[21]]]],[17,[[7,[74]]]],[23,[[7,[74]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[[],15],[[],15],[[],15],[[],15],[17,41],[[]],[[]],[[]],[[]],[23,8],[16,[[7,[73,47]]]],[16,[[7,[47]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[47,9],10],[[47,9],10],[75,47],[[]],[76,47],[77,47],[21,47],[78,47],[79,47],[80,47],[[]],[81],[[],73],[[],7],[[],7],[[],15],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[82,82],[83,83],[84,84],[46,46],[85,85],[45,45],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],85],[[82,82],8],[[83,83],8],[[84,84],8],[[46,46],8],[[85,85],8],[[76,76],8],[[82,9],10],[[83,9],10],[[84,9],10],[[46,9],10],[[85,9],10],[[76,9],10],[[76,9],10],[[45,9],10],[[]],[[]],[8,84],[[]],[[]],[83,46],[[]],[[]],[[]],[[46,72],[[7,[85,76]]]],[82],[85],[83,73],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[83,8],[84,8],[85,8],0,[[85,85],[[12,[6]]]],[81],[46,8],0,[82,7],[83,7],[84,7],[46,7],[85,7],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[18,[[7,[86,47]]]],[[[88,[[87,[35]]]],18],[[7,[86,47]]]],[[[89,[[87,[36]]]],18],[[7,[86,47]]]],[[[90,[[87,[36]]]],18],[[7,[86,47]]]],[[[92,[[87,[91]]]],18],[[7,[86,47]]]],[[[94,[[93,[35]]]],18],[[7,[86,47]]]],[[[95,[[93,[35]]]],18],[[7,[86,47]]]],[[[96,[[93,[36]]]],18],[[7,[86,47]]]],[[[97,[[93,[36]]]],18],[[7,[86,47]]]],[[[98,[[93,[36]]]],18],[[7,[86,47]]]],[[[99,[[93,[36]]]],18],[[7,[86,47]]]],[[[100,[[93,[91]]]],18],[[7,[86,47]]]],[[[101,[[93,[91]]]],18],[[7,[86,47]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[86,37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],102],[[],22],[[26,27],[[7,[28,29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[103,[[33,[32]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[[105,[104,48]]],[[105,[104,48]]]],[22,22],[106,106],[103,103],[26,26],[107,107],[108,108],[109,109],[110,110],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[103,103],6],[[26,26],6],[[108,108],6],[[110,110],6],0,[[],106],[[[105,[48]]]],[[26,27],[[7,[28,29]]]],[[],[[7,[26]]]],[103,41],[[22,22],8],[[103,103],8],[[26,26],8],[[107,107],8],[[108,108],8],[[109,109],8],[[110,110],8],[[[112,[[0,[111,48]]]],9],10],[[22,9],10],[[106,9],10],[[80,9],10],[[80,9],10],[[103,9],[[7,[51]]]],[[103,9],[[7,[51]]]],[[26,9],[[7,[51]]]],[[26,9],[[7,[51]]]],[[107,9],[[7,[51]]]],[[107,9],[[7,[51]]]],[[108,9],[[7,[51]]]],[[109,9],[[7,[51]]]],[[110,9],[[7,[51]]]],[103,8],[113,[[114,[48]]]],[115,[[114,[48]]]],[[]],[[]],[[]],[[]],[[]],[79,80],[[]],[21,80],[[]],[28,26],[[]],[[]],[[]],[[]],[[]],[[26,102],[[112,[48]]]],[[107,102],[[112,[48]]]],[16,[[7,[26]]]],[16,[[7,[107]]]],[60,[[7,[103,21]]]],[26,[[12,[116]]]],[26,[[31,[116,30]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[[114,[48]]],8],[26,8],[103],[26],[108],[110],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[26,117],[[],[[7,[112,80]]]],[[[12,[118]],116],[[7,[112,80]]]],[105,[[7,[112,80]]]],[[105,[12,[118]],116],[[7,[112,80]]]],[[[112,[48]]],[[7,[[112,[48]],80]]]],[26,[[7,[[112,[48]],80]]]],[107,[[7,[[112,[48]],80]]]],[[],[[7,[114,80]]]],[[[114,[48]]],[[7,[[114,[48]],80]]]],[105,[[7,[114,80]]]],[[[105,[48]]]],[26,[[31,[26,30]]]],[107,[[31,[107,30]]]],[[[114,[48]],18],[[12,[115]]]],[[[114,[48]],18,37],113],[26,8],[[],8],[22,8],[26,8],[107,8],[[],8],[22,8],[[],8],[22,8],[26,8],[26,8],0,0,0,[103,[[7,[65,21]]]],[[],102],[26,119],[23,[[12,[61]]]],[103,61],[103,61],[[102,102],102],[[],16],[[61,[31,[30]]],[[7,[103,21]]]],[26,61],0,0,[23,[[7,[21]]]],[[[112,[48]],102],[[112,[48]]]],[[103,103],[[12,[6]]]],[[26,26],[[12,[6]]]],[[108,108],[[12,[6]]]],[[110,110],[[12,[6]]]],[[],61],0,[81],[103,[[7,[21]]]],[103,[[7,[[31,[[31,[2,30]],30]],21]]]],[103,61],[26,7],[[],71],[103,24],[[],102],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[107,37],[[7,[26,120]]]],[[],73],[[],73],[[],73],[[],73],[23,[[7,[21]]]],[23,[[7,[21]]]],[103,[[7,[103,74]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[12,[40]]]],[[],[[12,[121]]]],[61,[[12,[14]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[122,122],122],[[123,1,124,[126,[125]]]],0,[123,[[72,[1,[0,[127,104]]]]]],[[128,128]],[[123,129,27],[[7,[130]]]],[[123,129,27,131],[[7,[132]]]],[[123,133]],[[123,134],[[7,[130]]]],[123,135],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[123,136],[[7,[[139,[137,138]],140]]]],[123,[[139,[137,141]]]],[[123,142],[[7,[40,143]]]],[[123,142],[[7,[121,143]]]],[[123,142]],0,0,[123,144],[122,122],[134,134],[128,128],[[]],[[]],[[]],0,[123,[[7,[8]]]],0,[[],122],[[],134],[[],128],[145],[[123,1],[[12,[27]]]],[[123,49],12],[[123,1],73],[[],[[7,[122]]]],[[],[[7,[128]]]],[[122,122],8],[[128,128],8],[[145,145],8],0,0,[[123,146,147],[[7,[8,148]]]],[[122,9],[[7,[51]]]],[[122,9],[[7,[51]]]],[[[123,[111]],9],10],[[134,9],10],[[128,9],10],[[149,9],10],[[145,9],10],[[145,9],10],[[150,9],10],[[[150,[111]],9],10],[[[151,[111]],9],10],[[151,9],10],[[[152,[111,111]],9],10],[[152,9],10],[[153,9],10],[[153,9],10],[[154,9],10],[[154,9],10],[[]],[[]],[[]],[[[157,[155,[156,[1]]]]],128],[[]],[158,128],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[123,149],145],[123,122],[[123,1],62],[[123,149],145],[[123,3,[12,[159]],8],[[7,[160,161]]]],[[123,1],[[126,[44]]]],[[123,136],[[12,[[162,[[126,[142]],155]]]]]],[[123,11],[[12,[3]]]],0,0,0,0,[[123,131],[[7,[8,163]]]],[[123,142,164],[[7,[8,153]]]],[[123,11,14]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[49,8],[128,8],[[123,49],8],0,[123,72],0,[123,165],[123,127],[123,127],[[166,[12,[166]]],[[7,[123,151]]]],[123,167],[123,18],0,[[166,[12,[166]],18],[[7,[123,150]]]],[[166,[12,[166]],18],[[7,[123,47]]]],[[166,[12,[166]],18,168],[[7,[123,47]]]],[[166,[12,[166]],18],[[7,[123,152]]]],[[166,[12,[166]],18,168],[[7,[123,152]]]],[[166,[12,[166]],18,168],[[7,[123,150]]]],[[123,1],27],[[123,1],[[7,[[12,[46]],47]]]],[81],[81],[81],[81],[81],[[123,1],[[12,[62]]]],[123,37],[[123,142]],[122,7],[128,7],[[123,146,147],[[7,[8,148]]]],0,[123,169],[123,128],[[]],[[]],[[]],[[],73],[[],73],[[],73],[[],73],[[],73],[[],73],[[],73],[122,40],[123,127],0,[122,40],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[123,149],[[7,[145]]]],[[123,149],[[7,[145]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[123,135],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[123,1],[[0,[127,104]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,18,37],[[7,[73,47]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[170,170],[171,171],[172,172],[[]],[[]],[[]],[[[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[170,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[171,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[172,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[40,121,49],175],[[],170],[[],171],[[],172],0,0,[[174,9],10],[[174,9],10],[[175,9],10],[[173,9],10],[[170,9],10],[[171,9],10],[[172,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[173,40],[40,172],[81],0,[173,40],[[]],[[]],[[]],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[176,176],[[]],[[176,9],10],[[176,9],10],[[[161,[111]],9],10],[[161,9],10],[[140,9],10],[[140,9],10],[[]],[174,161],[76,161],[176,161],[[]],[177,161],[47,161],[[]],[[]],[[]],[[]],[81],[81],[81],[[]],[[],73],[[],73],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[178,[[12,[73]]]],[178,73],[[],[[7,[178]]]],[[123,16,8],[[7,[178,16]]]],[[178,9],10],[[]],[16,[[7,[178]]]],[[]],0,[178,7],[178,73],[[],7],[[],7],[[],15],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[44,179,124,[126,[125]]],[[12,[[126,[125]]]]]],0,0,[[44,37],180],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[180,17,37],44],[179,179],[181,181],[[[183,[[0,[104,182,111,104]]]]],[[183,[[0,[104,182,111,104]]]]]],[124,124],[44,44],[147,147],[184,184],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[179,179],6],[[124,124],6],[[],124],[[],44],[[],147],[[],184],[[[183,[[0,[182,111,104]]]]]],[[],[[12,[107]]]],[[[183,[185]]],[[12,[107]]]],[[[183,[[186,[115]]]]],[[12,[107]]]],[[[183,[[187,[115]]]]],[[12,[107]]]],[[179,179],8],[[181,181],8],[[124,124],8],[[184,184],8],[[44,179],[[12,[126]]]],[[179,9],10],[[148,9],10],[[148,9],10],[[181,9],10],[[[183,[[0,[111,182,111,104]]]],9],10],[[124,9],10],[[44,9],10],[[147,9],10],[[184,9],10],[188,179],[119,179],[[]],[189,148],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[179],[37,179],[[[183,[185]],37],179],[[[183,[[186,[115]]]],37],179],[[[183,[[187,[115]]]],37],179],[44,[[31,[179]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[182,111,104]],181],[[183,[[0,[182,111,104]]]]]],[[],44],[[179,179],[[12,[6]]]],[[124,124],[[12,[6]]]],[81],[[44,179,124],[[12,[[126,[125]]]]]],0,0,[[146,61,147,37],[[7,[148]]]],[[[183,[185]],146,61,147,37],[[7,[148]]]],[[[183,[[186,[115]]]],146,61,147,37],[[7,[148]]]],[[[183,[[187,[115]]]],146,61,147,37],[[7,[148]]]],[[146,147,37],[[7,[148]]]],[[146,147,37],[[7,[148]]]],0,[44,[[31,[126]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],73],0,0,[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[139,[190,141]]],[[139,[190,141]]]],[[139,11,160,61],[[7,[139,191]]]],[[139,11,160,61,13],[[7,[139,191]]]],[139,139],[[[139,[190,141]],41,40],[[139,[190,141]]]],[[139,11],139],[[139,11],[[7,[139,192]]]],[139,[[7,[139,192]]]],[[139,8],139],[[[139,[137,138]],41],[[7,[[139,[137,138]],193]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[139,194],139],[141,141],[138,138],[[[139,[104]]],[[139,[104]]]],[195,195],[194,194],[[]],[[]],[[]],[[]],[[]],[[195,195],6],[[194,194],6],[[139,190],[[139,[190]]]],[[139,27],139],[[],141],[[],138],[[],195],[[],194],[139,139],[[[139,[190,141]],41],[[139,[190,141]]]],[139,139],[139,139],[[139,13],139],[[195,195],8],[[194,194],8],[[139,40],139],[[139,121],139],[[[139,[190]]],[[7,[146,161]]]],[[141,9],10],[[138,9],10],[[[139,[111,111,111]],9],10],[[192,9],10],[[192,9],10],[[191,9],10],[[191,9],10],[[193,9],10],[[193,9],10],[[195,9],10],[[194,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[195],[194],[139,139],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[139,139],[[139,196],139],[139,139],[139,139],[[139,195],139],[[195,195],[[12,[6]]]],[[194,194],[[12,[6]]]],[[139,[72,[73,[31,[61]]]],1],139],[81],[81],[81],[[[139,[190,141]],31],[[139,[190,141]]]],[[139,159],139],[[195,142]],[[]],[[]],[[]],[[]],[[]],[[],73],[[],73],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[139,[31,[11]]],139],[[139,197],139],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0],"p":[[4,"KeychainKind"],[15,"u8"],[3,"LocalOutput"],[3,"WeightedUtxo"],[4,"Utxo"],[4,"Ordering"],[4,"Result"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"OutPoint"],[4,"Option"],[3,"Sequence"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[4,"Descriptor"],[4,"Network"],[4,"NetworkChecked"],[3,"Address"],[4,"Error"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"Tree"],[4,"DescriptorPublicKey"],[15,"u32"],[3,"DefiniteDescriptorKey"],[4,"ConversionError"],[3,"Global"],[3,"Vec"],[4,"Placeholder"],[3,"Satisfaction"],[4,"ScriptContextError"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"DescriptorType"],[15,"u64"],[3,"ScriptBuf"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[4,"Error"],[8,"ScriptContext"],[3,"Script"],[3,"Range"],[3,"Error"],[3,"Sh"],[3,"Bare"],[3,"Tr"],[3,"Wpkh"],[3,"Wsh"],[3,"Pkh"],[3,"Type"],[3,"ExtData"],[3,"Tree"],[15,"usize"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[4,"BareCtx"],[4,"TapTree"],[3,"Plan"],[3,"TxIn"],[4,"SigType"],[3,"BTreeMap"],[3,"String"],[4,"TranslateErr"],[4,"Error"],[4,"PolicyError"],[4,"HexToBytesError"],[4,"Error"],[4,"Error"],[4,"KeyError"],[3,"Demand"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[4,"Tap"],[3,"P2TR"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[3,"Bip86"],[3,"Bip86Public"],[6,"ValidNetworks"],[3,"SortedMultiVec"],[8,"Clone"],[3,"GeneratedKey"],[3,"PrivateKeyGenerateOptions"],[4,"DescriptorSecretKey"],[3,"SinglePub"],[3,"SinglePriv"],[4,"SinglePubKey"],[8,"Debug"],[4,"DescriptorKey"],[3,"Xpub"],[4,"ExtendedKey"],[3,"Xpriv"],[3,"DerivationPath"],[3,"Assets"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[3,"FeeRate"],[3,"Balance"],[3,"Wallet"],[3,"SignerOrdering"],[8,"TransactionSigner"],[3,"Arc"],[8,"Iterator"],[3,"ChangeSet"],[3,"Block"],[3,"CannotConnectError"],[3,"BlockId"],[4,"ApplyHeaderError"],[8,"IntoIterator"],[3,"Update"],[3,"TxGraph"],[3,"Txid"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[4,"BuildFeeBumpError"],[3,"CreateTx"],[3,"Transaction"],[4,"CalculateFeeError"],[3,"CheckPointIter"],[3,"AddressInfo"],[3,"Psbt"],[3,"SignOptions"],[4,"SignerError"],[4,"AddressIndex"],[4,"NewError"],[4,"LoadError"],[4,"NewOrLoadError"],[4,"InsertTxError"],[4,"ApplyBlockError"],[3,"ConfirmationTimeHeightAnchor"],[3,"ChangeSet"],[3,"ChangeSet"],[6,"ChangeSet"],[3,"PsbtSighashType"],[3,"Input"],[4,"CreateTxError"],[3,"CanonicalTx"],[3,"AlterCheckPointError"],[4,"ConfirmationTime"],[3,"CheckPoint"],[8,"IntoWalletDescriptor"],[3,"LocalChain"],[3,"BlockHash"],[3,"KeychainTxOutIndex"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[3,"CoinSelectionResult"],[4,"Error"],[4,"Excess"],[4,"MiniscriptPsbtError"],[4,"Error"],[3,"FullyNodedExport"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"PrivateKey"],[3,"DescriptorMultiXKey"],[3,"DescriptorXKey"],[3,"Hash"],[4,"Error"],[8,"CoinSelectionAlgorithm"],[4,"AddForeignUtxoError"],[4,"AddUtxoError"],[4,"AllowShrinkingError"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[4,"LockTime"],[15,"i32"],[13,"Foreign"],[8,"ExtractPolicy"],[13,"PsbtTimelocks"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[8,"DescriptorTemplate"],[8,"GeneratableKey"],[8,"ExtScriptContext"],[8,"GeneratableDefaultOptions"],[8,"PsbtUtils"],[8,"IsDust"],[13,"UnexpectedConnectedToHash"],[13,"ConfirmationHeightCannotBeGreaterThanTip"],[13,"LoadedGenesisDoesNotMatch"],[13,"LoadedNetworkDoesNotMatch"],[13,"InsufficientFunds"],[13,"Change"],[13,"NoChange"],[13,"InsufficientFunds"],[13,"RbfSequenceCsv"],[13,"LockTime"],[13,"FeeTooLow"],[13,"FeeRateTooLow"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"],[13,"InvalidTxid"]]},\ +"bdk":{"doc":"bdk","t":[13,13,2,13,4,13,3,2,2,4,2,3,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,12,12,0,14,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,12,12,0,11,12,11,0,12,11,11,11,2,2,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,12,5,11,11,11,11,0,12,12,12,13,6,4,2,4,6,8,6,8,16,4,3,13,13,2,8,4,13,13,6,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,10,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,5,5,13,13,4,13,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,13,13,4,13,3,6,13,13,6,13,13,13,13,13,13,13,13,13,13,13,4,3,4,13,13,13,13,13,4,4,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,3,3,8,6,3,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,16,16,8,4,13,8,8,3,8,13,13,13,16,4,6,13,13,13,13,13,16,13,3,13,8,4,13,13,13,3,3,4,3,13,6,13,13,13,5,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,10,11,11,12,12,11,11,11,11,11,11,10,12,11,11,11,11,11,10,11,5,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,8,10,10,10,4,3,4,3,13,3,13,13,13,13,4,8,13,13,13,4,13,13,13,13,13,4,4,13,13,13,13,13,3,3,13,13,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,0,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,12,11,12,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,5,12,12,12,12,12,12,12,12,13,13,3,13,8,3,6,4,4,13,3,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,5,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,4,13,13,13,4,13,13,13,13,13,13,13,13,4,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,3,6,12,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,13,13,13,13,13,13,13,8,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,4,3,3,3,13,4,8,13,11,12,12,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,10,11,11,11,10,11,12,11,12,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,4,4,4,13,3,13,13,4,3,13,13,13,13,13,13,3,8,4,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12],"n":["External","Foreign","HdKeyPaths","Internal","KeychainKind","Local","LocalOutput","SignOptions","TxBuilder","Utxo","Wallet","WeightedUtxo","as_byte","as_ref","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","confirmation_time","derivation_index","descriptor","descriptor","deserialize","deserialize","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fragment","from","from","from","from","hash","hash","into","into","into","into","is_spent","keychain","keys","outpoint","outpoint","partial_cmp","psbt","satisfaction_weight","sequence","serialize","serialize","signer","template","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","txout","txout","type_id","type_id","type_id","type_id","utxo","version","vzip","vzip","vzip","vzip","wallet","outpoint","psbt_input","sequence","Bare","DerivedDescriptor","Descriptor","DescriptorError","DescriptorPublicKey","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","Key","Legacy","Miniscript","MultiXPub","Pkh","Policy","ScriptContext","Segwitv0","Sh","Single","TapKeyOrigins","Tr","Wpkh","Wsh","XPub","address","as_enum","as_enum","as_inner","as_node","at_derivation_index","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","build_template","build_template_mall","calc_checksum","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_pk","check_pk","check_pk","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","contains_raw_pkh","derive","derived_descriptor","derived_descriptor","desc_type","deserialize","deserialize","dust_value","encode","eq","eq","eq","eq","error","explicit_script","ext","ext_check","extract_policy","extract_policy","extract_policy","find_derivation_index_for_spk","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from","from","from","from","from","from_ast","from_components_unchecked","from_str","from_str","from_str_ext","from_str_insane","from_tree","from_tree","get_nth_child","get_nth_pk","get_satisfaction","get_satisfaction_mall","has_mixed_timelocks","has_repeated_keys","has_wildcard","hash","hash","hash","hash","into","into","into","into","into_inner","into_single_descriptors","into_wallet_descriptor","into_wallet_descriptor","is_deriveable","is_multipath","is_non_malleable","iter","iter_pk","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","max_weight_to_satisfy","name_str","name_str","name_str","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_with_wpkh","new_sh_with_wsh","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_tr","new_wpkh","new_wsh","new_wsh_sortedmulti","node","other_top_level_checks","parse","parse_descriptor","parse_insane","parse_with_ext","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pk_len","pk_len","plan","plan_mall","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","sig_type","sig_type","sig_type","substitute_raw_pkh","template","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","within_resource_limits","calc_checksum","calc_checksum_bytes","Base58","Bip32","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","MultiPath","Pk","Policy","borrow","borrow_mut","fmt","fmt","from","from","from","from","from","from","from","from","into","provide","to_string","try_from","try_into","type_id","vzip","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","EcdsaSignature","Fingerprint","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","Pubkey","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","SchnorrSignature","Sha256Preimage","Thresh","XOnlyPubkey","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","contribution","csv","default","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","hash","hash","id","id","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","partial_cmp","provide","requires_path","satisfaction","serialize","serialize","serialize","serialize","serialize","timelock","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","current_height","input_max_height","psbt","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","Bip86","Bip86Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2TR","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","build","build","build","from","from","from","from","from","from","from","from","from","from","from","from","into","into","into","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","Entropy","Error","ExtScriptContext","ExtendedKey","FullKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","Key","KeyError","KeyMap","Legacy","Message","Miniscript","MultiXPrv","MultiXPub","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","Single","Single","SinglePriv","SinglePub","SinglePubKey","SortedMultiVec","Tap","ValidNetworks","XOnly","XPrv","XPub","any_network","as_enum","at_derivation_index","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_template","check_global_consensus_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_policy_validity","check_local_validity","check_pk","check_terminal_non_malleable","check_witness","clone","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","compressed","default","deref","derive","deserialize","encode","eq","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_public","from_secret","from_str","from_str","from_tree","full_derivation_path","full_derivation_paths","generate","generate_default","generate_with_entropy","generate_with_entropy_default","has_secret","has_wildcard","hash","hash","hash","hash","into","into","into","into","into","into","into","into","into","into","into","into","into_assets","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_single_keys","into_single_keys","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_multipath","is_multipath","is_segwit_v0","is_segwit_v0","is_taproot","is_taproot","is_uncompressed","is_x_only_key","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","name_str","new","num_der_paths","origin","origin","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","partial_cmp","pk_len","pks","provide","sanity_check","satisfy","script_size","serialize","sig_type","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_public","to_string","to_string","to_string","to_string","top_level_checks","top_level_type_check","translate_pk","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","PsbtUtils","fee_amount","fee_rate","get_utxo_for","AddressIndex","AddressInfo","ApplyBlockError","Balance","CannotConnect","ChangeSet","ConfirmationHeightCannotBeGreaterThanTip","Descriptor","Descriptor","Descriptor","InsertTxError","IsDust","LastUnused","Load","Load","LoadError","LoadedGenesisDoesNotMatch","LoadedNetworkDoesNotMatch","MissingGenesis","MissingNetwork","New","NewError","NewOrLoadError","NonEmptyDatabase","NotInitialized","NotInitialized","Peek","UnexpectedConnectedToHash","Update","Wallet","Write","Write","add","add_signer","address","all_unbounded_spk_iters","append","apply_block","apply_block_connected_to","apply_unconfirmed_txs","apply_update","as_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build_fee_bump","build_tx","calculate_fee","calculate_fee_rate","cancel_tx","chain","chain","checkpoints","clone","clone","clone","clone_into","clone_into","clone_into","coin_selection","commit","confirmed","default","default","default","deref","derivation_index","derivation_of_spk","descriptor_checksum","deserialize","deserialize","eq","eq","eq","error","export","finalize_psbt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_internal_address","get_psbt_input","get_signers","get_tx","get_utxo","graph","immature","index","indexed_tx_graph","insert_checkpoint","insert_tx","insert_txout","into","into","into","into","into","into","into","into","into","into","into","is_dust","is_empty","is_mine","keychain","keychains","last_active_indices","latest_checkpoint","list_output","list_unspent","load","local_chain","network","network","new","new_no_persist","new_no_persist_with_genesis_hash","new_or_load","new_or_load_with_genesis_hash","new_with_genesis_hash","next_derivation_index","policies","provide","provide","provide","provide","provide","public_descriptor","secp_ctx","sent_and_received","serialize","serialize","sign","signer","spk_index","staged","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","to_string","to_string","to_string","total","transactions","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_get_address","try_get_internal_address","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","tx_builder","tx_graph","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unbounded_spk_iter","untrusted_pending","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet_name_from_descriptor","connected_to_hash","expected_hash","tip_height","tx_height","expected","expected","got","got","BnBNoExactMatch","BnBTotalTriesExceeded","BranchAndBoundCoinSelection","Change","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","Error","Excess","InsufficientFunds","LargestFirstCoinSelection","NoChange","OldestFirstCoinSelection","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","coin_select","coin_select","coin_select","coin_select","decide_change","default","default","default","excess","fee_amount","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","into","into","into","into","into","into","local_selected_amount","new","provide","selected","selected_amount","to_owned","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","available","needed","amount","change_fee","dust_threshold","fee","remaining_amount","BuildFeeBumpError","ChangePolicyDescriptor","CoinSelection","Conversion","CreateTxError","Descriptor","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","InsufficientFunds","IrreplaceableTransaction","LockTime","MiniscriptPsbt","MiniscriptPsbtError","MissingKeyOrigin","MissingNonWitnessUtxo","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","OutputUpdate","Persist","Policy","Psbt","RbfSequence","RbfSequenceCsv","SpendingPolicyRequired","TransactionConfirmed","TransactionNotFound","UnknownUtxo","UnknownUtxo","UtxoUpdate","Version0","Version1Csv","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","into","into","into","provide","provide","provide","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","available","csv","needed","rbf","requested","required","required","required","FullyNodedExport","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","descriptor","deserialize","export_wallet","fmt","from","from_str","into","label","serialize","to_string","try_from","try_into","type_id","vzip","All","Dummy","Exclude","External","Fingerprint","Include","InputIndexOutOfRange","InputSigner","InvalidKey","InvalidNonWitnessUtxo","InvalidSighash","Legacy","MiniscriptPsbt","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","None","PkHash","Segwitv0","SighashError","SignOptions","SignerCommon","SignerContext","SignerError","SignerId","SignerOrdering","SignerWrapper","SignersContainer","Tap","TapLeavesOptions","TransactionSigner","UserCanceled","add_external","allow_all_sighashes","allow_grinding","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","default","deref","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","descriptor_secret_key","eq","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","hash","id","id","id","id","ids","into","into","into","into","into","into","into","into","new","new","partial_cmp","partial_cmp","provide","remove","remove_partial_sigs","remove_taproot_extras","sign_input","sign_input","sign_input","sign_input","sign_transaction","sign_transaction","sign_with_tap_internal_key","signers","tap_leaves_options","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_finalize","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","is_internal_key","AddForeignUtxoError","AddUtxoError","AllowShrinkingError","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","InvalidOutpoint","InvalidTxid","MissingScriptPubKey","MissingUtxo","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","UnknownUtxo","Untouched","add_data","add_foreign_utxo","add_foreign_utxo_with_sequence","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_dust","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","current_height","default","default","default","default","do_not_spend_change","drain_to","drain_wallet","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","hash","hash","include_output_redeem_witness_script","into","into","into","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","provide","provide","provide","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","foreign_utxo","input_txid"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Utxo","","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::checksum","","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::psbt","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::ApplyBlockError","","bdk::wallet::InsertTxError","","bdk::wallet::NewOrLoadError","","","","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::coin_selection::Error","","bdk::wallet::coin_selection::Excess","","","","","bdk::wallet::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::error::CreateTxError","","","","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerContext","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::tx_builder::AddForeignUtxoError",""],"d":["External keychain, used for deriving recipient addresses.","A UTXO owned by another wallet.","","Internal keychain, used for deriving change addresses.","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","","","An unspent transaction output (UTXO).","","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","","","","","","","","","","","","","","","","","","The confirmation time for transaction containing this utxo","The derivation index for the script pubkey in the wallet","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","Macro to write descriptor fragments with code","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Whether this UTXO is spent or not","Type of keychain","Key formats","Get the location of the UTXO","Reference to a transaction output","","Additional functions on the rust-bitcoin Psbt structure.","The weight of the witness data and scriptSig expressed in …","Get the sequence number if an explicit sequence number has …","","","","","","","","","","","","","","","","","Get the TxOut of the UTXO","Transaction output","","","","","The UTXO","Get the version of BDK at runtime","","","","","Wallet","The location of the output.","The information about the input we require to add it to a …","The nSequence value to set for this input.","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Script descriptor","","The descriptor pubkey, either a single pubkey or an xpub.","Alias for a Descriptor that can contain extended keys …","Trait implemented on Descriptors to add a method to …","Alias for the type of maps that represent derivation paths …","Trait for types which can be converted into an …","The consensus key associated with the type. Must be a …","Legacy ScriptContext To be used as P2SH scripts For …","The top-level miniscript abstract syntax tree (AST).","Multiple extended public keys.","Pay-to-PubKey-Hash","","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Single public key.","Alias for the type of maps that represent taproot key …","Pay-to-Taproot","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Extended public key (xpub).","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","","Replaces all wildcards (i.e. /*) in the descriptor with a …","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","Attempt to produce a non-malleable witness template given …","Attempt to produce a malleable witness template given the …","","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Each context has slightly different rules on what Pks are …","","","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","Whether the given miniscript contains a raw pkh fragment","Deprecated name for Self::at_derivation_index.","Convert all the public keys in the descriptor to …","Convert all the public keys in the descriptor to …","Get the DescriptorType of Descriptor","","","","Encode as a Bitcoin script","","","","","Descriptor errors","Computes the the underlying script before any hashing is …","Additional information helpful for extra analysis.","Check whether the miniscript follows the given Extra …","Extract the spending policy","","","Utility method for deriving the descriptor at each index …","","","","","","","","","","Returns the argument unchanged.","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Add type information(Type and Extdata) to Miniscript based …","Create a new Miniscript from a Terminal node and a Type …","","Parse a Miniscript from string and perform sanity checks …","Attempt to parse an Miniscripts that don’t follow the …","Attempt to parse an insane(scripts don’t clear sanity …","Parse an expression tree into a descriptor.","Parse an expression tree into a Miniscript. As a general …","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns satisfying non-malleable witness and scriptSig to …","Returns a possilbly mallable satisfying non-malleable …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","Whether or not the descriptor has any wildcards i.e. /*.","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Extracts the AstElem representing the root of the …","Get as many descriptors as different paths in this …","Convert to wallet descriptor","","Whether or not the descriptor has any wildcards","Whether this descriptor contains a key that has multiple …","Whether the miniscript is malleable","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","","","Lifting corresponds to conversion of a miniscript into a …","Depending on script context, the size of a satifaction …","","","Maximum size, in bytes, of a satisfying witness. For …","Computes an upper bound on the weight of a satisfying …","Maximum number of witness elements used to satisfy the …","Computes an upper bound on the difference between a …","Local helper function to display error messages with …","","","Create a new bare descriptor from witness script Errors …","Create a new pk descriptor","Create a new PkH descriptor","Create a new sh for a given redeem script Errors when …","Create a new sh sortedmulti descriptor with threshold k …","Create a new sh wrapper for the given wpkh descriptor","Create a new sh wrapper for the given wsh descriptor","Create a new sh wrapped wpkh from Pk. Errors when …","Create a new sh wrapped wsh descriptor with witness script …","Create a new sh wrapped wsh sortedmulti descriptor from …","Create new tr descriptor Errors when miniscript exceeds …","Create a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the AST.","Other top level checks that are context specific","Attempt to parse a Script into Miniscript representation.","Parse a descriptor that may contain secret keys","Attempt to parse an insane(scripts don’t clear sanity …","Attempt to parse an miniscript with extra features that …","","","","","Get the len of public key when serialized based on context …","","","Returns a plan if the provided assets are sufficient to …","Returns a plan if the provided assets are sufficient to …","Descriptor policy","Whether all spend paths of miniscript require a signature","Checks whether the descriptor is safe.","Check whether the underlying Miniscript is safe under the …","Attempts to produce a non-malleable satisfying witness and …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Computes the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor.","Size, in bytes of the script-pubkey. If this Miniscript is …","","","The type of signature required for satisfaction","","","Substitutes raw public keys hashes with the public keys as …","Descriptor templates","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Converts a descriptor using abstract keys to one using …","Translates a struct from one generic to another where the …","","","","","","","","","The correctness and malleability type information for the …","","","","","Computes the scriptSig that will be in place for an …","","","","","Whether the miniscript can exceed the resource …","Compute the checksum of a descriptor, excludes any …","Compute the checksum bytes of a descriptor, excludes any …","Error during base58 decoding","BIP32 error","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid byte found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","The descriptor contains multipath keys","Key-related error","Error while extracting and manipulating policies","","","","","","","Returns the argument unchanged.","","","","","","Calls U::from(self).","","","","","","","Absolute timeclock timestamp","Can not add to an item that is Satisfaction::None or …","Can not add to an item that is …","Options to build the satisfaction field in the policy","Can satisfy the policy item","An extra condition that must be satisfied but that is out …","Type for a map of sets of Condition items keyed by each set…","ECDSA Signature for a raw public key","An extended key fingerprint","Type for a map of folded sets of Condition items keyed by …","SHA256 then RIPEMD160 preimage hash","Double SHA256 preimage hash","Incompatible conditions (not currently used)","Index out of range for an item to satisfy a …","Can not merge CSV or timelock values unless both are less …","Multi-signature public keys with threshold count","Cannot satisfy or contribute to the policy item","Don’t generate satisfaction field","Not enough items are selected to satisfy a …","Only a partial satisfaction of some kind of threshold …","Can reach the threshold of some kind of threshold policy","A unique identifier for a key","Descriptor spending policy","Errors that can happen while extracting and manipulating …","Analyze the given PSBT to check for existing signatures","Like Psbt variant and also check for expired timelocks","A legacy public key","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","Schnorr Signature for a raw public key","SHA256 preimage hash","Threshold items with threshold count","A x-only public key","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Return the conditions that are set by the spending policy …","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the SatisfiableItem is a leaf item","Returns whether the Satisfaction is a leaf item","Returns true if there are no extra conditions to verify","Type of this policy node","","","Return whether or not a specific path in the policy tree …","How much a given PSBT already satisfies this policy node …","","","","","","Optional timelock condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Current blockchain height","The highest confirmation height between the inputs CSV …","Given PSBT","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","Extra conditions that also need to be satisfied","The items that can be satisfied by the descriptor or are …","The items that can be satisfied by the descriptor","Threshold","Threshold","Total number of items","Total number of items","Whether the items are sorted in lexicographic order (used …","Whether the items are sorted in lexicographic order (used …","The digest value","The digest value","The digest value","The digest value","The policy items","The raw public key or extended key fingerprint","The required threshold count","The required threshold count","The timelock value","The timelock value","BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to …","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","BIP86 template. Expands to tr(key/86'/{0,1}'/0'/{0,1}/*)","BIP86 public template. Expands to tr(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2TR template. Expands to a descriptor tr(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The descriptor pubkey, either a single pubkey or an xpub.","The descriptor secret key, either a single private key or …","Type specifying the amount of entropy required e.g. [u8;32]","Returned error in case of failure","Trait that adds extra useful methods to ScriptContexts","Enum for extended keys that can be either xprv or xpub","A bitcoin public key (compressed or uncompressed).","Trait that allows generating a key with the default options","Trait for keys that can be generated","Output of a GeneratableKey key generation","Trait for objects that can be turned into a public or …","The key has an invalid checksum","The key is not valid for the given network","The key cannot exist in the given script context","The consensus key associated with the type. Must be a …","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Multiple extended private keys.","Multiple extended public keys.","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single public key.","Single private key.","A descriptor bitcoin::PrivateKey with optional origin …","A descriptor SinglePubKey with optional origin information.","Single public key without any origin or range information.","Contents of a “sortedmulti” descriptor","Taproot scripts","Set of valid networks for a key","An xonly public key.","Extended private key (xpriv).","Extended public key (xpub).","Create a set containing mainnet, testnet, signet, and …","Returns the ScriptContext as a ScriptContextEnum","Replaces any wildcard (i.e. /*) in the key with a …","","","","","","","","","","","","","","","","","","","","","","","","","Attempt to produce a witness template given the assets …","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Policy rules at the Miniscript satisfaction time. It is …","Check the consensus + policy(if not disabled) rules …","Each context has slightly different rules on what Pks are …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","Deprecated name for Self::at_derivation_index.","","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Returns a vector containing the full derivation paths from …","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","Return whether or not the key contains the private data","Whether or not the key has a wildcard","","","","","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Get as many keys as derivation paths in this key.","Get as many keys as derivation paths in this key.","Transform the ExtendedKey into an Xpriv for the given …","Transform the ExtendedKey into an Xpub for the given …","Whether or not the key has a wildcard","Returns whether the script context is Legacy","Returns whether the script context is …","Whether or not this key has multiple derivation paths.","Whether or not this key has multiple derivation paths.","Returns whether the script context is Segwitv0","Returns whether the script context is …","Returns whether the script context is Tap, aka Taproot or …","Returns whether the script context is …","","","signatures required","The public key.","The private key.","","Create a set only containing mainnet","The fingerprint of the master key associated with this …","Depending on script context, the size of a satifaction …","Maximum size, in bytes, of a satisfying witness. In …","Maximum number of witness elements used to satisfy the …","Compute the intersection of two sets","Local helper function to display error messages with …","Create a new instance of SortedMultiVec given a list of …","","Origin information (fingerprint and derivation path).","Origin information (fingerprint and derivation path).","Other top level checks that are context specific","Override the computed set of valid networks","","","","","Get the len of public key when serialized based on context …","public keys inside sorted Multi","","utility function to sanity a sorted multi vec","Attempt to produce a satisfying witness for the witness …","Size, in bytes of the script-pubkey. If this Miniscript is …","","The type of signature required for satisfaction","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","","","Returns the public version of this key.","","","","","Check top level consensus rules.","Check whether the top-level is type B","This will panic if fpk returns an uncompressed key when …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Trait to add functions to extract utxos and calculate fees.","The total transaction fee amount, sum of input amounts …","The transaction’s fee rate. This value will only be …","Get the TxOut for the specified input index, if it doesn’…","The address index selection strategy to use to derived an …","A derived address and the index it was found at. For …","An error that may occur when applying a block to Wallet.","Balance, differentiated into various categories.","Occurs when the update chain cannot connect with original …","The changes made to a wallet by applying an Update.","The error variant that occurs when the caller attempts to …","There was problem with the passed-in descriptor(s).","There was a problem with the passed-in descriptor(s).","There is a problem with the passed-in descriptor.","An error that may occur when inserting a transaction into …","Trait to check if a value is below the dust limit. We are …","Return the address for the current descriptor index if it …","Loading data from the persistence backend failed.","Loading from the persistence backend failed.","The error type when loading a Wallet from persistence.","The loaded genesis hash does not match what was provided.","The loaded network type does not match what was provided.","Data loaded from persistence is missing genesis hash.","Data loaded from persistence is missing network type.","Return a new address after incrementing the current …","The error type when constructing a fresh Wallet.","Error type for when we try load a Wallet from persistence …","Database already has data.","Wallet not initialized, persistence backend is empty.","Wallet is not initialized, persistence backend is empty.","Return the address for a specific descriptor index. Does …","Occurs when the connected_to hash does not match the hash …","An update to Wallet.","A Bitcoin wallet","We were unable to write the wallet’s data to the …","Writing to the persistence backend failed.","","Add an external signer","Address","Get unbounded script pubkey iterators for both Internal …","","Introduces a block of height to the wallet, and tries to …","Applies relevant transactions from block of height to the …","Apply relevant unconfirmed transactions to the wallet.","Applies an update to the wallet and stages the changes …","","","","","","","","","","","","","","","","","","","","","","","","Bump the fee of a transaction previously created with this …","Start building a transaction.","Calculates the fee of a given transaction. Returns 0 if tx …","Calculate the FeeRate for a given transaction.","Informs the wallet that you no longer intend to broadcast …","Update for the wallet’s internal LocalChain.","Changes to the LocalChain.","Get all the checkpoints the wallet is currently storing …","","","","","","","Coin selection","Commits all currently staged changed to the persistence …","Confirmed and immediately spendable balance","","","","","The derivation index of this wallet. It will return None …","Finds how the wallet derived the script pubkey spk.","Return the checksum of the public descriptor associated to …","","","","","","Errors that can be thrown by the Wallet","Wallet export","Finalize a PSBT, i.e., for each input determine if …","","","","","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Infallibly return a derived address using the external …","Return the balance, separated into available, …","Returns the descriptor used to create addresses for a …","Infallibly return a derived address using the internal …","get the corresponding PSBT Input for a LocalUtxo","Get the signers","Get a single transaction from the wallet as a CanonicalTx …","Returns the utxo owned by this wallet corresponding to …","Update for the wallet’s internal TxGraph.","All coinbase outputs not yet matured","Child index of this address","Changes to IndexedTxGraph.","Add a new checkpoint to the wallet’s internal view of …","Add a transaction to the wallet’s internal view of the …","Inserts a TxOut at OutPoint into the wallet’s …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Check whether or not a value is below dust limit","","Return whether or not a script is part of this wallet …","Type of keychain","Iterator over all keychains in this wallet","Contains the last active derivation indices per keychain (K…","Returns the latest checkpoint.","List all relevant outputs (includes both spent and …","Return the list of unspent outputs of this wallet","Load Wallet from the given persistence backend.","Get a reference to the inner LocalChain.","Get the Bitcoin network the wallet is using.","Stores the network type of the wallet.","Initialize an empty Wallet.","Creates a wallet that does not persist data.","Creates a wallet that does not persist data, with a custom …","Either loads Wallet from persistence, or initializes it if …","Either loads Wallet from persistence, or initializes it if …","Initialize an empty Wallet with a custom genesis hash.","The index of the next address that you would get if you …","Return the spending policies for the wallet’s descriptor","","","","","","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","Compute the tx’s sent and received amounts (in satoshis).","","","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Get a reference to the inner KeychainTxOutIndex.","Returns the changes that will be committed with the next …","","","","","","","","","","","Get the whole balance visible to the wallet.","Iterate over the transactions in the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","","","","","","Return a derived address using the external descriptor, …","Return a derived address using the internal (change) …","","","","","","","","","","","","Transaction builder","Get a reference to the inner TxGraph.","","","","","","","","","","","","Get an unbounded script pubkey iterator for the given …","Unconfirmed UTXOs received from an external wallet","","","","","","","","","","","","Deterministically generate a unique name given the …","Block hash of connected_to.","Expected block hash of connected_to, as derived from block.","The internal chain’s tip height.","The introduced transaction’s confirmation height.","The expected genesis block hash.","The expected network type.","The block hash loaded from persistence.","The network type loaded from persistence.","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Branch and bound coin selection","It’s possible to create spendable output from excess …","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Errors that can be thrown by the coin_selection module","Remaining amount after performing coin selection","Wallet’s UTXO set is not enough to cover recipient’s …","Simple and dumb coin selection","It’s not possible to create spendable output from excess …","OldestFirstCoinSelection always picks the utxo with the …","","","","","","","","","","","","","","","","","","","Perform the coin selection","","","","Decide if change can be created","","","","Remaining amount after deducing fees and outgoing outputs","Total fee amount for the selected utxos in satoshis","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","The total value of the inputs selected from the local …","Create new instance with target size for change output","","List of outputs selected for use as inputs","The total value of the inputs selected.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","Sats needed for some transaction","Effective amount available to create change after …","The calculated fee for the drain TxOut with the selected …","Threshold to consider amount as dust for this particular …","The deducted change output fee","Exceeding amount of current selection over outgoing value …","Error returned from Wallet::build_fee_bump","The change_policy was set but the wallet does not have a …","There was an error with coin selection","Descriptor key conversion error","Error returned from TxBuilder::finish","There was a problem with the descriptors passed in","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","Wallet’s UTXO set is not enough to cover recipient’s …","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Requested LockTime is less than is required to spend from …","Miniscript PSBT error","Errors returned by miniscript when updating inconsistent …","In order to use the TxBuilder::add_global_xpubs option …","Missing non_witness_utxo on foreign utxo for given OutPoint","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Return error type for …","We were unable to write wallet data to the persistence …","There was a problem while extracting and manipulating …","Partially signed bitcoin transaction error","Cannot enable RBF with a Sequence >= 0xFFFFFFFE","Cannot enable RBF with Sequence given a required OP_CSV","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","Happens when trying to spend an UTXO that is not in the …","Return error type for PsbtExt::update_input_with_descriptor","Requested invalid transaction version ‘0’","Requested transaction version 1, but at least 2 is needed …","","","","","","","","","","","","","","","Returns the argument unchanged.","","","","Returns the argument unchanged.","","","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","","","","","","","","","","","","","","","","","","Sats available for spending","Required OP_CSV Sequence","Sats needed for some transaction","Given RBF Sequence","Requested LockTime","Required LockTime","Required fee absolute value (satoshi)","Required fee rate","Structure that contains the export of a wallet","Alias for FullyNodedExport","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","Return the external descriptor","","Export a wallet","","Returns the argument unchanged.","","Calls U::from(self).","Arbitrary label for the wallet","","","","","","","The signer will sign all the leaves it has a key for.","Dummy identifier","The signer won’t sign the specified leaves.","To be used only by external libraries implementing …","The fingerprint of a BIP32 extended key","The signer won’t sign leaves other than the ones …","Input index is out of range","PSBT Input signer","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","Invalid SIGHASH for the signing context in use","Legacy context","Miniscript PSBT error","The fingerprint and derivation path are missing from the …","The private key is missing for the required public key","The non_witness_utxo field of the transaction is required …","The witness_script field of the transaction is required to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","The signer won’t sign any leaf.","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Segwit v0 context (BIP 143)","Error while computing the hash to sign","Options for a software signer","Common signer methods","Signing context","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Wrapper to pair a signer with its context","Container for multiple signers","Taproot context (BIP 340)","Customize which taproot script-path leaves the signer …","PSBT signer","The user canceled the operation","Adds an external signer to the container for the specified …","Whether the signer should use the sighash_type set in the …","Whether we should grind ECDSA signature to ensure signing …","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","Build a new signer container from a KeyMap","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Return the SignerId for this signer","","","","Returns the list of identifiers of all the signers in the …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Create a wrapped signer from a signer and a context","Default constructor","","","","Removes a signer from the container and returns it","Whether to remove partial signatures from the PSBT inputs …","Whether to remove taproot specific fields from the PSBT on …","Sign a single psbt input","","","","Sign all the inputs of the psbt","","Whether we should try to sign a taproot transaction with …","Returns the list of signers in the container, sorted by …","Specifies which Taproot script-spend leaves we should sign …","","","","","","","","","Whether the signer should trust the witness_utxo, if the …","Whether to try finalizing the PSBT after the inputs are …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Whether the signer can sign for the internal key or not","Error returned from TxBuilder::add_foreign_utxo.","Error returned from TxBuilder::add_utxo and …","Error returned from TxBuilder::allow_shrinking","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Requested outpoint doesn’t exist in the tx (vout greater …","Foreign utxo outpoint txid does not match PSBT input txid","Script/PubKey was not in the original transaction","Foreign utxo missing witness_utxo or non_witness_utxo","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Happens when trying to spend an UTXO that is not in the …","Unchanged","Add data as an output, using OP_RETURN","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Same as add_foreign_utxo but allows to set the nSequence …","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Set whether or not the dust limit is checked.","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","Set the current blockchain height.","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee The fee_absolute method refers to the …","Set a custom fee rate.","Finish building the transaction.","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Fill-in the psbt::Output::redeem_script and …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","","","","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","","","","","","Foreign UTXO outpoint","PSBT input txid"],"i":[1,5,0,1,0,5,0,0,0,0,0,0,1,1,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,4,5,1,3,3,0,0,1,3,1,3,4,5,1,3,4,5,0,1,3,4,5,1,3,1,3,4,5,3,3,0,5,3,1,0,4,5,1,3,0,0,1,3,4,5,1,3,4,5,1,3,4,5,5,3,1,3,4,5,4,0,1,3,4,5,0,198,198,198,17,0,0,0,0,0,0,0,0,48,0,0,26,17,0,0,0,17,26,0,17,17,17,26,17,35,36,23,23,17,17,35,36,23,17,35,36,23,23,23,23,0,48,35,36,48,36,48,48,35,36,48,35,36,48,48,35,36,48,35,36,48,35,36,0,17,35,36,23,17,35,36,23,17,35,36,23,23,17,17,17,17,17,23,17,23,17,35,36,23,0,17,23,23,199,17,23,17,17,17,35,36,23,23,17,23,17,17,17,17,17,17,17,35,36,23,23,23,17,23,23,23,17,23,23,23,17,17,23,23,17,17,35,36,23,17,35,36,23,23,17,166,62,17,17,23,23,23,17,23,23,48,35,36,23,17,23,17,48,35,36,17,17,17,17,17,17,17,17,17,17,17,17,17,17,23,48,23,17,23,23,17,35,36,23,48,35,36,17,17,0,23,17,23,17,23,23,17,17,23,17,23,48,35,36,23,0,17,35,36,23,17,23,17,48,48,17,23,17,35,36,23,17,35,36,23,23,17,35,36,23,17,17,35,36,23,23,0,0,47,47,0,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,83,77,77,0,84,0,0,83,82,0,83,83,77,77,77,83,84,45,77,84,84,0,0,0,45,45,82,83,83,0,0,83,83,83,82,82,83,84,46,85,77,45,82,83,84,46,85,77,45,82,83,84,46,85,45,82,83,84,46,85,45,46,85,85,82,83,84,46,85,77,82,83,84,46,85,77,77,45,82,83,84,84,46,46,85,77,45,46,82,85,83,46,82,83,84,46,85,77,45,83,84,85,46,85,77,46,46,82,83,84,46,85,85,82,83,84,46,85,45,77,82,83,84,46,85,77,45,82,83,84,46,85,77,45,82,83,84,46,85,77,45,82,83,84,46,85,77,45,200,200,200,201,202,203,202,203,202,203,202,203,202,203,204,205,206,207,208,209,209,208,210,211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,212,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,86,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,88,89,90,92,94,95,96,97,98,99,100,101,75,0,0,0,0,213,213,0,0,110,0,0,0,0,75,75,75,48,0,0,22,75,75,107,26,213,114,0,114,0,0,22,26,107,0,0,0,0,22,0,110,107,26,0,214,26,114,105,112,22,106,75,103,26,107,108,109,110,114,105,112,22,106,75,103,26,107,108,109,110,103,48,48,48,48,48,48,48,48,48,105,22,106,103,26,107,108,109,110,105,22,106,103,26,107,108,109,110,103,26,108,110,106,106,105,26,26,103,22,103,26,107,108,109,110,112,22,106,75,75,103,103,26,26,107,107,108,109,110,103,114,114,114,105,112,22,106,75,75,75,103,26,26,107,108,109,110,112,112,26,107,103,26,26,213,215,213,215,114,26,103,26,108,110,114,105,112,22,106,75,103,26,107,108,109,110,26,87,93,105,105,112,26,107,93,114,105,105,26,107,114,114,26,214,22,26,107,214,22,214,22,26,26,103,108,109,103,0,26,48,103,103,0,48,103,26,108,109,48,112,103,26,108,110,48,103,75,103,103,103,26,48,103,0,105,22,106,103,26,107,108,109,110,107,75,103,26,107,48,48,103,114,105,112,22,106,75,103,26,107,108,109,110,114,105,112,22,106,75,103,26,107,108,109,110,114,105,112,22,106,75,103,26,107,108,109,110,114,105,112,22,106,75,103,26,107,108,109,110,0,216,216,216,0,0,0,0,154,0,153,150,151,152,0,0,149,151,152,0,152,152,151,151,149,0,0,150,151,152,149,154,0,0,150,152,122,123,145,123,128,123,123,123,123,123,122,123,134,128,149,145,150,151,152,153,154,122,123,134,128,149,145,150,151,152,153,154,123,123,123,123,123,134,128,123,122,134,128,122,134,128,0,123,122,122,134,128,145,123,123,123,122,128,122,128,145,0,0,123,122,122,123,134,128,149,145,145,150,150,151,151,152,152,153,153,154,154,122,123,134,128,128,128,149,145,150,151,152,153,154,123,123,123,123,123,123,123,123,134,122,145,128,123,123,123,122,123,134,128,149,145,150,151,152,153,154,217,128,123,145,123,134,123,123,123,123,123,123,128,123,123,123,123,123,123,123,123,150,151,152,153,154,123,123,123,122,128,123,0,123,123,122,134,128,122,145,150,151,152,153,154,122,123,122,122,122,123,134,128,149,145,150,151,152,153,154,123,123,122,123,134,128,149,145,150,151,152,153,154,0,123,122,123,134,128,149,145,150,151,152,153,154,123,122,122,123,134,128,149,145,150,151,152,153,154,0,218,218,219,219,220,221,220,221,174,174,0,175,0,0,0,0,0,174,0,175,0,174,175,173,170,171,172,174,175,173,170,171,172,170,171,172,170,171,172,190,170,171,172,0,170,171,172,173,173,174,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,173,172,174,173,173,170,171,172,174,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,174,175,173,170,171,172,222,222,223,224,224,223,224,0,161,161,176,0,161,161,140,161,161,140,161,161,0,161,161,161,161,161,176,161,161,161,161,161,161,140,140,161,140,176,161,161,176,161,140,176,161,140,176,176,176,176,161,161,140,140,176,161,161,161,161,161,161,140,176,161,140,176,161,140,176,176,161,140,176,161,140,176,161,140,176,161,140,176,161,140,225,226,225,226,227,227,228,229,0,0,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,178,184,179,184,148,179,184,148,0,148,148,148,181,148,148,148,148,148,148,148,184,179,181,148,0,0,0,0,0,0,0,0,181,0,0,148,44,147,147,44,147,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,44,179,181,183,124,44,147,184,179,181,183,124,44,147,184,179,124,124,44,147,184,183,230,183,183,183,179,181,124,184,44,179,148,148,181,183,124,44,147,184,179,179,179,148,148,181,183,124,44,147,184,179,230,183,183,183,44,179,148,181,183,124,44,147,184,183,44,179,124,148,44,147,147,231,183,183,183,125,183,147,44,147,179,181,183,124,44,147,184,148,147,147,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,179,148,181,183,124,44,147,184,232,0,0,0,195,0,194,194,0,0,191,191,193,191,194,195,0,0,0,192,195,139,139,139,139,139,139,139,139,139,139,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,139,141,138,139,195,194,141,138,139,195,194,195,194,139,139,141,138,195,194,139,139,139,139,139,195,194,139,139,139,141,138,139,192,192,191,191,193,193,195,194,141,138,139,192,191,193,195,194,195,194,139,141,138,139,192,191,193,195,194,139,139,139,139,139,195,194,139,192,191,193,139,139,195,141,138,139,195,194,192,191,193,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,141,138,139,192,191,193,195,194,139,139,141,138,139,192,191,193,195,194,233,233],"f":[0,0,0,0,0,0,0,0,0,0,0,0,[1,2],[1],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[1,1],[3,3],[4,4],[5,5],[[]],[[]],[[]],[[]],[[1,1],6],0,0,0,0,[[],[[7,[1]]]],[[],[[7,[3]]]],[[1,1],8],[[3,3],8],[[4,4],8],[[5,5],8],[[1,9],10],[[3,9],10],[[4,9],10],[[5,9],10],0,[[]],[[]],[[]],[[]],[1],[3],[[]],[[]],[[]],[[]],0,0,0,[5,11],0,[[1,1],[[12,[6]]]],0,0,[5,[[12,[13]]]],[1,7],[3,7],0,0,[[]],[[]],[[]],[[]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[5,14],0,[[],15],[[],15],[[],15],[[],15],0,[[],16],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[17,18],[[7,[[20,[19]],21]]]],[[],22],[[],22],[23,24],[23,[[25,[23]]]],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[23,[[31,[23,30]]]],[23,[[33,[32]]]],[23,[[33,[32]]]],0,[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],[[],[[7,[34]]]],0,[17,17],[35,35],[36,36],[23,23],[[]],[[]],[[]],[[]],[[17,17],6],[[35,35],6],[[36,36],6],[[23,23],6],[23,8],[[[17,[26]],27],[[7,[[17,[28]],29]]]],[[[17,[26]],37,27],[[7,[[17,[38]],29]]]],[[[17,[28]],37],[[7,[[17,[38]],29]]]],[17,39],[[],[[7,[17]]]],[[],[[7,[23]]]],[[[17,[26]]],40],[23,41],[[17,17],8],[[35,35],8],[[36,36],8],[[23,23],8],0,[17,[[7,[41,21]]]],0,[[23,42],[[7,[43]]]],[[44,45,37],[[7,[[12,[46]],47]]]],[[[17,[26]],44,45,37],[[7,[[12,[46]],47]]]],[[[23,[26,48]],44,45,37],[[7,[[12,[46]],47]]]],[[[17,[26]],37,49,[50,[27]]],[[7,[12,29]]]],[[17,9],[[7,[51]]]],[[17,9],[[7,[51]]]],[[35,9],[[7,[51]]]],[[36,9],[[7,[51]]]],[[23,9],[[7,[51]]]],[[23,9],[[7,[51]]]],[17,8],[23,8],[52,17],[[]],[53,17],[54,17],[55,17],[56,17],[57,17],[[]],[[]],[[]],[24,[[7,[23,21]]]],[[24,58,59],23],[16,[[7,[17,21]]]],[16,[[7,[23,21]]]],[[16,42],[[7,[23,21]]]],[16,[[7,[23,21]]]],[60,[[7,[17,21]]]],[60,[[7,[23,21]]]],[[23,61],[[12,[23]]]],[[23,61],12],[17,[[7,[21]]]],[17,[[7,[21]]]],[23,8],[23,8],[[[17,[26]]],8],[17],[35],[36],[23],[[]],[[]],[[]],[[]],[23,24],[[[17,[26]]],[[7,[[31,[[17,[26]],30]],21]]]],[[37,18],[[7,[47]]]],[[62,37,18],[[7,[47]]]],[[[17,[26]]],8],[[[17,[26]]],8],[23,8],[23,63],[23,64],[17,[[7,[65,21]]]],[23,[[7,[65,21]]]],[23,[[7,[66]]]],[23,[[12,[61]]]],[23,[[12,[61]]]],[23,[[12,[61]]]],[23,[[7,[61,21]]]],[17,[[7,[61,21]]]],[23,[[7,[61,21]]]],[17,[[7,[61,21]]]],[[],16],[[],16],[[],16],[[[23,[67]]],[[7,[17,21]]]],[[],17],[[],[[7,[17,21]]]],[[[23,[35]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],[55,17],[57,17],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],[[[12,[68]]],[[7,[17,21]]]],[[],[[7,[17,21]]]],[[[23,[36]]],[[7,[17,21]]]],[[61,[31,[30]]],[[7,[17,21]]]],0,[23,[[7,[21]]]],[49,[[7,[23,21]]]],[[37,16],[[7,[21]]]],[49,[[7,[23,21]]]],[[49,42],[[7,[23,21]]]],[[17,17],[[12,[6]]]],[[35,35],[[12,[6]]]],[[36,36],[[12,[6]]]],[[23,23],[[12,[6]]]],[[],61],[[],61],[[],61],[[[17,[28]]],[[7,[69,[17,[28]]]]]],[[[17,[28]]],[[7,[69,[17,[28]]]]]],0,[23,8],[17,[[7,[21]]]],[23,[[7,[43]]]],[[17,70],[[7,[21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[23,[[7,[[31,[[31,[2,30]],30]],21]]]],[17,[[7,[41,21]]]],[17,41],[23,61],[17,7],[23,7],[[],71],[[],71],[[],71],[[23,72],23],0,[[]],[[]],[[]],[[]],[[],73],[[],73],[[[17,[26]],72],73],[23,[[7,[21]]]],[23,[[7,[21]]]],[17,[[7,[74]]]],[23,[[7,[74]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[[],15],[[],15],[[],15],[[],15],[17,41],[[]],[[]],[[]],[[]],[23,8],[16,[[7,[73,47]]]],[16,[[7,[47]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[47,9],10],[[47,9],10],[75,47],[76,47],[[]],[77,47],[78,47],[21,47],[79,47],[80,47],[[]],[81],[[],73],[[],7],[[],7],[[],15],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[82,82],[83,83],[84,84],[46,46],[85,85],[45,45],[[]],[[]],[[]],[[]],[[]],[[]],0,0,[[],85],[[82,82],8],[[83,83],8],[[84,84],8],[[46,46],8],[[85,85],8],[[77,77],8],[[82,9],10],[[83,9],10],[[84,9],10],[[46,9],10],[[85,9],10],[[77,9],10],[[77,9],10],[[45,9],10],[[]],[[]],[8,84],[[]],[83,46],[[]],[[]],[[]],[[]],[[46,72],[[7,[85,77]]]],[82],[85],[83,73],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[83,8],[84,8],[85,8],0,[[85,85],[[12,[6]]]],[81],[46,8],0,[82,7],[83,7],[84,7],[46,7],[85,7],0,[[]],[[]],[[]],[[]],[[]],[[]],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[18,[[7,[86,47]]]],[[[88,[[87,[35]]]],18],[[7,[86,47]]]],[[[89,[[87,[36]]]],18],[[7,[86,47]]]],[[[90,[[87,[36]]]],18],[[7,[86,47]]]],[[[92,[[87,[91]]]],18],[[7,[86,47]]]],[[[94,[[93,[35]]]],18],[[7,[86,47]]]],[[[95,[[93,[35]]]],18],[[7,[86,47]]]],[[[96,[[93,[36]]]],18],[[7,[86,47]]]],[[[97,[[93,[36]]]],18],[[7,[86,47]]]],[[[98,[[93,[36]]]],18],[[7,[86,47]]]],[[[99,[[93,[36]]]],18],[[7,[86,47]]]],[[[100,[[93,[91]]]],18],[[7,[86,47]]]],[[[101,[[93,[91]]]],18],[[7,[86,47]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[86,37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[37,18],[[7,[47]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[],102],[[],22],[[26,27],[[7,[28,29]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[103,[[33,[32]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[23,[[7,[34]]]],[[],[[7,[34]]]],[24,[[7,[34]]]],[[],[[7,[34]]]],[[[105,[104,48]]],[[105,[104,48]]]],[22,22],[106,106],[103,103],[26,26],[107,107],[108,108],[109,109],[110,110],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[103,103],6],[[26,26],6],[[108,108],6],[[110,110],6],0,[[],106],[[[105,[48]]]],[[26,27],[[7,[28,29]]]],[[],[[7,[26]]]],[103,41],[[22,22],8],[[103,103],8],[[26,26],8],[[107,107],8],[[108,108],8],[[109,109],8],[[110,110],8],[[[112,[[0,[111,48]]]],9],10],[[22,9],10],[[106,9],10],[[75,9],10],[[75,9],10],[[103,9],[[7,[51]]]],[[103,9],[[7,[51]]]],[[26,9],[[7,[51]]]],[[26,9],[[7,[51]]]],[[107,9],[[7,[51]]]],[[107,9],[[7,[51]]]],[[108,9],[[7,[51]]]],[[109,9],[[7,[51]]]],[[110,9],[[7,[51]]]],[103,8],[[]],[113,[[114,[48]]]],[115,[[114,[48]]]],[[]],[[]],[[]],[[]],[21,75],[76,75],[[]],[[]],[28,26],[[]],[[]],[[]],[[]],[[]],[[26,102],[[112,[48]]]],[[107,102],[[112,[48]]]],[16,[[7,[26]]]],[16,[[7,[107]]]],[60,[[7,[103,21]]]],[26,[[12,[116]]]],[26,[[31,[116,30]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[],[[7,[105]]]],[[[114,[48]]],8],[26,8],[103],[26],[108],[110],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[26,117],[[],[[7,[112,75]]]],[[[12,[118]],116],[[7,[112,75]]]],[105,[[7,[112,75]]]],[[105,[12,[118]],116],[[7,[112,75]]]],[[[112,[48]]],[[7,[[112,[48]],75]]]],[26,[[7,[[112,[48]],75]]]],[107,[[7,[[112,[48]],75]]]],[[],[[7,[114,75]]]],[[[114,[48]]],[[7,[[114,[48]],75]]]],[105,[[7,[114,75]]]],[[[105,[48]]]],[26,[[31,[26,30]]]],[107,[[31,[107,30]]]],[[[114,[48]],18],[[12,[113]]]],[[[114,[48]],18,37],115],[26,8],[[],8],[22,8],[26,8],[107,8],[[],8],[22,8],[[],8],[22,8],[26,8],[26,8],0,0,0,[103,[[7,[65,21]]]],[[],102],[26,119],[23,[[12,[61]]]],[103,61],[103,61],[[102,102],102],[[],16],[[61,[31,[30]]],[[7,[103,21]]]],[26,61],0,0,[23,[[7,[21]]]],[[[112,[48]],102],[[112,[48]]]],[[103,103],[[12,[6]]]],[[26,26],[[12,[6]]]],[[108,108],[[12,[6]]]],[[110,110],[[12,[6]]]],[[],61],0,[81],[103,[[7,[21]]]],[103,[[7,[[31,[[31,[2,30]],30]],21]]]],[103,61],[26,7],[[],71],[103,24],[[],102],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[107,37],[[7,[26,120]]]],[[],73],[[],73],[[],73],[[],73],[23,[[7,[21]]]],[23,[[7,[21]]]],[103,[[7,[103,74]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[],[[12,[40]]]],[[],[[12,[121]]]],[61,[[12,[14]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[122,122],122],[[123,1,124,[126,[125]]]],0,[123,[[72,[1,[0,[127,104]]]]]],[[128,128]],[[123,129,27],[[7,[130]]]],[[123,129,27,131],[[7,[132]]]],[[123,133]],[[123,134],[[7,[130]]]],[123,135],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[123,136],[[7,[[139,[137,138]],140]]]],[123,[[139,[137,141]]]],[[123,142],[[7,[40,143]]]],[[123,142],[[7,[121,143]]]],[[123,142]],0,0,[123,144],[122,122],[134,134],[128,128],[[]],[[]],[[]],0,[123,[[7,[8]]]],0,[[],122],[[],134],[[],128],[145],[[123,1],[[12,[27]]]],[[123,49],12],[[123,1],73],[[],[[7,[122]]]],[[],[[7,[128]]]],[[122,122],8],[[128,128],8],[[145,145],8],0,0,[[123,146,147],[[7,[8,148]]]],[[122,9],[[7,[51]]]],[[122,9],[[7,[51]]]],[[[123,[111]],9],10],[[134,9],10],[[128,9],10],[[149,9],10],[[145,9],10],[[145,9],10],[[150,9],10],[[[150,[111]],9],10],[[[151,[111]],9],10],[[151,9],10],[[[152,[111,111]],9],10],[[152,9],10],[[153,9],10],[[153,9],10],[[154,9],10],[[154,9],10],[[]],[[]],[[]],[[[157,[155,[156,[1]]]]],128],[[]],[158,128],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[123,149],145],[123,122],[[123,1],62],[[123,149],145],[[123,3,[12,[159]],8],[[7,[160,161]]]],[[123,1],[[126,[44]]]],[[123,136],[[12,[[162,[[126,[142]],155]]]]]],[[123,11],[[12,[3]]]],0,0,0,0,[[123,131],[[7,[8,163]]]],[[123,142,164],[[7,[8,153]]]],[[123,11,14]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[49,8],[128,8],[[123,49],8],0,[123,72],0,[123,165],[123,127],[123,127],[[166,[12,[166]]],[[7,[123,151]]]],[123,167],[123,18],0,[[166,[12,[166]],18],[[7,[123,150]]]],[[166,[12,[166]],18],[[7,[123,47]]]],[[166,[12,[166]],18,168],[[7,[123,47]]]],[[166,[12,[166]],18],[[7,[123,152]]]],[[166,[12,[166]],18,168],[[7,[123,152]]]],[[166,[12,[166]],18,168],[[7,[123,150]]]],[[123,1],27],[[123,1],[[7,[[12,[46]],47]]]],[81],[81],[81],[81],[81],[[123,1],[[12,[62]]]],[123,37],[[123,142]],[122,7],[128,7],[[123,146,147],[[7,[8,148]]]],0,[123,169],[123,128],[[]],[[]],[[]],[[],73],[[],73],[[],73],[[],73],[[],73],[[],73],[[],73],[122,40],[123,127],0,[122,40],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[123,149],[[7,[145]]]],[[123,149],[[7,[145]]]],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],0,[123,135],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[123,1],[[0,[127,104]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,18,37],[[7,[73,47]]]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[170,170],[171,171],[172,172],[[]],[[]],[[]],[[[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[170,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[171,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[172,[31,[4]],[31,[4]],121,40,49],[[7,[173,174]]]],[[40,121,49],175],[[],170],[[],171],[[],172],0,0,[[174,9],10],[[174,9],10],[[175,9],10],[[173,9],10],[[170,9],10],[[171,9],10],[[172,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[173,40],[40,172],[81],0,[173,40],[[]],[[]],[[]],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[176,176],[[]],[[176,9],10],[[176,9],10],[[[161,[111]],9],10],[[161,9],10],[[140,9],10],[[140,9],10],[[]],[174,161],[77,161],[176,161],[[]],[177,161],[47,161],[[]],[[]],[[]],[[]],[81],[81],[81],[[]],[[],73],[[],73],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,[[]],[[]],[178,[[12,[73]]]],[178,73],[[],[[7,[178]]]],[[123,16,8],[[7,[178,16]]]],[[178,9],10],[[]],[16,[[7,[178]]]],[[]],0,[178,7],[178,73],[[],7],[[],7],[[],15],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[44,179,124,[126,[125]]],[[12,[[126,[125]]]]]],0,0,[[44,37],180],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[180,17,37],44],[179,179],[181,181],[[[183,[[0,[104,182,111,104]]]]],[[183,[[0,[104,182,111,104]]]]]],[124,124],[44,44],[147,147],[184,184],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[179,179],6],[[124,124],6],[[],124],[[],44],[[],147],[[],184],[[[183,[[0,[182,111,104]]]]]],[[],[[12,[107]]]],[[[183,[185]]],[[12,[107]]]],[[[183,[[186,[113]]]]],[[12,[107]]]],[[[183,[[187,[113]]]]],[[12,[107]]]],[[179,179],8],[[181,181],8],[[124,124],8],[[184,184],8],[[44,179],[[12,[126]]]],[[179,9],10],[[148,9],10],[[148,9],10],[[181,9],10],[[[183,[[0,[111,182,111,104]]]],9],10],[[124,9],10],[[44,9],10],[[147,9],10],[[184,9],10],[188,179],[119,179],[[]],[189,148],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[179],[37,179],[[[183,[185]],37],179],[[[183,[[186,[113]]]],37],179],[[[183,[[187,[113]]]],37],179],[44,[[31,[179]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[0,[182,111,104]],181],[[183,[[0,[182,111,104]]]]]],[[],44],[[179,179],[[12,[6]]]],[[124,124],[[12,[6]]]],[81],[[44,179,124],[[12,[[126,[125]]]]]],0,0,[[146,61,147,37],[[7,[148]]]],[[[183,[185]],146,61,147,37],[[7,[148]]]],[[[183,[[186,[113]]]],146,61,147,37],[[7,[148]]]],[[[183,[[187,[113]]]],146,61,147,37],[[7,[148]]]],[[146,147,37],[[7,[148]]]],[[146,147,37],[[7,[148]]]],0,[44,[[31,[126]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],73],0,0,[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[139,[190,141]]],[[139,[190,141]]]],[[139,11,160,61],[[7,[139,191]]]],[[139,11,160,61,13],[[7,[139,191]]]],[139,139],[[[139,[190,141]],41,40],[[139,[190,141]]]],[[139,11],139],[[139,11],[[7,[139,192]]]],[139,[[7,[139,192]]]],[[139,8],139],[[[139,[137,138]],41],[[7,[[139,[137,138]],193]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[139,194],139],[141,141],[138,138],[[[139,[104]]],[[139,[104]]]],[195,195],[194,194],[[]],[[]],[[]],[[]],[[]],[[195,195],6],[[194,194],6],[[139,190],[[139,[190]]]],[[139,27],139],[[],141],[[],138],[[],195],[[],194],[139,139],[[[139,[190,141]],41],[[139,[190,141]]]],[139,139],[139,139],[[139,13],139],[[195,195],8],[[194,194],8],[[139,40],139],[[139,121],139],[[[139,[190]]],[[7,[146,161]]]],[[141,9],10],[[138,9],10],[[[139,[111,111,111]],9],10],[[192,9],10],[[192,9],10],[[191,9],10],[[191,9],10],[[193,9],10],[[193,9],10],[[195,9],10],[[194,9],10],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[195],[194],[139,139],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[139,139],[[139,196],139],[139,139],[139,139],[[139,195],139],[[195,195],[[12,[6]]]],[[194,194],[[12,[6]]]],[[139,[72,[73,[31,[61]]]],1],139],[81],[81],[81],[[[139,[190,141]],31],[[139,[190,141]]]],[[139,159],139],[[195,142]],[[]],[[]],[[]],[[]],[[]],[[],73],[[],73],[[],73],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],7],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[139,[31,[11]]],139],[[139,197],139],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0],"p":[[4,"KeychainKind"],[15,"u8"],[3,"LocalOutput"],[3,"WeightedUtxo"],[4,"Utxo"],[4,"Ordering"],[4,"Result"],[15,"bool"],[3,"Formatter"],[6,"Result"],[3,"OutPoint"],[4,"Option"],[3,"Sequence"],[3,"TxOut"],[3,"TypeId"],[15,"str"],[4,"Descriptor"],[4,"Network"],[4,"NetworkChecked"],[3,"Address"],[4,"Error"],[4,"ScriptContextEnum"],[3,"Miniscript"],[4,"Terminal"],[4,"Tree"],[4,"DescriptorPublicKey"],[15,"u32"],[3,"DefiniteDescriptorKey"],[4,"ConversionError"],[3,"Global"],[3,"Vec"],[4,"Placeholder"],[3,"Satisfaction"],[4,"ScriptContextError"],[4,"Legacy"],[4,"Segwitv0"],[3,"Secp256k1"],[3,"PublicKey"],[4,"DescriptorType"],[15,"u64"],[3,"ScriptBuf"],[3,"ExtParams"],[4,"AnalysisError"],[3,"SignersContainer"],[4,"BuildSatisfaction"],[3,"Policy"],[4,"Error"],[8,"ScriptContext"],[3,"Script"],[3,"Range"],[3,"Error"],[3,"Tr"],[3,"Sh"],[3,"Bare"],[3,"Wpkh"],[3,"Pkh"],[3,"Wsh"],[3,"Type"],[3,"ExtData"],[3,"Tree"],[15,"usize"],[6,"ExtendedDescriptor"],[3,"Iter"],[3,"PkIter"],[4,"Policy"],[4,"LiftError"],[4,"BareCtx"],[4,"TapTree"],[3,"Plan"],[3,"TxIn"],[4,"SigType"],[3,"BTreeMap"],[3,"String"],[4,"TranslateErr"],[4,"KeyError"],[4,"Error"],[4,"PolicyError"],[4,"HexToBytesError"],[4,"Error"],[4,"Error"],[3,"Demand"],[4,"PkOrF"],[4,"SatisfiableItem"],[4,"Satisfaction"],[3,"Condition"],[6,"DescriptorTemplateOut"],[8,"IntoDescriptorKey"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[4,"Tap"],[3,"P2TR"],[8,"DerivableKey"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[3,"Bip86"],[3,"Bip86Public"],[6,"ValidNetworks"],[3,"SortedMultiVec"],[8,"Clone"],[3,"GeneratedKey"],[3,"PrivateKeyGenerateOptions"],[4,"DescriptorSecretKey"],[3,"SinglePub"],[3,"SinglePriv"],[4,"SinglePubKey"],[8,"Debug"],[4,"DescriptorKey"],[3,"Xpriv"],[4,"ExtendedKey"],[3,"Xpub"],[3,"DerivationPath"],[3,"Assets"],[6,"KeySource"],[3,"Fingerprint"],[3,"DescriptorKeyParseError"],[3,"FeeRate"],[3,"Balance"],[3,"Wallet"],[3,"SignerOrdering"],[8,"TransactionSigner"],[3,"Arc"],[8,"Iterator"],[3,"ChangeSet"],[3,"Block"],[3,"CannotConnectError"],[3,"BlockId"],[4,"ApplyHeaderError"],[8,"IntoIterator"],[3,"Update"],[3,"TxGraph"],[3,"Txid"],[6,"DefaultCoinSelectionAlgorithm"],[3,"BumpFee"],[3,"TxBuilder"],[4,"BuildFeeBumpError"],[3,"CreateTx"],[3,"Transaction"],[4,"CalculateFeeError"],[3,"CheckPointIter"],[3,"AddressInfo"],[3,"Psbt"],[3,"SignOptions"],[4,"SignerError"],[4,"AddressIndex"],[4,"NewError"],[4,"LoadError"],[4,"NewOrLoadError"],[4,"InsertTxError"],[4,"ApplyBlockError"],[3,"ConfirmationTimeHeightAnchor"],[3,"ChangeSet"],[3,"ChangeSet"],[6,"ChangeSet"],[3,"PsbtSighashType"],[3,"Input"],[4,"CreateTxError"],[3,"CanonicalTx"],[3,"AlterCheckPointError"],[4,"ConfirmationTime"],[3,"CheckPoint"],[8,"IntoWalletDescriptor"],[3,"LocalChain"],[3,"BlockHash"],[3,"KeychainTxOutIndex"],[3,"LargestFirstCoinSelection"],[3,"OldestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[3,"CoinSelectionResult"],[4,"Error"],[4,"Excess"],[4,"MiniscriptPsbtError"],[4,"Error"],[3,"FullyNodedExport"],[4,"SignerId"],[6,"KeyMap"],[4,"SignerContext"],[8,"Sized"],[3,"SignerWrapper"],[4,"TapLeavesOptions"],[3,"PrivateKey"],[3,"DescriptorMultiXKey"],[3,"DescriptorXKey"],[3,"Hash"],[4,"Error"],[8,"CoinSelectionAlgorithm"],[4,"AddForeignUtxoError"],[4,"AddUtxoError"],[4,"AllowShrinkingError"],[4,"ChangeSpendPolicy"],[4,"TxOrdering"],[4,"LockTime"],[15,"i32"],[13,"Foreign"],[8,"ExtractPolicy"],[13,"PsbtTimelocks"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[8,"DescriptorTemplate"],[8,"GeneratableKey"],[8,"ExtScriptContext"],[8,"GeneratableDefaultOptions"],[8,"PsbtUtils"],[8,"IsDust"],[13,"UnexpectedConnectedToHash"],[13,"ConfirmationHeightCannotBeGreaterThanTip"],[13,"LoadedGenesisDoesNotMatch"],[13,"LoadedNetworkDoesNotMatch"],[13,"InsufficientFunds"],[13,"Change"],[13,"NoChange"],[13,"InsufficientFunds"],[13,"RbfSequenceCsv"],[13,"LockTime"],[13,"FeeTooLow"],[13,"FeeRateTooLow"],[8,"SignerCommon"],[8,"InputSigner"],[13,"Tap"],[13,"InvalidTxid"]]},\ "bdk_bitcoind_rpc":{"doc":"This crate is used for emitting blockchain data from the …","t":[8,3,3,2,12,11,11,11,11,11,11,12,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11],"n":["BitcoindRpcErrorExt","BlockEvent","Emitter","bitcoincore_rpc","block","block_hash","block_height","borrow","borrow","borrow_mut","borrow_mut","checkpoint","connected_to","fmt","from","from","into","into","is_not_found_error","mempool","new","next_block","next_header","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip"],"q":["bdk_bitcoind_rpc","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Extends bitcoincore_rpc::Error.","A newly emitted block from Emitter.","The Emitter is used to emit data sourced from …","","Either a full Block or Header of the new block.","The block hash of this new block.","The block height of this new block.","","","","","The checkpoint of the new block.","The BlockId of a previous block that this block connects …","","Returns the argument unchanged.","Returns the argument unchanged.","Calls U::from(self).","Calls U::from(self).","Returns whether the error is a “not found” error.","Emit mempool transactions, alongside their first-seen unix …","Construct a new Emitter.","Emit the next block height and block (if any).","Emit the next block height and header (if any).","","","","","","","",""],"i":[0,0,0,0,1,1,1,10,1,10,1,1,1,1,10,1,10,1,19,10,10,10,10,10,1,10,1,10,1,10,1],"f":[0,0,0,0,0,[1,2],[1,3],[[]],[[]],[[]],[[]],0,[1,4],[[[1,[5]],6],7],[[]],[[]],[[]],[[]],[[],8],[[[10,[9]]],[[13,[11,12]]]],[[14,3],[[10,[9]]]],[[[10,[9]]],[[13,[[16,[[1,[15]]]],12]]]],[[[10,[9]]],[[13,[[16,[[1,[17]]]],12]]]],[[],13],[[],13],[[],13],[[],13],[[],18],[[],18],[[]],[[]]],"p":[[3,"BlockEvent"],[3,"BlockHash"],[15,"u32"],[3,"BlockId"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[15,"bool"],[8,"RpcApi"],[3,"Emitter"],[3,"Vec"],[4,"Error"],[4,"Result"],[3,"CheckPoint"],[3,"Block"],[4,"Option"],[3,"Header"],[3,"TypeId"],[8,"BitcoindRpcErrorExt"]]},\ "bdk_chain":{"doc":"This crate is a collection of core structures for Bitcoin …","t":[8,8,8,17,3,17,8,4,3,4,3,13,13,8,16,3,2,16,3,8,3,3,2,13,13,16,11,10,11,11,11,12,12,10,11,2,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,10,11,11,11,11,11,12,12,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,10,11,12,11,11,11,0,10,0,11,2,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,12,12,12,3,16,3,8,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,10,10,12,10,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,3,4,13,3,6,3,3,13,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,4,3,3,13,13,3,3,3,3,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,11,11,12,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["Anchor","AnchorFromBlockPosition","Append","BIP32_MAX_INDEX","BlockId","COINBASE_MATURITY","ChainOracle","ChainPosition","ConfirmationHeightAnchor","ConfirmationTime","ConfirmationTimeHeightAnchor","Confirmed","Confirmed","DescriptorExt","Error","FullTxOut","IndexedTxGraph","LoadError","Persist","PersistBackend","SpkIterator","SpkTxOutIndex","TxGraph","Unconfirmed","Unconfirmed","WriteError","all_spks","anchor_block","anchor_block","anchor_block","anchor_block","anchor_block","anchor_block","append","apply_changeset","bitcoin","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","chain_position","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cloned","cmp","cmp","cmp","cmp","cmp","cmp","commit","confirmation_height","confirmation_height","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_height_upper_bound","confirmation_time","default","default","default","default","descriptor","deserialize","deserialize","deserialize","deserialize","dust_value","eq","eq","eq","eq","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from_block_position","from_block_position","from_block_position","from_block_position","get_chain_tip","hash","hash","hash","hash","hash","hash","height","index_of_spk","index_tx","index_txout","indexed_tx_graph","initial_changeset","insert_spk","into","into","into","into","into","into","into","into","into","into_iter","is_block_in_chain","is_confirmed","is_confirmed","is_confirmed_and_spendable","is_empty","is_mature","is_on_coinbase","is_relevant","is_tx_relevant","is_used","keychain","load_from_persistence","local_chain","mark_used","miniscript","net_value","new","new","new_with_range","next","nth","outpoint","outpoints","outputs_in_range","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","scan","scan_txout","sent_and_received","serialize","serialize","serialize","serialize","spent_by","spk_at_index","stage","stage_and_commit","staged","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","tx_graph","txout","txout","txouts","txouts_in_tx","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unconfirmed","unmark_used","unused_spks","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","write_changes","height","last_seen","time","ChangeSet","ChangeSet","IndexedTxGraph","Indexer","append","apply_block","apply_block_relevant","apply_changeset","apply_changeset","apply_update","batch_insert_relevant","batch_insert_relevant_unconfirmed","batch_insert_unconfirmed","borrow","borrow","borrow_mut","borrow_mut","clone","clone_into","default","default","deserialize","eq","fmt","fmt","from","from","from","from","graph","graph","index","index_tx","index_txout","indexer","initial_changeset","initial_changeset","insert_anchor","insert_seen_at","insert_tx","insert_txout","into","into","is_empty","is_tx_relevant","new","serialize","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","Balance","ChangeSet","KeychainTxOutIndex","add","add_keychain","all_unbounded_spk_iters","append","apply_changeset","apply_changeset","as_inner","as_ref","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone_into","clone_into","clone_into","confirmed","default","default","default","deserialize","deserialize","eq","eq","fmt","fmt","fmt","fmt","from","from","from","immature","index_of_spk","index_tx","index_txout","initial_changeset","inner","into","into","into","is_empty","is_tx_relevant","is_used","keychain_outpoints","keychain_outpoints_in_range","keychains","last_revealed_index","last_revealed_indices","last_used_index","last_used_indices","lookahead","lookahead_to_target","mark_used","net_value","new","next_index","next_unused_spk","outpoints","reveal_next_spk","reveal_to_target","reveal_to_target_multi","revealed_keychain_spks","revealed_spks","sent_and_received","serialize","serialize","spk_at_index","to_owned","to_owned","to_owned","to_string","total","trusted_pending","trusted_spendable","try_from","try_from","try_from","try_into","try_into","try_into","txout","txouts","txouts_in_tx","type_id","type_id","type_id","unbounded_spk_iter","unmark_used","untrusted_pending","unused_keychain_spks","unused_spks","vzip","vzip","vzip","AlterCheckPointError","ApplyHeaderError","CannotConnect","CannotConnectError","ChangeSet","CheckPoint","CheckPointIter","InconsistentBlocks","LocalChain","MissingGenesisError","Update","apply_changeset","apply_header","apply_header_connected_to","apply_update","block_id","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","disconnect_from","eq","eq","eq","eq","eq","eq","eq","extend","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from_block_ids","from_blocks","from_changeset","from_genesis_hash","from_header","from_tip","genesis_hash","get","get","get_chain_tip","hash","height","height","initial_changeset","insert_block","into","into","into","into","into","into","into","into","into_iter","into_iter","into_update","introduce_older_blocks","is_block_in_chain","iter","iter_checkpoints","new","next","original_hash","prev","provide","provide","provide","provide","push","range","range","tip","tip","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_include_height","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update_hash","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","CalculateFeeError","CanonicalTx","ChangeSet","MissingTxOut","NegativeFee","TxAncestors","TxDescendants","TxGraph","TxNode","all_anchors","all_txouts","anchor_heights","anchors","anchors","append","apply_changeset","apply_update","as_ref","balance","batch_insert_unconfirmed","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","calculate_fee","chain_position","checked_sum","checked_sum","checked_sum","checked_sum","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","deref","deserialize","direct_conflicts","eq","eq","eq","eq","eq","filter_chain_txouts","filter_chain_unspents","floating_txouts","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","full_txs","get_chain_position","get_chain_spend","get_tx","get_tx_node","get_txout","initial_changeset","insert_anchor","insert_seen_at","insert_tx","insert_txout","into","into","into","into","into","into","into","into_iter","into_iter","is_empty","is_empty","last_seen","last_seen_unconfirmed","list_chain_txs","map_anchors","map_anchors","missing_heights","missing_heights_from","new","next","next","outspends","partial_cmp","partial_cmp","provide","serialize","to_owned","to_owned","to_owned","to_owned","to_string","try_balance","try_filter_chain_txouts","try_filter_chain_unspents","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_get_chain_position","try_get_chain_spend","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_list_chain_txs","tx","tx_node","tx_outputs","tx_spends","txid","txouts","txouts","txs","type_id","type_id","type_id","type_id","type_id","type_id","type_id","update_last_seen_unconfirmed","vzip","vzip","vzip","vzip","vzip","vzip","vzip","walk_ancestors","walk_conflicts","walk_descendants"],"q":["bdk_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::ConfirmationTime","","","bdk_chain::indexed_tx_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::keychain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::local_chain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk_chain::tx_graph","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Trait that “anchors” blockchain data to a specific …","An Anchor that can be constructed from a given block, …","Trait that makes an object appendable.","Maximum BIP32 derivation index.","A reference to a block in the canonical chain.","How many confirmations are needed f or a coinbase output …","Represents a service that tracks the blockchain.","Represents the observed position of some chain data.","An Anchor implementation that also records the exact …","Block height and timestamp at which a transaction is …","An Anchor implementation that also records the exact …","The chain data is seen as confirmed, and in anchored by A.","The transaction is confirmed","A trait to extend the functionality of a miniscript …","Error type.","A TxOut with as much data as we can retrieve about it","","The error the backend returns when it fails to load …","Persist wraps a PersistBackend (B) to create a convenient …","A persistence backend for Persist.","An iterator for derived script pubkeys.","An index storing TxOuts that have a script pubkey that …","","The chain data is not confirmed and last seen in the …","The transaction is unconfirmed","The error the backend returns when it fails to write.","The script pubkeys that are being tracked by the index.","Returns the BlockId that the associated blockchain data is …","","","","The anchor block.","The anchor block.","Append another object of the same type onto self.","","","","","","","","","","","","","","","","","","","","","The position of the transaction in outpoint in the overall …","","","","","","","","","","","","","","","","","Maps a ChainPosition<&A> into a ChainPosition<A> by …","","","","","","","Commit the staged changes to the underlying persistence …","The exact confirmation height of the transaction.","The confirmation height of the transaction being anchored.","Get the upper bound of the chain data’s confirmation …","Get the upper bound of the chain data’s confirmation …","Determines the upper bound of the confirmation height.","","","The confirmation time of the transaction being anchored.","","","","","Get a reference to the internal descriptor.","","","","","Returns the minimum value (in satoshis) at which an output …","","","","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Construct the anchor from a given block, block height and …","","","","Get the best chain’s chain tip.","","","","","","The hash of the block.","The height of the block.","Returns the index associated with the script pubkey.","","","Contains the IndexedTxGraph and associated types. Refer to …","","Adds a script pubkey to scan for. Returns false and does …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","Determines whether block of BlockId exists as an ancestor …","Returns whether ChainPosition is confirmed or not.","Returns whether ConfirmationTime is the confirmed variant.","Whether the utxo is/was/will be spendable with chain tip.","Returns whether the structure is considered empty.","Whether the txout is considered mature.","Whether this output is on a coinbase transaction.","Whether any of the inputs of this transaction spend a …","","Returns whether the script pubkey at index has been used …","Module for keychain related structures.","Return the aggregate changeset C from persistence.","The LocalChain is a local implementation of ChainOracle.","Marks the script pubkey at index as used even though it …","","Computes the net value that this transaction gives to the …","Create a new Persist from PersistBackend.","Create a new script pubkey iterator from descriptor.","Create a new script pubkey iterator from descriptor and a …","","","The location of the TxOut.","Get a reference to the set of indexed outpoints.","Iterates over all the outputs with script pubkeys in an …","","","","","","","Scans a transaction’s outputs for matching script …","Scan a single TxOut for a matching script pubkey and …","Computes total input value going from script pubkeys in …","","","","","The txid and chain position of the transaction (if any) …","Returns the script that has been inserted at the index.","Stage a changeset to be committed later with commit.","Stages a new changeset and commits it (along with any …","Get the changes that have not been committed yet.","","","","","","","","","","","","","","","","","","","","","","","","","","","Module for structures that store and traverse transactions.","Returns the txout and script pubkey index of the TxOut at …","The TxOut.","Iterate over all known txouts that spend to tracked script …","Finds all txouts on a transaction that has previously been …","","","","","","","","","","Construct an unconfirmed variant using the given last_seen …","Undoes the effect of mark_used. Returns whether the index …","Iterates over all unused script pubkeys in an index range.","","","","","","","","","","Writes a changeset to the persistence backend.","Confirmation height.","The last-seen timestamp in unix seconds.","Confirmation time in unix seconds.","Represents changes to an IndexedTxGraph.","The resultant “changeset” when new transaction data is …","The IndexedTxGraph combines a TxGraph and an Indexer …","Utilities for indexing transaction data.","","Batch insert all transactions of the given block of height.","Batch insert all transactions of the given block of height…","Apply changeset to itself.","Applies the ChangeSet to the IndexedTxGraph.","Apply an update directly.","Batch insert transactions, filtering out those that are …","Batch insert unconfirmed transactions, filtering out those …","Batch insert unconfirmed transactions.","","","","","","","","","","","","","Returns the argument unchanged.","","","Returns the argument unchanged.","Get a reference of the internal transaction graph.","TxGraph changeset.","Transaction index.","Scans a transaction for relevant outpoints, which are …","Scan and index the given outpoint and txout.","Indexer changeset.","Determines the ChangeSet between self and an empty Indexer.","Determines the ChangeSet between self and an empty …","Insert an anchor for a given transaction.","Insert a unix timestamp of when a transaction is seen in …","Insert and index a transaction into the graph.","Insert a floating txout of given outpoint.","Calls U::from(self).","Calls U::from(self).","","Determines whether the transaction should be included in …","Construct a new IndexedTxGraph with a given index.","","","","","","","","","","","Balance, differentiated into various categories.","Represents updates to the derivation index of a …","KeychainTxOutIndex controls how script pubkeys are …","","Add a keychain to the tracker’s txout_index with a …","Get unbounded spk iterators for all keychains.","Append another ChangeSet into self.","","Applies the derivation changeset to the KeychainTxOutIndex…","Get the inner map of the keychain to its new derivation …","","","","","","","","","","","","","","Confirmed and immediately spendable balance","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","All coinbase outputs not yet matured","Returns the keychain and keychain index associated with …","","","","Return a reference to the internal SpkTxOutIndex.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Returns whether the changeset are empty.","","Returns whether the spk under the keychain’s index has …","Iterate over all OutPoints that point to TxOuts with …","Iterate over OutPoints that point to TxOuts with script …","Return a reference to the internal map of keychain to …","Get the last derivation index revealed for keychain.","Get the last derivation index that is revealed for each …","Returns the highest derivation index of the keychain where …","Returns the highest derivation index of each keychain that …","Get the lookahead setting.","Store lookahead scripts until target_index (inclusive).","Marks the script pubkey at index as used even though the …","Computes the net value that this transaction gives to the …","Construct a KeychainTxOutIndex with the given lookahead.","Get the next derivation index for keychain. The next index …","Gets the next unused script pubkey in the keychain. I.e., …","Get a reference to the set of indexed outpoints.","Attempts to reveal the next script pubkey for keychain.","Reveals script pubkeys of the keychain’s descriptor up …","Convenience method to call Self::reveal_to_target on …","Iterate over revealed spks of the given keychain.","Iterate over revealed spks of all keychains.","Computes total input value going from script pubkeys in …","","","Return the script that exists under the given keychain’s …","","","","","Get the whole balance visible to the wallet.","Unconfirmed UTXOs generated by a wallet tx","Get sum of trusted_pending and confirmed coins.","","","","","","","Return the TxOut of outpoint if it has been indexed.","Iterate over known txouts that spend to tracked script …","Finds all txouts on a transaction that has previously been …","","","","Get an unbounded spk iterator over a given keychain.","Undoes the effect of mark_used. Returns whether the index …","Unconfirmed UTXOs received from an external wallet","Iterate over revealed, but unused, spks of the given …","Iterate over revealed, but unused, spks of all keychains.","","","","Represents a failure when trying to insert/remove a …","The error type for LocalChain::apply_header_connected_to.","Occurs when the update cannot connect with the original …","Occurs when an update does not have a common checkpoint …","The ChangeSet represents changes to LocalChain.","A LocalChain checkpoint is used to find the agreement …","Iterates over checkpoints backwards.","Occurs when connected_to block conflicts with either the …","This is a local implementation of ChainOracle.","An error which occurs when a LocalChain is constructed …","Used to update LocalChain.","Apply the given changeset.","Update the chain with a given Header connecting it with …","Update the chain with a given Header at height which you …","Applies the given update to the chain.","Get the BlockId of the checkpoint.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Removes blocks from (and inclusive of) the given block_id.","","","","","","","","Extends the checkpoint linked list by a iterator of block …","","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Construct a checkpoint from a list of BlockIds in …","Constructs a LocalChain from a BTreeMap of height to …","Construct a LocalChain from an initial changeset.","Construct LocalChain from genesis hash.","Construct a checkpoint from the given header and block …","Construct a LocalChain from a given checkpoint tip.","Get the genesis hash.","Get checkpoint at height.","Get checkpoint at given height (if it exists).","","Get the block hash of the checkpoint.","Get the height of the checkpoint.","The checkpoint’s height.","Derives an initial ChangeSet, meaning that it can be …","Insert a BlockId.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","Convenience method to convert the CheckPoint into an Update…","Whether the update allows for introducing older blocks.","","Iterate from this checkpoint in descending height.","Iterate over checkpoints in descending height order.","Construct a new base block at the front of a linked list.","","The original checkpoint’s block hash which cannot be …","Get the previous checkpoint in the chain","","","","","Puts another checkpoint onto the linked list representing …","Iterate checkpoints over a height range.","Iterate checkpoints over a height range.","Get the highest checkpoint.","The update chain’s new tip.","","","","","","","","","","","","","","","","","","","","The suggested checkpoint to include to connect the two …","","","","","","","","","","","","","","","","","The attempted update to the original_block hash.","","","","","","","","","Errors returned by TxGraph::calculate_fee.","A transaction that is included in the chain, or is still …","The ChangeSet represents changes to a TxGraph.","Missing TxOut for one or more of the inputs of the tx","When the transaction is invalid according to the graph it …","An iterator that traverses ancestors of a given root …","An iterator that traverses transaction descendants.","A graph of transactions and spends.","A transaction node in the TxGraph.","Get all transaction anchors known by TxGraph.","Iterate over all tx outputs known by TxGraph.","Iterates over the heights of that the new transaction …","The blocks that the transaction is “anchored” in.","Added anchors.","","Applies ChangeSet to TxGraph.","Extends this graph with another so that self becomes the …","","Get the total balance of outpoints that are in chain of …","Batch insert unconfirmed transactions.","","","","","","","","","","","","","","","Calculates the fee of a given transaction. Returns 0 if tx …","How the transaction is observed as (confirmed or …","","","","","","","","","","","","","","","","","","","Given a transaction, return an iterator of txids that …","","","","","","Get a filtered list of outputs from the given outpoints …","Get a filtered list of unspent outputs (UTXOs) from the …","Iterate over floating txouts known by TxGraph.","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Iterate over all full transactions in the graph.","Get the position of the transaction in chain with tip …","Get the txid of the spending transaction and where the …","Get a transaction by txid. This only returns Some for full …","Get a transaction node by txid. This only returns Some for …","Obtains a single tx output (if any) at the specified …","Determines the ChangeSet between self and an empty TxGraph.","Inserts the given anchor into TxGraph.","Inserts the given seen_at for txid into TxGraph.","Inserts the given transaction into TxGraph.","Inserts the given TxOut at OutPoint.","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","","","Whether the graph has any transactions or outputs in it.","","Added last-seen unix timestamps of transactions.","The last-seen unix timestamp of the transaction as …","List graph transactions that are in chain with chain_tip.","Transform the TxGraph to have Anchors of another type.","Transform the ChangeSet to have Anchors of another type.","Find missing block heights of chain.","Returns an iterator for the anchor_heights in this …","Construct a new TxGraph from a list of transactions.","","","The transactions spending from this output.","","","","","","","","","","Get the total balance of outpoints that are in chain of …","Get a filtered list of outputs from the given outpoints …","Get a filtered list of unspent outputs (UTXOs) from the …","","","","","","","","Get the position of the transaction in chain with tip …","Get the txid of the spending transaction and where the …","","","","","","","","List graph transactions that are in chain with chain_tip.","A partial or full representation of the transaction.","The transaction node (as part of the graph).","Returns known outputs of a given txid.","Iterates over the transactions spending from txid.","Txid of the transaction.","Iterates over all outpoints contained within ChangeSet.","Added txouts.","Added transactions.","","","","","","","","Update the last seen time for all unconfirmed transactions.","","","","","","","","Creates an iterator that filters and maps ancestor …","Creates an iterator that both filters and maps conflicting …","Creates an iterator that filters and maps descendants from …"],"i":[0,0,0,0,0,0,0,0,0,0,0,8,9,0,77,0,0,78,0,0,0,0,0,8,9,78,3,17,5,6,7,6,7,40,3,0,3,8,9,5,6,7,10,13,11,3,8,9,5,6,7,10,13,11,10,3,8,9,5,6,7,10,11,3,8,9,5,6,7,10,11,8,8,9,5,6,7,10,13,6,7,17,17,8,6,7,7,3,5,6,7,11,9,5,6,7,79,8,9,5,6,7,10,3,8,9,5,6,7,10,13,3,8,9,9,5,5,5,6,7,10,13,11,80,5,6,7,77,8,9,5,6,7,5,5,3,3,3,0,3,3,3,8,9,5,6,7,10,13,11,11,77,8,9,10,40,10,10,3,3,3,0,78,0,3,0,3,13,11,11,11,11,10,3,3,8,9,5,6,7,10,3,3,3,9,5,6,7,10,3,13,13,13,3,8,9,5,6,7,10,11,3,8,9,5,6,7,10,13,11,3,8,9,5,6,7,10,13,11,0,3,10,3,3,3,8,9,5,6,7,10,13,11,9,3,3,3,8,9,5,6,7,10,13,11,78,81,82,81,0,42,0,0,41,43,43,42,43,43,43,43,43,43,41,43,41,41,41,43,41,41,41,43,41,43,41,41,41,43,41,43,42,42,41,42,43,43,43,43,43,43,41,41,42,43,41,41,43,41,43,41,43,41,43,41,0,0,0,49,50,50,47,50,50,47,47,50,47,49,50,47,49,50,47,49,50,47,49,49,50,47,49,47,49,47,49,50,47,49,49,50,47,49,49,50,50,50,50,50,50,47,49,47,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,47,49,50,50,47,49,49,49,49,49,50,47,49,50,47,49,50,50,50,50,47,49,50,50,49,50,50,50,47,49,0,0,59,0,0,0,0,59,0,0,0,54,54,54,54,61,64,61,60,54,56,62,58,59,64,61,60,54,56,62,58,59,61,60,54,56,62,58,59,61,60,54,56,62,58,59,54,61,60,54,56,62,58,59,61,61,60,54,56,56,62,62,58,58,59,59,64,61,60,54,56,62,58,59,61,54,54,54,61,54,54,61,54,54,61,61,62,54,54,64,61,60,54,56,62,58,59,64,61,61,60,54,61,54,61,64,62,61,56,62,58,59,61,61,54,54,60,61,60,54,56,62,58,59,56,62,58,59,64,61,60,54,56,62,58,59,58,64,61,60,54,56,62,58,59,64,61,60,54,56,62,58,59,62,64,61,60,54,56,62,58,59,0,0,0,68,68,0,0,0,0,44,44,48,71,48,48,44,44,44,44,44,74,75,44,71,72,68,48,74,75,44,71,72,68,48,44,72,74,74,75,75,44,71,72,48,44,71,72,48,71,72,44,48,71,48,44,44,71,72,68,48,44,44,44,44,71,72,68,68,48,74,75,44,71,72,68,48,44,44,44,44,44,44,44,44,44,44,44,74,75,44,71,72,68,48,74,75,44,48,48,71,44,44,48,44,48,44,74,75,44,71,72,68,48,44,71,72,48,68,44,44,44,74,75,44,71,72,68,48,44,44,74,75,44,71,72,68,48,44,71,72,44,44,71,48,48,48,74,75,44,71,72,68,48,44,74,75,44,71,72,68,48,44,44,44],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[3,[[0,[1,2]]]]],4],[[],5],[5,5],[6,5],[7,5],0,0,[[]],[[[3,[[0,[1,2]]]]]],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,[[[3,[1]]],[[3,[1]]]],[[[8,[1]]],[[8,[1]]]],[9,9],[5,5],[6,6],[7,7],[[[10,[1]]],[[10,[1]]]],[[[11,[1]]],[[11,[1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[8,[[8,[1]]]],[[[8,[2]],8],12],[[9,9],12],[[5,5],12],[[6,6],12],[[7,7],12],[[[10,[2]],10],12],[13,[[15,[14]]]],0,0,[[],16],[[],16],[[[8,[17]]],[[14,[16]]]],[6,16],[7,16],0,[[],3],[[],5],[[],6],[[],7],[11],[[],[[15,[9]]]],[[],[[15,[5]]]],[[],[[15,[6]]]],[[],[[15,[7]]]],[[],18],[[[8,[19]],8],20],[[9,9],20],[[5,5],20],[[6,6],20],[[7,7],20],[[[10,[19]],10],20],[[[3,[21]],22],23],[[[8,[21]],22],23],[[9,22],23],[[5,22],23],[[6,22],23],[[7,22],23],[[[10,[21]],22],23],[[[13,[21,21]],22],23],[[]],[[]],[[[8,[7]]],9],[[]],[[],5],[[]],[[],5],[[]],[[]],[[]],[[]],[[]],[[24,5,25]],[[24,5,25],5],[[24,5,25],6],[[24,5,25],7],[[],[[15,[5]]]],[[[8,[26]]]],[9],[5],[6],[7],0,0,[[[3,[[0,[1,2]]]],27],14],[[[3,[[0,[1,2]]]],28]],[[[3,[[0,[1,2]]]],29,30]],0,[[[3,[[0,[1,2]]]]]],[[[3,[[0,[1,2]]]],[0,[1,2]],31],20],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[5,5],[[15,[[14,[20]]]]]],[8,20],[9,20],[[[10,[17]],16],20],[[],20],[[[10,[17]],16],20],0,[[[3,[[0,[1,2]]]],28],20],[[[3,[[0,[1,2]]]],28],20],[[[3,[[0,[1,2]]]]],20],0,[[],[[15,[14]]]],0,[[[3,[[0,[1,2]]]]],20],0,[[[3,[[0,[1,2]]]],28],32],[[],13],[[],11],[[],11],[11,14],[[11,25],14],0,[[[3,[[0,[1,2]]]]],33],[[[3,[[0,[1,2]]]],[34,[[0,[1,2]]]]],35],[[[8,[36]],8],[[14,[12]]]],[[9,9],[[14,[12]]]],[[5,5],[[14,[12]]]],[[6,6],[[14,[12]]]],[[7,7],[[14,[12]]]],[[[10,[36]],10],[[14,[12]]]],[[[3,[[0,[1,2]]]],28],[[33,[[0,[1,2]]]]]],[[[3,[[0,[1,2]]]],29,30],14],[[[3,[[0,[1,2]]]],28]],[9,15],[5,15],[6,15],[7,15],0,[[[3,[[0,[1,2]]]]],[[14,[27]]]],[13],[13,[[15,[14]]]],[13],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],0,[[[3,[[0,[1,2]]]],29],14],0,[[[3,[[0,[1,2]]]]],[[0,[35,37]]]],[[[3,[[0,[1,2]]]],38],35],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[18,9],[[[3,[[0,[1,2]]]]],20],[[[3,[[0,[1,2]]]]],[[0,[35,1]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],15],0,0,0,0,0,0,0,[[[41,[17,40]],[41,[17,40]]]],[[[43,[42]],24,16],41],[[[43,[42]],24,16],41],[[]],[[[43,[17,42]],[41,[17]]]],[[[43,[17,42]],[44,[17]]],[[41,[17]]]],[[[43,[17,42]],45],[[41,[17]]]],[[[43,[17,42]],45],[[41,[17]]]],[[[43,[17,42]],45],[[41,[17]]]],[[]],[[]],[[]],[[]],[[[41,[1,1]]],[[41,[1,1]]]],[[]],[[],[[43,[46]]]],[[],[[41,[46]]]],[[],[[15,[41]]]],[[[41,[19,19]],41],20],[[[43,[21,21]],22],23],[[[41,[21,21]],22],23],[[]],[47,[[41,[47]]]],[48,[[41,[46]]]],[[]],[43,44],0,0,[28],[[29,30]],0,[[]],[[[43,[17,42]]],[[41,[17]]]],[[[43,[17,42]],38,17],[[41,[17]]]],[[[43,[17,42]],38,18],[[41,[17]]]],[[[43,[17,42]],28],[[41,[17]]]],[[[43,[17,42]],29,30],[[41,[17]]]],[[]],[[]],[[[41,[17,40]]],20],[28,20],[[],43],[41,15],[[]],[[],15],[[],15],[[],15],[[],15],[[],39],[[],39],[[]],[[]],0,0,0,[[49,49],49],[[[50,[[0,[1,2,21]]]],[0,[1,2,21]],[52,[51]]]],[[[50,[[0,[1,2,21]]]]],[[4,[[0,[1,2,21]],[11,[[52,[51]]]]]]]],[[[47,[2]],[47,[2]]]],[[[50,[[0,[1,2,21]]]]]],[[[50,[[0,[1,2,21]]]],[47,[[0,[1,2,21]]]]]],[47,4],[47,4],[[]],[[]],[[]],[[]],[[]],[[]],[[[50,[1]]],[[50,[1]]]],[[[47,[1]]],[[47,[1]]]],[49,49],[[]],[[]],[[]],0,[[],50],[[],47],[[],49],[[],[[15,[47]]]],[[],[[15,[49]]]],[[[47,[19]],47],20],[[49,49],20],[[[50,[21]],22],23],[[[47,[21]],22],23],[[49,22],23],[[49,22],23],[[]],[[]],[[]],0,[[[50,[[0,[1,2,21]]]],27],14],[[[50,[[0,[1,2,21]]]],28]],[[[50,[[0,[1,2,21]]]],29,30]],[[[50,[[0,[1,2,21]]]]]],[[[50,[[0,[1,2,21]]]]],3],[[]],[[]],[[]],[[[47,[2]]],20],[[[50,[[0,[1,2,21]]]],28],20],[[[50,[[0,[1,2,21]]]],[0,[1,2,21]],16],20],[[[50,[[0,[1,2,21]]]]],35],[[[50,[[0,[1,2,21]]]],[34,[16]]],35],[[[50,[[0,[1,2,21]]]]],4],[[[50,[[0,[1,2,21]]]]],[[14,[16]]]],[[[50,[[0,[1,2,21]]]]],4],[[[50,[[0,[1,2,21]]]]],[[14,[16]]]],[[[50,[[0,[1,2,21]]]]],[[4,[[0,[1,2,21]],16]]]],[[[50,[[0,[1,2,21]]]]],16],[[[50,[[0,[1,2,21]]]],16]],[[[50,[[0,[1,2,21]]]],[0,[1,2,21]],16],20],[[[50,[[0,[1,2,21]]]],28],32],[16,50],[[[50,[[0,[1,2,21]]]]]],[[[50,[[0,[1,2,21]]]]]],[[[50,[[0,[1,2,21]]]]],33],[[[50,[[0,[1,2,21]]]]]],[[[50,[[0,[1,2,21]]]],16]],[[[50,[[0,[1,2,21]]]],4]],[[[50,[[0,[1,2,21]]]]],[[0,[35,1]]]],[[[50,[[0,[1,2,21]]]]],[[0,[35,1]]]],[[[50,[[0,[1,2,21]]]],28]],[47,15],[49,15],[[[50,[[0,[1,2,21]]]],[0,[1,2,21]],16],[[14,[27]]]],[[]],[[]],[[]],[[],53],[49,18],0,[49,18],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[[50,[[0,[1,2,21]]]],29],14],[[[50,[[0,[1,2,21]]]]],[[0,[35,37]]]],[[[50,[[0,[1,2,21]]]],38],35],[[],39],[[],39],[[],39],[[[50,[[0,[1,2,21]]]]],[[11,[[52,[51]]]]]],[[[50,[[0,[1,2,21]]]],[0,[1,2,21]],16],20],0,[[[50,[[0,[1,2,21]]]]],[[0,[35,1]]]],[[[50,[[0,[1,2,21]]]]],[[0,[35,1]]]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,0,0,[[54,55],[[15,[56]]]],[[54,57,16],[[15,[55,58]]]],[[54,57,16,5],[[15,[55,59]]]],[[54,60],[[15,[55,58]]]],[61,5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[61,61],[60,60],[54,54],[56,56],[62,62],[58,58],[59,59],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[54,5],[[15,[55,56]]]],[[61,61],20],[[60,60],20],[[54,54],20],[[56,56],20],[[62,62],20],[[58,58],20],[[59,59],20],[[61,45],[[15,[61,61]]]],[[61,22],23],[[60,22],23],[[54,22],23],[[56,22],23],[[56,22],23],[[62,22],23],[[62,22],23],[[58,22],23],[[58,22],23],[[59,22],23],[[59,22],23],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[45,[[15,[61,[14,[61]]]]]],[[[4,[16,63]]],[[15,[54,56]]]],[55,[[15,[54,56]]]],[63],[[57,16],61],[61,[[15,[54,56]]]],[54,63],[[61,16],[[14,[61]]]],[[54,16],[[14,[61]]]],[54,[[15,[5]]]],[61,63],[61,16],0,[54,55],[[54,5],[[15,[55,62]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[61],[[61,20],60],0,[[54,5,5],[[15,[[14,[20]]]]]],[61,64],[54,64],[5,61],[64,14],0,[61,[[14,[61]]]],[65],[65],[65],[65],[[61,5],[[15,[61,61]]]],[61,66],[54,66],[54,61],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],53],[[],53],[[],53],[[],53],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],0,[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,0,0,0,0,0,0,[44,33],[44,66],[48,66],0,0,[[[48,[2]],[48,[2]]]],[[[44,[[0,[1,2]]]],[48,[[0,[1,2]]]]]],[[[44,[[0,[1,2]]]],[44,[[0,[1,2]]]]],[[48,[[0,[1,2]]]]]],[44,44],[[[44,[17]],5,45,67],49],[[[44,[[0,[1,2]]]],45],[[48,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[44,28],[[15,[18,68]]]],0,[[],[[14,[69]]]],[[],[[14,[70]]]],[[],[[14,[69]]]],[[],[[14,[70]]]],[[[44,[1]]],[[44,[1]]]],[[[71,[1,1]]],[[71,[1,1]]]],[[[72,[1,1]]],[[72,[1,1]]]],[[[48,[1]]],[[48,[1]]]],[[]],[[]],[[]],[[]],[[[71,[2,2]],71],12],[[[72,[2,2]],72],12],[[],44],[[],48],[71],[[],[[15,[48]]]],[[44,28],66],[[[44,[19]],44],20],[[[71,[19,19]],71],20],[[[72,[19,19]],72],20],[[68,68],20],[[[48,[19]],48],20],[[[44,[17]],5,45],66],[[[44,[17]],5,45],66],[44,66],[[[44,[21]],22],23],[[[71,[21,21]],22],23],[[[72,[21,21]],22],23],[[68,22],23],[[68,22],23],[[[48,[21]],22],23],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[44,66],[[[44,[17]],5,38],[[14,[8]]]],[[[44,[17]],5,29],14],[[44,38],[[14,[[73,[28]]]]]],[[44,38],[[14,[[71,[[73,[28]]]]]]]],[[44,29],[[14,[30]]]],[[[44,[[0,[1,2]]]]],[[48,[[0,[1,2]]]]]],[[[44,[[0,[1,2]]]],38,[0,[1,2]]],[[48,[[0,[1,2]]]]]],[[[44,[[0,[1,2]]]],38,18],[[48,[[0,[1,2]]]]]],[[[44,[[0,[1,2]]]],28],[[48,[[0,[1,2]]]]]],[[[44,[[0,[1,2]]]],29,30],[[48,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[44,20],[[[48,[2]]],20],0,0,[[[44,[17]],5],66],[[[44,[[0,[1,2]]]]],[[44,[[0,[1,2]]]]]],[[[48,[2]]],[[48,[2]]]],[[[44,[17]],54],66],[[48,54],66],[45,[[44,[[0,[1,2]]]]]],[74,14],[75,14],[[44,29],76],[[[71,[36,36]],71],[[14,[12]]]],[[[72,[36,36]],72],[[14,[12]]]],[65],[48,15],[[]],[[]],[[]],[[]],[[],53],[[[44,[17]],5,45,67],[[15,[49]]]],[[[44,[17]],5,45],66],[[[44,[17]],5,45],66],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[[44,[17]],5,38],[[15,[[14,[8]]]]]],[[[44,[17]],5,29],[[15,[14]]]],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[[44,[17]],5],66],0,0,[[44,38],[[14,[[4,[16,30]]]]]],[[44,38],35],0,[48,66],0,0,[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[],39],[[[44,[[0,[1,2]]]],18],[[48,[[0,[1,2]]]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[44,[[0,[1,2]]]]],[[74,[[0,[1,2]]]]]],[[44,28],75],[[[44,[[0,[1,2]]]],38],[[75,[[0,[1,2]]]]]]],"p":[[8,"Clone"],[8,"Ord"],[3,"SpkTxOutIndex"],[3,"BTreeMap"],[3,"BlockId"],[3,"ConfirmationHeightAnchor"],[3,"ConfirmationTimeHeightAnchor"],[4,"ChainPosition"],[4,"ConfirmationTime"],[3,"FullTxOut"],[3,"SpkIterator"],[4,"Ordering"],[3,"Persist"],[4,"Option"],[4,"Result"],[15,"u32"],[8,"Anchor"],[15,"u64"],[8,"PartialEq"],[15,"bool"],[8,"Debug"],[3,"Formatter"],[6,"Result"],[3,"Block"],[15,"usize"],[8,"Hash"],[3,"Script"],[3,"Transaction"],[3,"OutPoint"],[3,"TxOut"],[3,"ScriptBuf"],[15,"i64"],[3,"BTreeSet"],[8,"RangeBounds"],[8,"DoubleEndedIterator"],[8,"PartialOrd"],[8,"ExactSizeIterator"],[3,"Txid"],[3,"TypeId"],[8,"Append"],[3,"ChangeSet"],[8,"Indexer"],[3,"IndexedTxGraph"],[3,"TxGraph"],[8,"IntoIterator"],[8,"Default"],[3,"ChangeSet"],[3,"ChangeSet"],[3,"Balance"],[3,"KeychainTxOutIndex"],[4,"DescriptorPublicKey"],[4,"Descriptor"],[3,"String"],[3,"LocalChain"],[6,"ChangeSet"],[3,"MissingGenesisError"],[3,"Header"],[3,"CannotConnectError"],[4,"ApplyHeaderError"],[3,"Update"],[3,"CheckPoint"],[3,"AlterCheckPointError"],[3,"BlockHash"],[3,"CheckPointIter"],[3,"Demand"],[8,"Iterator"],[8,"FnMut"],[4,"CalculateFeeError"],[3,"Amount"],[3,"SignedAmount"],[3,"TxNode"],[3,"CanonicalTx"],[3,"Arc"],[3,"TxAncestors"],[3,"TxDescendants"],[3,"HashSet"],[8,"ChainOracle"],[8,"PersistBackend"],[8,"DescriptorExt"],[8,"AnchorFromBlockPosition"],[13,"Confirmed"],[13,"Unconfirmed"]]},\ "bdk_coin_select":{"doc":"","t":[3,3,4,4,3,3,13,6,13,3,4,13,13,13,3,4,3,13,13,17,13,13,13,13,13,3,11,11,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,5,11,11,11,12,11,12,11,11,11,11,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,12,12,12,12,11,11,11,11,12,11,12,12,11,12,12,12,11,11,11,11,12,11,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11],"n":["Bnb","BnbIter","BnbLimit","BranchStrategy","CoinSelector","CoinSelectorOpt","Continue","DecideStrategy","Duration","ExcessStrategy","ExcessStrategyKind","MinAbsoluteFee","MinDrainValue","Rounds","Selection","SelectionConstraint","SelectionError","SkipBoth","SkipInclusion","TXIN_BASE_WEIGHT","TargetFee","TargetValue","ToDrain","ToFee","ToRecipient","WeightedValue","advertise_new_score","all_selected","apply_selection","backtrack","base_weight","best_score","best_strategy","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","candidate","candidates","clone","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","coin_select_bnb","current_excess","current_weight","deselect","drain_value","drain_waste","drain_weight","effective_target","effective_value","eq","eq","excess","excess_strategies","fee","feerate","finish","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","forward","from","from","from","from","from","from","from","from","from","from","from","from","from","from","fund_outputs","hash","input_count","into","into","into","into","into","into","into","into","into","into","into","into","into_iter","into_iter","is_empty","is_segwit","is_selected","long_term_feerate","long_term_feerate","max_extra_target","min_absolute_fee","min_drain_value","new","new","new","next","opts","partial_cmp","pool","pool_pos","provide","recipient_value","rem_abs","rem_eff","select","select_all","select_until_finished","selected","selected","selected_absolute_value","selected_count","selected_effective_value","selected_indexes","selected_waste","selected_weight","selection","spend_drain_weight","target_feerate","target_value","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","to_string","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","unselected","unselected_indexes","value","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","waste","weight","weight","will_continue"],"q":["bdk_coin_select","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Bnb represents the current state of the BnB algorithm.","","Determines how we should limit rounds of branch and bound.","Strategy in which we should branch.","CoinSelector selects and deselects from a set of …","","We continue exploring subtrees of this node, starting with …","Closure to decide the branching strategy, alongside a …","","","","Min absolute fee is not met","Min drain value is not met","","","","","We skip both the inclusion and omission branches of this …","We continue exploring ONLY the omission branch of this …","Txin “base” fields include outpoint (32+4) and …","The target fee (given the feerate) is not met","The target is not met","","","","A WeightedValue represents an input candidate for …","Compare the advertised score with the current best. The …","","","Attempt to backtrack to the previously selected node’s …","The weight of the template transaction, including fixed …","","Returns the ExcessStrategy that results in the least waste.","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","This is a variation of the Branch and Bound Coin Selection …","Current excess.","Current weight of template tx + selected inputs.","","","","Additional weight if we include the drain (change) output.","This is the effective target value.","Effective value of this input candidate: …","","","","","","Returns feerate in sats/wu.","","","","","","","","","","","","","Continue down this branch and skip the inclusion branch if …","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","","The total number of inputs; so we can calculate extra …","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Calls U::from(self).","Turns our Bnb state into an iterator.","","","Whether this WeightedValue contains at least one segwit …","","","The feerate","Additional leeway for the target value.","The minimum absolute fee. I.e., needed for RBF.","Minimum value allowed for a drain (change) output.","Creates a new Bnb.","Create a new WeightedValue that represents a single input.","","","","","","","","","","","","","","","","Absolute value sum of all selected inputs.","","Effective value sum of all selected inputs.","","Waste sum of all selected inputs.","Weight sum of all selected inputs.","","Weight of spending the drain (change) output in the future.","The feerate we should try and achieve in sats per weight …","The value we need to select. If the value is None, then …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Total value of the UTXO(s) that this WeightedValue …","","","","","","","","","","","","","","Total weight of including this/these UTXO(s). txin fields: …","",""],"i":[0,0,0,0,0,0,34,0,22,0,0,11,11,22,0,0,0,34,34,0,11,11,12,12,12,0,2,4,5,2,9,2,5,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,4,4,8,9,4,10,11,5,12,13,8,9,4,10,11,5,12,13,12,0,4,4,4,13,9,9,4,8,11,12,5,5,13,13,4,8,9,4,10,10,11,11,5,12,12,13,2,34,2,26,22,22,22,8,9,4,10,11,5,12,13,9,12,8,34,2,26,22,8,9,4,10,11,5,12,13,2,26,4,8,4,9,9,9,9,9,2,8,4,26,4,12,2,2,10,13,2,2,4,4,4,4,5,4,4,4,4,4,4,2,9,9,9,8,9,4,10,11,5,12,13,10,11,12,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,34,2,26,22,8,9,4,10,11,5,12,13,4,4,8,34,2,26,22,8,9,4,10,11,5,12,13,13,8,13,34],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,[[[2,[1]],1],3],[4,3],[5,6],[[[2,[1]]],3],0,0,[5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[4,7],8],0,[8,8],[9,9],[4,4],[10,10],[11,11],[5,5],[12,12],[13,13],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[12,12],14],[4,[[15,[4]]]],[4,16],[4,17],[[4,7],3],0,[9,16],0,[4,16],[[8,18],16],[[11,11],3],[[12,12],3],0,0,0,[13,18],[4,[[19,[5,10]]]],[[8,20],21],[[9,20],21],[[4,20],21],[[10,20],21],[[10,20],21],[[11,20],21],[[11,20],21],[[5,20],21],[[12,20],21],[[12,20],21],[[13,20],21],[[[2,[1]],3]],[[]],[[]],[[]],[[]],[7,22],[23,22],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[24,17],9],[12],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[[2,[1]],25],[[26,[1]]]],[[]],[4,3],0,[[4,7],3],[9,18],0,0,0,0,[[4,27,1],[[2,[1]]]],[[28,17,3],8],[[27,9],4],[[[26,[[0,[1,29,30]]]]],15],0,[[12,12],[[15,[14]]]],0,0,[31],0,0,0,[[4,7],3],[4],[4,[[19,[5,10]]]],[4,6],0,[4,28],[4,7],[4,16],[4,6],[4,16],[4,17],0,0,0,0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],32],[[],32],[[],32],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],19],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[[],33],[4,6],[4,6],0,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],0,0,0,[34,3]],"p":[[8,"Ord"],[3,"Bnb"],[15,"bool"],[3,"CoinSelector"],[3,"Selection"],[8,"Iterator"],[15,"usize"],[3,"WeightedValue"],[3,"CoinSelectorOpt"],[3,"SelectionError"],[4,"SelectionConstraint"],[4,"ExcessStrategyKind"],[3,"ExcessStrategy"],[4,"Ordering"],[4,"Option"],[15,"i64"],[15,"u32"],[15,"f32"],[4,"Result"],[3,"Formatter"],[6,"Result"],[4,"BnbLimit"],[3,"Duration"],[3,"TxOut"],[6,"DecideStrategy"],[3,"BnbIter"],[3,"Vec"],[15,"u64"],[8,"Copy"],[8,"Display"],[3,"Demand"],[3,"String"],[3,"TypeId"],[4,"BranchStrategy"]]},\ diff --git a/examples/index.html b/examples/index.html index 17c097fe4c..d55135ff53 100644 --- a/examples/index.html +++ b/examples/index.html @@ -29,7 +29,7 @@ - + @@ -53,7 +53,7 @@ Blog
    GitHub - (opens new window)

    # Examples

    Click the links below and learn from community-built example projects.

    # BDK-CLI (opens new window)

    A command line interface to experiment with the bitcoindevkit.

    # DevkitWallet (opens new window)

    A demo app for the bitcoindevkit on Android using bdk-kotlin.

    # Padawan Wallet (opens new window)

    A testnet-only bitcoin wallet full of tutorials on how to use bitcoin wallets.

    # BDKSwiftExampleWallet (opens new window)

    An example iOS app using bdk-swift.

    # Tatooine (opens new window)

    Tatooine is a small bitcoin testnet faucet built with Ktor, a Kotlin asynchronous framework for creating microservices and web applications.

    # SEBA Bank Proof of reserves (opens new window)

    The bdk library aims to be the core building block for Bitcoin wallets of any kind. The bdk-reserves library provides an implementation of proof-of-reserves for bdk.

    # Stackmate (opens new window)

    A multi-purpose Bitcoin Wallet.

    # Spotbit (opens new window)

    Spotbit's purpose is to allow users to access price feeds in a customisable way that preserves privacy and mitigate the reliance on a single source of data.

    - + diff --git a/foundation/index.html b/foundation/index.html index bd8dcdd842..61b3bfc58d 100644 --- a/foundation/index.html +++ b/foundation/index.html @@ -29,7 +29,7 @@ - + @@ -74,6 +74,6 @@
    - + diff --git a/getting-started/index.html b/getting-started/index.html index e4b0b428ac..8b8738bf55 100644 --- a/getting-started/index.html +++ b/getting-started/index.html @@ -31,7 +31,7 @@ - + @@ -105,7 +105,7 @@ wallet.get_descriptor_for_keychain(KeychainKind::External).to_string(), wallet.get_descriptor_for_keychain(KeychainKind::Internal).to_string()); } -

    More information about each component used in the code can be found in BDK Documentation (opens new window).

    More information about each component used in the code can be found in BDK Documentation (opens new window).

    - + diff --git a/index.html b/index.html index dbfb18deb9..c9b159f5be 100644 --- a/index.html +++ b/index.html @@ -29,7 +29,7 @@ - + @@ -80,6 +80,6 @@
    - + diff --git a/sitemap.xml b/sitemap.xml index 3cc0a6fe8f..d4507be938 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -https://bitcoindevkit.org/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/_2024-q4-update/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bitcoin-core-rpc-demo/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bdk-cli-basics/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bdk-core-pt1/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bdk-cli-basics-multisig-2of3/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bdk-rn-making-of/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bdk-with-tor/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/bindings-scope/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/compact-filters-demo/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/descriptor-based-paper-wallet/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/exploring-bdk-flutter/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-1/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/exploring-bdk-rn/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-3/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-2/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/12/first-bdk-taproot-tx-look-at-the-code-part-2/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/11/first-bdk-taproot-tx-look-at-the-code-part-1/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/descriptors-in-the-wild/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/getting-started-with-rust-hwi/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/hidden-power-of-bitcoin/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/improving-coin-selection-in-bdk/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2020/12/hello-world/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2020/12/release-v0.2.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/miniscript-vulnerability/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/release-v0.3.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/02/release-v0.4.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/04/release-v0.6.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/03/release-v0.5.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/05/release-v0.7.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/06/release-v0.8.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/2021/07/release-v0.9.0/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/spending-policy-demo/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/road-to-bdk-1/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/using-bdk-with-hardware-wallets/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/compiler/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/installation/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/concept/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/interface/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/introduction/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/playground/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/case-studies/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/bdk-cli/regtest/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/foundation/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/examples/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/descriptors/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/getting-started/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/supporters/2024-04-10T19:23:58.000Zdailyhttps://bitcoindevkit.org/blog/dailyhttps://bitcoindevkit.org/blog/tags/dailyhttps://bitcoindevkit.org/blog/author/dailyhttps://bitcoindevkit.org/blog/tags/BDK/dailyhttps://bitcoindevkit.org/blog/tags/project/dailyhttps://bitcoindevkit.org/blog/tags/tutorial/dailyhttps://bitcoindevkit.org/blog/tags/Bitcoin%20Core/dailyhttps://bitcoindevkit.org/blog/tags/RPC/dailyhttps://bitcoindevkit.org/blog/tags/Wallet/dailyhttps://bitcoindevkit.org/blog/tags/bdk-cli/dailyhttps://bitcoindevkit.org/blog/tags/basics/dailyhttps://bitcoindevkit.org/blog/tags/novice/dailyhttps://bitcoindevkit.org/blog/tags/architecture/dailyhttps://bitcoindevkit.org/blog/tags/multi-sig/dailyhttps://bitcoindevkit.org/blog/tags/BDK-RN/dailyhttps://bitcoindevkit.org/blog/tags/Development/dailyhttps://bitcoindevkit.org/blog/tags/Architecture/dailyhttps://bitcoindevkit.org/blog/tags/tor/dailyhttps://bitcoindevkit.org/blog/tags/wallet/dailyhttps://bitcoindevkit.org/blog/tags/blockchain/dailyhttps://bitcoindevkit.org/blog/tags/bindings/dailyhttps://bitcoindevkit.org/blog/tags/compact_filters/dailyhttps://bitcoindevkit.org/blog/tags/BIP157/dailyhttps://bitcoindevkit.org/blog/tags/Neutrino/dailyhttps://bitcoindevkit.org/blog/tags/guide/dailyhttps://bitcoindevkit.org/blog/tags/descriptor/dailyhttps://bitcoindevkit.org/blog/tags/paper%20wallets/dailyhttps://bitcoindevkit.org/blog/tags/bitcoin/dailyhttps://bitcoindevkit.org/blog/tags/React%20Native/dailyhttps://bitcoindevkit.org/blog/tags/Flutter/dailyhttps://bitcoindevkit.org/blog/tags/iOS/dailyhttps://bitcoindevkit.org/blog/tags/Android/dailyhttps://bitcoindevkit.org/blog/tags/mobile/dailyhttps://bitcoindevkit.org/blog/tags/bdk-rn/dailyhttps://bitcoindevkit.org/blog/tags/bdk/dailyhttps://bitcoindevkit.org/blog/tags/fee/dailyhttps://bitcoindevkit.org/blog/tags/machine%20learning/dailyhttps://bitcoindevkit.org/blog/tags/taproot/dailyhttps://bitcoindevkit.org/blog/tags/miniscript/dailyhttps://bitcoindevkit.org/blog/tags/Hardware%20Wallets/dailyhttps://bitcoindevkit.org/blog/tags/bitcoin-cli/dailyhttps://bitcoindevkit.org/blog/tags/coin%20selection/dailyhttps://bitcoindevkit.org/blog/tags/development/dailyhttps://bitcoindevkit.org/blog/tags/summer%20of%20bitcoin/dailyhttps://bitcoindevkit.org/blog/tags/getting%20started/dailyhttps://bitcoindevkit.org/blog/tags/rust/dailyhttps://bitcoindevkit.org/blog/tags/release/dailyhttps://bitcoindevkit.org/blog/tags/security/dailyhttps://bitcoindevkit.org/blog/author/Steve%20Myers/dailyhttps://bitcoindevkit.org/blog/author/Daniela%20Brozzoni/dailyhttps://bitcoindevkit.org/blog/author/Rajarshi%20Maitra/dailyhttps://bitcoindevkit.org/blog/author/waterst0ne/dailyhttps://bitcoindevkit.org/blog/author/Lloyd%20Fournier/dailyhttps://bitcoindevkit.org/blog/author/Bitcoin%20Zavior/dailyhttps://bitcoindevkit.org/blog/author/rorp/dailyhttps://bitcoindevkit.org/blog/author/thunderbiscuit/dailyhttps://bitcoindevkit.org/blog/author/Riccardo%20Casatta/dailyhttps://bitcoindevkit.org/blog/author/Alekos%20Filini/dailyhttps://bitcoindevkit.org/blog/author/Gabriele%20Domenichini/dailyhttps://bitcoindevkit.org/blog/author/Wszdexdrf/dailyhttps://bitcoindevkit.org/blog/author/Sandipan%20Dey/dailyhttps://bitcoindevkit.org/blog/author/C%C3%A9sar%20Alvarez%20Vallero/dailyhttps://bitcoindevkit.org/blog/page/2/dailyhttps://bitcoindevkit.org/blog/page/3/dailyhttps://bitcoindevkit.org/blog/page/4/dailyhttps://bitcoindevkit.org/blog/author/Alekos%20Filini/page/2/daily \ No newline at end of file +https://bitcoindevkit.org/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/_2024-q4-update/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bdk-cli-basics-multisig-2of3/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bdk-cli-basics/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bdk-core-pt1/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bitcoin-core-rpc-demo/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bdk-rn-making-of/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bdk-with-tor/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/bindings-scope/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/compact-filters-demo/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/descriptors-in-the-wild/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/descriptor-based-paper-wallet/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/exploring-bdk-flutter/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/exploring-bdk-rn/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-1/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-3/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/fee-estimation-for-light-clients-part-2/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/11/first-bdk-taproot-tx-look-at-the-code-part-1/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/12/first-bdk-taproot-tx-look-at-the-code-part-2/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/getting-started-with-rust-hwi/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/hidden-power-of-bitcoin/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2020/12/hello-world/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/improving-coin-selection-in-bdk/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/miniscript-vulnerability/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2020/12/release-v0.2.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/01/release-v0.3.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/02/release-v0.4.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/03/release-v0.5.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/05/release-v0.7.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/07/release-v0.9.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/road-to-bdk-1/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/04/release-v0.6.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/2021/06/release-v0.8.0/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/spending-policy-demo/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/using-bdk-with-hardware-wallets/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/compiler/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/concept/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/installation/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/interface/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/introduction/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/playground/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/bdk-cli/regtest/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/case-studies/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/descriptors/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/examples/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/getting-started/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/foundation/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/supporters/2024-04-15T20:13:59.000Zdailyhttps://bitcoindevkit.org/blog/dailyhttps://bitcoindevkit.org/blog/tags/dailyhttps://bitcoindevkit.org/blog/author/dailyhttps://bitcoindevkit.org/blog/tags/BDK/dailyhttps://bitcoindevkit.org/blog/tags/project/dailyhttps://bitcoindevkit.org/blog/tags/tutorial/dailyhttps://bitcoindevkit.org/blog/tags/bdk-cli/dailyhttps://bitcoindevkit.org/blog/tags/multi-sig/dailyhttps://bitcoindevkit.org/blog/tags/basics/dailyhttps://bitcoindevkit.org/blog/tags/novice/dailyhttps://bitcoindevkit.org/blog/tags/architecture/dailyhttps://bitcoindevkit.org/blog/tags/Bitcoin%20Core/dailyhttps://bitcoindevkit.org/blog/tags/RPC/dailyhttps://bitcoindevkit.org/blog/tags/Wallet/dailyhttps://bitcoindevkit.org/blog/tags/BDK-RN/dailyhttps://bitcoindevkit.org/blog/tags/Development/dailyhttps://bitcoindevkit.org/blog/tags/Architecture/dailyhttps://bitcoindevkit.org/blog/tags/tor/dailyhttps://bitcoindevkit.org/blog/tags/wallet/dailyhttps://bitcoindevkit.org/blog/tags/blockchain/dailyhttps://bitcoindevkit.org/blog/tags/bindings/dailyhttps://bitcoindevkit.org/blog/tags/compact_filters/dailyhttps://bitcoindevkit.org/blog/tags/BIP157/dailyhttps://bitcoindevkit.org/blog/tags/Neutrino/dailyhttps://bitcoindevkit.org/blog/tags/guide/dailyhttps://bitcoindevkit.org/blog/tags/descriptor/dailyhttps://bitcoindevkit.org/blog/tags/paper%20wallets/dailyhttps://bitcoindevkit.org/blog/tags/bitcoin/dailyhttps://bitcoindevkit.org/blog/tags/React%20Native/dailyhttps://bitcoindevkit.org/blog/tags/Flutter/dailyhttps://bitcoindevkit.org/blog/tags/iOS/dailyhttps://bitcoindevkit.org/blog/tags/Android/dailyhttps://bitcoindevkit.org/blog/tags/mobile/dailyhttps://bitcoindevkit.org/blog/tags/bdk-rn/dailyhttps://bitcoindevkit.org/blog/tags/bdk/dailyhttps://bitcoindevkit.org/blog/tags/fee/dailyhttps://bitcoindevkit.org/blog/tags/machine%20learning/dailyhttps://bitcoindevkit.org/blog/tags/taproot/dailyhttps://bitcoindevkit.org/blog/tags/miniscript/dailyhttps://bitcoindevkit.org/blog/tags/Hardware%20Wallets/dailyhttps://bitcoindevkit.org/blog/tags/bitcoin-cli/dailyhttps://bitcoindevkit.org/blog/tags/getting%20started/dailyhttps://bitcoindevkit.org/blog/tags/rust/dailyhttps://bitcoindevkit.org/blog/tags/coin%20selection/dailyhttps://bitcoindevkit.org/blog/tags/development/dailyhttps://bitcoindevkit.org/blog/tags/summer%20of%20bitcoin/dailyhttps://bitcoindevkit.org/blog/tags/security/dailyhttps://bitcoindevkit.org/blog/tags/release/dailyhttps://bitcoindevkit.org/blog/author/Steve%20Myers/dailyhttps://bitcoindevkit.org/blog/author/Daniela%20Brozzoni/dailyhttps://bitcoindevkit.org/blog/author/waterst0ne/dailyhttps://bitcoindevkit.org/blog/author/Lloyd%20Fournier/dailyhttps://bitcoindevkit.org/blog/author/Rajarshi%20Maitra/dailyhttps://bitcoindevkit.org/blog/author/Bitcoin%20Zavior/dailyhttps://bitcoindevkit.org/blog/author/rorp/dailyhttps://bitcoindevkit.org/blog/author/thunderbiscuit/dailyhttps://bitcoindevkit.org/blog/author/Gabriele%20Domenichini/dailyhttps://bitcoindevkit.org/blog/author/Riccardo%20Casatta/dailyhttps://bitcoindevkit.org/blog/author/Alekos%20Filini/dailyhttps://bitcoindevkit.org/blog/author/Wszdexdrf/dailyhttps://bitcoindevkit.org/blog/author/Sandipan%20Dey/dailyhttps://bitcoindevkit.org/blog/author/C%C3%A9sar%20Alvarez%20Vallero/dailyhttps://bitcoindevkit.org/blog/page/2/dailyhttps://bitcoindevkit.org/blog/page/3/dailyhttps://bitcoindevkit.org/blog/page/4/dailyhttps://bitcoindevkit.org/blog/author/Alekos%20Filini/page/2/daily \ No newline at end of file diff --git a/supporters/index.html b/supporters/index.html index 28e98a3ec2..9d8cebf79d 100644 --- a/supporters/index.html +++ b/supporters/index.html @@ -29,7 +29,7 @@ - + @@ -63,7 +63,7 @@ Brink Sponsor Kraken Kraken -
    - +