Compare commits
30 Commits
release/0.
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
634d7db36e | ||
|
|
2233517495 | ||
|
|
49716471d4 | ||
|
|
ced11cb1ee | ||
|
|
5f7d8a9077 | ||
|
|
d77f5b84c3 | ||
|
|
6555170d28 | ||
|
|
c763609b8b | ||
|
|
340fa19bb8 | ||
|
|
ff2734663e | ||
|
|
f399b799e4 | ||
|
|
cdde26a8ea | ||
|
|
34af88df6f | ||
|
|
12e9a18357 | ||
|
|
bada9b82e0 | ||
|
|
41f15fe80f | ||
|
|
54953fa208 | ||
|
|
b7ccf81c7a | ||
|
|
3792a98426 | ||
|
|
5dd79e9632 | ||
|
|
9ae938ca8c | ||
|
|
05aa7157df | ||
|
|
275bd94148 | ||
|
|
146cb039c3 | ||
|
|
41fdadb09c | ||
|
|
4ed6e364e6 | ||
|
|
d0cd3b0f38 | ||
|
|
f216417fd2 | ||
|
|
7d1a4500ef | ||
|
|
a408387bff |
4
.github/workflows/build-python-wheels.yaml
vendored
4
.github/workflows/build-python-wheels.yaml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-macos-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||
|
||||
build-windows-wheel:
|
||||
name: 'Build windows wheel'
|
||||
@@ -123,4 +123,4 @@ jobs:
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-win-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
|
||||
|
||||
4
.github/workflows/publish-python.yaml
vendored
4
.github/workflows/publish-python.yaml
vendored
@@ -82,7 +82,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-macos-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||
|
||||
build-windows-wheel:
|
||||
name: 'Build windows wheel'
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-win-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
|
||||
|
||||
publish-pypi:
|
||||
name: 'Publish on PyPI'
|
||||
|
||||
5
.github/workflows/test-android.yaml
vendored
5
.github/workflows/test-android.yaml
vendored
@@ -46,11 +46,6 @@ jobs:
|
||||
- name: Install rust android targets
|
||||
run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
|
||||
|
||||
- name: Build bdk-android library
|
||||
run: |
|
||||
cd bdk-android
|
||||
./gradlew buildAndroidLib
|
||||
|
||||
- name: Run Android tests
|
||||
run: |
|
||||
cd bdk-android
|
||||
|
||||
5
.github/workflows/test-jvm.yaml
vendored
5
.github/workflows/test-jvm.yaml
vendored
@@ -31,11 +31,6 @@ jobs:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Build bdk-jvm library
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
./gradlew buildJvmLib
|
||||
|
||||
- name: Run JVM tests
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
|
||||
290
Cargo.lock
generated
290
Cargo.lock
generated
@@ -2,6 +2,12 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.6"
|
||||
@@ -24,9 +30,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.66"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
|
||||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
@@ -74,10 +80,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.59"
|
||||
name = "assert_matches"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
|
||||
checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -108,16 +120,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "bdk"
|
||||
version = "0.25.0"
|
||||
name = "base64-compat"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1e7eb54c6288eca1b698e6e33dd82ebe6c08a93ec1a96bb6926ddceed22c703"
|
||||
checksum = "5a8d4d2746f89841e49230dd26917df1876050f95abafafbe34f47cb534b88d7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bdk"
|
||||
version = "0.26.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b238a07736baee43ba9663933e44b1c6c27b43ef871b9486e175902335d83880"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"async-trait",
|
||||
"bdk-macros",
|
||||
"bip39",
|
||||
"bitcoin",
|
||||
"bitcoincore-rpc",
|
||||
"electrum-client",
|
||||
"esplora-client",
|
||||
"getrandom",
|
||||
@@ -134,8 +156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bdk-ffi"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"bdk",
|
||||
"uniffi",
|
||||
"uniffi_build",
|
||||
@@ -218,6 +241,30 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoincore-rpc"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0261b2bb7617e0c91b452a837bbd1291fd34ad6990cb8e3ffc28239cc045b5ca"
|
||||
dependencies = [
|
||||
"bitcoincore-rpc-json",
|
||||
"jsonrpc",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoincore-rpc-json"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c231bea28e314879c5aef240f6052e8a72a369e3c9f9b20d9bfbb33ad18029b2"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@@ -275,9 +322,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.77"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
|
||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@@ -285,12 +332,6 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chunked_transfer"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.34.0"
|
||||
@@ -386,19 +427,19 @@ dependencies = [
|
||||
"byteorder",
|
||||
"libc",
|
||||
"log",
|
||||
"rustls 0.20.7",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"webpki 0.22.0",
|
||||
"webpki-roots 0.22.5",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "esplora-client"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b94400573de17e346ab91ec08ad13d37e871e400b9930d4cb2b6b02253e760e"
|
||||
checksum = "38bbba572d03ca4d628b653f01e60ba6947c67df65ee8910c79daaf252897924"
|
||||
dependencies = [
|
||||
"bitcoin",
|
||||
"log",
|
||||
@@ -418,6 +459,16 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "form_urlencoded"
|
||||
version = "1.1.0"
|
||||
@@ -554,9 +605,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
@@ -567,6 +618,18 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f8423b78fc94d12ef1a4a9d13c348c9a78766dda0cc18817adf0faf77e670c8"
|
||||
dependencies = [
|
||||
"base64-compat",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@@ -575,9 +638,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.138"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
@@ -669,10 +732,19 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.1"
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
@@ -680,9 +752,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
@@ -703,9 +775,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"instant",
|
||||
@@ -717,9 +789,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
|
||||
checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
@@ -777,18 +849,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
version = "1.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -868,19 +940,6 @@ dependencies = [
|
||||
"smallvec 1.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"log",
|
||||
"ring",
|
||||
"sct 0.6.1",
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.20.7"
|
||||
@@ -889,15 +948,15 @@ checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"sct 0.7.0",
|
||||
"webpki 0.22.0",
|
||||
"sct",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.11"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@@ -925,16 +984,6 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sct"
|
||||
version = "0.7.0"
|
||||
@@ -947,9 +996,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.24.1"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964"
|
||||
checksum = "d9512ffd81e3a3503ed401f79c33168b9148c75038956039166cd750eaa037c3"
|
||||
dependencies = [
|
||||
"bitcoin_hashes 0.11.0",
|
||||
"rand",
|
||||
@@ -968,27 +1017,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.14"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
|
||||
checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.149"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.149"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -997,15 +1046,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.89"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
|
||||
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
|
||||
[[package]]
|
||||
name = "sled"
|
||||
version = "0.34.7"
|
||||
@@ -1098,9 +1153,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.105"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1156,9 +1211,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
@@ -1180,9 +1235,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
@@ -1207,9 +1262,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "uniffi"
|
||||
version = "0.21.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f54af5ada67d1173457a99a7bb44a7917f63e7466764cb4714865c7a6678b830"
|
||||
checksum = "b983553c0d1ad73547c65fa0c399aa800bee4a70ad330198e1c7a523212da5ee"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -1225,9 +1280,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_bindgen"
|
||||
version = "0.21.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12cc4af3c0180c7e86c4a3acf2b6587af04ba2567b1e948993df10f421796621"
|
||||
checksum = "5d46080a4840abccf7c0cce21931dae53215cbd7dd969b5e63c486235ce91a2a"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"askama",
|
||||
@@ -1248,9 +1303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_build"
|
||||
version = "0.21.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "510287c368a9386eb731ebe824a6fc6c82a105e20d020af1aa20519c1c1561db"
|
||||
checksum = "d035e50433ee3d52ab0dcdcf3b9b26f2cc2ec39294b3c07d95865a518709455f"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"camino",
|
||||
@@ -1258,10 +1313,20 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_macros"
|
||||
version = "0.21.0"
|
||||
name = "uniffi_checksum_derive"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8604503caa2cbcf271578dc51ca236d40e3b22e1514ffa2e638e2c39f6ad10"
|
||||
checksum = "78b6e16d46caf942016997af8bbdf4b163bf8ae3deb0b667d9643de7b7ffd4c9"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_macros"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c96a574677566f83ea8458dac1dd7792fd63e7c3f9dbcd865f0e8d6f8057b127"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"camino",
|
||||
@@ -1278,11 +1343,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "uniffi_meta"
|
||||
version = "0.21.0"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd9417cc653937681436b93838d8c5f97a5b8c58697813982ee8810bd1dc3b57"
|
||||
checksum = "729835442da829c9b6f7c111c76cf87b2498e129101203bec94f0c39a3296a38"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"siphasher",
|
||||
"uniffi_checksum_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1293,21 +1360,21 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "2.2.0"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3131cd6cb18488da91da1d10ed31e966f453c06b65bf010d35638456976a3fd7"
|
||||
checksum = "733b5ad78377302af52c0dbcb2623d78fe50e4b3bf215948ff29e9ee031d8566"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chunked_transfer",
|
||||
"flate2",
|
||||
"log",
|
||||
"once_cell",
|
||||
"rustls 0.19.1",
|
||||
"rustls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"socks",
|
||||
"url",
|
||||
"webpki 0.21.4",
|
||||
"webpki-roots 0.21.1",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1409,16 +1476,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki"
|
||||
version = "0.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki"
|
||||
version = "0.22.0"
|
||||
@@ -1431,20 +1488,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.21.1"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aabe153544e473b775453675851ecc86863d2a81d786d741f6b76778f2a48940"
|
||||
checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
|
||||
dependencies = [
|
||||
"webpki 0.21.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.22.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
|
||||
dependencies = [
|
||||
"webpki 0.22.0",
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
6
api-docs/README.md
Normal file
6
api-docs/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# API documentation
|
||||
The Bitcoin Dev Kit language bindings make use of the [uniffi-rs](https://github.com/mozilla/uniffi-rs) library to produce their bindings. While efforts are ongoing to allow inline documentation on the Rust side to be ported to the bindings code, this is not currently possible.
|
||||
|
||||
This directory contains our temporary solution to this problem. A set of files mimicking the bindings libraries in their function signatures, but without any implementation. This allows for documentation build tools to produce API docs similarly to how we would like them to be if they could be inlined.
|
||||
|
||||
You can find the resulting API documentation websites in the ["API Reference" section of the sidebar](https://bitcoindevkit.org/getting-started/) under the "Docs" tab on the bitcoindevkit official website.
|
||||
@@ -120,15 +120,17 @@ data class SledDbConfiguration(
|
||||
* @property retry Request retry count.
|
||||
* @property timeout Request timeout (seconds).
|
||||
* @property stopGap Stop searching addresses for transactions after finding an unused gap of this length.
|
||||
* @property validateDomain Validate the domain when using SSL.
|
||||
*
|
||||
* @sample org.bitcoindevkit.electrumBlockchainConfigSample
|
||||
*/
|
||||
data class ElectrumConfig (
|
||||
data class ElectrumConfig(
|
||||
var url: String,
|
||||
var socks5: String?,
|
||||
var retry: UByte,
|
||||
var timeout: UByte?,
|
||||
var stopGap: ULong
|
||||
var stopGap: ULong,
|
||||
var validateDomain: Boolean
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -142,7 +144,7 @@ data class ElectrumConfig (
|
||||
*
|
||||
* @sample org.bitcoindevkit.esploraBlockchainConfigSample
|
||||
*/
|
||||
data class EsploraConfig (
|
||||
data class EsploraConfig(
|
||||
var baseUrl: String,
|
||||
var proxy: String?,
|
||||
var concurrency: UByte?,
|
||||
@@ -150,6 +152,56 @@ data class EsploraConfig (
|
||||
var timeout: ULong?
|
||||
)
|
||||
|
||||
/**
|
||||
* Authentication mechanism for RPC connection to full node.
|
||||
*/
|
||||
sealed class Auth {
|
||||
/** No authentication */
|
||||
object None: Auth()
|
||||
|
||||
/** Authentication with username and password, usually [Auth.Cookie] should be preferred */
|
||||
data class UserPass(val username: String, val password: String): Auth()
|
||||
|
||||
/** Authentication with a cookie file */
|
||||
data class Cookie(val file: String): Auth()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sync parameters for Bitcoin Core RPC.
|
||||
*
|
||||
* In general, BDK tries to sync `scriptPubKey`s cached in `Database` with
|
||||
* `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining
|
||||
* how the `importdescriptors` RPC calls are to be made.
|
||||
*
|
||||
* @property startScriptCount The minimum number of scripts to scan for on initial sync.
|
||||
* @property startTime Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).
|
||||
* @property forceStartTime Forces every sync to use `start_time` as import timestamp.
|
||||
* @property pollRateSec RPC poll rate (in seconds) to get state updates.
|
||||
*/
|
||||
data class RcpSyncParams(
|
||||
val startScriptCount: ULong,
|
||||
val startTime: Ulong,
|
||||
val forceStartTime: Boolean,
|
||||
val pollRateSec: ULong,
|
||||
)
|
||||
|
||||
/**
|
||||
* RpcBlockchain configuration options
|
||||
*
|
||||
* @property url The bitcoin node url.
|
||||
* @property auth The bicoin node authentication mechanism.
|
||||
* @property network The network we are using (it will be checked the bitcoin node network matches this).
|
||||
* @property walletName The wallet name in the bitcoin node.
|
||||
* @property syncParams Sync parameters.
|
||||
*/
|
||||
data class RpcConfig(
|
||||
val url: String,
|
||||
val auth: Auth,
|
||||
val network: Network,
|
||||
val walletName: String,
|
||||
val syncParams: RcpSyncParams?,
|
||||
)
|
||||
|
||||
/**
|
||||
* Type that can contain any of the blockchain configurations defined by the library.
|
||||
*
|
||||
@@ -161,6 +213,9 @@ sealed class BlockchainConfig {
|
||||
|
||||
/** Esplora client. */
|
||||
data class Esplora(val config: EsploraConfig) : BlockchainConfig()
|
||||
|
||||
/** Bitcoin Core RPC client. */
|
||||
data class Rpc(val config: RpcConfig) : BlockchainConfig()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +248,7 @@ class Blockchain(
|
||||
config: BlockchainConfig
|
||||
) {
|
||||
/** Broadcast a transaction. */
|
||||
fun broadcast(psbt: PartiallySignedBitcoinTransaction): String {}
|
||||
fun broadcast(psbt: PartiallySignedBitcoinTransaction) {}
|
||||
|
||||
/** Get the current height of the blockchain. */
|
||||
fun getHeight(): UInt {}
|
||||
@@ -295,15 +350,15 @@ data class BlockTime (
|
||||
* @constructor Create a BDK wallet.
|
||||
*
|
||||
* @param descriptor The main (or "external") descriptor.
|
||||
* @param changeDescriptor The change (or "internal") descriptor.
|
||||
* @param changeDescriptor? The change (or "internal") descriptor.
|
||||
* @param network The network to act on.
|
||||
* @param databaseConfig The database configuration.
|
||||
*
|
||||
* @sample org.bitcoindevkit.walletSample
|
||||
*/
|
||||
class Wallet(
|
||||
descriptor: String,
|
||||
changeDescriptor: String,
|
||||
descriptor: Descriptor,
|
||||
changeDescriptor: Descriptor?,
|
||||
network: Network,
|
||||
databaseConfig: DatabaseConfig,
|
||||
) {
|
||||
@@ -314,8 +369,8 @@ class Wallet(
|
||||
*/
|
||||
fun getAddress(addressIndex: AddressIndex): AddressInfo {}
|
||||
|
||||
/** Return the balance, meaning the sum of this wallet’s unspent outputs’ values. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
|
||||
fun getBalance(): ULong {}
|
||||
/** Return the wallet's balance, across different categories. See [Balance] for the categories. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
|
||||
fun getBalance(): Balance {}
|
||||
|
||||
/** Sign a transaction with all the wallet’s signers. */
|
||||
fun sign(psbt: PartiallySignedBitcoinTransaction): Boolean {}
|
||||
@@ -410,7 +465,7 @@ class TxBuilder() {
|
||||
* [drainWallet] to spend all of them. When bumping the fees of a transaction made with this option,
|
||||
* you probably want to use [BumpFeeTxBuilder.allowShrinking] to allow this output to be reduced to pay for the extra fees.
|
||||
*/
|
||||
fun drainTo(address: String): TxBuilder {}
|
||||
fun drainTo(script: Script): TxBuilder {}
|
||||
|
||||
/** Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`. */
|
||||
fun enableRbf(): TxBuilder {}
|
||||
@@ -495,7 +550,7 @@ class DescriptorSecretKey(network: Network, mnemonic: Mnemonic, password: String
|
||||
/** Return the public version of the descriptor. */
|
||||
fun asPublic(): DescriptorPublicKey {}
|
||||
|
||||
/* Return the raw private key as bytes. */
|
||||
/** Return the raw private key as bytes. */
|
||||
fun secretBytes(): List<UByte>
|
||||
|
||||
/** Return the private descriptor as a string. */
|
||||
@@ -523,6 +578,62 @@ class DescriptorPublicKey(network: Network, mnemonic: String, password: String?)
|
||||
fun asString(): String
|
||||
}
|
||||
|
||||
/**
|
||||
* A output descriptor.
|
||||
*
|
||||
* @param descriptor The descriptor in string format.
|
||||
* @param network The network this descriptor is to be used on.
|
||||
*
|
||||
* @sample org.bitcoindevkit.descriptorTemplates1
|
||||
* @sample org.bitcoindevkit.descriptorTemplates2
|
||||
*/
|
||||
class Descriptor(descriptor: String, network: Network) {
|
||||
/**
|
||||
* BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/\*)
|
||||
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
|
||||
*/
|
||||
fun newBip44(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/**
|
||||
* BIP44 public template. Expands to pkh(key/{0,1}/\*)
|
||||
* This assumes that the key used has already been derived with m/44'/0'/0' for Mainnet or m/44'/1'/0' for Testnet.
|
||||
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||
*/
|
||||
fun newBip44Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/**
|
||||
* BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/\*))
|
||||
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
|
||||
*/
|
||||
fun newBip49(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/**
|
||||
* BIP49 public template. Expands to sh(wpkh(key/{0,1}/\*))
|
||||
* This assumes that the key used has already been derived with m/49'/0'/0' for Mainnet or m/49'/1'/0' for Testnet.
|
||||
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||
*/
|
||||
fun newBip49Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/**
|
||||
* BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/\*)
|
||||
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
|
||||
*/
|
||||
fun newBip84(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/**
|
||||
* BIP84 public template. Expands to wpkh(key/{0,1}/\*)
|
||||
* This assumes that the key used has already been derived with m/84'/0'/0' for Mainnet or m/84'/1'/0' for Testnet.
|
||||
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
|
||||
*/
|
||||
fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
|
||||
|
||||
/** Return the public version of the output descriptor. */
|
||||
fun asString(): String {}
|
||||
|
||||
/** Return the private version of the output descriptor if available, otherwise return the public version. */
|
||||
fun asStringPrivate(): String {}
|
||||
}
|
||||
|
||||
/**
|
||||
* An enum describing entropy length (aka word count) in the mnemonic.
|
||||
*/
|
||||
@@ -568,7 +679,7 @@ class Script(rawOutputScript: List<UByte>)
|
||||
* @param address The address in string format.
|
||||
*/
|
||||
class Address(address: String) {
|
||||
/* Return the ScriptPubKey. */
|
||||
/** Return the ScriptPubKey. */
|
||||
fun scriptPubkey(): Script
|
||||
}
|
||||
|
||||
|
||||
@@ -243,3 +243,34 @@ fun mnemonicSample() {
|
||||
|
||||
println(mnemonic0.asString(), mnemonic1.asString(), mnemonic2.asString())
|
||||
}
|
||||
|
||||
fun descriptorTemplates1() {
|
||||
// Bip84 private descriptor
|
||||
val recoveryPhrase: String = "scene change clap smart together mind wheel knee clip normal trial unusual"
|
||||
val mnemonic = Mnemonic.fromString(recoveryPhrase)
|
||||
val bip32ExtendedRootKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
|
||||
val bip84ExternalDescriptor: Descriptor = Descriptor.newBip84(bip32ExtendedRootKey, KeychainKind.EXTERNAL, Network.TESTNET)
|
||||
}
|
||||
|
||||
fun descriptorTemplates2() {
|
||||
// Bip49 public descriptor
|
||||
// assume we already have the xpub for m/49'/0'/1' created on an external device that only shared the xpub with the wallet
|
||||
// using the template requires the parent fingerprint to populate correctly the metadata of PSBTs, which the external device would provide
|
||||
// the xpub (tpub for testnet): tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR
|
||||
// the fingerprint: d1d04177
|
||||
val descriptorPublicKey: DescriptorPublicKey = DescriptorPublicKey.fromString("tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR")
|
||||
val bip49PublicDescriptor: Descriptor = Descriptor.newBip49Public(
|
||||
publicKey = descriptorPublicKey,
|
||||
fingerprint = "d1d04177",
|
||||
keychain = KeychainKind.EXTERNAL,
|
||||
network = Network.TESTNET,
|
||||
)
|
||||
println(bip49PublicDescriptor.asString()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
|
||||
println(bip49PublicDescriptor.asStringPrivate()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
|
||||
|
||||
// Creating it starting from the full xprv derived from a mnemonic will give you the same public descriptor
|
||||
val mnemonic = Mnemonic.fromString("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect")
|
||||
val bip32ExtendedRootKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
|
||||
val bip49PrivateDescriptor: Descriptor = Descriptor.newBip49(bip32ExtendedRootKey, KeychainKind.EXTERNAL, Network.TESTNET)
|
||||
println(bip49PrivateDescriptor.asString()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEm
|
||||
val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u)
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
|
||||
)
|
||||
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
|
||||
val newAddress = wallet.getAddress(AddressIndex.LAST_UNUSED)
|
||||
@@ -95,5 +95,18 @@ and use the `publishToMavenLocal` task without excluding the signing task:
|
||||
./gradlew publishToMavenLocal
|
||||
```
|
||||
|
||||
## Known issues
|
||||
Depending on the JVM version you use, you might not have the JNA dependency on your classpath. The exception thrown will be
|
||||
```shell
|
||||
class file for com.sun.jna.Pointer not found
|
||||
```
|
||||
The solution is to add JNA as a dependency like so:
|
||||
```kotlin
|
||||
dependencies {
|
||||
// ...
|
||||
implementation("net.java.dev.jna:jna:5.12.1")
|
||||
}
|
||||
```
|
||||
|
||||
[`bdk`]: https://github.com/bitcoindevkit/bdk
|
||||
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
|
||||
|
||||
@@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
kotlin.code.style=official
|
||||
libraryVersion=0.12.0-SNAPSHOT
|
||||
libraryVersion=0.26.0
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
// library version is defined in gradle.properties
|
||||
val libraryVersion: String by project
|
||||
|
||||
@@ -107,3 +109,9 @@ signing {
|
||||
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
|
||||
sign(publishing.publications)
|
||||
}
|
||||
|
||||
// This task dependency ensures that we build the bindings
|
||||
// binaries before running the tests
|
||||
tasks.withType<KotlinCompile> {
|
||||
dependsOn("buildAndroidLib")
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ class AndroidLibTest {
|
||||
}
|
||||
}
|
||||
|
||||
private val descriptor =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
private val descriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
|
||||
|
||||
private val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
@@ -47,7 +46,8 @@ class AndroidLibTest {
|
||||
null,
|
||||
5u,
|
||||
null,
|
||||
100u
|
||||
100u,
|
||||
true,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bdk-ffi"
|
||||
version = "0.25.0"
|
||||
version = "0.26.0"
|
||||
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
@@ -10,10 +10,12 @@ crate-type = ["staticlib", "cdylib"]
|
||||
name = "bdkffi"
|
||||
|
||||
[dependencies]
|
||||
bdk = { version = "0.25", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
|
||||
|
||||
bdk = { version = "0.26", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
|
||||
uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
uniffi = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.5.0"
|
||||
|
||||
@@ -45,6 +45,7 @@ enum BdkError {
|
||||
"Esplora",
|
||||
"Sled",
|
||||
"Rusqlite",
|
||||
"Rpc",
|
||||
};
|
||||
|
||||
dictionary AddressInfo {
|
||||
@@ -116,6 +117,7 @@ dictionary ElectrumConfig {
|
||||
u8 retry;
|
||||
u8? timeout;
|
||||
u64 stop_gap;
|
||||
boolean validate_domain;
|
||||
};
|
||||
|
||||
dictionary EsploraConfig {
|
||||
@@ -126,10 +128,33 @@ dictionary EsploraConfig {
|
||||
u64? timeout;
|
||||
};
|
||||
|
||||
[Enum]
|
||||
interface Auth {
|
||||
None();
|
||||
UserPass(string username, string password);
|
||||
Cookie(string file);
|
||||
};
|
||||
|
||||
dictionary RpcSyncParams {
|
||||
u64 start_script_count;
|
||||
u64 start_time;
|
||||
boolean force_start_time;
|
||||
u64 poll_rate_sec;
|
||||
};
|
||||
|
||||
dictionary RpcConfig {
|
||||
string url;
|
||||
Auth auth;
|
||||
Network network;
|
||||
string wallet_name;
|
||||
RpcSyncParams? sync_params;
|
||||
};
|
||||
|
||||
[Enum]
|
||||
interface BlockchainConfig {
|
||||
Electrum(ElectrumConfig config);
|
||||
Esplora(EsploraConfig config);
|
||||
Rpc(RpcConfig config);
|
||||
};
|
||||
|
||||
interface Blockchain {
|
||||
@@ -179,7 +204,7 @@ dictionary ScriptAmount {
|
||||
|
||||
interface Wallet {
|
||||
[Throws=BdkError]
|
||||
constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config);
|
||||
constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config);
|
||||
|
||||
[Throws=BdkError]
|
||||
AddressInfo get_address(AddressIndex address_index);
|
||||
@@ -257,7 +282,7 @@ interface TxBuilder {
|
||||
|
||||
TxBuilder drain_wallet();
|
||||
|
||||
TxBuilder drain_to(string address);
|
||||
TxBuilder drain_to(Script script);
|
||||
|
||||
TxBuilder enable_rbf();
|
||||
|
||||
@@ -333,6 +358,33 @@ interface DescriptorPublicKey {
|
||||
string as_string();
|
||||
};
|
||||
|
||||
interface Descriptor {
|
||||
[Throws=BdkError]
|
||||
constructor(string descriptor, Network network);
|
||||
|
||||
[Name=new_bip44]
|
||||
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
|
||||
|
||||
[Name=new_bip44_public]
|
||||
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
|
||||
|
||||
[Name=new_bip49]
|
||||
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
|
||||
|
||||
[Name=new_bip49_public]
|
||||
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
|
||||
|
||||
[Name=new_bip84]
|
||||
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
|
||||
|
||||
[Name=new_bip84_public]
|
||||
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
|
||||
|
||||
string as_string();
|
||||
|
||||
string as_string_private();
|
||||
};
|
||||
|
||||
interface Address {
|
||||
[Throws=BdkError]
|
||||
constructor(string address);
|
||||
|
||||
@@ -1,28 +1,34 @@
|
||||
use bdk::bitcoin::blockdata::script::Script as BdkScript;
|
||||
use bdk::bitcoin::hashes::hex::ToHex;
|
||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
|
||||
use bdk::bitcoin::util::bip32::{DerivationPath as BdkDerivationPath, Fingerprint};
|
||||
use bdk::bitcoin::util::psbt::serialize::Serialize;
|
||||
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
||||
use bdk::bitcoin::Sequence;
|
||||
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
|
||||
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
||||
use bdk::blockchain::rpc::Auth as BdkAuth;
|
||||
use bdk::blockchain::GetBlockHash;
|
||||
use bdk::blockchain::GetHeight;
|
||||
use bdk::blockchain::{
|
||||
electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain,
|
||||
electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig,
|
||||
rpc::RpcConfig as BdkRpcConfig, rpc::RpcSyncParams as BdkRpcSyncParams, ConfigurableBlockchain,
|
||||
};
|
||||
use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress};
|
||||
use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration};
|
||||
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
||||
use bdk::descriptor::DescriptorXKey;
|
||||
use bdk::descriptor::{DescriptorXKey, ExtendedDescriptor, IntoWalletDescriptor};
|
||||
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
|
||||
use bdk::keys::{
|
||||
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
||||
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
||||
KeyMap,
|
||||
};
|
||||
use bdk::miniscript::BareCtx;
|
||||
use bdk::psbt::PsbtUtils;
|
||||
use bdk::template::{
|
||||
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate,
|
||||
};
|
||||
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
||||
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
||||
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
||||
@@ -34,6 +40,7 @@ use std::collections::HashSet;
|
||||
use std::convert::{From, TryFrom};
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
@@ -111,6 +118,8 @@ pub struct ElectrumConfig {
|
||||
pub timeout: Option<u8>,
|
||||
/// Stop searching addresses for transactions after finding an unused gap of this length
|
||||
pub stop_gap: u64,
|
||||
/// Validate the domain when using SSL
|
||||
pub validate_domain: bool,
|
||||
}
|
||||
|
||||
/// Configuration for an EsploraBlockchain
|
||||
@@ -134,12 +143,84 @@ pub struct EsploraConfig {
|
||||
pub timeout: Option<u64>,
|
||||
}
|
||||
|
||||
pub enum Auth {
|
||||
/// No authentication
|
||||
None,
|
||||
/// Authentication with username and password, usually [Auth::Cookie] should be preferred
|
||||
UserPass {
|
||||
/// Username
|
||||
username: String,
|
||||
/// Password
|
||||
password: String,
|
||||
},
|
||||
/// Authentication with a cookie file
|
||||
Cookie {
|
||||
/// Cookie file
|
||||
file: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<Auth> for BdkAuth {
|
||||
fn from(auth: Auth) -> Self {
|
||||
match auth {
|
||||
Auth::None => BdkAuth::None,
|
||||
Auth::UserPass { username, password } => BdkAuth::UserPass { username, password },
|
||||
Auth::Cookie { file } => BdkAuth::Cookie {
|
||||
file: PathBuf::from(file),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync parameters for Bitcoin Core RPC.
|
||||
///
|
||||
/// In general, BDK tries to sync `scriptPubKey`s cached in `Database` with
|
||||
/// `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining
|
||||
/// how the `importdescriptors` RPC calls are to be made.
|
||||
pub struct RpcSyncParams {
|
||||
/// The minimum number of scripts to scan for on initial sync.
|
||||
pub start_script_count: u64,
|
||||
/// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).
|
||||
pub start_time: u64,
|
||||
/// Forces every sync to use `start_time` as import timestamp.
|
||||
pub force_start_time: bool,
|
||||
/// RPC poll rate (in seconds) to get state updates.
|
||||
pub poll_rate_sec: u64,
|
||||
}
|
||||
|
||||
impl From<RpcSyncParams> for BdkRpcSyncParams {
|
||||
fn from(params: RpcSyncParams) -> Self {
|
||||
BdkRpcSyncParams {
|
||||
start_script_count: params.start_script_count as usize,
|
||||
start_time: params.start_time,
|
||||
force_start_time: params.force_start_time,
|
||||
poll_rate_sec: params.poll_rate_sec,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// RpcBlockchain configuration options
|
||||
pub struct RpcConfig {
|
||||
/// The bitcoin node url
|
||||
pub url: String,
|
||||
/// The bitcoin node authentication mechanism
|
||||
pub auth: Auth,
|
||||
/// The network we are using (it will be checked the bitcoin node network matches this)
|
||||
pub network: Network,
|
||||
/// The wallet name in the bitcoin node, consider using [crate::wallet::wallet_name_from_descriptor] for this
|
||||
pub wallet_name: String,
|
||||
/// Sync parameters
|
||||
pub sync_params: Option<RpcSyncParams>,
|
||||
}
|
||||
|
||||
/// Type that can contain any of the blockchain configurations defined by the library.
|
||||
pub enum BlockchainConfig {
|
||||
/// Electrum client
|
||||
Electrum { config: ElectrumConfig },
|
||||
/// Esplora client
|
||||
Esplora { config: EsploraConfig },
|
||||
/// Bitcoin Core RPC client
|
||||
Rpc { config: RpcConfig },
|
||||
}
|
||||
|
||||
/// A wallet transaction
|
||||
@@ -189,6 +270,7 @@ impl Blockchain {
|
||||
timeout: config.timeout,
|
||||
url: config.url,
|
||||
stop_gap: usize::try_from(config.stop_gap).unwrap(),
|
||||
validate_domain: config.validate_domain,
|
||||
})
|
||||
}
|
||||
BlockchainConfig::Esplora { config } => {
|
||||
@@ -200,6 +282,13 @@ impl Blockchain {
|
||||
timeout: config.timeout,
|
||||
})
|
||||
}
|
||||
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
|
||||
url: config.url,
|
||||
auth: config.auth.into(),
|
||||
network: config.network,
|
||||
wallet_name: config.wallet_name,
|
||||
sync_params: config.sync_params.map(|p| p.into()),
|
||||
}),
|
||||
};
|
||||
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
|
||||
Ok(Self {
|
||||
@@ -227,10 +316,6 @@ impl Blockchain {
|
||||
}
|
||||
}
|
||||
|
||||
struct Wallet {
|
||||
wallet_mutex: Mutex<BdkWallet<AnyDatabase>>,
|
||||
}
|
||||
|
||||
/// A reference to a transaction output.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct OutPoint {
|
||||
@@ -407,6 +492,11 @@ impl PartiallySignedTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Wallet {
|
||||
wallet_mutex: Mutex<BdkWallet<AnyDatabase>>,
|
||||
}
|
||||
|
||||
/// A Bitcoin wallet.
|
||||
/// The Wallet acts as a way of coherently interfacing with output descriptors and related transactions. Its main components are:
|
||||
/// 1. Output descriptors from which it can derive addresses.
|
||||
@@ -414,8 +504,8 @@ impl PartiallySignedTransaction {
|
||||
/// 3. Signers that can contribute signatures to addresses instantiated from the descriptors.
|
||||
impl Wallet {
|
||||
fn new(
|
||||
descriptor: String,
|
||||
change_descriptor: Option<String>,
|
||||
descriptor: Arc<Descriptor>,
|
||||
change_descriptor: Option<Arc<Descriptor>>,
|
||||
network: Network,
|
||||
database_config: DatabaseConfig,
|
||||
) -> Result<Self, BdkError> {
|
||||
@@ -425,6 +515,9 @@ impl Wallet {
|
||||
DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config),
|
||||
};
|
||||
let database = AnyDatabase::from_config(&any_database_config)?;
|
||||
let descriptor: String = descriptor.as_string_private();
|
||||
let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
|
||||
|
||||
let wallet_mutex = Mutex::new(BdkWallet::new(
|
||||
&descriptor,
|
||||
change_descriptor.as_ref(),
|
||||
@@ -501,12 +594,6 @@ impl Wallet {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_script_pubkey(address: &str) -> Result<BdkScript, BdkError> {
|
||||
BdkAddress::from_str(address)
|
||||
.map(|x| x.script_pubkey())
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||
}
|
||||
|
||||
/// A Bitcoin address.
|
||||
struct Address {
|
||||
address: BdkAddress,
|
||||
@@ -527,7 +614,7 @@ impl Address {
|
||||
}
|
||||
|
||||
/// A Bitcoin script.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Script {
|
||||
script: BdkScript,
|
||||
}
|
||||
@@ -565,7 +652,7 @@ struct TxBuilder {
|
||||
fee_rate: Option<f32>,
|
||||
fee_absolute: Option<u64>,
|
||||
drain_wallet: bool,
|
||||
drain_to: Option<String>,
|
||||
drain_to: Option<BdkScript>,
|
||||
rbf: Option<RbfValue>,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
@@ -703,9 +790,9 @@ impl TxBuilder {
|
||||
/// either provide the utxos that the transaction should spend via add_utxos, or set drain_wallet to spend all of them.
|
||||
/// When bumping the fees of a transaction made with this option, you probably want to use BumpFeeTxBuilder.allow_shrinking
|
||||
/// to allow this output to be reduced to pay for the extra fees.
|
||||
fn drain_to(&self, address: String) -> Arc<Self> {
|
||||
fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
|
||||
Arc::new(TxBuilder {
|
||||
drain_to: Some(address),
|
||||
drain_to: Some(script.script.clone()),
|
||||
..self.clone()
|
||||
})
|
||||
}
|
||||
@@ -766,8 +853,8 @@ impl TxBuilder {
|
||||
if self.drain_wallet {
|
||||
tx_builder.drain_wallet();
|
||||
}
|
||||
if let Some(address) = &self.drain_to {
|
||||
tx_builder.drain_to(to_script_pubkey(address)?);
|
||||
if let Some(script) = &self.drain_to {
|
||||
tx_builder.drain_to(script.clone());
|
||||
}
|
||||
if let Some(rbf) = &self.rbf {
|
||||
match *rbf {
|
||||
@@ -1103,6 +1190,186 @@ impl DescriptorPublicKey {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Descriptor {
|
||||
pub extended_descriptor: ExtendedDescriptor,
|
||||
pub key_map: KeyMap,
|
||||
}
|
||||
|
||||
impl Descriptor {
|
||||
fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
|
||||
let secp = Secp256k1::new();
|
||||
let (extended_descriptor, key_map) = descriptor.into_wallet_descriptor(&secp, network)?;
|
||||
Ok(Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
})
|
||||
}
|
||||
|
||||
fn new_bip44(
|
||||
secret_key: Arc<DescriptorSecretKey>,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip44(derivable_key, keychain_kind).build(network).unwrap();
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_bip44_public(
|
||||
public_key: Arc<DescriptorPublicKey>,
|
||||
fingerprint: String,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
||||
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip44Public(derivable_key, fingerprint, keychain_kind)
|
||||
.build(network)
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorPublicKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_bip49(
|
||||
secret_key: Arc<DescriptorSecretKey>,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip49(derivable_key, keychain_kind).build(network).unwrap();
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_bip49_public(
|
||||
public_key: Arc<DescriptorPublicKey>,
|
||||
fingerprint: String,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
||||
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip49Public(derivable_key, fingerprint, keychain_kind)
|
||||
.build(network)
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorPublicKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_bip84(
|
||||
secret_key: Arc<DescriptorSecretKey>,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip84(derivable_key, keychain_kind).build(network).unwrap();
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_bip84_public(
|
||||
public_key: Arc<DescriptorPublicKey>,
|
||||
fingerprint: String,
|
||||
keychain_kind: KeychainKind,
|
||||
network: Network,
|
||||
) -> Self {
|
||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
||||
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
|
||||
|
||||
match derivable_key.deref() {
|
||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||
let derivable_key = descriptor_x_key.xkey;
|
||||
let (extended_descriptor, key_map, _) =
|
||||
Bip84Public(derivable_key, fingerprint, keychain_kind)
|
||||
.build(network)
|
||||
.unwrap();
|
||||
|
||||
Self {
|
||||
extended_descriptor,
|
||||
key_map,
|
||||
}
|
||||
}
|
||||
BdkDescriptorPublicKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn as_string_private(&self) -> String {
|
||||
let descriptor = &self.extended_descriptor;
|
||||
let key_map = &self.key_map;
|
||||
descriptor.to_string_with_secret(key_map)
|
||||
}
|
||||
|
||||
fn as_string(&self) -> String {
|
||||
self.extended_descriptor.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
|
||||
|
||||
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
|
||||
@@ -1111,8 +1378,10 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::*;
|
||||
use assert_matches::assert_matches;
|
||||
use bdk::bitcoin::Address;
|
||||
use bdk::bitcoin::Network::Testnet;
|
||||
use bdk::descriptor::DescriptorError::Key;
|
||||
use bdk::keys::KeyError::InvalidNetwork;
|
||||
use bdk::wallet::get_funded_wallet;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Mutex;
|
||||
@@ -1125,11 +1394,14 @@ mod test {
|
||||
wallet_mutex: Mutex::new(funded_wallet),
|
||||
};
|
||||
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
|
||||
let drain_to_script = crate::Address::new(drain_to_address)
|
||||
.unwrap()
|
||||
.script_pubkey();
|
||||
let tx_builder = TxBuilder::new()
|
||||
.drain_wallet()
|
||||
.drain_to(drain_to_address.clone());
|
||||
.drain_to(drain_to_script.clone());
|
||||
assert!(tx_builder.drain_wallet);
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_address));
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone()));
|
||||
|
||||
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
|
||||
let psbt = tx_builder_result.psbt.internal.lock().unwrap().clone();
|
||||
@@ -1160,7 +1432,7 @@ mod test {
|
||||
.cloned()
|
||||
.unwrap()
|
||||
.script_pubkey,
|
||||
Testnet,
|
||||
Network::Testnet,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
@@ -1183,7 +1455,7 @@ mod test {
|
||||
|
||||
fn get_descriptor_secret_key() -> DescriptorSecretKey {
|
||||
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
|
||||
DescriptorSecretKey::new(Testnet, Arc::new(mnemonic), None)
|
||||
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None)
|
||||
}
|
||||
|
||||
fn derive_dsk(
|
||||
@@ -1317,13 +1589,17 @@ mod test {
|
||||
wallet_mutex: Mutex::new(funded_wallet),
|
||||
};
|
||||
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
|
||||
let drain_to_script = crate::Address::new(drain_to_address)
|
||||
.unwrap()
|
||||
.script_pubkey();
|
||||
|
||||
let tx_builder = TxBuilder::new()
|
||||
.fee_rate(2.0)
|
||||
.drain_wallet()
|
||||
.drain_to(drain_to_address.clone());
|
||||
.drain_to(drain_to_script.clone());
|
||||
//dbg!(&tx_builder);
|
||||
assert!(tx_builder.drain_wallet);
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_address));
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone()));
|
||||
|
||||
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
|
||||
|
||||
@@ -1336,4 +1612,141 @@ mod test {
|
||||
assert!(tx_builder_result.psbt.fee_amount().is_some());
|
||||
assert_eq!(tx_builder_result.psbt.fee_amount().unwrap(), 220);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_descriptor_templates() {
|
||||
let master: Arc<DescriptorSecretKey> = Arc::new(get_descriptor_secret_key());
|
||||
println!("Master: {:?}", master.as_string());
|
||||
// tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h
|
||||
|
||||
let handmade_public_44 = master
|
||||
.derive(Arc::new(
|
||||
DerivationPath::new("m/44h/1h/0h".to_string()).unwrap(),
|
||||
))
|
||||
.unwrap()
|
||||
.as_public();
|
||||
println!("Public 44: {}", handmade_public_44.as_string());
|
||||
// Public 44: [d1d04177/44'/1'/0']tpubDCoPjomfTqh1e7o1WgGpQtARWtkueXQAepTeNpWiitS3Sdv8RKJ1yvTrGHcwjDXp2SKyMrTEca4LoN7gEUiGCWboyWe2rz99Kf4jK4m2Zmx/*
|
||||
|
||||
let handmade_public_49 = master
|
||||
.derive(Arc::new(
|
||||
DerivationPath::new("m/49h/1h/0h".to_string()).unwrap(),
|
||||
))
|
||||
.unwrap()
|
||||
.as_public();
|
||||
println!("Public 49: {}", handmade_public_49.as_string());
|
||||
// Public 49: [d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/*
|
||||
|
||||
let handmade_public_84 = master
|
||||
.derive(Arc::new(
|
||||
DerivationPath::new("m/84h/1h/0h".to_string()).unwrap(),
|
||||
))
|
||||
.unwrap()
|
||||
.as_public();
|
||||
println!("Public 84: {}", handmade_public_84.as_string());
|
||||
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
|
||||
|
||||
let template_private_44 =
|
||||
Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet);
|
||||
let template_private_49 =
|
||||
Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet);
|
||||
let template_private_84 =
|
||||
Descriptor::new_bip84(master, KeychainKind::External, Network::Testnet);
|
||||
|
||||
// the extended public keys are the same when creating them manually as they are with the templates
|
||||
println!("Template 49: {}", template_private_49.as_string());
|
||||
println!("Template 44: {}", template_private_44.as_string());
|
||||
println!("Template 84: {}", template_private_84.as_string());
|
||||
|
||||
// for the public versions of the templates these are incorrect, bug report and fix in bitcoindevkit/bdk#817 and bitcoindevkit/bdk#818
|
||||
let template_public_44 = Descriptor::new_bip44_public(
|
||||
handmade_public_44,
|
||||
"d1d04177".to_string(),
|
||||
KeychainKind::External,
|
||||
Network::Testnet,
|
||||
);
|
||||
let template_public_49 = Descriptor::new_bip49_public(
|
||||
handmade_public_49,
|
||||
"d1d04177".to_string(),
|
||||
KeychainKind::External,
|
||||
Network::Testnet,
|
||||
);
|
||||
let template_public_84 = Descriptor::new_bip84_public(
|
||||
handmade_public_84,
|
||||
"d1d04177".to_string(),
|
||||
KeychainKind::External,
|
||||
Network::Testnet,
|
||||
);
|
||||
|
||||
println!("Template public 49: {}", template_public_49.as_string());
|
||||
println!("Template public 44: {}", template_public_44.as_string());
|
||||
println!("Template public 84: {}", template_public_84.as_string());
|
||||
|
||||
// when using a public key, both as_string and as_string_private return the same string
|
||||
assert_eq!(
|
||||
template_public_44.as_string_private(),
|
||||
template_public_44.as_string()
|
||||
);
|
||||
assert_eq!(
|
||||
template_public_49.as_string_private(),
|
||||
template_public_49.as_string()
|
||||
);
|
||||
assert_eq!(
|
||||
template_public_84.as_string_private(),
|
||||
template_public_84.as_string()
|
||||
);
|
||||
|
||||
// when using as_string on a private key, we get the same result as when using it on a public key
|
||||
assert_eq!(
|
||||
template_private_44.as_string(),
|
||||
template_public_44.as_string()
|
||||
);
|
||||
assert_eq!(
|
||||
template_private_49.as_string(),
|
||||
template_public_49.as_string()
|
||||
);
|
||||
assert_eq!(
|
||||
template_private_84.as_string(),
|
||||
template_public_84.as_string()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_descriptor_from_string() {
|
||||
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet);
|
||||
let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin);
|
||||
|
||||
// Creating a Descriptor using an extended key that doesn't match the network provided will throw and InvalidNetwork Error
|
||||
assert!(descriptor1.is_ok());
|
||||
assert_matches!(
|
||||
descriptor2.unwrap_err(),
|
||||
bdk::Error::Descriptor(Key(InvalidNetwork))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wallet_from_descriptor() {
|
||||
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap();
|
||||
|
||||
let wallet1 = Wallet::new(
|
||||
Arc::new(Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap()),
|
||||
None,
|
||||
Network::Testnet,
|
||||
DatabaseConfig::Memory
|
||||
);
|
||||
|
||||
let wallet2 = Wallet::new(
|
||||
Arc::new(descriptor1),
|
||||
None,
|
||||
Network::Bitcoin,
|
||||
DatabaseConfig::Memory,
|
||||
);
|
||||
|
||||
// Creating a wallet using a Descriptor with an extended key that doesn't match the network provided in the wallet constructor will throw and InvalidNetwork Error
|
||||
assert!(wallet1.is_ok());
|
||||
assert_matches!(
|
||||
wallet2.unwrap_err(),
|
||||
bdk::Error::Descriptor(Key(InvalidNetwork))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEm
|
||||
val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u)
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
|
||||
)
|
||||
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
|
||||
val newAddress = wallet.getAddress(AddressIndex.LAST_UNUSED)
|
||||
@@ -82,5 +82,18 @@ and use the `publishToMavenLocal` task without excluding the signing task:
|
||||
./gradlew publishToMavenLocal
|
||||
```
|
||||
|
||||
## Known issues
|
||||
Depending on the JVM version you use, you might not have the JNA dependency on your classpath. The exception thrown will be
|
||||
```shell
|
||||
class file for com.sun.jna.Pointer not found
|
||||
```
|
||||
The solution is to add JNA as a dependency like so:
|
||||
```kotlin
|
||||
dependencies {
|
||||
// ...
|
||||
implementation("net.java.dev.jna:jna:5.12.1")
|
||||
}
|
||||
```
|
||||
|
||||
[`bdk`]: https://github.com/bitcoindevkit/bdk
|
||||
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.enableJetifier=true
|
||||
kotlin.code.style=official
|
||||
libraryVersion=0.12.0-SNAPSHOT
|
||||
libraryVersion=0.26.0
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.*
|
||||
import org.gradle.api.tasks.testing.logging.TestLogEvent.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
// library version is defined in gradle.properties
|
||||
val libraryVersion: String by project
|
||||
@@ -101,3 +102,9 @@ signing {
|
||||
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
|
||||
sign(publishing.publications)
|
||||
}
|
||||
|
||||
// This task dependency ensures that we build the bindings
|
||||
// binaries before running the tests
|
||||
tasks.withType<KotlinCompile> {
|
||||
dependsOn("buildJvmLib")
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ class JvmLibTest {
|
||||
}
|
||||
}
|
||||
|
||||
private val descriptor =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
private val descriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
|
||||
|
||||
private val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
@@ -39,7 +38,8 @@ class JvmLibTest {
|
||||
null,
|
||||
5u,
|
||||
null,
|
||||
100u
|
||||
100u,
|
||||
true,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ pip install bdkpython
|
||||
import bdkpython as bdk
|
||||
|
||||
|
||||
descriptor = "wpkh(tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/84h/0h/0h/0/*)"
|
||||
descriptor = bdk.Descriptor("wpkh(tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/84h/0h/0h/0/*)", bdk.Network.TESTNET)
|
||||
db_config = bdk.DatabaseConfig.MEMORY()
|
||||
blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
bdk.ElectrumConfig(
|
||||
@@ -26,7 +26,8 @@ blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
None,
|
||||
5,
|
||||
None,
|
||||
100
|
||||
100,
|
||||
True,
|
||||
)
|
||||
)
|
||||
blockchain = bdk.Blockchain(blockchain_config)
|
||||
@@ -59,7 +60,7 @@ rust_ext = RustExtension(
|
||||
|
||||
setup(
|
||||
name='bdkpython',
|
||||
version='0.6.0.dev0',
|
||||
version='0.26.2',
|
||||
description="The Python language bindings for the Bitcoin Development Kit",
|
||||
long_description=LONG_DESCRIPTION,
|
||||
long_description_content_type='text/markdown',
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import bdkpython as bdk
|
||||
import unittest
|
||||
|
||||
descriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
|
||||
descriptor = bdk.Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", bdk.Network.TESTNET)
|
||||
db_config = bdk.DatabaseConfig.MEMORY()
|
||||
blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
bdk.ElectrumConfig(
|
||||
@@ -9,7 +10,8 @@ blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
None,
|
||||
5,
|
||||
None,
|
||||
100
|
||||
100,
|
||||
True,
|
||||
)
|
||||
)
|
||||
blockchain = bdk.Blockchain(blockchain_config)
|
||||
|
||||
@@ -5,14 +5,14 @@ This project builds a Swift package that provides [Swift] language bindings for
|
||||
|
||||
Supported target platforms are:
|
||||
|
||||
- MacOS, X86_64 and M1 (aarch64)
|
||||
- macOS, X86_64 and M1 (aarch64)
|
||||
- iOS, iPhones (aarch64)
|
||||
- iOS simulator, X86_64 and M1 (aarch64)
|
||||
|
||||
## How to Use
|
||||
|
||||
To use the Swift language bindings for [`bdk`] in your [Xcode] iOS or MacOS project add
|
||||
the github repository https://github.com/bitcoindevkit/bdk-swift and select one of the
|
||||
To use the Swift language bindings for [`bdk`] in your [Xcode] iOS or macOS project add
|
||||
the GitHub repository https://github.com/bitcoindevkit/bdk-swift and select one of the
|
||||
release versions. You may then import and use the `BitcoinDevKit` library in your Swift
|
||||
code. For example:
|
||||
|
||||
@@ -40,11 +40,11 @@ swift test
|
||||
## How to Build and Publish
|
||||
|
||||
If you are a maintainer of this project or want to build and publish this project to your
|
||||
own Github repository use the following steps:
|
||||
own GitHub repository use the following steps:
|
||||
|
||||
1. If it doesn't already exist, create a new `release/0.MINOR` branch from the `master` branch.
|
||||
2. Add a tag `v0.MINOR.PATCH`.
|
||||
3. Run the `publish-spm` workflow on Github from the `bdk-swift` repo for version `0.MINOR.PATCH`.
|
||||
3. Run the `publish-spm` workflow on GitHub from the `bdk-swift` repo for version `0.MINOR.PATCH`.
|
||||
|
||||
[Swift]: https://developer.apple.com/swift/
|
||||
[Xcode]: https://developer.apple.com/documentation/Xcode
|
||||
|
||||
@@ -3,7 +3,10 @@ import XCTest
|
||||
|
||||
final class BitcoinDevKitTests: XCTestCase {
|
||||
func testMemoryWalletNewAddress() throws {
|
||||
let desc = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
let desc = try Descriptor(
|
||||
descriptor: "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
|
||||
network: Network.regtest
|
||||
)
|
||||
let databaseConfig = DatabaseConfig.memory
|
||||
let wallet = try Wallet.init(descriptor: desc, changeDescriptor: nil, network: Network.regtest, databaseConfig: databaseConfig)
|
||||
let addressInfo = try wallet.getAddress(addressIndex: AddressIndex.new)
|
||||
|
||||
Reference in New Issue
Block a user