Compare commits
63 Commits
release/0.
...
release/0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60f1aef3e0 | ||
|
|
7490d8d8b6 | ||
|
|
5d71773e7f | ||
|
|
ebde685f06 | ||
|
|
8d1ecd1d8c | ||
|
|
25a48e0565 | ||
|
|
b305f8f44e | ||
|
|
ef080130bf | ||
|
|
e798e1573f | ||
|
|
743862fb60 | ||
|
|
b7e38b18be | ||
|
|
ef73aa3490 | ||
|
|
fbec953149 | ||
|
|
0b07b8ed05 | ||
|
|
b59327e5ea | ||
|
|
e6500baae7 | ||
|
|
85f220b953 | ||
|
|
106d31c9c3 | ||
|
|
4ae169f860 | ||
|
|
7717ebb097 | ||
|
|
c3e8469686 | ||
|
|
faf23b7d25 | ||
|
|
1da01b4a0b | ||
|
|
f1ba03bf50 | ||
|
|
bc182c7164 | ||
|
|
5fc189717d | ||
|
|
849bfe79c1 | ||
|
|
dc79b78b2d | ||
|
|
7cc08f1d6f | ||
|
|
031fcb02da | ||
|
|
5f9b5682e5 | ||
|
|
d0a7315c9d | ||
|
|
0bfc56b0e8 | ||
|
|
3dd6c203e8 | ||
|
|
76acbf575b | ||
|
|
039b64de5c | ||
|
|
fe7e4e21c0 | ||
|
|
77f89afc68 | ||
|
|
25033f6bd6 | ||
|
|
3cb2c2c394 | ||
|
|
5092987b26 | ||
|
|
aea25dbf21 | ||
|
|
ed67eba910 | ||
|
|
90606b2455 | ||
|
|
49e8fe461e | ||
|
|
de88184b8c | ||
|
|
3be2c0495f | ||
|
|
2c4c64515f | ||
|
|
17323d3184 | ||
|
|
b382511a9e | ||
|
|
d3895441d3 | ||
|
|
269512a673 | ||
|
|
d27206787a | ||
|
|
c1b1fd6f5d | ||
|
|
7062fbd047 | ||
|
|
0e34a6bacf | ||
|
|
89e85a20cf | ||
|
|
d8718c3f05 | ||
|
|
871a06d1ce | ||
|
|
b820d6a2ba | ||
|
|
79d9fa2909 | ||
|
|
a0e0467d39 | ||
|
|
f2296704e6 |
17
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: Enhancement request
|
||||||
|
about: Request a new feature or change to an existing feature
|
||||||
|
title: ''
|
||||||
|
labels: 'enhancement'
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the enhancement**
|
||||||
|
<!-- A clear and concise description of what you would like added or changed. -->
|
||||||
|
|
||||||
|
**Use case**
|
||||||
|
<!-- Tell us how you or others will use this new feature or change to an existing feature. -->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context about the enhancement here. -->
|
||||||
132
.github/ISSUE_TEMPLATE/minor_release.md
vendored
132
.github/ISSUE_TEMPLATE/minor_release.md
vendored
@@ -7,77 +7,81 @@ assignees: ''
|
|||||||
---
|
---
|
||||||
|
|
||||||
## Create a new minor release
|
## Create a new minor release
|
||||||
### _Main Workflow_
|
## 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.
|
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.
|
2. - [ ] Once the new bdk release is out, update the PR to replace the release candidate with the full release and merge.
|
||||||
3. - [ ] Update the Android, JVM, Python, and Swift libraries as per the ["**_Sub-Workflows_**" section below](#Sub-Workflows). Open a single PR on master for all of these changes called `Prepare language bindings libraries for 0.X release`
|
|
||||||
|
### 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.
|
||||||
|
```shell
|
||||||
|
# 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
|
||||||
|
```shell
|
||||||
|
cd ./bdk-jvm/
|
||||||
|
./gradlew buildJvmLib
|
||||||
|
./gradlew test
|
||||||
|
```
|
||||||
|
10. - [ ] Update the readme if necessary
|
||||||
|
#### _Swift_
|
||||||
|
11. - [ ] Run the tests and adjust if necessary
|
||||||
|
```shell
|
||||||
|
./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 ./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
|
||||||
|
```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).
|
||||||
18. - [ ] Create a new branch off of `master` called `release/version`
|
18. - [ ] Create a new branch off of `master` called `release/version`
|
||||||
19. - [ ] Checkout that branch and open a PR to update the Android, JVM, and Python libraries' versions
|
19. - [ ] Update bdk-android version from `SNAPSHOT` version to release version
|
||||||
- [ ] Update bdk-android version from `SNAPSHOT` version to release version
|
20. - [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
|
||||||
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
|
21. - [ ] Update bdk-python version from `.dev` version to release version
|
||||||
- [ ] 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).
|
||||||
20. - [ ] Merge the PR updating all of the languages to their release versions
|
23. - [ ] Get a review and ACK and merge the PR updating all the languages to their release versions
|
||||||
21. - [ ] 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.
|
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.
|
||||||
```sh
|
```shell
|
||||||
git tag v0.6.0 --sign --edit
|
git tag v0.6.0 --sign --edit
|
||||||
git push upstream v0.6.0
|
git push upstream v0.6.0
|
||||||
```
|
```
|
||||||
22. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
|
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`)
|
||||||
23. - [ ] 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`)
|
26. - [ ] Make sure the released libraries work and contain the artifacts you would expect
|
||||||
24. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
|
27. - [ ] Aggregate all the changelog notices from the PRs and add them to the changelog file
|
||||||
25. - [ ] Build and publish API docs for JVM, Android, and Java on the website
|
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`
|
||||||
```bash!
|
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 dokkaHtml # bdk-jvm (Dokka)
|
||||||
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
|
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation)
|
||||||
./gradlew dokkaHtml # bdk-android (Dokka)
|
./gradlew dokkaHtml # bdk-android (Dokka)
|
||||||
```
|
```
|
||||||
26. - [ ] Tweet about the library
|
33. - [ ] Post in the announcement channel
|
||||||
27. - [ ] Post in the announcement channel
|
34. - [ ] Tweet about the library
|
||||||
|
|
||||||
### _Sub Workflows_
|
|
||||||
#### _Android_
|
|
||||||
4. - [ ] Update the API docs to reflect the changes in the API
|
|
||||||
5. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
|
|
||||||
6. - [ ] 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
|
|
||||||
```
|
|
||||||
7. - [ ] Update the readme if necessary
|
|
||||||
|
|
||||||
#### _JVM_
|
|
||||||
8. - [ ] Update the API docs to reflect the changes in the API
|
|
||||||
9. - [ ] Delete the `target` directory in bdk-ffi and all previous artifacts to make sure you're building the library from scratch
|
|
||||||
10. - [ ] Build the library and run the tests, and adjust if necessary
|
|
||||||
```sh
|
|
||||||
cd bdk-jvm
|
|
||||||
./gradlew buildJvmLib
|
|
||||||
./gradlew test
|
|
||||||
```
|
|
||||||
11. - [ ] Update the readme if necessary
|
|
||||||
|
|
||||||
#### _Swift_
|
|
||||||
12. - [ ] Run the tests and adjust if necessary
|
|
||||||
```sh
|
|
||||||
./bdk-swift/build-local-swift.sh
|
|
||||||
cd bdk-swift
|
|
||||||
swift test
|
|
||||||
```
|
|
||||||
13. - [ ] Update the readme if necessary
|
|
||||||
|
|
||||||
#### _Python_
|
|
||||||
14. - [ ] 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
|
|
||||||
15. - [ ] Build the library
|
|
||||||
```shell
|
|
||||||
pip3 install --requirement requirements.txt
|
|
||||||
bash ./generate.sh
|
|
||||||
python3 setup.py --verbose bdist_wheel
|
|
||||||
```
|
|
||||||
16. - [ ] Run the tests and adjust if necessary
|
|
||||||
```shell
|
|
||||||
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl
|
|
||||||
python -m unittest --verbose tests/test_bdk.py
|
|
||||||
```
|
|
||||||
17. - [ ] Update the readme and `setup.py` if necessary
|
|
||||||
|
|||||||
84
.github/ISSUE_TEMPLATE/patch_release.md
vendored
84
.github/ISSUE_TEMPLATE/patch_release.md
vendored
@@ -1,84 +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`
|
|
||||||
- [ ] Create a new branch off of `master` called `release/version`
|
|
||||||
18. - [ ] Checkout that branch and open a PR to update the Android, JVM, and Python libraries' versions
|
|
||||||
- [ ] 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 of 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. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one)
|
|
||||||
22. - [ ] 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`)
|
|
||||||
23. - [ ] Bump the versions on master from `0.9.0-SNAPSHOT` to `0.10.0-SNAPSHOT`, `0.6.0.dev0` to `0.7.0.dev0`
|
|
||||||
24. - [ ] 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)
|
|
||||||
```
|
|
||||||
25. - [ ] Tweet about the library
|
|
||||||
26. - [ ] Post in the announcement channel
|
|
||||||
2
.github/workflows/audit.yml
vendored
2
.github/workflows/audit.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
name: Security audit
|
name: Security audit
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: actions-rs/audit-check@v1
|
- uses: actions-rs/audit-check@v1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
14
.github/workflows/cont_integration.yml
vendored
14
.github/workflows/cont_integration.yml
vendored
@@ -14,18 +14,18 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
rust:
|
rust:
|
||||||
- version: 1.63.0 # STABLE
|
- version: 1.71.0 # STABLE
|
||||||
clippy: true
|
clippy: true
|
||||||
- version: 1.61.0 # MSRV
|
- version: 1.61.0 # MSRV
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Generate cache key
|
- name: Generate cache key
|
||||||
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
|
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
|
||||||
|
|
||||||
- name: Cache
|
- name: Cache
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -46,6 +46,12 @@ jobs:
|
|||||||
- name: Update toolchain
|
- name: Update toolchain
|
||||||
run: rustup update
|
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
|
- name: Build
|
||||||
run: cargo build
|
run: cargo build
|
||||||
|
|
||||||
@@ -61,7 +67,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set default toolchain
|
- name: Set default toolchain
|
||||||
run: rustup default nightly
|
run: rustup default nightly
|
||||||
|
|||||||
6
.github/workflows/publish-android.yaml
vendored
6
.github/workflows/publish-android.yaml
vendored
@@ -20,10 +20,10 @@ jobs:
|
|||||||
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
|
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
|
||||||
|
|
||||||
- name: "Check out PR branch"
|
- name: "Check out PR branch"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Cache"
|
- name: "Cache"
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: "Set up JDK"
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
|||||||
93
.github/workflows/publish-jvm.yaml
vendored
93
.github/workflows/publish-jvm.yaml
vendored
@@ -2,14 +2,14 @@ name: Publish bdk-jvm to Maven Central
|
|||||||
on: [workflow_dispatch]
|
on: [workflow_dispatch]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-jvm-macOS-M1-native-lib:
|
build-macOS-native-libs:
|
||||||
name: "Create M1 and x86_64 JVM native binaries"
|
name: "Create M1 and x86_64 native binaries"
|
||||||
runs-on: macos-12
|
runs-on: macos-12
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout publishing branch"
|
- name: "Checkout publishing branch"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Cache
|
- name: "Cache"
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -18,8 +18,8 @@ jobs:
|
|||||||
./target
|
./target
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
@@ -27,36 +27,59 @@ jobs:
|
|||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Set default Rust version to 1.67.0"
|
||||||
run: rustup default 1.67.0
|
run: rustup default 1.67.0
|
||||||
|
|
||||||
- name: Install aarch64 Rust target
|
- name: "Install aarch64 Rust target"
|
||||||
run: rustup target add aarch64-apple-darwin
|
run: rustup target add aarch64-apple-darwin
|
||||||
|
|
||||||
- name: Build bdk-jvm library
|
- name: "Build bdk-jvm library"
|
||||||
run: |
|
run: |
|
||||||
cd bdk-jvm
|
cd bdk-jvm
|
||||||
./gradlew buildJvmLib
|
./gradlew buildJvmLib
|
||||||
|
|
||||||
# build aarch64 + x86_64 native libraries and upload
|
- name: "Upload macOS native libraries for reuse in publishing job"
|
||||||
- name: Upload macOS native libraries for reuse in publishing job
|
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
# name: no name is required because we upload the entire directory
|
name: artifact-macos
|
||||||
# the default name "artifact" will be used
|
|
||||||
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/
|
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/
|
||||||
|
|
||||||
build-jvm-full-library:
|
build-windows-native-lib:
|
||||||
|
name: "Create Windows native binaries"
|
||||||
|
runs-on: windows-2022
|
||||||
|
steps:
|
||||||
|
- name: "Checkout publishing branch"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: "Set up JDK"
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
distribution: temurin
|
||||||
|
java-version: 11
|
||||||
|
|
||||||
|
- name: "Set default Rust version to 1.67.0"
|
||||||
|
run: rustup default 1.67.0
|
||||||
|
|
||||||
|
- name: "Install x86_64-pc-windows-msvc Rust target"
|
||||||
|
run: rustup target add x86_64-pc-windows-msvc
|
||||||
|
|
||||||
|
- name: "Build bdk-jvm library"
|
||||||
|
run: |
|
||||||
|
cd bdk-jvm
|
||||||
|
./gradlew buildJvmLib
|
||||||
|
|
||||||
|
- name: "Upload Windows native libraries for reuse in publishing job"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifact-windows
|
||||||
|
path: D:\a\bdk-ffi\bdk-ffi\bdk-jvm\lib\src\main\resources\
|
||||||
|
|
||||||
|
build-full-library:
|
||||||
name: Create full bdk-jvm library
|
name: Create full bdk-jvm library
|
||||||
needs: [build-jvm-macOS-M1-native-lib]
|
needs: [build-macOS-native-libs, build-windows-native-lib]
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout publishing branch
|
- name: "Checkout publishing branch"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Update bdk-ffi git submodule
|
- name: "Cache"
|
||||||
run: |
|
|
||||||
git submodule set-url bdk-ffi https://github.com/bitcoindevkit/bdk-ffi.git
|
|
||||||
git submodule update --init bdk-ffi
|
|
||||||
|
|
||||||
- name: Cache
|
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -65,8 +88,8 @@ jobs:
|
|||||||
./target
|
./target
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
@@ -74,20 +97,30 @@ jobs:
|
|||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Set default Rust version to 1.67.0"
|
||||||
run: rustup default 1.67.0
|
run: rustup default 1.67.0
|
||||||
|
|
||||||
- name: Build bdk-jvm library
|
- name: "Build bdk-jvm library"
|
||||||
run: |
|
run: |
|
||||||
cd bdk-jvm
|
cd bdk-jvm
|
||||||
./gradlew buildJvmLib
|
./gradlew buildJvmLib
|
||||||
|
|
||||||
- name: Download macOS native libraries from previous job
|
- name: "Download macOS native binaries from previous job"
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
id: download
|
|
||||||
with:
|
with:
|
||||||
# download the artifact created in the prior job (named "artifact")
|
name: artifact-macos
|
||||||
name: artifact
|
|
||||||
path: ./bdk-jvm/lib/src/main/resources/
|
path: ./bdk-jvm/lib/src/main/resources/
|
||||||
|
|
||||||
- name: Publish to Maven Central
|
- name: "Download Windows native libraries from previous job"
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifact-windows
|
||||||
|
path: ./bdk-jvm/lib/src/main/resources/
|
||||||
|
|
||||||
|
- name: "Upload library code and binaries"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: artifact-full
|
||||||
|
path: ./bdk-jvm/lib/
|
||||||
|
|
||||||
|
- name: "Publish to Maven Central"
|
||||||
env:
|
env:
|
||||||
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }}
|
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }}
|
||||||
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }}
|
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }}
|
||||||
|
|||||||
105
.github/workflows/publish-python.yaml
vendored
105
.github/workflows/publish-python.yaml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Build and publish Python wheels
|
name: Publish bdkpython to PyPI
|
||||||
on: [workflow_dispatch]
|
on: [workflow_dispatch]
|
||||||
|
|
||||||
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
|
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
|
||||||
@@ -7,7 +7,7 @@ on: [workflow_dispatch]
|
|||||||
# tries to load glibc and fails because it requires a more recent version.
|
# tries to load glibc and fails because it requires a more recent version.
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-manylinux2014-x86_64-wheel:
|
build-manylinux2014-x86_64-wheels:
|
||||||
name: "Build Manylinux 2014 x86_64 wheel"
|
name: "Build Manylinux 2014 x86_64 wheel"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
defaults:
|
defaults:
|
||||||
@@ -26,35 +26,29 @@ jobs:
|
|||||||
- cp310-cp310
|
- cp310-cp310
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: rustup default 1.67.0
|
run: bash ./scripts/generate-linux.sh
|
||||||
|
|
||||||
- name: "Install requirements"
|
|
||||||
run: ${PYBIN}/pip install -r requirements.txt
|
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
|
||||||
run: bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
# see issue #350 for more information
|
# see issue #350 for more information
|
||||||
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
|
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:
|
with:
|
||||||
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
||||||
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||||
|
|
||||||
build-macos-universal-wheel:
|
build-macos-arm64-wheels:
|
||||||
name: "Build macOS universal wheel"
|
name: "Build macOS arm64 wheel"
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: bdk-python
|
working-directory: bdk-python
|
||||||
@@ -66,33 +60,66 @@ jobs:
|
|||||||
- "3.10"
|
- "3.10"
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/setup-python@v2
|
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: |
|
run: bash ./scripts/generate-macos-arm64.sh
|
||||||
python3 --version
|
|
||||||
rustup target add aarch64-apple-darwin
|
|
||||||
pip3 install --user -r requirements.txt
|
|
||||||
bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
env:
|
|
||||||
ARCHFLAGS: "-arch x86_64 -arch arm64"
|
|
||||||
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
# see issue #350 for more information
|
# see issue #350 for more information
|
||||||
run: python3 setup.py bdist_wheel --plat-name macosx_12_0_universal2 --verbose
|
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- name: "Upload artifacts"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bdkpython-macos-${{ matrix.python }}
|
name: bdkpython-macos-arm64-${{ matrix.python }}
|
||||||
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||||
|
|
||||||
build-windows-wheel:
|
build-macos-x86_64-wheels:
|
||||||
|
name: "Build macOS x86_64 wheel"
|
||||||
|
runs-on: macos-13
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: bdk-python
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python:
|
||||||
|
- "3.8"
|
||||||
|
- "3.9"
|
||||||
|
- "3.10"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
|
- name: "Generate bdk.py and binaries"
|
||||||
|
run: bash ./scripts/generate-macos-x86_64.sh
|
||||||
|
|
||||||
|
- name: "Build wheel"
|
||||||
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
|
# see issue #350 for more information
|
||||||
|
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
|
||||||
|
|
||||||
|
- 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
|
||||||
|
|
||||||
|
build-windows-wheels:
|
||||||
name: "Build Windows wheel"
|
name: "Build Windows wheel"
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
defaults:
|
defaults:
|
||||||
@@ -106,23 +133,21 @@ jobs:
|
|||||||
- "3.10"
|
- "3.10"
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/setup-python@v2
|
- uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: |
|
run: bash ./scripts/generate-windows.sh
|
||||||
python --version
|
|
||||||
pip install --user -r requirements.txt
|
|
||||||
bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
run: python setup.py bdist_wheel --verbose
|
run: python setup.py bdist_wheel --verbose
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2
|
- name: "Upload artifacts"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bdkpython-win-${{ matrix.python }}
|
name: bdkpython-win-${{ matrix.python }}
|
||||||
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
|
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
|
||||||
@@ -133,13 +158,13 @@ jobs:
|
|||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: bdk-python
|
working-directory: bdk-python
|
||||||
needs: [build-manylinux2014-x86_64-wheel, build-macos-universal-wheel, build-windows-wheel]
|
needs: [build-manylinux2014-x86_64-wheels, build-macos-arm64-wheels, build-macos-x86_64-wheels, build-windows-wheels]
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Download artifacts in dist/ directory"
|
- name: "Download artifacts in dist/ directory"
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
path: dist/
|
path: dist/
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/test-android.yaml
vendored
6
.github/workflows/test-android.yaml
vendored
@@ -29,10 +29,10 @@ jobs:
|
|||||||
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
|
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
|
||||||
|
|
||||||
- name: "Check out PR branch"
|
- name: "Check out PR branch"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Cache"
|
- name: "Cache"
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: "Set up JDK"
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
|
|||||||
16
.github/workflows/test-jvm.yaml
vendored
16
.github/workflows/test-jvm.yaml
vendored
@@ -14,11 +14,11 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Check out PR branch
|
- name: "Check out PR branch"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Cache
|
- name: "Cache"
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cargo/registry
|
~/.cargo/registry
|
||||||
@@ -26,8 +26,8 @@ jobs:
|
|||||||
./target
|
./target
|
||||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Set up JDK
|
- name: "Set up JDK"
|
||||||
uses: actions/setup-java@v2
|
uses: actions/setup-java@v3
|
||||||
with:
|
with:
|
||||||
distribution: temurin
|
distribution: temurin
|
||||||
java-version: 11
|
java-version: 11
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Set default Rust version to 1.67.0"
|
||||||
run: rustup default 1.67.0
|
run: rustup default 1.67.0
|
||||||
|
|
||||||
- name: Run JVM tests
|
- name: "Run JVM tests"
|
||||||
run: |
|
run: |
|
||||||
cd bdk-jvm
|
cd bdk-jvm
|
||||||
./gradlew test --console=rich
|
./gradlew test
|
||||||
|
|||||||
135
.github/workflows/test-python.yaml
vendored
135
.github/workflows/test-python.yaml
vendored
@@ -16,7 +16,7 @@ on:
|
|||||||
# tries to load glibc and fails because it requires a more recent version.
|
# tries to load glibc and fails because it requires a more recent version.
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-manylinux2014-x86_64-wheel:
|
build-manylinux2014-x86_64-wheels:
|
||||||
name: "Build and test Manylinux 2014 x86_64 wheels"
|
name: "Build and test Manylinux 2014 x86_64 wheels"
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
defaults:
|
defaults:
|
||||||
@@ -35,42 +35,36 @@ jobs:
|
|||||||
- cp310-cp310
|
- cp310-cp310
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
toolchain: stable
|
toolchain: stable
|
||||||
|
|
||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: rustup default 1.67.0
|
run: bash ./scripts/generate-linux.sh
|
||||||
|
|
||||||
- name: "Install requirements"
|
|
||||||
run: ${PYBIN}/pip install -r requirements.txt
|
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
|
||||||
run: bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
run: ${PYBIN}/python setup.py bdist_wheel --verbose
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
|
# see issue #350 for more information
|
||||||
|
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
|
||||||
|
|
||||||
- name: "Install wheel"
|
- name: "Install wheel"
|
||||||
run: ${PYBIN}/pip install ./dist/*.whl
|
run: ${PYBIN}/pip install ./dist/*.whl
|
||||||
|
|
||||||
- name: "Run tests"
|
- name: "Run tests"
|
||||||
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
|
||||||
# see issue #350 for more information
|
|
||||||
run: ${PYBIN}/python -m unittest tests/test_bdk.py --plat-name manylinux_2_17_x86_64 --verbose
|
|
||||||
|
|
||||||
- name: "Upload artifact test"
|
- name: "Upload artifact test"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
||||||
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||||
|
|
||||||
build-macos-universal-wheel:
|
build-macos-arm64-wheels:
|
||||||
name: "Build and test macOS wheels"
|
name: "Build and test macOS arm64 wheels"
|
||||||
runs-on: macos-12
|
runs-on: macos-13
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
working-directory: bdk-python
|
working-directory: bdk-python
|
||||||
@@ -81,25 +75,64 @@ jobs:
|
|||||||
- "3.9"
|
- "3.9"
|
||||||
- "3.10"
|
- "3.10"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/setup-python@v2
|
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: |
|
run: bash ./scripts/generate-macos-arm64.sh
|
||||||
python3 --version
|
|
||||||
rustup target add aarch64-apple-darwin
|
|
||||||
pip3 install --user -r requirements.txt
|
|
||||||
bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
env:
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
ARCHFLAGS: "-arch x86_64 -arch arm64"
|
# see issue #350 for more information
|
||||||
run: python3 setup.py bdist_wheel --verbose
|
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
|
||||||
|
|
||||||
|
# You can't install the arm64 wheel on the CI, so we skip these steps and simply test that the wheel builds
|
||||||
|
# - name: "Install wheel and run tests"
|
||||||
|
# run: |
|
||||||
|
# pip3 install ./dist/*.whl
|
||||||
|
# python3 -m unittest tests/test_bdk.py --verbose
|
||||||
|
|
||||||
|
- name: "Upload artifact test"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: bdkpython-macos-arm64-${{ matrix.python }}
|
||||||
|
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
|
||||||
|
|
||||||
|
build-macos-x86_64-wheels:
|
||||||
|
name: "Build and test macOS x86_64 wheels"
|
||||||
|
runs-on: macos-13
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: bdk-python
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python:
|
||||||
|
- "3.8"
|
||||||
|
- "3.9"
|
||||||
|
- "3.10"
|
||||||
|
steps:
|
||||||
|
- name: "Checkout"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: true
|
||||||
|
- uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
|
- name: "Generate bdk.py and binaries"
|
||||||
|
run: bash ./scripts/generate-macos-x86_64.sh
|
||||||
|
|
||||||
|
- name: "Build wheel"
|
||||||
|
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
|
||||||
|
# see issue #350 for more information
|
||||||
|
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
|
||||||
|
|
||||||
- name: "Install wheel"
|
- name: "Install wheel"
|
||||||
run: pip3 install ./dist/*.whl
|
run: pip3 install ./dist/*.whl
|
||||||
@@ -107,7 +140,13 @@ jobs:
|
|||||||
- name: "Run tests"
|
- name: "Run tests"
|
||||||
run: python3 -m unittest tests/test_bdk.py --verbose
|
run: python3 -m unittest tests/test_bdk.py --verbose
|
||||||
|
|
||||||
build-windows-wheel:
|
- name: "Upload artifact test"
|
||||||
|
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
|
||||||
|
|
||||||
|
build-windows-wheels:
|
||||||
name: "Build and test Windows wheels"
|
name: "Build and test Windows wheels"
|
||||||
runs-on: windows-2022
|
runs-on: windows-2022
|
||||||
defaults:
|
defaults:
|
||||||
@@ -121,28 +160,30 @@ jobs:
|
|||||||
- "3.10"
|
- "3.10"
|
||||||
steps:
|
steps:
|
||||||
- name: "Checkout"
|
- name: "Checkout"
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: actions/setup-python@v2
|
|
||||||
|
- name: "Install Python"
|
||||||
|
uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
- name: "Generate bdk.py"
|
- name: "Generate bdk.py and binaries"
|
||||||
run: |
|
run: bash ./scripts/generate-windows.sh
|
||||||
python --version
|
|
||||||
pip install --user -r requirements.txt
|
|
||||||
bash generate.sh
|
|
||||||
|
|
||||||
- name: "Build wheel"
|
- name: "Build wheel"
|
||||||
run: python setup.py bdist_wheel --verbose
|
run: python setup.py bdist_wheel --verbose
|
||||||
|
|
||||||
# TODO: On Windows the pip install ./dist/*.whl step fails with the following error:
|
- name: "Upload artifact test"
|
||||||
# Run pip install ./dist/*.whl
|
uses: actions/upload-artifact@v3
|
||||||
# WARNING: Requirement './dist/*.whl' looks like a filename, but the file does not exist
|
with:
|
||||||
# ERROR: *.whl is not a valid wheel filename.*.whl is not a valid wheel name
|
name: bdkpython-windows-${{ matrix.python }}
|
||||||
# So we skip the installing and the tests and simply test that the wheel builds
|
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
|
||||||
# - name: Install wheel
|
|
||||||
# run: pip install ./dist/*.whl
|
- name: "Install dependencies"
|
||||||
# - name: Run tests
|
run: Get-ChildItem 'D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl' | ForEach-Object {pip install $_.FullName}
|
||||||
# run: python -m unittest tests/test_bdk.py --verbose
|
shell: powershell
|
||||||
|
|
||||||
|
- name: "Run tests"
|
||||||
|
run: python -m unittest tests/test_bdk.py --verbose
|
||||||
|
|||||||
4
.github/workflows/test-swift.yaml
vendored
4
.github/workflows/test-swift.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
runs-on: macos-12
|
runs-on: macos-12
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: "Set default Rust version to 1.67.0"
|
- name: "Set default Rust version to 1.67.0"
|
||||||
run: rustup default 1.67.0
|
run: rustup default 1.67.0
|
||||||
@@ -36,7 +36,7 @@ jobs:
|
|||||||
- name: Build bdk-ffi for aarch64-apple-darwin
|
- name: Build bdk-ffi for aarch64-apple-darwin
|
||||||
run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
|
run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
|
||||||
|
|
||||||
- name: Create lipo-ios-sim and lipo-macos
|
- name: Create lipo-macos
|
||||||
run: |
|
run: |
|
||||||
mkdir -p target/lipo-macos/release-smaller
|
mkdir -p target/lipo-macos/release-smaller
|
||||||
lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a
|
lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a
|
||||||
|
|||||||
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,14 +1,54 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
All notable changes to this project prior to release **0.9.0** are documented in this file. Future
|
Changelog information can also be found in each release's git tag (which can be viewed with `git tag -ln100 "v*"`), as well as on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases) page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
|
||||||
changelog information can be found in each release's git tag and can be viewed with `git tag -ln100 "v*"`.
|
|
||||||
Changelog info is also documented on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases)
|
|
||||||
page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
|
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
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).
|
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]
|
||||||
|
- Drop support for Python 3.6 and 3.7 [#351]
|
||||||
|
- Drop support for very old Linux versions that do not support the manylinux_2_17_x86_64 platform tag [#351]
|
||||||
|
- APIs changed:
|
||||||
|
- Expose Address payload and network properties. [#325]
|
||||||
|
- Add SignOptions to Wallet.sign() params. [#326]
|
||||||
|
- address field on `AddressInfo` type is now of type `Address` [#333]
|
||||||
|
- new PartiallySignedTransaction.json_serialize() function to get JSON serialized value of all PSBT fields. [#334]
|
||||||
|
- Add from_script constructor to `Address` type [#337]
|
||||||
|
|
||||||
|
[#325]: https://github.com/bitcoindevkit/bdk-ffi/pull/325
|
||||||
|
[#326]: https://github.com/bitcoindevkit/bdk-ffi/pull/326
|
||||||
|
[#333]: https://github.com/bitcoindevkit/bdk-ffi/pull/333
|
||||||
|
[#334]: https://github.com/bitcoindevkit/bdk-ffi/pull/334
|
||||||
|
[#337]: https://github.com/bitcoindevkit/bdk-ffi/pull/337
|
||||||
|
[#341]: https://github.com/bitcoindevkit/bdk-ffi/pull/341
|
||||||
|
[#351]: https://github.com/bitcoindevkit/bdk-ffi/pull/351
|
||||||
|
|
||||||
## [v0.27.1]
|
## [v0.27.1]
|
||||||
- Update BDK to latest version 0.27.1 [#312]
|
- Update BDK to version 0.27.1 [#312]
|
||||||
- APIs changed
|
- APIs changed
|
||||||
- `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296]
|
- `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296]
|
||||||
- `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296]
|
- `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296]
|
||||||
@@ -23,7 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312
|
[#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312
|
||||||
|
|
||||||
## [v0.26.0]
|
## [v0.26.0]
|
||||||
- Update BDK to latest version 0.26.0 [#288]
|
- Update BDK to version 0.26.0 [#288]
|
||||||
- APIs changed
|
- APIs changed
|
||||||
- The descriptor and change_descriptor arguments on the wallet constructor now take a `Descriptor` instead of a `String`. [#260]
|
- The descriptor and change_descriptor arguments on the wallet constructor now take a `Descriptor` instead of a `String`. [#260]
|
||||||
- TxBuilder.drain_to() argument is now `Script` instead of address `String`. [#279]
|
- TxBuilder.drain_to() argument is now `Script` instead of address `String`. [#279]
|
||||||
@@ -46,7 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288
|
[#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288
|
||||||
|
|
||||||
## [v0.25.0]
|
## [v0.25.0]
|
||||||
- Update BDK to latest version 0.25.0 [#272]
|
- Update BDK to version 0.25.0 [#272]
|
||||||
- APIs Added:
|
- APIs Added:
|
||||||
- from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]
|
- from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]
|
||||||
|
|
||||||
@@ -54,7 +94,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272
|
[#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272
|
||||||
|
|
||||||
## [v0.11.0]
|
## [v0.11.0]
|
||||||
- Update BDK to latest version 0.24.0 [#221]
|
- Update BDK to version 0.24.0 [#221]
|
||||||
- APIs changed
|
- APIs changed
|
||||||
- The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String.
|
- The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String.
|
||||||
- APIs added
|
- APIs added
|
||||||
@@ -70,7 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
[#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221
|
[#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221
|
||||||
|
|
||||||
## [v0.10.0]
|
## [v0.10.0]
|
||||||
- Update BDK to latest version 0.23.0 [#204]
|
- Update BDK to version 0.23.0 [#204]
|
||||||
- Update uniffi-rs to latest version 0.21.0 [#216]
|
- Update uniffi-rs to latest version 0.21.0 [#216]
|
||||||
- Breaking Changes
|
- Breaking Changes
|
||||||
- Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209]
|
- Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209]
|
||||||
@@ -103,7 +143,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- APIs Added [#154]
|
- APIs Added [#154]
|
||||||
- `generate_mnemonic()`, returns string mnemonic
|
- `generate_mnemonic()`, returns string mnemonic
|
||||||
- `interface DescriptorSecretKey`
|
- `interface DescriptorSecretKey`
|
||||||
- `new(Network, string_mnenoinc, password)`, contructs DescriptorSecretKey
|
- `new(Network, string_mnenoinc, password)`, constructs DescriptorSecretKey
|
||||||
- `derive(DerivationPath)`, derives and returns child DescriptorSecretKey
|
- `derive(DerivationPath)`, derives and returns child DescriptorSecretKey
|
||||||
- `extend(DerivationPath)`, extends and returns DescriptorSecretKey
|
- `extend(DerivationPath)`, extends and returns DescriptorSecretKey
|
||||||
- `as_public()`, returns DescriptorSecretKey as DescriptorPublicKey
|
- `as_public()`, returns DescriptorSecretKey as DescriptorPublicKey
|
||||||
@@ -183,8 +223,9 @@ 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
|
[BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding
|
||||||
|
|
||||||
## [v0.2.0]
|
[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.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
|
[v0.26.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.25.0...v0.26.0
|
||||||
[v0.25.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.11.0...v0.25.0
|
[v0.25.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.11.0...v0.25.0
|
||||||
|
|||||||
571
Cargo.lock
generated
571
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -9,4 +9,4 @@ opt-level = 'z' # Optimize for size.
|
|||||||
lto = true # Enable Link Time Optimization
|
lto = true # Enable Link Time Optimization
|
||||||
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
|
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
|
||||||
panic = 'abort' # Abort on panic
|
panic = 'abort' # Abort on panic
|
||||||
strip = true # Strip symbols from binary*
|
strip = true # Strip symbols from binary
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -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] | |
|
| Swift | iOS, macOS | [bdk-swift (GitHub)] | [Readme bdk-swift] | |
|
||||||
| Python | linux, macOS, Windows | [bdk-python (PyPI)] | [Readme bdk-python] | |
|
| 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
|
## Contributing
|
||||||
|
|
||||||
### Adding new structs and functions
|
### Adding new structs and functions
|
||||||
@@ -49,8 +64,8 @@ See the [UniFFI User Guide](https://mozilla.github.io/uniffi-rs/)
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bitcoindevkit:bdk-android:<version>")
|
implementation("org.bitcoindevkit:bdk-android:<version>")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -60,8 +75,8 @@ dependencies {
|
|||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bitcoindevkit:bdk-jvm:<version>")
|
implementation("org.bitcoindevkit:bdk-jvm:<version>")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -489,6 +489,9 @@ class Wallet(
|
|||||||
*/
|
*/
|
||||||
fun getInternalAddress(addressIndex: AddressIndex): AddressInfo {}
|
fun getInternalAddress(addressIndex: AddressIndex): AddressInfo {}
|
||||||
|
|
||||||
|
/** Return whether or not a script is part of this wallet (either internal or external). */
|
||||||
|
fun isMine(script: Script): Boolean {}
|
||||||
|
|
||||||
/** 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. */
|
/** 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 {}
|
fun getBalance(): Balance {}
|
||||||
|
|
||||||
@@ -782,6 +785,19 @@ class Descriptor(descriptor: String, network: Network) {
|
|||||||
*/
|
*/
|
||||||
fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, 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. */
|
/** Return the public version of the output descriptor. */
|
||||||
fun asString(): String {}
|
fun asString(): String {}
|
||||||
|
|
||||||
@@ -826,7 +842,10 @@ data class TxBuilderResult (
|
|||||||
/**
|
/**
|
||||||
* A bitcoin script.
|
* A bitcoin script.
|
||||||
*/
|
*/
|
||||||
class Script(rawOutputScript: List<UByte>)
|
class Script(rawOutputScript: List<UByte>) {
|
||||||
|
/** Return the script as bytes. */
|
||||||
|
fun toBytes(): List<UByte> {}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitcoin address.
|
* A bitcoin address.
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bitcoindevkit:bdk-android:<version>")
|
implementation("org.bitcoindevkit:bdk-android:<version>")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ repositories {
|
|||||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
|
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -54,19 +54,23 @@ _Note that Kotlin version `1.6.10` or later is required to build the library._
|
|||||||
```shell
|
```shell
|
||||||
git clone https://github.com/bitcoindevkit/bdk-ffi
|
git clone https://github.com/bitcoindevkit/bdk-ffi
|
||||||
```
|
```
|
||||||
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
|
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
|
||||||
3. If building on macOS install required intel and m1 jvm targets
|
3. Install Rust (note that we are currently building using Rust 1.67.0):
|
||||||
|
```shell
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
rustup default 1.67.0
|
||||||
|
```
|
||||||
4. Install required targets
|
4. Install required targets
|
||||||
```sh
|
```sh
|
||||||
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
|
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
|
||||||
```
|
```
|
||||||
5. Install Android SDK and Build-Tools for API level 30+
|
5. Install Android SDK and Build-Tools for API level 30+
|
||||||
6. Setup `$ANDROID_SDK_ROOT` and `$ANDROID_NDK_ROOT` path variables (which are required by the
|
6. Setup `$ANDROID_SDK_ROOT` and `$ANDROID_NDK_ROOT` path variables (which are required by the
|
||||||
build tool), for example (NDK major version 21 is required):
|
build tool), for example (note that currently, NDK version 21.4.7075529 is required):
|
||||||
```shell
|
```shell
|
||||||
export ANDROID_SDK_ROOT=~/Android/Sdk
|
export ANDROID_SDK_ROOT=~/Android/Sdk
|
||||||
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.<NDK_VERSION>
|
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529
|
||||||
```
|
```
|
||||||
7. Build kotlin bindings
|
7. Build kotlin bindings
|
||||||
```sh
|
```sh
|
||||||
# build Android library
|
# build Android library
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ org.gradle.jvmargs=-Xmx1536m
|
|||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
libraryVersion=0.28.0
|
libraryVersion=0.31.1
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "bdk-ffi"
|
name = "bdk-ffi"
|
||||||
version = "0.28.0"
|
version = "0.31.1"
|
||||||
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
|
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib", "staticlib", "cdylib"]
|
crate-type = ["lib", "staticlib", "cdylib"]
|
||||||
#crate-type = ["staticlib", "cdylib"]
|
|
||||||
#crate-type = ["cdylib"]
|
|
||||||
name = "bdkffi"
|
name = "bdkffi"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
@@ -19,12 +17,12 @@ path = "uniffi-bindgen.rs"
|
|||||||
default = ["uniffi/cli"]
|
default = ["uniffi/cli"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bdk = { version = "0.28", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
|
bdk = { version = "0.29.0", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
|
||||||
uniffi = { version = "0.23.0" }
|
uniffi = { version = "=0.23.0" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
uniffi = { version = "0.23.0", features = ["build"] }
|
uniffi = { version = "=0.23.0", features = ["build"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
uniffi = { version = "0.23.0", features = ["bindgen-tests"] }
|
uniffi = { version = "=0.23.0", features = ["bindgen-tests"] }
|
||||||
assert_matches = "1.5.0"
|
assert_matches = "1.5.0"
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ enum BdkError {
|
|||||||
"Sled",
|
"Sled",
|
||||||
"Rusqlite",
|
"Rusqlite",
|
||||||
"Rpc",
|
"Rpc",
|
||||||
|
"HardenedIndex"
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary AddressInfo {
|
dictionary AddressInfo {
|
||||||
@@ -221,28 +222,31 @@ interface Wallet {
|
|||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config);
|
constructor(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config);
|
||||||
|
|
||||||
|
Network network();
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
AddressInfo get_address(AddressIndex address_index);
|
AddressInfo get_address(AddressIndex address_index);
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
AddressInfo get_internal_address(AddressIndex address_index);
|
AddressInfo get_internal_address(AddressIndex address_index);
|
||||||
|
|
||||||
|
[Throws=BdkError]
|
||||||
|
boolean is_mine(Script script);
|
||||||
|
|
||||||
|
[Throws=BdkError]
|
||||||
|
sequence<LocalUtxo> list_unspent();
|
||||||
|
|
||||||
|
[Throws=BdkError]
|
||||||
|
sequence<TransactionDetails> list_transactions(boolean include_raw);
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
Balance get_balance();
|
Balance get_balance();
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options);
|
boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options);
|
||||||
|
|
||||||
[Throws=BdkError]
|
|
||||||
sequence<TransactionDetails> list_transactions(boolean include_raw);
|
|
||||||
|
|
||||||
Network network();
|
|
||||||
|
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
void sync([ByRef] Blockchain blockchain, Progress? progress);
|
void sync([ByRef] Blockchain blockchain, Progress? progress);
|
||||||
|
|
||||||
[Throws=BdkError]
|
|
||||||
sequence<LocalUtxo> list_unspent();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FeeRate {
|
interface FeeRate {
|
||||||
@@ -358,7 +362,7 @@ interface TxBuilder {
|
|||||||
interface BumpFeeTxBuilder {
|
interface BumpFeeTxBuilder {
|
||||||
constructor(string txid, float new_fee_rate);
|
constructor(string txid, float new_fee_rate);
|
||||||
|
|
||||||
BumpFeeTxBuilder allow_shrinking(string address);
|
BumpFeeTxBuilder allow_shrinking(Script script_pubkey);
|
||||||
|
|
||||||
BumpFeeTxBuilder enable_rbf();
|
BumpFeeTxBuilder enable_rbf();
|
||||||
|
|
||||||
@@ -439,6 +443,12 @@ interface Descriptor {
|
|||||||
[Name=new_bip84_public]
|
[Name=new_bip84_public]
|
||||||
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
|
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();
|
||||||
|
|
||||||
string as_string_private();
|
string as_string_private();
|
||||||
@@ -446,7 +456,7 @@ interface Descriptor {
|
|||||||
|
|
||||||
interface Address {
|
interface Address {
|
||||||
[Throws=BdkError]
|
[Throws=BdkError]
|
||||||
constructor(string address);
|
constructor(string address, Network network);
|
||||||
|
|
||||||
[Name=from_script, Throws=BdkError]
|
[Name=from_script, Throws=BdkError]
|
||||||
constructor(Script script, Network network);
|
constructor(Script script, Network network);
|
||||||
@@ -459,14 +469,16 @@ interface Address {
|
|||||||
|
|
||||||
string to_qr_uri();
|
string to_qr_uri();
|
||||||
|
|
||||||
|
boolean is_valid_for_network(Network network);
|
||||||
|
|
||||||
string as_string();
|
string as_string();
|
||||||
};
|
};
|
||||||
|
|
||||||
[Enum]
|
[Enum]
|
||||||
interface Payload {
|
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);
|
WitnessProgram(WitnessVersion version, sequence<u8> program);
|
||||||
};
|
};
|
||||||
@@ -493,4 +505,6 @@ enum WitnessVersion {
|
|||||||
|
|
||||||
interface Script {
|
interface Script {
|
||||||
constructor(sequence<u8> raw_output_script);
|
constructor(sequence<u8> raw_output_script);
|
||||||
|
|
||||||
|
sequence<u8> to_bytes();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// use crate::BlockchainConfig;
|
// use crate::BlockchainConfig;
|
||||||
|
use crate::Network;
|
||||||
use crate::{BdkError, Transaction};
|
use crate::{BdkError, Transaction};
|
||||||
use bdk::bitcoin::Network;
|
|
||||||
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
||||||
use bdk::blockchain::rpc::Auth as BdkAuth;
|
use bdk::blockchain::rpc::Auth as BdkAuth;
|
||||||
use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams;
|
use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams;
|
||||||
@@ -17,7 +17,7 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
|
|
||||||
pub(crate) struct Blockchain {
|
pub(crate) struct Blockchain {
|
||||||
blockchain_mutex: Mutex<AnyBlockchain>,
|
inner_mutex: Mutex<AnyBlockchain>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blockchain {
|
impl Blockchain {
|
||||||
@@ -45,23 +45,23 @@ impl Blockchain {
|
|||||||
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
|
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
|
||||||
url: config.url,
|
url: config.url,
|
||||||
auth: config.auth.into(),
|
auth: config.auth.into(),
|
||||||
network: config.network,
|
network: config.network.into(),
|
||||||
wallet_name: config.wallet_name,
|
wallet_name: config.wallet_name,
|
||||||
sync_params: config.sync_params.map(|p| p.into()),
|
sync_params: config.sync_params.map(|p| p.into()),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
|
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
blockchain_mutex: Mutex::new(blockchain),
|
inner_mutex: Mutex::new(blockchain),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> {
|
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> {
|
pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> {
|
||||||
let tx = &transaction.internal;
|
let tx = &transaction.inner;
|
||||||
self.get_blockchain().broadcast(tx)
|
self.get_blockchain().broadcast(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
|
use crate::Network;
|
||||||
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
|
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
|
||||||
|
use bdk::bitcoin::bip32::Fingerprint;
|
||||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||||
use bdk::bitcoin::util::bip32::Fingerprint;
|
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
|
||||||
use bdk::bitcoin::Network;
|
|
||||||
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor, KeyMap};
|
|
||||||
use bdk::keys::{
|
use bdk::keys::{
|
||||||
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
|
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
|
||||||
|
KeyMap,
|
||||||
};
|
};
|
||||||
use bdk::template::{
|
use bdk::template::{
|
||||||
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, DescriptorTemplate,
|
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
|
||||||
|
DescriptorTemplate,
|
||||||
};
|
};
|
||||||
use bdk::KeychainKind;
|
use bdk::KeychainKind;
|
||||||
use std::ops::Deref;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -23,7 +24,8 @@ pub(crate) struct Descriptor {
|
|||||||
impl Descriptor {
|
impl Descriptor {
|
||||||
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
|
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
|
||||||
let secp = Secp256k1::new();
|
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 {
|
Ok(Self {
|
||||||
extended_descriptor,
|
extended_descriptor,
|
||||||
key_map,
|
key_map,
|
||||||
@@ -35,13 +37,14 @@ impl Descriptor {
|
|||||||
keychain_kind: KeychainKind,
|
keychain_kind: KeychainKind,
|
||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> 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) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
|
||||||
Bip44(derivable_key, keychain_kind).build(network).unwrap();
|
.build(network.into())
|
||||||
|
.unwrap();
|
||||||
Self {
|
Self {
|
||||||
extended_descriptor,
|
extended_descriptor,
|
||||||
key_map,
|
key_map,
|
||||||
@@ -50,6 +53,9 @@ impl Descriptor {
|
|||||||
BdkDescriptorSecretKey::Single(_) => {
|
BdkDescriptorSecretKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorSecretKey::MultiXPrv(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,14 +66,14 @@ impl Descriptor {
|
|||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
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) => {
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) =
|
||||||
Bip44Public(derivable_key, fingerprint, keychain_kind)
|
Bip44Public(derivable_key, fingerprint, keychain_kind)
|
||||||
.build(network)
|
.build(network.into())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -78,6 +84,9 @@ impl Descriptor {
|
|||||||
BdkDescriptorPublicKey::Single(_) => {
|
BdkDescriptorPublicKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorPublicKey::MultiXPub(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,13 +95,14 @@ impl Descriptor {
|
|||||||
keychain_kind: KeychainKind,
|
keychain_kind: KeychainKind,
|
||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> 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) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
|
||||||
Bip49(derivable_key, keychain_kind).build(network).unwrap();
|
.build(network.into())
|
||||||
|
.unwrap();
|
||||||
Self {
|
Self {
|
||||||
extended_descriptor,
|
extended_descriptor,
|
||||||
key_map,
|
key_map,
|
||||||
@@ -101,6 +111,9 @@ impl Descriptor {
|
|||||||
BdkDescriptorSecretKey::Single(_) => {
|
BdkDescriptorSecretKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorSecretKey::MultiXPrv(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,14 +124,14 @@ impl Descriptor {
|
|||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
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) => {
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) =
|
||||||
Bip49Public(derivable_key, fingerprint, keychain_kind)
|
Bip49Public(derivable_key, fingerprint, keychain_kind)
|
||||||
.build(network)
|
.build(network.into())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -129,6 +142,9 @@ impl Descriptor {
|
|||||||
BdkDescriptorPublicKey::Single(_) => {
|
BdkDescriptorPublicKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorPublicKey::MultiXPub(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,13 +153,14 @@ impl Descriptor {
|
|||||||
keychain_kind: KeychainKind,
|
keychain_kind: KeychainKind,
|
||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> 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) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
|
||||||
Bip84(derivable_key, keychain_kind).build(network).unwrap();
|
.build(network.into())
|
||||||
|
.unwrap();
|
||||||
Self {
|
Self {
|
||||||
extended_descriptor,
|
extended_descriptor,
|
||||||
key_map,
|
key_map,
|
||||||
@@ -152,6 +169,9 @@ impl Descriptor {
|
|||||||
BdkDescriptorSecretKey::Single(_) => {
|
BdkDescriptorSecretKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorSecretKey::MultiXPrv(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,14 +182,14 @@ impl Descriptor {
|
|||||||
network: Network,
|
network: Network,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
|
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) => {
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
let derivable_key = descriptor_x_key.xkey;
|
let derivable_key = descriptor_x_key.xkey;
|
||||||
let (extended_descriptor, key_map, _) =
|
let (extended_descriptor, key_map, _) =
|
||||||
Bip84Public(derivable_key, fingerprint, keychain_kind)
|
Bip84Public(derivable_key, fingerprint, keychain_kind)
|
||||||
.build(network)
|
.build(network.into())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@@ -180,6 +200,67 @@ impl Descriptor {
|
|||||||
BdkDescriptorPublicKey::Single(_) => {
|
BdkDescriptorPublicKey::Single(_) => {
|
||||||
unreachable!()
|
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();
|
.as_public();
|
||||||
println!("Public 84: {}", handmade_public_84.as_string());
|
println!("Public 84: {}", handmade_public_84.as_string());
|
||||||
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
|
// 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 =
|
let template_private_44 =
|
||||||
Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet);
|
Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet);
|
||||||
let template_private_49 =
|
let template_private_49 =
|
||||||
Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet);
|
Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet);
|
||||||
let template_private_84 =
|
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
|
// 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 49: {}", template_private_49.as_string());
|
||||||
println!("Template 44: {}", template_private_44.as_string());
|
println!("Template 44: {}", template_private_44.as_string());
|
||||||
println!("Template 84: {}", template_private_84.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(
|
let template_public_44 = Descriptor::new_bip44_public(
|
||||||
handmade_public_44,
|
handmade_public_44,
|
||||||
"d1d04177".to_string(),
|
"d1d04177".to_string(),
|
||||||
@@ -268,9 +359,16 @@ mod test {
|
|||||||
KeychainKind::External,
|
KeychainKind::External,
|
||||||
Network::Testnet,
|
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 49: {}", template_public_49.as_string());
|
||||||
println!("Template public 44: {}", template_public_44.as_string());
|
println!("Template public 44: {}", template_public_44.as_string());
|
||||||
println!("Template public 84: {}", template_public_84.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
|
// when using a public key, both as_string and as_string_private return the same string
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
template_public_44.as_string_private(),
|
template_public_44.as_string_private(),
|
||||||
@@ -284,6 +382,10 @@ mod test {
|
|||||||
template_public_84.as_string_private(),
|
template_public_84.as_string_private(),
|
||||||
template_public_84.as_string()
|
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
|
// when using as_string on a private key, we get the same result as when using it on a public key
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
template_private_44.as_string(),
|
template_private_44.as_string(),
|
||||||
@@ -297,6 +399,10 @@ mod test {
|
|||||||
template_private_84.as_string(),
|
template_private_84.as_string(),
|
||||||
template_public_84.as_string()
|
template_public_84.as_string()
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
template_private_86.as_string(),
|
||||||
|
template_public_86.as_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn test_descriptor_from_string() {
|
fn test_descriptor_from_string() {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use crate::BdkError;
|
use crate::BdkError;
|
||||||
|
|
||||||
|
use crate::Network;
|
||||||
|
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
|
||||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
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::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
|
||||||
use bdk::keys::{
|
use bdk::keys::{
|
||||||
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
||||||
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
||||||
};
|
};
|
||||||
|
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
|
||||||
use bdk::miniscript::BareCtx;
|
use bdk::miniscript::BareCtx;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
@@ -17,7 +17,7 @@ use std::sync::{Arc, Mutex};
|
|||||||
/// Mnemonic phrases are a human-readable version of the private keys.
|
/// Mnemonic phrases are a human-readable version of the private keys.
|
||||||
/// Supported number of words are 12, 15, 18, 21 and 24.
|
/// Supported number of words are 12, 15, 18, 21 and 24.
|
||||||
pub(crate) struct Mnemonic {
|
pub(crate) struct Mnemonic {
|
||||||
internal: BdkMnemonic,
|
inner: BdkMnemonic,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mnemonic {
|
impl Mnemonic {
|
||||||
@@ -26,13 +26,13 @@ impl Mnemonic {
|
|||||||
let generated_key: GeneratedKey<_, BareCtx> =
|
let generated_key: GeneratedKey<_, BareCtx> =
|
||||||
BdkMnemonic::generate((word_count, Language::English)).unwrap();
|
BdkMnemonic::generate((word_count, Language::English)).unwrap();
|
||||||
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).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
|
/// Parse a Mnemonic with given string
|
||||||
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
|
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
|
||||||
BdkMnemonic::from_str(&mnemonic)
|
BdkMnemonic::from_str(&mnemonic)
|
||||||
.map(|m| Mnemonic { internal: m })
|
.map(|m| Mnemonic { inner: m })
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
.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.
|
/// 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> {
|
pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
|
||||||
BdkMnemonic::from_entropy(entropy.as_slice())
|
BdkMnemonic::from_entropy(entropy.as_slice())
|
||||||
.map(|m| Mnemonic { internal: m })
|
.map(|m| Mnemonic { inner: m })
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns Mnemonic as string
|
/// Returns Mnemonic as string
|
||||||
pub(crate) fn as_string(&self) -> String {
|
pub(crate) fn as_string(&self) -> String {
|
||||||
self.internal.to_string()
|
self.inner.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct DerivationPath {
|
pub(crate) struct DerivationPath {
|
||||||
derivation_path_mutex: Mutex<BdkDerivationPath>,
|
inner_mutex: Mutex<BdkDerivationPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DerivationPath {
|
impl DerivationPath {
|
||||||
pub(crate) fn new(path: String) -> Result<Self, BdkError> {
|
pub(crate) fn new(path: String) -> Result<Self, BdkError> {
|
||||||
BdkDerivationPath::from_str(&path)
|
BdkDerivationPath::from_str(&path)
|
||||||
.map(|x| DerivationPath {
|
.map(|x| DerivationPath {
|
||||||
derivation_path_mutex: Mutex::new(x),
|
inner_mutex: Mutex::new(x),
|
||||||
})
|
})
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
}
|
}
|
||||||
@@ -66,21 +66,21 @@ impl DerivationPath {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct DescriptorSecretKey {
|
pub(crate) struct DescriptorSecretKey {
|
||||||
pub(crate) descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
|
pub(crate) inner: BdkDescriptorSecretKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DescriptorSecretKey {
|
impl DescriptorSecretKey {
|
||||||
pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
|
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 xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
|
||||||
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
||||||
origin: None,
|
origin: None,
|
||||||
xkey: xkey.into_xprv(network).unwrap(),
|
xkey: xkey.into_xprv(network.into()).unwrap(),
|
||||||
derivation_path: BdkDerivationPath::master(),
|
derivation_path: BdkDerivationPath::master(),
|
||||||
wildcard: bdk::descriptor::Wildcard::Unhardened,
|
wildcard: Wildcard::Unhardened,
|
||||||
});
|
});
|
||||||
Self {
|
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())
|
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
Ok(Self {
|
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> {
|
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
let descriptor_secret_key = &self.inner;
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
let path = path.inner_mutex.lock().unwrap().deref().clone();
|
||||||
match descriptor_secret_key.deref() {
|
match descriptor_secret_key {
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
|
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
|
||||||
let key_source = match descriptor_x_key.origin.clone() {
|
let key_source = match descriptor_x_key.origin.clone() {
|
||||||
@@ -110,19 +110,22 @@ impl DescriptorSecretKey {
|
|||||||
wildcard: descriptor_x_key.wildcard,
|
wildcard: descriptor_x_key.wildcard,
|
||||||
});
|
});
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
|
inner: derived_descriptor_secret_key,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||||
"Cannot derive from a single key".to_string(),
|
"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> {
|
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
let descriptor_secret_key = &self.inner;
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
let path = path.inner_mutex.lock().unwrap().deref().clone();
|
||||||
match descriptor_secret_key.deref() {
|
match descriptor_secret_key {
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
let extended_path = descriptor_x_key.derivation_path.extend(path);
|
let extended_path = descriptor_x_key.derivation_path.extend(path);
|
||||||
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
||||||
@@ -132,51 +135,52 @@ impl DescriptorSecretKey {
|
|||||||
wildcard: descriptor_x_key.wildcard,
|
wildcard: descriptor_x_key.wildcard,
|
||||||
});
|
});
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
|
inner: extended_descriptor_secret_key,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||||
"Cannot extend from a single key".to_string(),
|
"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> {
|
pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let descriptor_public_key = self
|
let descriptor_public_key = self.inner.to_public(&secp).unwrap();
|
||||||
.descriptor_secret_key_mutex
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.to_public(&secp)
|
|
||||||
.unwrap();
|
|
||||||
Arc::new(DescriptorPublicKey {
|
Arc::new(DescriptorPublicKey {
|
||||||
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
inner: descriptor_public_key,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the private key as bytes.
|
/// Get the private key as bytes.
|
||||||
pub(crate) fn secret_bytes(&self) -> Vec<u8> {
|
pub(crate) fn secret_bytes(&self) -> Vec<u8> {
|
||||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
let inner = &self.inner;
|
||||||
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() {
|
let secret_bytes: Vec<u8> = match inner {
|
||||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||||
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
|
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
|
||||||
}
|
}
|
||||||
BdkDescriptorSecretKey::Single(_) => {
|
BdkDescriptorSecretKey::Single(_) => {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
BdkDescriptorSecretKey::MultiXPrv(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
secret_bytes
|
secret_bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn as_string(&self) -> String {
|
pub(crate) fn as_string(&self) -> String {
|
||||||
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
|
self.inner.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct DescriptorPublicKey {
|
pub(crate) struct DescriptorPublicKey {
|
||||||
pub(crate) descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
|
pub(crate) inner: BdkDescriptorPublicKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DescriptorPublicKey {
|
impl DescriptorPublicKey {
|
||||||
@@ -184,16 +188,16 @@ impl DescriptorPublicKey {
|
|||||||
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
|
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||||
Ok(Self {
|
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> {
|
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
let secp = Secp256k1::new();
|
let secp = Secp256k1::new();
|
||||||
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
let descriptor_public_key = &self.inner;
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
let path = path.inner_mutex.lock().unwrap().deref().clone();
|
||||||
|
|
||||||
match descriptor_public_key.deref() {
|
match descriptor_public_key {
|
||||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
|
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
|
||||||
let key_source = match descriptor_x_key.origin.clone() {
|
let key_source = match descriptor_x_key.origin.clone() {
|
||||||
@@ -207,19 +211,22 @@ impl DescriptorPublicKey {
|
|||||||
wildcard: descriptor_x_key.wildcard,
|
wildcard: descriptor_x_key.wildcard,
|
||||||
});
|
});
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
|
inner: derived_descriptor_public_key,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||||
"Cannot derive from a single key".to_string(),
|
"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> {
|
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||||
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
let descriptor_public_key = &self.inner;
|
||||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
let path = path.inner_mutex.lock().unwrap().deref().clone();
|
||||||
match descriptor_public_key.deref() {
|
match descriptor_public_key {
|
||||||
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
|
||||||
let extended_path = descriptor_x_key.derivation_path.extend(path);
|
let extended_path = descriptor_x_key.derivation_path.extend(path);
|
||||||
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
|
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
|
||||||
@@ -229,17 +236,20 @@ impl DescriptorPublicKey {
|
|||||||
wildcard: descriptor_x_key.wildcard,
|
wildcard: descriptor_x_key.wildcard,
|
||||||
});
|
});
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
|
inner: extended_descriptor_public_key,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||||
"Cannot extend from a single key".to_string(),
|
"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 {
|
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 {
|
mod test {
|
||||||
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
|
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
|
||||||
use crate::BdkError;
|
use crate::BdkError;
|
||||||
use bdk::bitcoin::hashes::hex::ToHex;
|
use crate::Network;
|
||||||
use bdk::bitcoin::Network;
|
|
||||||
use std::sync::Arc;
|
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();
|
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)
|
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None)
|
||||||
}
|
}
|
||||||
@@ -293,14 +302,14 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_generate_descriptor_secret_key() {
|
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_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
|
||||||
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
|
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_self() {
|
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();
|
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap();
|
||||||
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
|
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
|
||||||
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
||||||
@@ -310,7 +319,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_descriptors_keys() {
|
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();
|
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
|
||||||
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
|
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
|
||||||
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
||||||
@@ -320,7 +329,7 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extend_descriptor_keys() {
|
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();
|
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
|
||||||
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
|
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
|
||||||
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
|
||||||
@@ -334,7 +343,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_str_descriptor_secret_key() {
|
fn test_from_str_inner() {
|
||||||
let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
|
let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
|
||||||
let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
|
let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
|
||||||
let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
|
let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
|
||||||
@@ -347,8 +356,8 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_and_extend_descriptor_secret_key() {
|
fn test_derive_and_extend_inner() {
|
||||||
let master_dsk = get_descriptor_secret_key();
|
let master_dsk = get_inner();
|
||||||
// derive DescriptorSecretKey with path "m/0" from master
|
// derive DescriptorSecretKey with path "m/0" from master
|
||||||
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
|
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
|
||||||
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
|
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
|
||||||
@@ -359,18 +368,8 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_hardened_path_using_public() {
|
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");
|
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
|
||||||
assert!(derived_dpk.is_err());
|
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"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,17 +15,19 @@ use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
|
|||||||
use crate::psbt::PartiallySignedTransaction;
|
use crate::psbt::PartiallySignedTransaction;
|
||||||
use crate::wallet::SignOptions;
|
use crate::wallet::SignOptions;
|
||||||
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
|
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::TxIn as BdkTxIn;
|
||||||
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
|
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
|
||||||
|
use bdk::bitcoin::consensus::encode::serialize;
|
||||||
use bdk::bitcoin::consensus::Decodable;
|
use bdk::bitcoin::consensus::Decodable;
|
||||||
use bdk::bitcoin::psbt::serialize::Serialize;
|
use bdk::bitcoin::network::constants::Network as BdkNetwork;
|
||||||
use bdk::bitcoin::util::address::{Payload as BdkPayload, WitnessVersion};
|
|
||||||
use bdk::bitcoin::{
|
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::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::keys::bip39::WordCount;
|
||||||
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
||||||
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
||||||
@@ -41,6 +43,26 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
uniffi::include_scaffolding!("bdk");
|
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.
|
/// A output script and an amount of satoshis.
|
||||||
pub struct ScriptAmount {
|
pub struct ScriptAmount {
|
||||||
pub script: Arc<Script>,
|
pub script: Arc<Script>,
|
||||||
@@ -202,9 +224,7 @@ impl From<&BdkTxOut> for TxOut {
|
|||||||
fn from(tx_out: &BdkTxOut) -> Self {
|
fn from(tx_out: &BdkTxOut) -> Self {
|
||||||
TxOut {
|
TxOut {
|
||||||
value: tx_out.value,
|
value: tx_out.value,
|
||||||
script_pubkey: Arc::new(Script {
|
script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
|
||||||
script: tx_out.script_pubkey.clone(),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,9 +245,7 @@ impl From<BdkLocalUtxo> for LocalUtxo {
|
|||||||
},
|
},
|
||||||
txout: TxOut {
|
txout: TxOut {
|
||||||
value: local_utxo.txout.value,
|
value: local_utxo.txout.value,
|
||||||
script_pubkey: Arc::new(Script {
|
script_pubkey: Arc::new(Script(local_utxo.txout.script_pubkey)),
|
||||||
script: local_utxo.txout.script_pubkey,
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
keychain: local_utxo.keychain,
|
keychain: local_utxo.keychain,
|
||||||
is_spent: local_utxo.is_spent,
|
is_spent: local_utxo.is_spent,
|
||||||
@@ -274,9 +292,7 @@ impl From<&BdkTxIn> for TxIn {
|
|||||||
txid: tx_in.previous_output.txid.to_string(),
|
txid: tx_in.previous_output.txid.to_string(),
|
||||||
vout: tx_in.previous_output.vout,
|
vout: tx_in.previous_output.vout,
|
||||||
},
|
},
|
||||||
script_sig: Arc::new(Script {
|
script_sig: Arc::new(Script(tx_in.script_sig.clone())),
|
||||||
script: tx_in.script_sig.clone(),
|
|
||||||
}),
|
|
||||||
sequence: tx_in.sequence.0,
|
sequence: tx_in.sequence.0,
|
||||||
witness: tx_in.witness.to_vec(),
|
witness: tx_in.witness.to_vec(),
|
||||||
}
|
}
|
||||||
@@ -286,128 +302,144 @@ impl From<&BdkTxIn> for TxIn {
|
|||||||
/// A Bitcoin transaction.
|
/// A Bitcoin transaction.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Transaction {
|
pub struct Transaction {
|
||||||
internal: BdkTransaction,
|
inner: BdkTransaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transaction {
|
impl Transaction {
|
||||||
fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
|
fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
|
||||||
let mut decoder = Cursor::new(transaction_bytes);
|
let mut decoder = Cursor::new(transaction_bytes);
|
||||||
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
|
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
|
||||||
Ok(Transaction { internal: tx })
|
Ok(Transaction { inner: tx })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn txid(&self) -> String {
|
fn txid(&self) -> String {
|
||||||
self.internal.txid().to_string()
|
self.inner.txid().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weight(&self) -> u64 {
|
fn weight(&self) -> u64 {
|
||||||
self.internal.weight() as u64
|
self.inner.weight().to_wu()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> u64 {
|
fn size(&self) -> u64 {
|
||||||
self.internal.size() as u64
|
self.inner.size() as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn vsize(&self) -> u64 {
|
fn vsize(&self) -> u64 {
|
||||||
self.internal.vsize() as u64
|
self.inner.vsize() as u64
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize(&self) -> Vec<u8> {
|
fn serialize(&self) -> Vec<u8> {
|
||||||
self.internal.serialize()
|
serialize(&self.inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_coin_base(&self) -> bool {
|
fn is_coin_base(&self) -> bool {
|
||||||
self.internal.is_coin_base()
|
self.inner.is_coin_base()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_explicitly_rbf(&self) -> bool {
|
fn is_explicitly_rbf(&self) -> bool {
|
||||||
self.internal.is_explicitly_rbf()
|
self.inner.is_explicitly_rbf()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_lock_time_enabled(&self) -> bool {
|
fn is_lock_time_enabled(&self) -> bool {
|
||||||
self.internal.is_lock_time_enabled()
|
self.inner.is_lock_time_enabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn version(&self) -> i32 {
|
fn version(&self) -> i32 {
|
||||||
self.internal.version
|
self.inner.version
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lock_time(&self) -> u32 {
|
fn lock_time(&self) -> u32 {
|
||||||
self.internal.lock_time.0
|
self.inner.lock_time.to_consensus_u32()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input(&self) -> Vec<TxIn> {
|
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> {
|
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 {
|
impl From<BdkTransaction> for Transaction {
|
||||||
fn from(tx: BdkTransaction) -> Self {
|
fn from(tx: BdkTransaction) -> Self {
|
||||||
Transaction { internal: tx }
|
Transaction { inner: tx }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Bitcoin address.
|
/// A Bitcoin address.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
address: BdkAddress,
|
inner: BdkAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Address {
|
impl Address {
|
||||||
fn new(address: String) -> Result<Self, BdkError> {
|
pub fn new(address: String, network: Network) -> Result<Self, BdkError> {
|
||||||
BdkAddress::from_str(address.as_str())
|
let parsed_address = address
|
||||||
.map(|a| Address { address: a })
|
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
.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
|
/// alternative constructor
|
||||||
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
|
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
|
||||||
BdkAddress::from_script(&script.script, network)
|
BdkAddress::from_script(&script.0, network.into())
|
||||||
.map(|a| Address { address: a })
|
.map(|a| Address { inner: a })
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn payload(&self) -> Payload {
|
fn payload(&self) -> Payload {
|
||||||
match &self.address.payload.clone() {
|
match &self.inner.payload.clone() {
|
||||||
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
|
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
|
||||||
pubkey_hash: pubkey_hash.to_vec(),
|
pubkey_hash: pubkey_hash.to_string(),
|
||||||
},
|
},
|
||||||
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
|
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
|
||||||
script_hash: script_hash.to_vec(),
|
script_hash: script_hash.to_string(),
|
||||||
},
|
},
|
||||||
BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
|
BdkPayload::WitnessProgram(witness_program) => Payload::WitnessProgram {
|
||||||
version: *version,
|
version: witness_program.version(),
|
||||||
program: program.clone(),
|
program: Vec::from(witness_program.program().as_bytes()),
|
||||||
},
|
},
|
||||||
|
_ => panic!("Unsupported address payload type"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn network(&self) -> Network {
|
fn network(&self) -> Network {
|
||||||
self.address.network
|
self.inner.network.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn script_pubkey(&self) -> Arc<Script> {
|
fn script_pubkey(&self) -> Arc<Script> {
|
||||||
Arc::new(Script {
|
Arc::new(Script(self.inner.script_pubkey()))
|
||||||
script: self.address.script_pubkey(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_qr_uri(&self) -> String {
|
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 {
|
fn as_string(&self) -> String {
|
||||||
self.address.to_string()
|
self.inner.to_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BdkAddress> for Address {
|
impl From<BdkAddress> for Address {
|
||||||
fn from(address: BdkAddress) -> Self {
|
fn from(address: BdkAddress) -> Self {
|
||||||
Address { address }
|
Address { inner: address }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,9 +447,9 @@ impl From<BdkAddress> for Address {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Payload {
|
pub enum Payload {
|
||||||
/// P2PKH address.
|
/// P2PKH address.
|
||||||
PubkeyHash { pubkey_hash: Vec<u8> },
|
PubkeyHash { pubkey_hash: String },
|
||||||
/// P2SH address.
|
/// P2SH address.
|
||||||
ScriptHash { script_hash: Vec<u8> },
|
ScriptHash { script_hash: String },
|
||||||
/// Segwit address.
|
/// Segwit address.
|
||||||
WitnessProgram {
|
WitnessProgram {
|
||||||
/// The witness program version.
|
/// The witness program version.
|
||||||
@@ -427,25 +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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BdkScript> for Script {
|
|
||||||
fn from(bdk_script: BdkScript) -> Self {
|
|
||||||
Script { script: bdk_script }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum RbfValue {
|
enum RbfValue {
|
||||||
Default,
|
Default,
|
||||||
@@ -459,6 +472,37 @@ pub struct TxBuilderResult {
|
|||||||
pub transaction_details: TransactionDetails,
|
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);
|
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.
|
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
|
||||||
@@ -466,30 +510,33 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
|
|||||||
// crate.
|
// crate.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Transaction;
|
|
||||||
use crate::Network::Regtest;
|
use crate::Network::Regtest;
|
||||||
use crate::{Address, Payload};
|
use crate::{Address, Payload};
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
|
use bdk::bitcoin::address::WitnessVersion;
|
||||||
use bdk::bitcoin::hashes::hex::FromHex;
|
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.
|
// Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes.
|
||||||
#[test]
|
// #[test]
|
||||||
fn test_transaction_serde() {
|
// fn test_transaction_serde() {
|
||||||
let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
|
// let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
|
||||||
let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
|
// let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
|
||||||
let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
|
// let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
|
||||||
assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
|
// assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
|
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
|
||||||
#[test]
|
#[test]
|
||||||
fn test_address_witness_program() {
|
fn test_address_witness_program() {
|
||||||
let address =
|
let address = Address::new(
|
||||||
Address::new("bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string()).unwrap();
|
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string(),
|
||||||
|
Network::Regtest.into(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let payload = address.payload();
|
let payload = address.payload();
|
||||||
assert_matches!(payload, Payload::WitnessProgram { version, program } => {
|
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!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
|
||||||
});
|
});
|
||||||
assert_eq!(address.network(), Regtest);
|
assert_eq!(address.network(), Regtest);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use bdk::bitcoin::hashes::hex::ToHex;
|
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
||||||
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
|
||||||
use bdk::bitcoincore_rpc::jsonrpc::serde_json;
|
use bdk::bitcoincore_rpc::jsonrpc::serde_json;
|
||||||
use bdk::psbt::PsbtUtils;
|
use bdk::psbt::PsbtUtils;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@@ -10,7 +9,7 @@ use crate::{BdkError, FeeRate, Transaction};
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct PartiallySignedTransaction {
|
pub(crate) struct PartiallySignedTransaction {
|
||||||
pub(crate) internal: Mutex<BdkPartiallySignedTransaction>,
|
pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartiallySignedTransaction {
|
impl PartiallySignedTransaction {
|
||||||
@@ -18,24 +17,24 @@ impl PartiallySignedTransaction {
|
|||||||
let psbt: BdkPartiallySignedTransaction =
|
let psbt: BdkPartiallySignedTransaction =
|
||||||
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
|
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
|
||||||
Ok(PartiallySignedTransaction {
|
Ok(PartiallySignedTransaction {
|
||||||
internal: Mutex::new(psbt),
|
inner: Mutex::new(psbt),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn serialize(&self) -> String {
|
pub(crate) fn serialize(&self) -> String {
|
||||||
let psbt = self.internal.lock().unwrap().clone();
|
let psbt = self.inner.lock().unwrap().clone();
|
||||||
psbt.to_string()
|
psbt.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn txid(&self) -> 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();
|
let txid = tx.txid();
|
||||||
txid.to_hex()
|
txid.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the transaction.
|
/// Return the transaction.
|
||||||
pub(crate) fn extract_tx(&self) -> Arc<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())
|
Arc::new(tx.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,19 +45,19 @@ impl PartiallySignedTransaction {
|
|||||||
&self,
|
&self,
|
||||||
other: Arc<PartiallySignedTransaction>,
|
other: Arc<PartiallySignedTransaction>,
|
||||||
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
||||||
let other_psbt = other.internal.lock().unwrap().clone();
|
let other_psbt = other.inner.lock().unwrap().clone();
|
||||||
let mut original_psbt = self.internal.lock().unwrap().clone();
|
let mut original_psbt = self.inner.lock().unwrap().clone();
|
||||||
|
|
||||||
original_psbt.combine(other_psbt)?;
|
original_psbt.combine(other_psbt)?;
|
||||||
Ok(Arc::new(PartiallySignedTransaction {
|
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.
|
/// 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.
|
/// If the PSBT is missing a TxOut for an input returns None.
|
||||||
pub(crate) fn fee_amount(&self) -> Option<u64> {
|
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
|
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the
|
||||||
@@ -66,12 +65,12 @@ impl PartiallySignedTransaction {
|
|||||||
/// transaction.
|
/// transaction.
|
||||||
/// If the PSBT is missing a TxOut for an input returns None.
|
/// If the PSBT is missing a TxOut for an input returns None.
|
||||||
pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
|
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.
|
/// Serialize the PSBT data structure as a String of JSON.
|
||||||
pub(crate) fn json_serialize(&self) -> String {
|
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()
|
serde_json::to_string(psbt.deref()).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,6 +81,7 @@ impl PartiallySignedTransaction {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::wallet::{TxBuilder, Wallet};
|
use crate::wallet::{TxBuilder, Wallet};
|
||||||
|
use crate::Network;
|
||||||
use bdk::wallet::get_funded_wallet;
|
use bdk::wallet::get_funded_wallet;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
@@ -90,10 +90,10 @@ mod test {
|
|||||||
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
||||||
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
||||||
let test_wallet = Wallet {
|
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_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()
|
.unwrap()
|
||||||
.script_pubkey();
|
.script_pubkey();
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ mod test {
|
|||||||
.drain_to(drain_to_script.clone());
|
.drain_to(drain_to_script.clone());
|
||||||
//dbg!(&tx_builder);
|
//dbg!(&tx_builder);
|
||||||
assert!(tx_builder.drain_wallet);
|
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 tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use bdk::bitcoin::blockdata::script::Script as BdkScript;
|
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
|
||||||
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Sequence, Txid};
|
use bdk::bitcoin::script::PushBytesBuf;
|
||||||
|
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence, Txid};
|
||||||
use bdk::database::any::AnyDatabase;
|
use bdk::database::any::AnyDatabase;
|
||||||
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
||||||
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
||||||
@@ -8,6 +9,7 @@ use bdk::{
|
|||||||
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
|
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
|
||||||
};
|
};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
@@ -16,6 +18,7 @@ use crate::blockchain::Blockchain;
|
|||||||
use crate::database::DatabaseConfig;
|
use crate::database::DatabaseConfig;
|
||||||
use crate::descriptor::Descriptor;
|
use crate::descriptor::Descriptor;
|
||||||
use crate::psbt::PartiallySignedTransaction;
|
use crate::psbt::PartiallySignedTransaction;
|
||||||
|
use crate::Network;
|
||||||
use crate::{
|
use crate::{
|
||||||
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder,
|
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder,
|
||||||
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
|
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
|
||||||
@@ -23,7 +26,7 @@ use crate::{
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct Wallet {
|
pub(crate) struct Wallet {
|
||||||
pub(crate) wallet_mutex: Mutex<BdkWallet<AnyDatabase>>,
|
pub(crate) inner_mutex: Mutex<BdkWallet<AnyDatabase>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Bitcoin wallet.
|
/// A Bitcoin wallet.
|
||||||
@@ -50,19 +53,26 @@ impl Wallet {
|
|||||||
let wallet_mutex = Mutex::new(BdkWallet::new(
|
let wallet_mutex = Mutex::new(BdkWallet::new(
|
||||||
&descriptor,
|
&descriptor,
|
||||||
change_descriptor.as_ref(),
|
change_descriptor.as_ref(),
|
||||||
network,
|
network.into(),
|
||||||
database,
|
database,
|
||||||
)?);
|
)?);
|
||||||
Ok(Wallet { wallet_mutex })
|
Ok(Wallet {
|
||||||
|
inner_mutex: wallet_mutex,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
|
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.
|
/// Get the Bitcoin network the wallet is using.
|
||||||
pub(crate) fn network(&self) -> Network {
|
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.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sync the internal database with the blockchain.
|
/// Sync the internal database with the blockchain.
|
||||||
@@ -126,7 +136,7 @@ impl Wallet {
|
|||||||
psbt: &PartiallySignedTransaction,
|
psbt: &PartiallySignedTransaction,
|
||||||
sign_options: Option<SignOptions>,
|
sign_options: Option<SignOptions>,
|
||||||
) -> Result<bool, BdkError> {
|
) -> Result<bool, BdkError> {
|
||||||
let mut psbt = psbt.internal.lock().unwrap();
|
let mut psbt = psbt.inner.lock().unwrap();
|
||||||
self.get_wallet().sign(
|
self.get_wallet().sign(
|
||||||
&mut psbt,
|
&mut psbt,
|
||||||
sign_options.map(SignOptions::into).unwrap_or_default(),
|
sign_options.map(SignOptions::into).unwrap_or_default(),
|
||||||
@@ -233,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.
|
/// Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct TxBuilder {
|
pub(crate) struct TxBuilder {
|
||||||
pub(crate) recipients: Vec<(BdkScript, u64)>,
|
pub(crate) recipients: Vec<(BdkScriptBuf, u64)>,
|
||||||
pub(crate) utxos: Vec<OutPoint>,
|
pub(crate) utxos: Vec<OutPoint>,
|
||||||
pub(crate) unspendable: HashSet<OutPoint>,
|
pub(crate) unspendable: HashSet<OutPoint>,
|
||||||
pub(crate) change_policy: ChangeSpendPolicy,
|
pub(crate) change_policy: ChangeSpendPolicy,
|
||||||
@@ -241,7 +251,7 @@ pub(crate) struct TxBuilder {
|
|||||||
pub(crate) fee_rate: Option<f32>,
|
pub(crate) fee_rate: Option<f32>,
|
||||||
pub(crate) fee_absolute: Option<u64>,
|
pub(crate) fee_absolute: Option<u64>,
|
||||||
pub(crate) drain_wallet: bool,
|
pub(crate) drain_wallet: bool,
|
||||||
pub(crate) drain_to: Option<BdkScript>,
|
pub(crate) drain_to: Option<BdkScriptBuf>,
|
||||||
pub(crate) rbf: Option<RbfValue>,
|
pub(crate) rbf: Option<RbfValue>,
|
||||||
pub(crate) data: Vec<u8>,
|
pub(crate) data: Vec<u8>,
|
||||||
}
|
}
|
||||||
@@ -265,8 +275,8 @@ impl TxBuilder {
|
|||||||
|
|
||||||
/// Add a recipient to the internal list.
|
/// Add a recipient to the internal list.
|
||||||
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
|
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
|
||||||
let mut recipients: Vec<(BdkScript, u64)> = self.recipients.clone();
|
let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
|
||||||
recipients.append(&mut vec![(script.script.clone(), amount)]);
|
recipients.append(&mut vec![(script.0.clone(), amount)]);
|
||||||
Arc::new(TxBuilder {
|
Arc::new(TxBuilder {
|
||||||
recipients,
|
recipients,
|
||||||
..self.clone()
|
..self.clone()
|
||||||
@@ -276,7 +286,7 @@ impl TxBuilder {
|
|||||||
pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
|
pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
|
||||||
let recipients = recipients
|
let recipients = recipients
|
||||||
.iter()
|
.iter()
|
||||||
.map(|script_amount| (script_amount.script.script.clone(), script_amount.amount))
|
.map(|script_amount| (script_amount.script.0.clone(), script_amount.amount))
|
||||||
.collect();
|
.collect();
|
||||||
Arc::new(TxBuilder {
|
Arc::new(TxBuilder {
|
||||||
recipients,
|
recipients,
|
||||||
@@ -381,7 +391,7 @@ impl TxBuilder {
|
|||||||
/// to allow this output to be reduced to pay for the extra fees.
|
/// to allow this output to be reduced to pay for the extra fees.
|
||||||
pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
|
pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
|
||||||
Arc::new(TxBuilder {
|
Arc::new(TxBuilder {
|
||||||
drain_to: Some(script.script.clone()),
|
drain_to: Some(script.0.clone()),
|
||||||
..self.clone()
|
..self.clone()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -456,14 +466,17 @@ impl TxBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !&self.data.is_empty() {
|
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
|
tx_builder
|
||||||
.finish()
|
.finish()
|
||||||
.map(|(psbt, tx_details)| TxBuilderResult {
|
.map(|(psbt, tx_details)| TxBuilderResult {
|
||||||
psbt: Arc::new(PartiallySignedTransaction {
|
psbt: Arc::new(PartiallySignedTransaction {
|
||||||
internal: Mutex::new(psbt),
|
inner: Mutex::new(psbt),
|
||||||
}),
|
}),
|
||||||
transaction_details: TransactionDetails::from(tx_details),
|
transaction_details: TransactionDetails::from(tx_details),
|
||||||
})
|
})
|
||||||
@@ -475,7 +488,7 @@ impl TxBuilder {
|
|||||||
pub(crate) struct BumpFeeTxBuilder {
|
pub(crate) struct BumpFeeTxBuilder {
|
||||||
pub(crate) txid: String,
|
pub(crate) txid: String,
|
||||||
pub(crate) fee_rate: f32,
|
pub(crate) fee_rate: f32,
|
||||||
pub(crate) allow_shrinking: Option<String>,
|
pub(crate) allow_shrinking: Option<Arc<Script>>,
|
||||||
pub(crate) rbf: Option<RbfValue>,
|
pub(crate) rbf: Option<RbfValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -494,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
|
/// 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
|
/// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
|
||||||
/// can’t be found among the recipients of the transaction we are bumping.
|
/// can’t 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 {
|
Arc::new(Self {
|
||||||
allow_shrinking: Some(address),
|
allow_shrinking: Some(script_pubkey),
|
||||||
..self.clone()
|
..self.clone()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -529,10 +542,7 @@ impl BumpFeeTxBuilder {
|
|||||||
let mut tx_builder = wallet.build_fee_bump(txid)?;
|
let mut tx_builder = wallet.build_fee_bump(txid)?;
|
||||||
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
|
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
|
||||||
if let Some(allow_shrinking) = &self.allow_shrinking {
|
if let Some(allow_shrinking) = &self.allow_shrinking {
|
||||||
let address = BdkAddress::from_str(allow_shrinking)
|
tx_builder.allow_shrinking(allow_shrinking.0.clone())?;
|
||||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
|
||||||
let script = address.script_pubkey();
|
|
||||||
tx_builder.allow_shrinking(script)?;
|
|
||||||
}
|
}
|
||||||
if let Some(rbf) = &self.rbf {
|
if let Some(rbf) = &self.rbf {
|
||||||
match *rbf {
|
match *rbf {
|
||||||
@@ -547,7 +557,7 @@ impl BumpFeeTxBuilder {
|
|||||||
tx_builder
|
tx_builder
|
||||||
.finish()
|
.finish()
|
||||||
.map(|(psbt, _)| PartiallySignedTransaction {
|
.map(|(psbt, _)| PartiallySignedTransaction {
|
||||||
internal: Mutex::new(psbt),
|
inner: Mutex::new(psbt),
|
||||||
})
|
})
|
||||||
.map(Arc::new)
|
.map(Arc::new)
|
||||||
}
|
}
|
||||||
@@ -560,9 +570,14 @@ impl BumpFeeTxBuilder {
|
|||||||
mod test {
|
mod test {
|
||||||
use crate::database::DatabaseConfig;
|
use crate::database::DatabaseConfig;
|
||||||
use crate::descriptor::Descriptor;
|
use crate::descriptor::Descriptor;
|
||||||
|
use crate::keys::{DescriptorSecretKey, Mnemonic};
|
||||||
use crate::wallet::{AddressIndex, TxBuilder, Wallet};
|
use crate::wallet::{AddressIndex, TxBuilder, Wallet};
|
||||||
use bdk::bitcoin::{Address, Network};
|
use crate::Network;
|
||||||
|
use crate::Script;
|
||||||
|
use assert_matches::assert_matches;
|
||||||
|
use bdk::bitcoin::Address;
|
||||||
use bdk::wallet::get_funded_wallet;
|
use bdk::wallet::get_funded_wallet;
|
||||||
|
use bdk::KeychainKind;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
@@ -571,20 +586,20 @@ mod test {
|
|||||||
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
||||||
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
||||||
let test_wallet = Wallet {
|
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_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()
|
.unwrap()
|
||||||
.script_pubkey();
|
.script_pubkey();
|
||||||
let tx_builder = TxBuilder::new()
|
let tx_builder = TxBuilder::new()
|
||||||
.drain_wallet()
|
.drain_wallet()
|
||||||
.drain_to(drain_to_script.clone());
|
.drain_to(drain_to_script.clone());
|
||||||
assert!(tx_builder.drain_wallet);
|
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 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;
|
let tx_details = tx_builder_result.transaction_details;
|
||||||
|
|
||||||
// confirm one input with 50,000 sats
|
// confirm one input with 50,000 sats
|
||||||
@@ -612,12 +627,14 @@ mod test {
|
|||||||
.cloned()
|
.cloned()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.script_pubkey,
|
.script_pubkey,
|
||||||
Network::Testnet,
|
Network::Testnet.into(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
output_address,
|
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;
|
let output_value = psbt.unsigned_tx.output.get(0).cloned().unwrap().value;
|
||||||
assert_eq!(output_value, 49_890_u64); // input - fee
|
assert_eq!(output_value, 49_890_u64); // input - fee
|
||||||
@@ -802,4 +819,47 @@ mod test {
|
|||||||
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
|
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_is_mine() {
|
||||||
|
// is_mine should return true for addresses generated by the wallet
|
||||||
|
let mnemonic: 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();
|
||||||
|
let secret_key: DescriptorSecretKey =
|
||||||
|
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None);
|
||||||
|
let descriptor: Descriptor = Descriptor::new_bip84(
|
||||||
|
Arc::new(secret_key),
|
||||||
|
KeychainKind::External,
|
||||||
|
Network::Testnet,
|
||||||
|
);
|
||||||
|
let wallet: Wallet = Wallet::new(
|
||||||
|
Arc::new(descriptor),
|
||||||
|
None,
|
||||||
|
Network::Testnet,
|
||||||
|
DatabaseConfig::Memory,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let address = wallet.get_address(AddressIndex::New).unwrap();
|
||||||
|
let script: Arc<Script> = address.address.script_pubkey();
|
||||||
|
|
||||||
|
let is_mine_1: bool = wallet.is_mine(script).unwrap();
|
||||||
|
assert!(is_mine_1);
|
||||||
|
|
||||||
|
// is_mine returns false when provided a script that is not in the wallet
|
||||||
|
let other_wpkh = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)";
|
||||||
|
let other_descriptor = Descriptor::new(other_wpkh.to_string(), Network::Testnet).unwrap();
|
||||||
|
|
||||||
|
let other_wallet = Wallet::new(
|
||||||
|
Arc::new(other_descriptor),
|
||||||
|
None,
|
||||||
|
Network::Testnet,
|
||||||
|
DatabaseConfig::Memory,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let other_address = other_wallet.get_address(AddressIndex::New).unwrap();
|
||||||
|
let other_script: Arc<Script> = other_address.address.script_pubkey();
|
||||||
|
let is_mine_2: bool = wallet.is_mine(other_script).unwrap();
|
||||||
|
assert_matches!(is_mine_2, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# bdk-android
|
# bdk-jvm
|
||||||
This project builds a .jar package for the JVM platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the `bdk-ffi` project which is included in the root of this repository.
|
This project builds a .jar package for the JVM platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the `bdk-ffi` project which is included in the root of this repository.
|
||||||
|
|
||||||
## How to Use
|
## How to Use
|
||||||
@@ -25,8 +25,8 @@ val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8
|
|||||||
val databaseConfig = DatabaseConfig.Memory
|
val databaseConfig = DatabaseConfig.Memory
|
||||||
|
|
||||||
val blockchainConfig = BlockchainConfig.Electrum(
|
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 wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
|
||||||
val newAddress = wallet.getAddress(AddressIndex.LastUnused)
|
val newAddress = wallet.getAddress(AddressIndex.LastUnused)
|
||||||
```
|
```
|
||||||
@@ -38,32 +38,39 @@ repositories {
|
|||||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
|
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Example Projects
|
## Example Projects
|
||||||
* [Tatooine Faucet](https://github.com/thunderbiscuit/tatooine)
|
* [Tatooine Faucet](https://github.com/thunderbiscuit/tatooine)
|
||||||
|
|
||||||
## How to build
|
## How to build
|
||||||
_Note that Kotlin version `1.6.10` or later is required to build the library._
|
_Note that Kotlin version `1.6.10` or later is required to build the library._
|
||||||
|
1. Install JDK 11. It must be version 11 (not 17), otherwise it won't build. For example, with SDKMAN!:
|
||||||
1. Clone this repository.
|
```shell
|
||||||
|
curl -s "https://get.sdkman.io" | bash
|
||||||
|
source "$HOME/.sdkman/bin/sdkman-init.sh"
|
||||||
|
sdk install java 11.0.19-tem
|
||||||
|
```
|
||||||
|
2. Install Rust (note that we are currently building using Rust 1.67.0):
|
||||||
|
```shell
|
||||||
|
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||||
|
rustup default 1.67.0
|
||||||
|
```
|
||||||
|
3. Clone this repository.
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/bitcoindevkit/bdk-ffi
|
git clone https://github.com/bitcoindevkit/bdk-ffi
|
||||||
```
|
```
|
||||||
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
|
4. If building on macOS install required intel and m1 jvm targets
|
||||||
3. If building on macOS install required intel and m1 jvm targets
|
|
||||||
```sh
|
```sh
|
||||||
rustup target add x86_64-apple-darwin aarch64-apple-darwin
|
rustup target add x86_64-apple-darwin aarch64-apple-darwin
|
||||||
```
|
```
|
||||||
4. Build kotlin bindings
|
5. Build kotlin bindings
|
||||||
```sh
|
```sh
|
||||||
# build JVM library
|
./gradlew buildJvmLib
|
||||||
./gradlew buildJvmLib
|
```
|
||||||
```
|
|
||||||
|
|
||||||
## How to publish to your local Maven repo
|
## How to publish to your local Maven repo
|
||||||
```shell
|
```shell
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
org.gradle.jvmargs=-Xmx1536m
|
org.gradle.jvmargs=-Xmx1536m
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
libraryVersion=0.28.0
|
libraryVersion=0.31.1
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
}
|
}
|
||||||
@@ -107,4 +107,8 @@ signing {
|
|||||||
// binaries before running the tests
|
// binaries before running the tests
|
||||||
tasks.withType<KotlinCompile> {
|
tasks.withType<KotlinCompile> {
|
||||||
dependsOn("buildJvmLib")
|
dependsOn("buildJvmLib")
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ package org.bitcoindevkit.plugins
|
|||||||
val operatingSystem: OS = when {
|
val operatingSystem: OS = when {
|
||||||
System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC
|
System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC
|
||||||
System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX
|
System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX
|
||||||
|
System.getProperty("os.name").contains("windows", ignoreCase = true) -> OS.WINDOWS
|
||||||
else -> OS.OTHER
|
else -> OS.OTHER
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class OS {
|
enum class OS {
|
||||||
MAC,
|
MAC,
|
||||||
LINUX,
|
LINUX,
|
||||||
|
WINDOWS,
|
||||||
OTHER,
|
OTHER,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,20 @@ internal class UniFfiJvmPlugin : Plugin<Project> {
|
|||||||
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-apple-darwin")
|
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-apple-darwin")
|
||||||
args(cargoArgs)
|
args(cargoArgs)
|
||||||
}
|
}
|
||||||
} else if(operatingSystem == OS.LINUX) {
|
} else if (operatingSystem == OS.LINUX) {
|
||||||
exec {
|
exec {
|
||||||
workingDir("${project.projectDir}/../../bdk-ffi")
|
workingDir("${project.projectDir}/../../bdk-ffi")
|
||||||
executable("cargo")
|
executable("cargo")
|
||||||
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-unknown-linux-gnu")
|
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-unknown-linux-gnu")
|
||||||
args(cargoArgs)
|
args(cargoArgs)
|
||||||
}
|
}
|
||||||
|
} else if (operatingSystem == OS.WINDOWS) {
|
||||||
|
exec {
|
||||||
|
workingDir("${project.projectDir}/../../bdk-ffi")
|
||||||
|
executable("cargo")
|
||||||
|
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-pc-windows-msvc")
|
||||||
|
args(cargoArgs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,13 +77,25 @@ internal class UniFfiJvmPlugin : Plugin<Project> {
|
|||||||
ext = "so"
|
ext = "so"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
} else if (operatingSystem == OS.WINDOWS) {
|
||||||
|
libsToCopy.add(
|
||||||
|
CopyMetadata(
|
||||||
|
targetDir = "x86_64-pc-windows-msvc",
|
||||||
|
resDir = "win32-x86-64",
|
||||||
|
ext = "dll"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val libName = when (operatingSystem) {
|
||||||
|
OS.WINDOWS -> "bdkffi"
|
||||||
|
else -> "libbdkffi"
|
||||||
}
|
}
|
||||||
|
|
||||||
libsToCopy.forEach {
|
libsToCopy.forEach {
|
||||||
doFirst {
|
doFirst {
|
||||||
copy {
|
copy {
|
||||||
with(it) {
|
with(it) {
|
||||||
from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/libbdkffi.${this.ext}")
|
from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/${libName}.${this.ext}")
|
||||||
into("${project.projectDir}/../../bdk-jvm/lib/src/main/resources/${this.resDir}/")
|
into("${project.projectDir}/../../bdk-jvm/lib/src/main/resources/${this.resDir}/")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
include ./src/bdkpython/libbdkffi.dylib
|
include ./src/bdkpython/libbdkffi.dylib
|
||||||
include ./src/bdkpython/libbdkffi.so
|
include ./src/bdkpython/libbdkffi.so
|
||||||
|
include ./src/bdkpython/bdkffi.dll
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ pip install bdkpython
|
|||||||
## Run the tests
|
## Run the tests
|
||||||
```shell
|
```shell
|
||||||
pip install --requirement requirements.txt
|
pip install --requirement requirements.txt
|
||||||
bash ./generate.sh
|
bash ./scripts/generate-linux.sh # here you should run the script appropriate for your platform
|
||||||
python setup.py bdist_wheel --verbose
|
python setup.py bdist_wheel --verbose
|
||||||
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall
|
pip install ./dist/bdkpython-<yourversion>.whl --force-reinstall
|
||||||
python -m unittest --verbose tests/test_bdk.py
|
python -m unittest --verbose tests/test_bdk.py
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -23,26 +23,14 @@ python -m unittest --verbose tests/test_bdk.py
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
pip install --requirement requirements.txt
|
pip install --requirement requirements.txt
|
||||||
|
|
||||||
# Generate the bindings
|
# Generate the bindings (use the script appropriate for your platform)
|
||||||
bash generate.sh
|
bash ./scripts/generate-linux.sh
|
||||||
|
|
||||||
# Build the wheel
|
# Build the wheel
|
||||||
python setup.py --verbose bdist_wheel
|
python setup.py --verbose bdist_wheel
|
||||||
```
|
```
|
||||||
|
|
||||||
## Run tox to build and test locally
|
|
||||||
```shell
|
|
||||||
# install dev requirements
|
|
||||||
pip install --requirement requirements-dev.txt
|
|
||||||
|
|
||||||
# build bindings glue code (located at ./src/bdkpython/bdk.py)
|
|
||||||
source ./generate.sh
|
|
||||||
|
|
||||||
# build and test
|
|
||||||
tox -vv
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install locally
|
## Install locally
|
||||||
```shell
|
```shell
|
||||||
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl
|
pip install ./dist/bdkpython-<yourversion>.whl
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
OS=$(uname -s)
|
|
||||||
|
|
||||||
echo "Generating bdk.py..."
|
|
||||||
cd ../bdk-ffi/
|
|
||||||
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
|
|
||||||
|
|
||||||
echo "Generating native binaries..."
|
|
||||||
cargo build --profile release-smaller
|
|
||||||
case $OS in
|
|
||||||
"Darwin")
|
|
||||||
echo "Copying macOS libbdkffi.dylib..."
|
|
||||||
cp ../target/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
|
|
||||||
;;
|
|
||||||
"Linux")
|
|
||||||
echo "Copying linux libbdkffi.so..."
|
|
||||||
cp ../target/release-smaller/libbdkffi.so ../bdk-python/src/bdkpython/libbdkffi.so
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
cd ../bdk-python/
|
|
||||||
|
|
||||||
echo "All done!"
|
|
||||||
18
bdk-python/scripts/generate-linux.sh
Normal file
18
bdk-python/scripts/generate-linux.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
${PYBIN}/python --version
|
||||||
|
${PYBIN}/pip install -r requirements.txt
|
||||||
|
|
||||||
|
echo "Generating bdk.py..."
|
||||||
|
cd ../bdk-ffi/
|
||||||
|
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
|
||||||
|
|
||||||
|
echo "Generating native binaries..."
|
||||||
|
rustup default 1.67.0
|
||||||
|
cargo build --profile release-smaller
|
||||||
|
|
||||||
|
echo "Copying linux libbdkffi.so..."
|
||||||
|
cp ../target/release-smaller/libbdkffi.so ../bdk-python/src/bdkpython/libbdkffi.so
|
||||||
|
|
||||||
|
echo "All done!"
|
||||||
19
bdk-python/scripts/generate-macos-arm64.sh
Normal file
19
bdk-python/scripts/generate-macos-arm64.sh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
python3 --version
|
||||||
|
pip install --user -r requirements.txt
|
||||||
|
|
||||||
|
echo "Generating bdk.py..."
|
||||||
|
cd ../bdk-ffi/
|
||||||
|
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
|
||||||
|
|
||||||
|
echo "Generating native binaries..."
|
||||||
|
rustup default 1.67.0
|
||||||
|
rustup target add aarch64-apple-darwin
|
||||||
|
cargo build --profile release-smaller --target aarch64-apple-darwin
|
||||||
|
|
||||||
|
echo "Copying libraries libbdkffi.dylib..."
|
||||||
|
cp ../target/aarch64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
|
||||||
|
|
||||||
|
echo "All done!"
|
||||||
18
bdk-python/scripts/generate-macos-x86_64.sh
Normal file
18
bdk-python/scripts/generate-macos-x86_64.sh
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
python3 --version
|
||||||
|
pip install --user -r requirements.txt
|
||||||
|
|
||||||
|
echo "Generating bdk.py..."
|
||||||
|
cd ../bdk-ffi/
|
||||||
|
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
|
||||||
|
|
||||||
|
echo "Generating native binaries..."
|
||||||
|
rustup target add x86_64-apple-darwin
|
||||||
|
cargo build --profile release-smaller --target x86_64-apple-darwin
|
||||||
|
|
||||||
|
echo "Copying libraries libbdkffi.dylib..."
|
||||||
|
cp ../target/x86_64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
|
||||||
|
|
||||||
|
echo "All done!"
|
||||||
19
bdk-python/scripts/generate-windows.sh
Normal file
19
bdk-python/scripts/generate-windows.sh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
python3 --version
|
||||||
|
pip install --user -r requirements.txt
|
||||||
|
|
||||||
|
echo "Generating bdk.py..."
|
||||||
|
cd ../bdk-ffi/
|
||||||
|
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
|
||||||
|
|
||||||
|
echo "Generating native binaries..."
|
||||||
|
rustup default 1.67.0
|
||||||
|
rustup target add x86_64-pc-windows-msvc
|
||||||
|
cargo build --profile release-smaller --target x86_64-pc-windows-msvc
|
||||||
|
|
||||||
|
echo "Copying libraries bdkffi.dll..."
|
||||||
|
cp ../target/x86_64-pc-windows-msvc/release-smaller/bdkffi.dll ../bdk-python/src/bdkpython/bdkffi.dll
|
||||||
|
|
||||||
|
echo "All done!"
|
||||||
@@ -51,7 +51,7 @@ print(f"Wallet balance is: {balance.total}")
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="bdkpython",
|
name="bdkpython",
|
||||||
version="0.28.3",
|
version="0.31.0",
|
||||||
description="The Python language bindings for the Bitcoin Development Kit",
|
description="The Python language bindings for the Bitcoin Development Kit",
|
||||||
long_description=LONG_DESCRIPTION,
|
long_description=LONG_DESCRIPTION,
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
@@ -62,7 +62,6 @@ setup(
|
|||||||
url="https://github.com/bitcoindevkit/bdk-ffi",
|
url="https://github.com/bitcoindevkit/bdk-ffi",
|
||||||
author="Alekos Filini <alekos.filini@gmail.com>, Steve Myers <steve@notmandatory.org>",
|
author="Alekos Filini <alekos.filini@gmail.com>, Steve Myers <steve@notmandatory.org>",
|
||||||
license="MIT or Apache 2.0",
|
license="MIT or Apache 2.0",
|
||||||
|
|
||||||
# This is required to ensure the library name includes the python version, abi, and platform tags
|
# This is required to ensure the library name includes the python version, abi, and platform tags
|
||||||
# See issue #350 for more information
|
# See issue #350 for more information
|
||||||
has_ext_modules=lambda: True,
|
has_ext_modules=lambda: True,
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ let package = Package(
|
|||||||
.binaryTarget(name: "bdkFFI", path: "./bdkFFI.xcframework"),
|
.binaryTarget(name: "bdkFFI", path: "./bdkFFI.xcframework"),
|
||||||
.target(
|
.target(
|
||||||
name: "BitcoinDevKit",
|
name: "BitcoinDevKit",
|
||||||
dependencies: ["bdkFFI"]),
|
dependencies: ["bdkFFI"],
|
||||||
|
swiftSettings: [.unsafeFlags(["-suppress-warnings"])]
|
||||||
|
),
|
||||||
.testTarget(
|
.testTarget(
|
||||||
name: "BitcoinDevKitTests",
|
name: "BitcoinDevKitTests",
|
||||||
dependencies: ["BitcoinDevKit"]),
|
dependencies: ["BitcoinDevKit"]),
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>SupportedPlatform</key>
|
<key>SupportedPlatform</key>
|
||||||
<string>macos</string>
|
<string>macos</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>12.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>LibraryIdentifier</key>
|
<key>LibraryIdentifier</key>
|
||||||
@@ -31,6 +33,8 @@
|
|||||||
<string>ios</string>
|
<string>ios</string>
|
||||||
<key>SupportedPlatformVariant</key>
|
<key>SupportedPlatformVariant</key>
|
||||||
<string>simulator</string>
|
<string>simulator</string>
|
||||||
|
<key>MinimumOSVersion</key>
|
||||||
|
<string>15.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
<dict>
|
<dict>
|
||||||
<key>LibraryIdentifier</key>
|
<key>LibraryIdentifier</key>
|
||||||
@@ -43,6 +47,8 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>SupportedPlatform</key>
|
<key>SupportedPlatform</key>
|
||||||
<string>ios</string>
|
<string>ios</string>
|
||||||
|
<key>MinimumOSVersion</key>
|
||||||
|
<string>15.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -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>
|
||||||
@@ -5,10 +5,10 @@
|
|||||||
#
|
#
|
||||||
# Run the script from the repo root directory, ie: ./bdk-swift/build-local-swift.sh
|
# Run the script from the repo root directory, ie: ./bdk-swift/build-local-swift.sh
|
||||||
|
|
||||||
rustup install nightly-x86_64-apple-darwin
|
rustup install nightly-2023-04-10
|
||||||
rustup component add rust-src --toolchain nightly-x86_64-apple-darwin
|
rustup component add rust-src --toolchain nightly-2023-04-10
|
||||||
rustup target add aarch64-apple-ios x86_64-apple-ios
|
rustup target add aarch64-apple-ios x86_64-apple-ios
|
||||||
rustup target add aarch64-apple-ios-sim --toolchain nightly
|
rustup target add aarch64-apple-ios-sim --toolchain nightly-2023-04-10
|
||||||
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
rustup target add aarch64-apple-darwin x86_64-apple-darwin
|
||||||
|
|
||||||
pushd bdk-ffi
|
pushd bdk-ffi
|
||||||
@@ -20,10 +20,10 @@ cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-da
|
|||||||
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
|
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
|
||||||
cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-ios
|
cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-ios
|
||||||
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios
|
cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios
|
||||||
cargo +nightly build --package bdk-ffi --release -Z build-std --target aarch64-apple-ios-sim
|
cargo +nightly-2023-04-10 build --package bdk-ffi --profile release-smaller --target aarch64-apple-ios-sim
|
||||||
|
|
||||||
mkdir -p target/lipo-ios-sim/release-smaller
|
mkdir -p target/lipo-ios-sim/release-smaller
|
||||||
lipo target/aarch64-apple-ios-sim/release/libbdkffi.a target/x86_64-apple-ios/release-smaller/libbdkffi.a -create -output target/lipo-ios-sim/release-smaller/libbdkffi.a
|
lipo target/aarch64-apple-ios-sim/release-smaller/libbdkffi.a target/x86_64-apple-ios/release-smaller/libbdkffi.a -create -output target/lipo-ios-sim/release-smaller/libbdkffi.a
|
||||||
mkdir -p target/lipo-macos/release-smaller
|
mkdir -p target/lipo-macos/release-smaller
|
||||||
lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a
|
lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user