Compare commits

..

35 Commits

Author SHA1 Message Date
thunderbiscuit
60f1aef3e0 chore: bump jvm lib to 0.31.1 2024-04-19 18:42:43 -04:00
thunderbiscuit
7490d8d8b6 chore: bump android lib to 0.31.1 2024-04-19 17:57:35 -04:00
Matthew
5d71773e7f chore: bump library version from 0.31.0 to 0.31.1 2024-03-26 09:51:05 -05:00
Matthew
ebde685f06 fix: update bdk-swift framework info.plist for xcode 15.3 reqs 2024-03-18 13:36:20 -05:00
thunderbiscuit
8d1ecd1d8c Update libraries to official release versions 2024-01-17 14:34:30 -05:00
thunderbiscuit
25a48e0565 feat: add is_valid_for_network method on address type 2024-01-17 11:12:24 -05:00
thunderbiscuit
b305f8f44e feat: upgrade API to match bdk 0.29 2024-01-16 19:38:21 -05:00
thunderbiscuit
ef080130bf chore: pin uniffi to version 0.23.0 2024-01-10 16:17:23 -05:00
thunderbiscuit
e798e1573f chore: update bdk to version 0.29.0 2024-01-10 16:16:58 -05:00
thunderbiscuit
743862fb60 chore: update minor_release template 2023-09-12 11:38:18 -04:00
thunderbiscuit
b7e38b18be chore: bump snapshot and dev versions of libraries 2023-09-12 11:37:17 -04:00
thunderbiscuit
ef73aa3490 docs: add 0.30.0 release to changelog 2023-09-12 11:35:36 -04:00
thunderbiscuit
fbec953149 docs: update docs for new pinned dependency 2023-09-06 14:51:00 -04:00
thunderbiscuit
0b07b8ed05 docs: update Kotlin API docs 2023-09-06 13:52:48 -04:00
thunderbiscuit
b59327e5ea chore: pin flate2 to 1.0.26 when building with 1.61 2023-09-06 10:40:29 -04:00
thunderbiscuit
e6500baae7 chore: update library version to 0.30.0 2023-09-06 10:25:25 -04:00
thunderbiscuit
85f220b953 build: update webpki dependency as per RUSTSEC-2023-0052 2023-09-05 14:38:16 -04:00
thunderbiscuit
106d31c9c3 Refactor: Remove unused Mutex on DescriptorSecretKey inner field 2023-08-18 13:34:28 -04:00
thunderbiscuit
4ae169f860 Refactor: Remove unused Mutex on DescriptorPublicKey inner field 2023-08-18 12:58:11 -04:00
Matthew
7717ebb097 refactor: rename inner field names 2023-08-16 15:37:33 -05:00
Matthew
c3e8469686 feat(descriptor): add bip-86 template 2023-08-11 12:09:21 -05:00
Steve Myers
faf23b7d25 Merge bitcoindevkit/bdk-ffi#389: ci: fix to work with bdk 0.28.2 and msrv 1.61.0
1da01b4a0b ci: change rust stable version to 0.71.0 (Steve Myers)
f1ba03bf50 ci: fix to work with bdk 0.28.1 and msrv 1.61.0 (Steve Myers)

Pull request description:

  ### Description

  Fixes CI to work with BDK 0.28.x and MSRV 1.61.0. For MSRV had to pin two dependencies.

  ### Notes to the reviewers

  I also updated in CI our 'stable" version of rust to be current stable which is `1.71.0`.

  ### Changelog notice

  None, only CI changes.

  ### Checklists

  #### All Submissions:

  * [x] I've signed all my commits
  * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
  * [x] I ran `cargo fmt` and `cargo clippy` before committing

ACKs for top commit:
  thunderbiscuit:
    ACK 1da01b4a0b.

Tree-SHA512: 72f7d8dbef791daebf3f4d9d92722f1f3780d173501673ca6f47af39dd2102c85944ba603e4e9213d44a294ab1cec43dff82213fe53c5dea663279473be64a15
2023-08-10 14:03:52 -05:00
Steve Myers
1da01b4a0b ci: change rust stable version to 0.71.0 2023-08-10 11:54:33 -05:00
Steve Myers
f1ba03bf50 ci: fix to work with bdk 0.28.1 and msrv 1.61.0 2023-08-10 11:28:36 -05:00
thunderbiscuit
bc182c7164 Update CI actions to their latest versions
* checkout (v3)
* setup-java (v3)
* cache (v3)
* upload-artifact (v3)
* setup-python (v4)
2023-07-05 14:03:42 -04:00
thunderbiscuit
5fc189717d Fix CI bdk-jvm 2023-07-04 16:19:55 -04:00
thunderbiscuit
849bfe79c1 Add Windows target to Kotlin/JVM published library 2023-07-04 12:32:00 -04:00
thunderbiscuit
dc79b78b2d Fix Python readme and integrate new scripts 2023-06-30 16:18:27 -04:00
thunderbiscuit
7cc08f1d6f Fix publishing Python CI workflow 2023-06-30 16:17:46 -04:00
thunderbiscuit
031fcb02da Run Python Windows tests in CI 2023-06-30 16:01:01 -04:00
thunderbiscuit
5f9b5682e5 Use macos-13 image to test and publish Python libraries 2023-06-23 14:42:36 -04:00
thunderbiscuit
d0a7315c9d Remove patch release issue template 2023-06-16 22:28:32 -04:00
thunderbiscuit
0bfc56b0e8 Fix minor release issue template 2023-06-16 22:28:09 -04:00
thunderbiscuit
3dd6c203e8 Bump snapshot and dev versions of libraries 2023-06-16 22:11:12 -04:00
thunderbiscuit
76acbf575b Add release 0.29.0 to changelog 2023-06-16 22:09:14 -04:00
33 changed files with 935 additions and 675 deletions

View File

@@ -16,7 +16,7 @@ assignees: ''
3. - [ ] Update the API docs to reflect the changes in the API
4. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch.
5. - [ ] Build the library and run the tests, and adjust if necessary.
```sh
```shell
# start an emulator prior to running the tests
cd ./bdk-android/
./gradlew buildAndroidLib
@@ -27,7 +27,7 @@ cd ./bdk-android/
7. - [ ] Update the API docs to reflect the changes in the API
8. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
9. - [ ] Build the library and run the tests, and adjust if necessary
```sh
```shell
cd ./bdk-jvm/
./gradlew buildJvmLib
./gradlew test
@@ -35,7 +35,7 @@ cd ./bdk-jvm/
10. - [ ] Update the readme if necessary
#### _Swift_
11. - [ ] Run the tests and adjust if necessary
```sh
```shell
./bdk-swift/build-local-swift.sh
cd ./bdk-swift/
swift test
@@ -47,7 +47,7 @@ swift test
```shell
cd ./bdk-python/
pip3 install --requirement requirements.txt
bash ./generate.sh
bash ./scripts/generate-macos-arm64.sh # run the script for your particular platform
python3 setup.py --verbose bdist_wheel
```
15. - [ ] Run the tests and adjust if necessary
@@ -59,27 +59,29 @@ python -m unittest --verbose tests/test_bdk.py
### Release Workflow
17. - [ ] Update the Android, JVM, Python, and Swift libraries as per the _Specific Libraries' Workflows_ section above. Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/315).
- [ ] Create a new branch off of `master` called `release/version`
18. - [ ] Open a PR to that branch to update the Android, JVM, and Python libraries' versions. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/316).
- [ ] Update bdk-android version from `SNAPSHOT` version to release version
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
- [ ] Update bdk-python version from `.dev` version to release version
19. - [ ] Merge the PR updating all the languages to their release versions
20. - [ ] Create the tag and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor) and push it to GitHub.
```sh
18. - [ ] Create a new branch off of `master` called `release/version`
19. - [ ] Update bdk-android version from `SNAPSHOT` version to release version
20. - [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
21. - [ ] Update bdk-python version from `.dev` version to release version
22. - [ ] Open a PR to that release branch that updates the Android, JVM, and Python libraries' versions in step 19, 20, and 21. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/316).
23. - [ ] Get a review and ACK and merge the PR updating all the languages to their release versions
24. - [ ] Create the tag for the release and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor). Push the tag to GitHub.
```shell
git tag v0.6.0 --sign --edit
git push upstream v0.6.0
```
21. - [ ] Aggregate all the changelog notices from the PRs and add them to the changelog file
22. - [ ] Open a PR on master with the changes to the changelog file and the development versions bump. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/317).
23. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
24. - [ ] Trigger manual releases for all 4 libraries (for Swift, simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`)
25. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
26. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```bash!
25. - [ ] Trigger manual releases for all 4 libraries (for Swift, trigger the release on `master` and simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`)
26. - [ ] Make sure the released libraries work and contain the artifacts you would expect
27. - [ ] Aggregate all the changelog notices from the PRs and add them to the changelog file
28. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
29. - [ ] Apply changes to the minor_release and patch_release issue templates if they need any
30. - [ ] Open a PR on master with the changes in steps 29, 30, and 31. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/317). Get a review and merge the PR.
31. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
32. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```shell
./gradlew dokkaHtml # bdk-jvm (Dokka)
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
./gradlew dokkaHtml # bdk-android (Dokka)
```
27. - [ ] Tweet about the library
28. - [ ] Post in the announcement channel
33. - [ ] Post in the announcement channel
34. - [ ] Tweet about the library

View File

@@ -1,85 +0,0 @@
---
name: Patch Release
about: Create a new patch release [for release managers only]
title: 'Release MAJOR.MINOR.PATCH+1'
labels: 'release'
assignees: ''
---
# Creating a new patch release
## Bumping BDK Rust Version
1. - [ ] Open a PR with an update to `Cargo.toml` to the new bdk release candidate and ensure all CI workflows run correctly. Fix errors if necessary.
2. - [ ] Once the new bdk release is out, update the PR to replace the release candidate with the full release and merge.
### Specific Libraries' Workflows
#### _Android_
3. - [ ] Update the API docs to reflect the changes in the API
4. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch.
5. - [ ] Build the library and run the tests, and adjust if necessary.
```sh
# start an emulator prior to running the tests
cd ./bdk-android/
./gradlew buildAndroidLib
./gradlew connectedAndroidTest
```
6. - [ ] Update the readme if necessary
#### _JVM_
7. - [ ] Update the API docs to reflect the changes in the API
8. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
9. - [ ] Build the library and run the tests, and adjust if necessary
```sh
cd ./bdk-jvm/
./gradlew buildJvmLib
./gradlew test
```
10. - [ ] Update the readme if necessary
#### _Swift_
11. - [ ] Run the tests and adjust if necessary
```sh
./bdk-swift/build-local-swift.sh
cd ./bdk-swift/
swift test
```
12. - [ ] Update the readme if necessary
#### _Python_
13. - [ ] Delete the `.tox`, `dist`, `build`, and `bdkpython.egg-info` and rust `target` directories to make sure you are building the library from scratch without any caches
14. - [ ] Build the library
```shell
cd ./bdk-python/
pip3 install --requirement requirements.txt
bash ./generate.sh
python3 setup.py --verbose bdist_wheel
```
15. - [ ] Run the tests and adjust if necessary
```shell
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall
python -m unittest --verbose tests/test_bdk.py
```
16. - [ ] Update the readme and `setup.py` if necessary
### Release Workflow
17. - [ ] Update the Android, JVM, Python, and Swift libraries as per the _Specific Libraries' Workflows_ section above. Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/315).
- [ ] Create a new branch off of `master` called `release/version`
18. - [ ] Open a PR to that branch to update the Android, JVM, and Python libraries' versions. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/316).
- [ ] Update bdk-android version from `SNAPSHOT` version to release version
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
- [ ] Update bdk-python version from `.dev` version to release version
19. - [ ] Merge the PR updating all the languages to their release versions
20. - [ ] Create the tag and make sure to add the changelog info to the tag (works better if you prepare the tag message on the side in a text editor) and push it to GitHub.
```sh
git tag v0.6.0 --sign --edit
git push upstream v0.6.0
```
21. - [ ] Aggregate all the changelog notices from the PRs and add them to the changelog file
22. - [ ] Open a PR on master with the changes to the changelog file and the development versions bump. See [example PR here](https://github.com/bitcoindevkit/bdk-ffi/pull/317).
23. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
24. - [ ] Trigger manual releases for all 4 libraries (for Swift, simply add the version number in the text field when running the workflow manually. Note that the version number must not contain the `v`, i.e. `0.26.0`)
25. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
26. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```bash!
./gradlew dokkaHtml # bdk-jvm (Dokka)
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
./gradlew dokkaHtml # bdk-android (Dokka)
```
27. - [ ] Tweet about the library
28. - [ ] Post in the announcement channel

View File

@@ -13,7 +13,7 @@ jobs:
name: Security audit
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -14,18 +14,18 @@ jobs:
strategy:
matrix:
rust:
- version: 1.63.0 # STABLE
- version: 1.71.0 # STABLE
clippy: true
- version: 1.61.0 # MSRV
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Generate cache key
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
- name: Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -46,6 +46,12 @@ jobs:
- name: Update toolchain
run: rustup update
- name: Pin dependencies for MSRV
if: matrix.rust.version == '1.61.0'
run: |
cargo update -p hashlink --precise "0.8.1"
cargo update -p tokio --precise "1.29.1"
cargo update -p flate2 --precise "1.0.26"
- name: Build
run: cargo build
@@ -61,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set default toolchain
run: rustup default nightly

View File

@@ -20,10 +20,10 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -32,7 +32,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11

View File

@@ -7,7 +7,7 @@ jobs:
runs-on: macos-12
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
@@ -19,7 +19,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
@@ -46,10 +46,10 @@ jobs:
runs-on: windows-2022
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
@@ -77,7 +77,7 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
@@ -89,7 +89,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
@@ -102,7 +102,7 @@ jobs:
cd bdk-jvm
./gradlew buildJvmLib
- name: "Download native binaries from previous jobs"
- name: "Download macOS native binaries from previous job"
uses: actions/download-artifact@v3
with:
name: artifact-macos

View File

@@ -1,4 +1,4 @@
name: Build and publish Python wheels
name: Publish bdkpython to PyPI
on: [workflow_dispatch]
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
@@ -26,7 +26,7 @@ jobs:
- cp310-cp310
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- uses: actions-rs/toolchain@v1
@@ -41,7 +41,7 @@ jobs:
# see issue #350 for more information
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -60,12 +60,12 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -78,7 +78,7 @@ jobs:
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
- name: "Upload artifacts"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -97,12 +97,12 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -114,7 +114,7 @@ jobs:
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -133,10 +133,10 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -147,7 +147,7 @@ jobs:
run: python setup.py bdist_wheel --verbose
- name: "Upload artifacts"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-win-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
@@ -161,10 +161,10 @@ jobs:
needs: [build-manylinux2014-x86_64-wheels, build-macos-arm64-wheels, build-macos-x86_64-wheels, build-windows-wheels]
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Download artifacts in dist/ directory"
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
path: dist/

View File

@@ -29,10 +29,10 @@ jobs:
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch"
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -41,7 +41,7 @@ jobs:
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v2
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11

View File

@@ -14,11 +14,11 @@ jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Check out PR branch
uses: actions/checkout@v2
- name: "Check out PR branch"
uses: actions/checkout@v3
- name: Cache
uses: actions/cache@v2
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
@@ -26,8 +26,8 @@ jobs:
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set up JDK
uses: actions/setup-java@v2
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
@@ -35,7 +35,7 @@ jobs:
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: Run JVM tests
- name: "Run JVM tests"
run: |
cd bdk-jvm
./gradlew test --console=rich
./gradlew test

View File

@@ -35,7 +35,7 @@ jobs:
- cp310-cp310
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- uses: actions-rs/toolchain@v1
@@ -57,7 +57,7 @@ jobs:
run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -76,12 +76,12 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -100,7 +100,7 @@ jobs:
# python3 -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -119,10 +119,10 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v2
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -141,7 +141,7 @@ jobs:
run: python3 -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
@@ -160,12 +160,12 @@ jobs:
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
@@ -176,7 +176,7 @@ jobs:
run: python setup.py bdist_wheel --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: bdkpython-windows-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl

View File

@@ -15,7 +15,7 @@ jobs:
runs-on: macos-12
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0

View File

@@ -4,6 +4,29 @@ Changelog information can also be found in each release's git tag (which can be
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.30.0]
This release has a new API and a few internal optimizations and refactorings.
- APIs Added
- Add BIP-86 descriptor templates [#388]
[#388]: https://github.com/bitcoindevkit/bdk-ffi/pull/388
## [0.29.0]
This release has a number of new APIs, and adds support for Windows in bdk-jvm.
Changelog
- Add support for Windows in bdk-jvm [#336]
- Add support for older version of Linux distros in bdk-jvm [#345]
- APIs added
- Expose `is_mine()` method on the `Wallet` type [#355]
- Expose `to_bytes()` method on the `Script` type [#369]
[#336]: https://github.com/bitcoindevkit/bdk-ffi/pull/336
[#345]: https://github.com/bitcoindevkit/bdk-ffi/pull/345
[#355]: https://github.com/bitcoindevkit/bdk-ffi/pull/355
[#369]: https://github.com/bitcoindevkit/bdk-ffi/pull/369
## [v0.28.0]
- Update BDK to version 0.28.0 [#341]
- Drop support of pypy releases of Python libraries [#351]
@@ -200,6 +223,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding
[v0.30.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.29.0...v0.30.0
[v0.29.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.28.0...v0.29.0
[v0.28.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.27.1...v0.28.0
[v0.27.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.26.0...v0.27.1
[v0.26.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.25.0...v0.26.0

571
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,4 +9,4 @@ opt-level = 'z' # Optimize for size.
lto = true # Enable Link Time Optimization
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
panic = 'abort' # Abort on panic
strip = true # Strip symbols from binary*
strip = true # Strip symbols from binary

View File

@@ -22,6 +22,21 @@ The below directories (a separate repository in the case of bdk-swift) include i
| Swift | iOS, macOS | [bdk-swift (GitHub)] | [Readme bdk-swift] | |
| Python | linux, macOS, Windows | [bdk-python (PyPI)] | [Readme bdk-python] | |
## Minimum Supported Rust Version (MSRV)
This library should compile with any combination of features with Rust 1.61.0.
To build with the MSRV you will need to pin dependencies as follows:
```shell
# required for sqlite feature, hashlink 0.8.2 has MSRV 1.61.0
cargo update -p hashlink --precise "0.8.1"
# tokio 1.30.0 has MSRV 1.63.0
cargo update -p tokio --precise "1.29.1"
# flate2 1.0.27 and up do not work with Rust 1.61.0, but 1.0.26 does
cargo update -p flate2 --precise "1.0.26"
```
## Contributing
### Adding new structs and functions
@@ -49,8 +64,8 @@ See the [UniFFI User Guide](https://mozilla.github.io/uniffi-rs/)
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
}
```
@@ -60,8 +75,8 @@ dependencies {
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version>")
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version>")
}
```

View File

@@ -785,6 +785,19 @@ class Descriptor(descriptor: String, network: Network) {
*/
fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/**
* BIP86 template. Expands to wpkh(key/86'/{0,1}'/0'/{0,1}/\*)
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip86(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP86 public template. Expands to wpkh(key/{0,1}/\*)
* This assumes that the key used has already been derived with m/86'/0'/0' for Mainnet or m/86'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip86Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/** Return the public version of the output descriptor. */
fun asString(): String {}

View File

@@ -8,8 +8,8 @@ repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
}
```
@@ -38,8 +38,8 @@ repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
}
```

View File

@@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
libraryVersion=0.29.0
libraryVersion=0.31.1

View File

@@ -1,6 +1,6 @@
[package]
name = "bdk-ffi"
version = "0.29.0"
version = "0.31.1"
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
edition = "2018"
license = "MIT OR Apache-2.0"
@@ -17,12 +17,12 @@ path = "uniffi-bindgen.rs"
default = ["uniffi/cli"]
[dependencies]
bdk = { version = "0.28", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
uniffi = { version = "0.23.0" }
bdk = { version = "0.29.0", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
uniffi = { version = "=0.23.0" }
[build-dependencies]
uniffi = { version = "0.23.0", features = ["build"] }
uniffi = { version = "=0.23.0", features = ["build"] }
[dev-dependencies]
uniffi = { version = "0.23.0", features = ["bindgen-tests"] }
uniffi = { version = "=0.23.0", features = ["bindgen-tests"] }
assert_matches = "1.5.0"

View File

@@ -46,6 +46,7 @@ enum BdkError {
"Sled",
"Rusqlite",
"Rpc",
"HardenedIndex"
};
dictionary AddressInfo {
@@ -361,7 +362,7 @@ interface TxBuilder {
interface BumpFeeTxBuilder {
constructor(string txid, float new_fee_rate);
BumpFeeTxBuilder allow_shrinking(string address);
BumpFeeTxBuilder allow_shrinking(Script script_pubkey);
BumpFeeTxBuilder enable_rbf();
@@ -442,6 +443,12 @@ interface Descriptor {
[Name=new_bip84_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
[Name=new_bip86]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip86_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
string as_string();
string as_string_private();
@@ -449,7 +456,7 @@ interface Descriptor {
interface Address {
[Throws=BdkError]
constructor(string address);
constructor(string address, Network network);
[Name=from_script, Throws=BdkError]
constructor(Script script, Network network);
@@ -462,14 +469,16 @@ interface Address {
string to_qr_uri();
boolean is_valid_for_network(Network network);
string as_string();
};
[Enum]
interface Payload {
PubkeyHash(sequence<u8> pubkey_hash);
PubkeyHash(string pubkey_hash);
ScriptHash(sequence<u8> script_hash);
ScriptHash(string script_hash);
WitnessProgram(WitnessVersion version, sequence<u8> program);
};

View File

@@ -1,6 +1,6 @@
// use crate::BlockchainConfig;
use crate::Network;
use crate::{BdkError, Transaction};
use bdk::bitcoin::Network;
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
use bdk::blockchain::rpc::Auth as BdkAuth;
use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams;
@@ -17,7 +17,7 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex, MutexGuard};
pub(crate) struct Blockchain {
blockchain_mutex: Mutex<AnyBlockchain>,
inner_mutex: Mutex<AnyBlockchain>,
}
impl Blockchain {
@@ -45,23 +45,23 @@ impl Blockchain {
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
url: config.url,
auth: config.auth.into(),
network: config.network,
network: config.network.into(),
wallet_name: config.wallet_name,
sync_params: config.sync_params.map(|p| p.into()),
}),
};
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
Ok(Self {
blockchain_mutex: Mutex::new(blockchain),
inner_mutex: Mutex::new(blockchain),
})
}
pub(crate) fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> {
self.blockchain_mutex.lock().expect("blockchain")
self.inner_mutex.lock().expect("blockchain")
}
pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> {
let tx = &transaction.internal;
let tx = &transaction.inner;
self.get_blockchain().broadcast(tx)
}

View File

@@ -1,16 +1,17 @@
use crate::Network;
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
use bdk::bitcoin::bip32::Fingerprint;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::bitcoin::util::bip32::Fingerprint;
use bdk::bitcoin::Network;
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
use bdk::keys::{
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
KeyMap,
};
use bdk::template::{
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate,
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
DescriptorTemplate,
};
use bdk::KeychainKind;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
@@ -23,7 +24,8 @@ pub(crate) struct Descriptor {
impl Descriptor {
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
let secp = Secp256k1::new();
let (extended_descriptor, key_map) = descriptor.into_wallet_descriptor(&secp, network)?;
let (extended_descriptor, key_map) =
descriptor.into_wallet_descriptor(&secp, network.into())?;
Ok(Self {
extended_descriptor,
key_map,
@@ -35,13 +37,14 @@ impl Descriptor {
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
let derivable_key = &secret_key.inner;
match derivable_key.deref() {
match derivable_key {
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();
let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
@@ -50,6 +53,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
@@ -60,14 +66,14 @@ impl Descriptor {
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
let derivable_key = &public_key.inner;
match derivable_key.deref() {
match derivable_key {
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)
.build(network.into())
.unwrap();
Self {
@@ -78,6 +84,9 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
@@ -86,13 +95,14 @@ impl Descriptor {
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
let derivable_key = &secret_key.inner;
match derivable_key.deref() {
match derivable_key {
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();
let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
@@ -101,6 +111,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
@@ -111,14 +124,14 @@ impl Descriptor {
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
let derivable_key = &public_key.inner;
match derivable_key.deref() {
match derivable_key {
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)
.build(network.into())
.unwrap();
Self {
@@ -129,6 +142,9 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
@@ -137,13 +153,14 @@ impl Descriptor {
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = secret_key.descriptor_secret_key_mutex.lock().unwrap();
let derivable_key = &secret_key.inner;
match derivable_key.deref() {
match derivable_key {
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();
let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
@@ -152,6 +169,9 @@ impl Descriptor {
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
@@ -162,14 +182,14 @@ impl Descriptor {
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = public_key.descriptor_public_key_mutex.lock().unwrap();
let derivable_key = &public_key.inner;
match derivable_key.deref() {
match derivable_key {
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)
.build(network.into())
.unwrap();
Self {
@@ -180,6 +200,67 @@ impl Descriptor {
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86_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.inner;
match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) =
Bip86Public(derivable_key, fingerprint, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
@@ -239,17 +320,27 @@ mod test {
.as_public();
println!("Public 84: {}", handmade_public_84.as_string());
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
let handmade_public_86 = master
.derive(Arc::new(
DerivationPath::new("m/86h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 86: {}", handmade_public_86.as_string());
// Public 86: [d1d04177/86'/1'/0']tpubDCJzjbcGbdEfXMWaL6QmgVmuSfXkrue7m2YNoacWwyc7a2XjXaKojRqNEbo41CFL3PyYmKdhwg2fkGpLX4SQCbQjCGxAkWHJTw9WEeenrJb/*
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);
Descriptor::new_bip84(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_86 =
Descriptor::new_bip86(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
println!("Template 86: {}", template_private_86.as_string());
let template_public_44 = Descriptor::new_bip44_public(
handmade_public_44,
"d1d04177".to_string(),
@@ -268,9 +359,16 @@ mod test {
KeychainKind::External,
Network::Testnet,
);
let template_public_86 = Descriptor::new_bip86_public(
handmade_public_86,
"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());
println!("Template public 86: {}", template_public_86.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(),
@@ -284,6 +382,10 @@ mod test {
template_public_84.as_string_private(),
template_public_84.as_string()
);
assert_eq!(
template_public_86.as_string_private(),
template_public_86.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(),
@@ -297,6 +399,10 @@ mod test {
template_private_84.as_string(),
template_public_84.as_string()
);
assert_eq!(
template_private_86.as_string(),
template_public_86.as_string()
);
}
#[test]
fn test_descriptor_from_string() {

View File

@@ -1,14 +1,14 @@
use crate::BdkError;
use crate::Network;
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::Network;
use bdk::descriptor::DescriptorXKey;
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
use bdk::keys::{
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
};
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
use bdk::miniscript::BareCtx;
use std::ops::Deref;
use std::str::FromStr;
@@ -17,7 +17,7 @@ use std::sync::{Arc, Mutex};
/// Mnemonic phrases are a human-readable version of the private keys.
/// Supported number of words are 12, 15, 18, 21 and 24.
pub(crate) struct Mnemonic {
internal: BdkMnemonic,
inner: BdkMnemonic,
}
impl Mnemonic {
@@ -26,13 +26,13 @@ impl Mnemonic {
let generated_key: GeneratedKey<_, BareCtx> =
BdkMnemonic::generate((word_count, Language::English)).unwrap();
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
Mnemonic { internal: mnemonic }
Mnemonic { inner: mnemonic }
}
/// Parse a Mnemonic with given string
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
BdkMnemonic::from_str(&mnemonic)
.map(|m| Mnemonic { internal: m })
.map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
@@ -40,25 +40,25 @@ impl Mnemonic {
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
BdkMnemonic::from_entropy(entropy.as_slice())
.map(|m| Mnemonic { internal: m })
.map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
/// Returns Mnemonic as string
pub(crate) fn as_string(&self) -> String {
self.internal.to_string()
self.inner.to_string()
}
}
pub(crate) struct DerivationPath {
derivation_path_mutex: Mutex<BdkDerivationPath>,
inner_mutex: Mutex<BdkDerivationPath>,
}
impl DerivationPath {
pub(crate) fn new(path: String) -> Result<Self, BdkError> {
BdkDerivationPath::from_str(&path)
.map(|x| DerivationPath {
derivation_path_mutex: Mutex::new(x),
inner_mutex: Mutex::new(x),
})
.map_err(|e| BdkError::Generic(e.to_string()))
}
@@ -66,21 +66,21 @@ impl DerivationPath {
#[derive(Debug)]
pub(crate) struct DescriptorSecretKey {
pub(crate) descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
pub(crate) inner: BdkDescriptorSecretKey,
}
impl DescriptorSecretKey {
pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
let mnemonic = mnemonic.internal.clone();
let mnemonic = mnemonic.inner.clone();
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: None,
xkey: xkey.into_xprv(network).unwrap(),
xkey: xkey.into_xprv(network.into()).unwrap(),
derivation_path: BdkDerivationPath::master(),
wildcard: bdk::descriptor::Wildcard::Unhardened,
wildcard: Wildcard::Unhardened,
});
Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
inner: descriptor_secret_key,
}
}
@@ -88,15 +88,15 @@ impl DescriptorSecretKey {
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self {
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
inner: descriptor_secret_key,
})
}
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key.deref() {
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
@@ -110,19 +110,22 @@ impl DescriptorSecretKey {
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
inner: derived_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(),
)),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
}
}
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key.deref() {
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
@@ -132,51 +135,52 @@ impl DescriptorSecretKey {
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
inner: extended_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(),
)),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
}
}
pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> {
let secp = Secp256k1::new();
let descriptor_public_key = self
.descriptor_secret_key_mutex
.lock()
.unwrap()
.to_public(&secp)
.unwrap();
let descriptor_public_key = self.inner.to_public(&secp).unwrap();
Arc::new(DescriptorPublicKey {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
inner: descriptor_public_key,
})
}
/// Get the private key as bytes.
pub(crate) fn secret_bytes(&self) -> Vec<u8> {
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() {
let inner = &self.inner;
let secret_bytes: Vec<u8> = match inner {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
};
secret_bytes
}
pub(crate) fn as_string(&self) -> String {
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
self.inner.to_string()
}
}
#[derive(Debug)]
pub(crate) struct DescriptorPublicKey {
pub(crate) descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
pub(crate) inner: BdkDescriptorPublicKey,
}
impl DescriptorPublicKey {
@@ -184,16 +188,16 @@ impl DescriptorPublicKey {
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self {
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
inner: descriptor_public_key,
})
}
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key.deref() {
match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
@@ -207,19 +211,22 @@ impl DescriptorPublicKey {
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
inner: derived_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(),
)),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
}
}
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
match descriptor_public_key.deref() {
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
@@ -229,17 +236,20 @@ impl DescriptorPublicKey {
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
inner: extended_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(),
)),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
}
}
pub(crate) fn as_string(&self) -> String {
self.descriptor_public_key_mutex.lock().unwrap().to_string()
self.inner.to_string()
}
}
@@ -250,11 +260,10 @@ impl DescriptorPublicKey {
mod test {
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::BdkError;
use bdk::bitcoin::hashes::hex::ToHex;
use bdk::bitcoin::Network;
use crate::Network;
use std::sync::Arc;
fn get_descriptor_secret_key() -> DescriptorSecretKey {
fn get_inner() -> 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(Network::Testnet, Arc::new(mnemonic), None)
}
@@ -293,14 +302,14 @@ mod test {
#[test]
fn test_generate_descriptor_secret_key() {
let master_dsk = get_descriptor_secret_key();
let master_dsk = get_inner();
assert_eq!(master_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
}
#[test]
fn test_derive_self() {
let master_dsk = get_descriptor_secret_key();
let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -310,7 +319,7 @@ mod test {
#[test]
fn test_derive_descriptors_keys() {
let master_dsk = get_descriptor_secret_key();
let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -320,7 +329,7 @@ mod test {
#[test]
fn test_extend_descriptor_keys() {
let master_dsk = get_descriptor_secret_key();
let master_dsk = get_inner();
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
@@ -334,7 +343,7 @@ mod test {
}
#[test]
fn test_from_str_descriptor_secret_key() {
fn test_from_str_inner() {
let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
@@ -347,8 +356,8 @@ mod test {
}
#[test]
fn test_derive_and_extend_descriptor_secret_key() {
let master_dsk = get_descriptor_secret_key();
fn test_derive_and_extend_inner() {
let master_dsk = get_inner();
// derive DescriptorSecretKey with path "m/0" from master
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
@@ -359,18 +368,8 @@ mod test {
#[test]
fn test_derive_hardened_path_using_public() {
let master_dpk = get_descriptor_secret_key().as_public();
let master_dpk = get_inner().as_public();
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
assert!(derived_dpk.is_err());
}
#[test]
fn test_retrieve_master_secret_key() {
let master_dpk = get_descriptor_secret_key();
let master_private_key = master_dpk.secret_bytes().to_hex();
assert_eq!(
master_private_key,
"e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936"
)
}
}

View File

@@ -15,17 +15,19 @@ use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::psbt::PartiallySignedTransaction;
use crate::wallet::SignOptions;
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
use bdk::bitcoin::blockdata::script::Script as BdkScript;
use bdk::bitcoin::address::{NetworkUnchecked, Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn;
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::encode::serialize;
use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::psbt::serialize::Serialize;
use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::network::constants::Network as BdkNetwork;
use bdk::bitcoin::{
Address as BdkAddress, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
Address as BdkAddress, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
};
use bdk::blockchain::Progress as BdkProgress;
use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration};
use bdk::database::any::SledDbConfiguration;
use bdk::database::any::SqliteDbConfiguration;
use bdk::keys::bip39::WordCount;
use bdk::wallet::AddressIndex as BdkAddressIndex;
use bdk::wallet::AddressInfo as BdkAddressInfo;
@@ -41,6 +43,26 @@ use std::sync::Arc;
uniffi::include_scaffolding!("bdk");
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script(pub(crate) BdkScriptBuf);
impl Script {
pub fn new(raw_output_script: Vec<u8>) -> Self {
let script: BdkScriptBuf = raw_output_script.into();
Script(script)
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
}
}
impl From<BdkScriptBuf> for Script {
fn from(script: BdkScriptBuf) -> Self {
Script(script)
}
}
/// A output script and an amount of satoshis.
pub struct ScriptAmount {
pub script: Arc<Script>,
@@ -202,9 +224,7 @@ impl From<&BdkTxOut> for TxOut {
fn from(tx_out: &BdkTxOut) -> Self {
TxOut {
value: tx_out.value,
script_pubkey: Arc::new(Script {
script: tx_out.script_pubkey.clone(),
}),
script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
}
}
}
@@ -225,9 +245,7 @@ impl From<BdkLocalUtxo> for LocalUtxo {
},
txout: TxOut {
value: local_utxo.txout.value,
script_pubkey: Arc::new(Script {
script: local_utxo.txout.script_pubkey,
}),
script_pubkey: Arc::new(Script(local_utxo.txout.script_pubkey)),
},
keychain: local_utxo.keychain,
is_spent: local_utxo.is_spent,
@@ -274,9 +292,7 @@ impl From<&BdkTxIn> for TxIn {
txid: tx_in.previous_output.txid.to_string(),
vout: tx_in.previous_output.vout,
},
script_sig: Arc::new(Script {
script: tx_in.script_sig.clone(),
}),
script_sig: Arc::new(Script(tx_in.script_sig.clone())),
sequence: tx_in.sequence.0,
witness: tx_in.witness.to_vec(),
}
@@ -286,128 +302,144 @@ impl From<&BdkTxIn> for TxIn {
/// A Bitcoin transaction.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Transaction {
internal: BdkTransaction,
inner: BdkTransaction,
}
impl Transaction {
fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
let mut decoder = Cursor::new(transaction_bytes);
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
Ok(Transaction { internal: tx })
Ok(Transaction { inner: tx })
}
fn txid(&self) -> String {
self.internal.txid().to_string()
self.inner.txid().to_string()
}
fn weight(&self) -> u64 {
self.internal.weight() as u64
self.inner.weight().to_wu()
}
fn size(&self) -> u64 {
self.internal.size() as u64
self.inner.size() as u64
}
fn vsize(&self) -> u64 {
self.internal.vsize() as u64
self.inner.vsize() as u64
}
fn serialize(&self) -> Vec<u8> {
self.internal.serialize()
serialize(&self.inner)
}
fn is_coin_base(&self) -> bool {
self.internal.is_coin_base()
self.inner.is_coin_base()
}
fn is_explicitly_rbf(&self) -> bool {
self.internal.is_explicitly_rbf()
self.inner.is_explicitly_rbf()
}
fn is_lock_time_enabled(&self) -> bool {
self.internal.is_lock_time_enabled()
self.inner.is_lock_time_enabled()
}
fn version(&self) -> i32 {
self.internal.version
self.inner.version
}
fn lock_time(&self) -> u32 {
self.internal.lock_time.0
self.inner.lock_time.to_consensus_u32()
}
fn input(&self) -> Vec<TxIn> {
self.internal.input.iter().map(|x| x.into()).collect()
self.inner.input.iter().map(|x| x.into()).collect()
}
fn output(&self) -> Vec<TxOut> {
self.internal.output.iter().map(|x| x.into()).collect()
self.inner.output.iter().map(|x| x.into()).collect()
}
}
impl From<BdkTransaction> for Transaction {
fn from(tx: BdkTransaction) -> Self {
Transaction { internal: tx }
Transaction { inner: tx }
}
}
/// A Bitcoin address.
#[derive(Debug, PartialEq, Eq)]
pub struct Address {
address: BdkAddress,
inner: BdkAddress,
}
impl Address {
fn new(address: String) -> Result<Self, BdkError> {
BdkAddress::from_str(address.as_str())
.map(|a| Address { address: a })
.map_err(|e| BdkError::Generic(e.to_string()))
pub fn new(address: String, network: Network) -> Result<Self, BdkError> {
let parsed_address = address
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
.map_err(|e| BdkError::Generic(e.to_string()))?;
let network_checked_address = parsed_address
.require_network(network.into())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Address {
inner: network_checked_address,
})
}
/// alternative constructor
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
BdkAddress::from_script(&script.script, network)
.map(|a| Address { address: a })
BdkAddress::from_script(&script.0, network.into())
.map(|a| Address { inner: a })
.map_err(|e| BdkError::Generic(e.to_string()))
}
fn payload(&self) -> Payload {
match &self.address.payload.clone() {
match &self.inner.payload.clone() {
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
pubkey_hash: pubkey_hash.to_vec(),
pubkey_hash: pubkey_hash.to_string(),
},
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
script_hash: script_hash.to_vec(),
script_hash: script_hash.to_string(),
},
BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
version: *version,
program: program.clone(),
BdkPayload::WitnessProgram(witness_program) => Payload::WitnessProgram {
version: witness_program.version(),
program: Vec::from(witness_program.program().as_bytes()),
},
_ => panic!("Unsupported address payload type"),
}
}
fn network(&self) -> Network {
self.address.network
self.inner.network.into()
}
fn script_pubkey(&self) -> Arc<Script> {
Arc::new(Script {
script: self.address.script_pubkey(),
})
Arc::new(Script(self.inner.script_pubkey()))
}
fn to_qr_uri(&self) -> String {
self.address.to_qr_uri()
self.inner.to_qr_uri()
}
pub fn is_valid_for_network(&self, network: Network) -> bool {
let address_str = self.inner.to_string();
if let Ok(unchecked_address) = address_str.parse::<BdkAddress<NetworkUnchecked>>() {
unchecked_address.is_valid_for_network(network.into())
} else {
false
}
}
fn as_string(&self) -> String {
self.address.to_string()
self.inner.to_string()
}
}
impl From<BdkAddress> for Address {
fn from(address: BdkAddress) -> Self {
Address { address }
Address { inner: address }
}
}
@@ -415,9 +447,9 @@ impl From<BdkAddress> for Address {
#[derive(Debug)]
pub enum Payload {
/// P2PKH address.
PubkeyHash { pubkey_hash: Vec<u8> },
PubkeyHash { pubkey_hash: String },
/// P2SH address.
ScriptHash { script_hash: Vec<u8> },
ScriptHash { script_hash: String },
/// Segwit address.
WitnessProgram {
/// The witness program version.
@@ -427,29 +459,6 @@ pub enum Payload {
},
}
/// A Bitcoin script.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script {
script: BdkScript,
}
impl Script {
fn new(raw_output_script: Vec<u8>) -> Self {
let script: BdkScript = BdkScript::from(raw_output_script);
Script { script }
}
fn to_bytes(&self) -> Vec<u8> {
self.script.to_bytes()
}
}
impl From<BdkScript> for Script {
fn from(bdk_script: BdkScript) -> Self {
Script { script: bdk_script }
}
}
#[derive(Clone, Debug)]
enum RbfValue {
Default,
@@ -463,6 +472,37 @@ pub struct TxBuilderResult {
pub transaction_details: TransactionDetails,
}
#[derive(PartialEq, Debug)]
pub enum Network {
Bitcoin,
Testnet,
Signet,
Regtest,
}
impl From<Network> for BdkNetwork {
fn from(network: Network) -> Self {
match network {
Network::Bitcoin => BdkNetwork::Bitcoin,
Network::Testnet => BdkNetwork::Testnet,
Network::Signet => BdkNetwork::Signet,
Network::Regtest => BdkNetwork::Regtest,
}
}
}
impl From<BdkNetwork> for Network {
fn from(network: BdkNetwork) -> Self {
match network {
BdkNetwork::Bitcoin => Network::Bitcoin,
BdkNetwork::Testnet => Network::Testnet,
BdkNetwork::Signet => Network::Signet,
BdkNetwork::Regtest => Network::Regtest,
_ => panic!("Network {} not supported", network),
}
}
}
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.
@@ -470,30 +510,33 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
// crate.
#[cfg(test)]
mod test {
use super::Transaction;
use crate::Network::Regtest;
use crate::{Address, Payload};
use assert_matches::assert_matches;
use bdk::bitcoin::address::WitnessVersion;
use bdk::bitcoin::hashes::hex::FromHex;
use bdk::bitcoin::util::address::WitnessVersion;
use bdk::bitcoin::Network;
// Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes.
#[test]
fn test_transaction_serde() {
let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
}
// #[test]
// fn test_transaction_serde() {
// let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
// let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
// let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
// assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
// }
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
#[test]
fn test_address_witness_program() {
let address =
Address::new("bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string()).unwrap();
let address = Address::new(
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string(),
Network::Regtest.into(),
)
.unwrap();
let payload = address.payload();
assert_matches!(payload, Payload::WitnessProgram { version, program } => {
assert_eq!(version,WitnessVersion::V0);
assert_eq!(version, WitnessVersion::V0);
assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
});
assert_eq!(address.network(), Regtest);

View File

@@ -1,5 +1,4 @@
use bdk::bitcoin::hashes::hex::ToHex;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoincore_rpc::jsonrpc::serde_json;
use bdk::psbt::PsbtUtils;
use std::ops::Deref;
@@ -10,7 +9,7 @@ use crate::{BdkError, FeeRate, Transaction};
#[derive(Debug)]
pub(crate) struct PartiallySignedTransaction {
pub(crate) internal: Mutex<BdkPartiallySignedTransaction>,
pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
}
impl PartiallySignedTransaction {
@@ -18,24 +17,24 @@ impl PartiallySignedTransaction {
let psbt: BdkPartiallySignedTransaction =
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
Ok(PartiallySignedTransaction {
internal: Mutex::new(psbt),
inner: Mutex::new(psbt),
})
}
pub(crate) fn serialize(&self) -> String {
let psbt = self.internal.lock().unwrap().clone();
let psbt = self.inner.lock().unwrap().clone();
psbt.to_string()
}
pub(crate) fn txid(&self) -> String {
let tx = self.internal.lock().unwrap().clone().extract_tx();
let tx = self.inner.lock().unwrap().clone().extract_tx();
let txid = tx.txid();
txid.to_hex()
txid.to_string()
}
/// Return the transaction.
pub(crate) fn extract_tx(&self) -> Arc<Transaction> {
let tx = self.internal.lock().unwrap().clone().extract_tx();
let tx = self.inner.lock().unwrap().clone().extract_tx();
Arc::new(tx.into())
}
@@ -46,19 +45,19 @@ impl PartiallySignedTransaction {
&self,
other: Arc<PartiallySignedTransaction>,
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let other_psbt = other.internal.lock().unwrap().clone();
let mut original_psbt = self.internal.lock().unwrap().clone();
let other_psbt = other.inner.lock().unwrap().clone();
let mut original_psbt = self.inner.lock().unwrap().clone();
original_psbt.combine(other_psbt)?;
Ok(Arc::new(PartiallySignedTransaction {
internal: Mutex::new(original_psbt),
inner: Mutex::new(original_psbt),
}))
}
/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
/// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_amount(&self) -> Option<u64> {
self.internal.lock().unwrap().fee_amount()
self.inner.lock().unwrap().fee_amount()
}
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the
@@ -66,12 +65,12 @@ impl PartiallySignedTransaction {
/// transaction.
/// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
self.internal.lock().unwrap().fee_rate().map(Arc::new)
self.inner.lock().unwrap().fee_rate().map(Arc::new)
}
/// Serialize the PSBT data structure as a String of JSON.
pub(crate) fn json_serialize(&self) -> String {
let psbt = self.internal.lock().unwrap();
let psbt = self.inner.lock().unwrap();
serde_json::to_string(psbt.deref()).unwrap()
}
}
@@ -82,6 +81,7 @@ impl PartiallySignedTransaction {
#[cfg(test)]
mod test {
use crate::wallet::{TxBuilder, Wallet};
use crate::Network;
use bdk::wallet::get_funded_wallet;
use std::sync::Mutex;
@@ -90,10 +90,10 @@ mod test {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet {
wallet_mutex: Mutex::new(funded_wallet),
inner_mutex: Mutex::new(funded_wallet),
};
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address)
let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap()
.script_pubkey();
@@ -103,7 +103,7 @@ mod test {
.drain_to(drain_to_script.clone());
//dbg!(&tx_builder);
assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone()));
assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();

View File

@@ -1,5 +1,6 @@
use bdk::bitcoin::blockdata::script::Script as BdkScript;
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Sequence, Txid};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::script::PushBytesBuf;
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence, Txid};
use bdk::database::any::AnyDatabase;
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
use bdk::wallet::tx_builder::ChangeSpendPolicy;
@@ -8,6 +9,7 @@ use bdk::{
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex, MutexGuard};
@@ -16,6 +18,7 @@ use crate::blockchain::Blockchain;
use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor;
use crate::psbt::PartiallySignedTransaction;
use crate::Network;
use crate::{
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder,
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
@@ -23,7 +26,7 @@ use crate::{
#[derive(Debug)]
pub(crate) struct Wallet {
pub(crate) wallet_mutex: Mutex<BdkWallet<AnyDatabase>>,
pub(crate) inner_mutex: Mutex<BdkWallet<AnyDatabase>>,
}
/// A Bitcoin wallet.
@@ -50,24 +53,26 @@ impl Wallet {
let wallet_mutex = Mutex::new(BdkWallet::new(
&descriptor,
change_descriptor.as_ref(),
network,
network.into(),
database,
)?);
Ok(Wallet { wallet_mutex })
Ok(Wallet {
inner_mutex: wallet_mutex,
})
}
pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
self.wallet_mutex.lock().expect("wallet")
self.inner_mutex.lock().expect("wallet")
}
/// Get the Bitcoin network the wallet is using.
pub(crate) fn network(&self) -> Network {
self.get_wallet().network()
self.get_wallet().network().into()
}
/// Return whether or not a script is part of this wallet (either internal or external).
pub(crate) fn is_mine(&self, script: Arc<Script>) -> Result<bool, BdkError> {
self.get_wallet().is_mine(&script.script)
self.get_wallet().is_mine(&script.0)
}
/// Sync the internal database with the blockchain.
@@ -131,7 +136,7 @@ impl Wallet {
psbt: &PartiallySignedTransaction,
sign_options: Option<SignOptions>,
) -> Result<bool, BdkError> {
let mut psbt = psbt.internal.lock().unwrap();
let mut psbt = psbt.inner.lock().unwrap();
self.get_wallet().sign(
&mut psbt,
sign_options.map(SignOptions::into).unwrap_or_default(),
@@ -238,7 +243,7 @@ impl From<SignOptions> for BdkSignOptions {
/// Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added.
#[derive(Clone, Debug)]
pub(crate) struct TxBuilder {
pub(crate) recipients: Vec<(BdkScript, u64)>,
pub(crate) recipients: Vec<(BdkScriptBuf, u64)>,
pub(crate) utxos: Vec<OutPoint>,
pub(crate) unspendable: HashSet<OutPoint>,
pub(crate) change_policy: ChangeSpendPolicy,
@@ -246,7 +251,7 @@ pub(crate) struct TxBuilder {
pub(crate) fee_rate: Option<f32>,
pub(crate) fee_absolute: Option<u64>,
pub(crate) drain_wallet: bool,
pub(crate) drain_to: Option<BdkScript>,
pub(crate) drain_to: Option<BdkScriptBuf>,
pub(crate) rbf: Option<RbfValue>,
pub(crate) data: Vec<u8>,
}
@@ -270,8 +275,8 @@ impl TxBuilder {
/// Add a recipient to the internal list.
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
let mut recipients: Vec<(BdkScript, u64)> = self.recipients.clone();
recipients.append(&mut vec![(script.script.clone(), amount)]);
let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
recipients.append(&mut vec![(script.0.clone(), amount)]);
Arc::new(TxBuilder {
recipients,
..self.clone()
@@ -281,7 +286,7 @@ impl TxBuilder {
pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
let recipients = recipients
.iter()
.map(|script_amount| (script_amount.script.script.clone(), script_amount.amount))
.map(|script_amount| (script_amount.script.0.clone(), script_amount.amount))
.collect();
Arc::new(TxBuilder {
recipients,
@@ -386,7 +391,7 @@ impl TxBuilder {
/// to allow this output to be reduced to pay for the extra fees.
pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
Arc::new(TxBuilder {
drain_to: Some(script.script.clone()),
drain_to: Some(script.0.clone()),
..self.clone()
})
}
@@ -461,14 +466,17 @@ impl TxBuilder {
}
}
if !&self.data.is_empty() {
tx_builder.add_data(self.data.as_slice());
let push_bytes = PushBytesBuf::try_from(self.data.clone()).map_err(|_| {
BdkError::Generic("Failed to convert data to PushBytes".to_string())
})?;
tx_builder.add_data(&push_bytes);
}
tx_builder
.finish()
.map(|(psbt, tx_details)| TxBuilderResult {
psbt: Arc::new(PartiallySignedTransaction {
internal: Mutex::new(psbt),
inner: Mutex::new(psbt),
}),
transaction_details: TransactionDetails::from(tx_details),
})
@@ -480,7 +488,7 @@ impl TxBuilder {
pub(crate) struct BumpFeeTxBuilder {
pub(crate) txid: String,
pub(crate) fee_rate: f32,
pub(crate) allow_shrinking: Option<String>,
pub(crate) allow_shrinking: Option<Arc<Script>>,
pub(crate) rbf: Option<RbfValue>,
}
@@ -499,9 +507,9 @@ impl BumpFeeTxBuilder {
/// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved
/// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
/// cant be found among the recipients of the transaction we are bumping.
pub(crate) fn allow_shrinking(&self, address: String) -> Arc<Self> {
pub(crate) fn allow_shrinking(&self, script_pubkey: Arc<Script>) -> Arc<Self> {
Arc::new(Self {
allow_shrinking: Some(address),
allow_shrinking: Some(script_pubkey),
..self.clone()
})
}
@@ -534,10 +542,7 @@ impl BumpFeeTxBuilder {
let mut tx_builder = wallet.build_fee_bump(txid)?;
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
if let Some(allow_shrinking) = &self.allow_shrinking {
let address = BdkAddress::from_str(allow_shrinking)
.map_err(|e| BdkError::Generic(e.to_string()))?;
let script = address.script_pubkey();
tx_builder.allow_shrinking(script)?;
tx_builder.allow_shrinking(allow_shrinking.0.clone())?;
}
if let Some(rbf) = &self.rbf {
match *rbf {
@@ -552,7 +557,7 @@ impl BumpFeeTxBuilder {
tx_builder
.finish()
.map(|(psbt, _)| PartiallySignedTransaction {
internal: Mutex::new(psbt),
inner: Mutex::new(psbt),
})
.map(Arc::new)
}
@@ -567,9 +572,10 @@ mod test {
use crate::descriptor::Descriptor;
use crate::keys::{DescriptorSecretKey, Mnemonic};
use crate::wallet::{AddressIndex, TxBuilder, Wallet};
use crate::Network;
use crate::Script;
use assert_matches::assert_matches;
use bdk::bitcoin::{Address, Network};
use bdk::bitcoin::Address;
use bdk::wallet::get_funded_wallet;
use bdk::KeychainKind;
use std::str::FromStr;
@@ -580,20 +586,20 @@ mod test {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet {
wallet_mutex: Mutex::new(funded_wallet),
inner_mutex: Mutex::new(funded_wallet),
};
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address)
let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap()
.script_pubkey();
let tx_builder = TxBuilder::new()
.drain_wallet()
.drain_to(drain_to_script.clone());
assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.script.clone()));
assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
let psbt = tx_builder_result.psbt.internal.lock().unwrap().clone();
let psbt = tx_builder_result.psbt.inner.lock().unwrap().clone();
let tx_details = tx_builder_result.transaction_details;
// confirm one input with 50,000 sats
@@ -621,12 +627,14 @@ mod test {
.cloned()
.unwrap()
.script_pubkey,
Network::Testnet,
Network::Testnet.into(),
)
.unwrap();
assert_eq!(
output_address,
Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt").unwrap()
Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
.unwrap()
.assume_checked()
);
let output_value = psbt.unsigned_tx.output.get(0).cloned().unwrap().value;
assert_eq!(output_value, 49_890_u64); // input - fee

View File

@@ -25,8 +25,8 @@ val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8
val databaseConfig = DatabaseConfig.Memory
val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
)
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.LastUnused)
```
@@ -38,8 +38,8 @@ repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
}
```

View File

@@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx1536m
android.enableJetifier=true
kotlin.code.style=official
libraryVersion=0.29.2
libraryVersion=0.31.1

View File

@@ -51,7 +51,7 @@ print(f"Wallet balance is: {balance.total}")
setup(
name="bdkpython",
version="0.29.1",
version="0.31.0",
description="The Python language bindings for the Bitcoin Development Kit",
long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",

View File

@@ -16,6 +16,8 @@
</array>
<key>SupportedPlatform</key>
<string>macos</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
@@ -31,6 +33,8 @@
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict>
<dict>
<key>LibraryIdentifier</key>
@@ -43,6 +47,8 @@
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict>
</array>
<key>CFBundlePackageType</key>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>MinimumOSVersion</key>
<string>100</string>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>MinimumOSVersion</key>
<string>15.0</string>
</dict>
</plist>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.bitcoindevkit.bdkFFI</string>
<key>CFBundleName</key>
<string>bdkFFI</string>
<key>CFBundleVersion</key>
<string>0.31.1</string>
<key>CFBundleShortVersionString</key>
<string>0.31.1</string>
<key>CFBundleExecutable</key>
<string>bdkFFI</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict>
</plist>