Compare commits

..

1 Commits

Author SHA1 Message Date
thunderbiscuit
016bba93d1 Update libraries to official release versions 2023-02-21 11:00:08 -05:00
48 changed files with 1018 additions and 1514 deletions

View File

@@ -4,80 +4,98 @@ about: Create a new minor release [for release managers only]
title: 'Release MAJOR.MINOR+1.0' title: 'Release MAJOR.MINOR+1.0'
labels: 'release' labels: 'release'
assignees: '' assignees: ''
--- ---
## Create a new minor release ## Create a new minor release
### _Main Workflow_
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.
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`
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
- [ ] 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
20. - [ ] Merge the PR updating all of 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.
```sh
git tag v0.6.0 --sign --edit
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)
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`)
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`
25. - [ ] 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)
```
26. - [ ] Tweet about the library
27. - [ ] Post in the announcement channel
### _Sub Workflows_ ### Summary
#### _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_ <--release summary to be used in announcements-->
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_ ### Commit
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_ <--latest commit ID to include in this release-->
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 ### Changelog
```shell
pip3 install --requirement requirements.txt <--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
bash ./generate.sh
python3 setup.py --verbose bdist_wheel ### Checklist
```
16. - [ ] Run the tests and adjust if necessary Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
```shell branch **development** version is *MAJOR.MINOR.0*.
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl
python -m unittest --verbose tests/test_bdk.py #### On the day of the feature freeze
```
17. - [ ] Update the readme and `setup.py` if necessary Change the `master` branch to the next MINOR+1 version:
- [ ] Switch to the `master` branch.
- [ ] Create a new PR branch called `bump_dev_MAJOR_MINOR+1`, eg. `bump_dev_0_22`.
- [ ] Bump the `bump_dev_MAJOR_MINOR+1` branch to the next development MINOR+1 version.
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0`.
- The commit message should be "Bump version to MAJOR.MINOR+1.0".
- [ ] Create PR and merge the `bump_dev_MAJOR_MINOR+1` branch to `master`.
- Title PR "Bump version to MAJOR.MINOR+1.0".
Create a new release branch:
- [ ] Double check that your local `master` is up-to-date with the upstream repo.
- [ ] Create a new branch called `release/MAJOR.MINOR+1` from `master`.
Add a release candidate tag, this is optional and only needed for major `bdk-ffi` changes that
require a longer testing cycle:
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0-rc.1` version.
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0-rc.1`.
- The commit message should be "Bump version to MAJOR.MINOR+1.0-rc.1".
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
- The tag name should be `vMAJOR.MINOR+1.0-rc.1`
- Use message "Release MAJOR.MINOR+1.0 rc.1".
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
- [ ] Push the `release/MAJOR.MINOR` branch and new tag to the `bitcoindevkit/bdk` repo.
- Use `git push --tags` option to push the new `vMAJOR.MINOR+1.0-rc.1` tag.
If any issues need to be fixed before the *MAJOR.MINOR+1.0* version is released:
- [ ] Merge fix PRs to the `master` branch.
- [ ] Git cherry-pick fix commits to the `release/MAJOR.MINOR+1` branch.
- [ ] Verify fixes in `release/MAJOR.MINOR+1` branch.
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0-rc.x+1` version.
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0-rc.x+1`.
- The commit message should be "Bump version to MAJOR.MINOR+1.0-rc.x+1".
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
- The tag name should be `vMAJOR.MINOR+1.0-rc.x+1`, where x is the current release candidate number.
- Use tag message "Release MAJOR.MINOR+1.0 rc.x+1".
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
- Use `git push --tags` option to push the new `vMAJOR.MINOR+1.0-rc.x+1` tag.
#### On the day of the release
Tag and publish new release:
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0` version.
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0`.
- The commit message should be "Bump version to MAJOR.MINOR+1.0".
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
- The tag name should be `vMAJOR.MINOR+1.0`
- The first line of the tag message should be "Release MAJOR.MINOR+1.0".
- In the body of the tag message put a copy of the **Summary** and **Changelog** for the release.
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
- [ ] Wait for the CI to finish one last time.
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
- [ ] Create the release on GitHub.
- Go to "tags", click on the dots on the right and select "Create Release".
- Set the title to `Release MAJOR.MINOR+1.0`.
- In the release notes body put the **Summary** and **Changelog**.
- Use the "+ Auto-generate release notes" button to add details from included PRs.
- Until we reach a `1.0.0` release check the "Pre-release" box.
- [ ] After downstream language repos are also updated announce the release, using the **Summary**,
on Discord, Twitter and Mastodon.
- [ ] Celebrate 🎉
[Semantic Versioning]: https://semver.org/
[crates.io]: https://crates.io/crates/bdk
[docs.rs]: https://docs.rs/bdk/latest/bdk
["keep a changelog"]: https://keepachangelog.com/en/1.0.0/

View File

@@ -4,81 +4,66 @@ about: Create a new patch release [for release managers only]
title: 'Release MAJOR.MINOR.PATCH+1' title: 'Release MAJOR.MINOR.PATCH+1'
labels: 'release' labels: 'release'
assignees: '' assignees: ''
--- ---
# Creating a new patch release ## Create a new patch release
## Bumping BDK Rust Version ### Summary
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 <--release summary to be used in announcements-->
#### _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 ### Commit
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` <--latest commit ID to include in this release-->
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 ### Changelog
- [ ] Update bdk-jvm version from `SNAPSHOT` version to release version
- [ ] Update bdk-python version from `.dev` version to release version <--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
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. ### Checklist
```sh
git tag v0.6.0 --sign --edit Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
git push upstream v0.6.0 branch **development** version is *MAJOR.MINOR.PATCH*.
```
21. - [ ] Make release on GitHub (set as pre-release and generate auto release notes between the previous tag and the new one) ### On the day of the patch release
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` Change the `master` branch to the new PATCH+1 version:
24. - [ ] Build and publish API docs for JVM, Android, and Java on the website
```bash! - [ ] Switch to the `master` branch.
./gradlew dokkaHtml # bdk-jvm (Dokka) - [ ] Create a new PR branch called `bump_dev_MAJOR_MINOR_PATCH+1`, eg. `bump_dev_0_22_1`.
./gradlew dokkaJavadoc # bdk-jvm (java-style documentation) - [ ] Bump the `bump_dev_MAJOR_MINOR` branch to the next development PATCH+1 version.
./gradlew dokkaHtml # bdk-android (Dokka) - Change the `Cargo.toml` version value to `MAJOR.MINOR.PATCH+1`.
``` - The commit message should be "Bump version to MAJOR.MINOR.PATCH+1".
25. - [ ] Tweet about the library - [ ] Create PR and merge the `bump_dev_MAJOR_MINOR_PATCH+1` branch to `master`.
26. - [ ] Post in the announcement channel - Title PR "Bump version to MAJOR.MINOR.PATCH+1".
Cherry-pick, tag and publish new PATCH+1 release:
- [ ] Merge fix PRs to the `master` branch.
- [ ] Git cherry-pick fix commits to the `release/MAJOR.MINOR` branch to be patched.
- [ ] Verify fixes in `release/MAJOR.MINOR` branch.
- [ ] Bump the `release/MAJOR.MINOR.PATCH+1` branch to `MAJOR.MINOR.PATCH+1` version.
- Change the `Cargo.toml` version value to `MAJOR.MINOR.MINOR.PATCH+1`.
- The commit message should be "Bump version to MAJOR.MINOR.PATCH+1".
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR` branch.
- The tag name should be `vMAJOR.MINOR.PATCH+1`
- The first line of the tag message should be "Release MAJOR.MINOR.PATCH+1".
- In the body of the tag message put a copy of the **Summary** and **Changelog** for the release.
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
- [ ] Wait for the CI to finish one last time.
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
- [ ] Create the release on GitHub.
- Go to "tags", click on the dots on the right and select "Create Release".
- Set the title to `Release MAJOR.MINOR.PATCH+1`.
- In the release notes body put the **Summary** and **Changelog**.
- Use the "+ Auto-generate release notes" button to add details from included PRs.
- Until we reach a `1.0.0` release check the "Pre-release" box.
- [ ] After downstream language repos are also updated announce the release, using the **Summary**,
on Discord, Twitter and Mastodon.
- [ ] Celebrate 🎉
[Semantic Versioning]: https://semver.org/
[crates.io]: https://crates.io/crates/bdk
[docs.rs]: https://docs.rs/bdk/latest/bdk
["keep a changelog"]: https://keepachangelog.com/en/1.0.0/

View File

@@ -10,7 +10,7 @@ on:
jobs: jobs:
security_audit: security_audit:
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@v2

View File

@@ -0,0 +1,126 @@
name: Build Python wheels
on:
push:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
# makes it very hard to use GitHub's javascript actions (checkout, upload-artifact, etc).
# They mount their own nodejs interpreter inside your container, but since that's not statically linked it
# tries to load glibc and fails because it requires a more recent version.
jobs:
build-manylinux2014-x86_64-wheel:
name: 'Build Manylinux 2014 x86_64 wheel'
runs-on: ubuntu-latest
defaults:
run:
working-directory: bdk-python
container:
image: quay.io/pypa/manylinux2014_x86_64
env:
PLAT: manylinux2014_x86_64
PYBIN: '/opt/python/${{ matrix.python }}/bin'
strategy:
matrix:
python: # Update this list whenever the docker image is updated (check /opt/python/)
# - cp36-cp36m
# - cp37-cp37m
# - cp38-cp38
# - cp39-cp39
- cp310-cp310
# - pp37-pypy37_pp73
# - pp38-pypy38_pp73
steps:
- name: checkout
uses: actions/checkout@v2
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: install requirements
run: ${PYBIN}/pip install -r requirements.txt
- name: generate bindings
run: bash generate.sh
- name: build wheel
run: ${PYBIN}/pip wheel . --no-deps -w /tmp/wheelhouse
- name: repair wheel
run: auditwheel repair /tmp/wheelhouse/* --plat "$PLAT" -w /tmp/wheelhouse-repaired
- uses: actions/upload-artifact@v2
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /tmp/wheelhouse-repaired/*.whl
build-macos-universal-wheel:
name: 'Build macOS universal wheel'
runs-on: macos-latest
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
# - '3.7'
# - '3.8'
# - '3.9'
- '3.10'
steps:
- name: checkout
uses: actions/checkout@v2
with:
submodules: true
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- run: python3 --version
- run: rustup target add aarch64-apple-darwin
- run: pip3 install --user -r requirements.txt
- run: pip3 install --user wheel
- run: bash generate.sh
- name: build wheel
env:
ARCHFLAGS: "-arch x86_64 -arch arm64"
run: python3 setup.py -v bdist_wheel
- uses: actions/upload-artifact@v2
with:
name: bdkpython-macos-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheel:
name: 'Build windows wheel'
runs-on: windows-latest
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
# - '3.7'
# - '3.8'
# - '3.9'
- '3.10'
steps:
- name: checkout
uses: actions/checkout@v2
with:
submodules: true
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- run: python --version
- run: pip install --user -r requirements.txt
- run: bash generate.sh
shell: bash
- run: pip install --user wheel
- name: build wheel
run: python setup.py -v bdist_wheel
- uses: actions/upload-artifact@v2
with:
name: bdkpython-win-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl

View File

@@ -1,4 +1,4 @@
name: Rust layer CI name: bdk-ffi CI
on: on:
push: push:
paths: paths:
@@ -8,9 +8,10 @@ on:
- "bdk-ffi/**" - "bdk-ffi/**"
jobs: jobs:
build-test: build-test:
name: Build and test name: Build and test
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
rust: rust:
@@ -18,13 +19,11 @@ jobs:
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@v2
- 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@v2
with: with:
path: | path: |
@@ -32,29 +31,22 @@ jobs:
~/.cargo/git ~/.cargo/git
target target
key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }} key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: Set default toolchain - name: Set default toolchain
run: rustup default ${{ matrix.rust.version }} run: rustup default ${{ matrix.rust.version }}
- name: Set profile - name: Set profile
run: rustup set profile minimal run: rustup set profile minimal
- name: Add clippy - name: Add clippy
if: ${{ matrix.rust.clippy }} if: ${{ matrix.rust.clippy }}
run: rustup component add clippy run: rustup component add clippy
- name: Update toolchain - name: Update toolchain
run: rustup update run: rustup update
- name: Build - name: Build
run: cargo build run: cargo build
- name: Clippy - name: Clippy
if: ${{ matrix.rust.clippy }} if: ${{ matrix.rust.clippy }}
run: cargo clippy --all-targets --features "uniffi/bindgen-tests" -- -D warnings run: cargo clippy --all-targets -- -D warnings
- name: Test - name: Test
run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test --features uniffi/bindgen-tests run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test
fmt: fmt:
name: Rust fmt name: Rust fmt
@@ -62,18 +54,13 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set default toolchain - name: Set default toolchain
run: rustup default nightly run: rustup default nightly
- name: Set profile - name: Set profile
run: rustup set profile minimal run: rustup set profile minimal
- name: Add rustfmt - name: Add rustfmt
run: rustup component add rustfmt run: rustup component add rustfmt
- name: Update toolchain - name: Update toolchain
run: rustup update run: rustup update
- name: Check fmt - name: Check fmt
run: cargo fmt --all -- --config format_code_in_doc_comments=true --check run: cargo fmt --all -- --config format_code_in_doc_comments=true --check

View File

@@ -1,28 +1,26 @@
name: Publish bdk-android to Maven Central name: Publish bdk-android to Maven Central
on: [workflow_dispatch] on: [workflow_dispatch]
# The default Android NDK on the ubuntu-22.04 image is 25.2.9519653
# We replace the default environment variable ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.2.9519653
# with an older version of the NDK (21.4.7075529) using the fix proposed here: https://github.com/actions/runner-images/issues/5930
# For information on why this is needed at the moment see issues #242 and #243, and PR #282
env: env:
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529 ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
# By default, the new ubuntu-20.04 images use the following ANDROID_NDK_ROOT
# ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.0.8775105
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: "Install Android NDK 21.4.7075529" - name: Install Android NDK 21.4.7075529
run: | run: |
ANDROID_ROOT=/usr/local/lib/android ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
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@v2
- name: "Cache" - name: cache
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: |
@@ -31,24 +29,21 @@ 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@v2
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
- name: "Set default Rust version to 1.67.0" - name: Install rust android targets
run: rustup default 1.67.0
- name: "Install Rust Android targets"
run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
- name: "Build bdk-android library" - name: Build bdk-android library
run: | run: |
cd bdk-android cd bdk-android
./gradlew buildAndroidLib ./gradlew buildAndroidLib
- name: "Publish to Maven Local and Maven Central" - name: Publish to Maven Local and 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 }}

View File

@@ -3,10 +3,10 @@ on: [workflow_dispatch]
jobs: jobs:
build-jvm-macOS-M1-native-lib: build-jvm-macOS-M1-native-lib:
name: "Create M1 and x86_64 JVM native binaries" name: Create M1 and x86_64 JVM 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@v2
- name: Cache - name: Cache
@@ -24,9 +24,6 @@ jobs:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
- name: "Set default Rust version to 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
@@ -46,7 +43,7 @@ jobs:
build-jvm-full-library: build-jvm-full-library:
name: Create full bdk-jvm library name: Create full bdk-jvm library
needs: [build-jvm-macOS-M1-native-lib] needs: [build-jvm-macOS-M1-native-lib]
runs-on: ubuntu-20.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout publishing branch - name: Checkout publishing branch
uses: actions/checkout@v2 uses: actions/checkout@v2
@@ -71,9 +68,6 @@ jobs:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
- name: "Set default Rust version to 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

View File

@@ -8,8 +8,8 @@ on: [workflow_dispatch]
jobs: jobs:
build-manylinux2014-x86_64-wheel: build-manylinux2014-x86_64-wheel:
name: "Build Manylinux 2014 x86_64 wheel" name: 'Build Manylinux 2014 x86_64 wheel'
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
@@ -17,133 +17,127 @@ jobs:
image: quay.io/pypa/manylinux2014_x86_64 image: quay.io/pypa/manylinux2014_x86_64
env: env:
PLAT: manylinux2014_x86_64 PLAT: manylinux2014_x86_64
PYBIN: "/opt/python/${{ matrix.python }}/bin" PYBIN: '/opt/python/${{ matrix.python }}/bin'
strategy: strategy:
matrix: matrix:
python: # Update this list whenever the docker image is updated (check /opt/python/) python: # Update this list whenever the docker image is updated (check /opt/python/)
- cp36-cp36m
- cp37-cp37m
- cp38-cp38 - cp38-cp38
- cp39-cp39 - cp39-cp39
- cp310-cp310 - cp310-cp310
- pp37-pypy37_pp73
- pp38-pypy38_pp73
steps: steps:
- name: "Checkout" - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- uses: actions-rs/toolchain@v1 - uses: actions-rs/toolchain@v1
with: with:
toolchain: stable toolchain: stable
- name: install requirements
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install requirements"
run: ${PYBIN}/pip install -r requirements.txt run: ${PYBIN}/pip install -r requirements.txt
- name: generate bindings
- name: "Generate bdk.py"
run: bash generate.sh run: bash generate.sh
- name: build wheel
- name: "Build wheel" run: ${PYBIN}/pip wheel . --no-deps -w /tmp/wheelhouse
# Specifying the plat-name argument is necessary to build a wheel with the correct name, - name: repair wheel
# see issue #350 for more information run: auditwheel repair /tmp/wheelhouse/* --plat "$PLAT" -w /tmp/wheelhouse-repaired
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
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: /tmp/wheelhouse-repaired/*.whl
build-macos-universal-wheel: build-macos-universal-wheel:
name: "Build macOS universal wheel" name: 'Build macOS universal wheel'
runs-on: macos-12 runs-on: macos-latest
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
strategy: strategy:
matrix: matrix:
python: python:
- "3.8" - '3.7'
- "3.9" - '3.8'
- "3.10" - '3.9'
- '3.10'
steps: steps:
- name: "Checkout" - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2 - uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- run: python3 --version
- name: "Generate bdk.py" - run: rustup target add aarch64-apple-darwin
run: | - run: pip3 install --user -r requirements.txt
python3 --version - run: pip3 install --user wheel
rustup target add aarch64-apple-darwin - run: bash generate.sh
pip3 install --user -r requirements.txt - name: build wheel
bash generate.sh
- name: "Build wheel"
env: env:
ARCHFLAGS: "-arch x86_64 -arch arm64" ARCHFLAGS: "-arch x86_64 -arch arm64"
# Specifying the plat-name argument is necessary to build a wheel with the correct name, run: python3 setup.py -v bdist_wheel
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_12_0_universal2 --verbose
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
with: with:
name: bdkpython-macos-${{ matrix.python }} name: bdkpython-macos-${{ 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-windows-wheel:
name: "Build Windows wheel" name: 'Build windows wheel'
runs-on: windows-2022 runs-on: windows-latest
defaults: defaults:
run: run:
working-directory: bdk-python working-directory: bdk-python
strategy: strategy:
matrix: matrix:
python: python:
- "3.8" - '3.7'
- "3.9" - '3.8'
- "3.10" - '3.9'
- '3.10'
steps: steps:
- name: "Checkout" - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: true submodules: true
- uses: actions/setup-python@v2 - uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- run: python --version
- name: "Generate bdk.py" - run: pip install --user -r requirements.txt
run: | - run: bash generate.sh
python --version shell: bash
pip install --user -r requirements.txt - run: pip install --user wheel
bash generate.sh - name: build wheel
run: python setup.py -v bdist_wheel
- name: "Build wheel"
run: python setup.py bdist_wheel --verbose
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
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
publish-pypi: publish-pypi:
name: "Publish on PyPI" name: 'Publish on PyPI'
runs-on: ubuntu-20.04 runs-on: ubuntu-latest
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-wheel, build-macos-universal-wheel, build-windows-wheel]
# needs: [build-macos-universal-wheel]
steps: steps:
- name: "Checkout" - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: "Download artifacts in dist/ directory" - name: 'Download artifacts in dist/ directory'
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
with: with:
path: dist/ path: dist/
# - name: "Publish on test PyPI" # - name: Display structure of downloaded files
# run: ls -R
# - name: 'Publish on test PyPI'
# uses: pypa/gh-action-pypi-publish@release/v1 # uses: pypa/gh-action-pypi-publish@release/v1
# with: # with:
# user: __token__ # user: __token__
@@ -151,7 +145,7 @@ jobs:
# repository_url: https://test.pypi.org/legacy/ # repository_url: https://test.pypi.org/legacy/
# packages_dir: dist/*/ # packages_dir: dist/*/
- name: "Publish on PyPI" - name: 'Publish on PyPI'
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
with: with:
user: __token__ user: __token__

View File

@@ -1,6 +1,5 @@
name: Test Android name: Test Android
on: on:
workflow_dispatch:
push: push:
paths: paths:
- "bdk-ffi/**" - "bdk-ffi/**"
@@ -10,28 +9,26 @@ on:
- "bdk-ffi/**" - "bdk-ffi/**"
- "bdk-android/**" - "bdk-android/**"
# The default Android NDK on the ubuntu-22.04 image is 25.2.9519653
# We replace the default environment variable ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.2.9519653
# with an older version of the NDK (21.4.7075529) using the fix proposed here: https://github.com/actions/runner-images/issues/5930
# For information on why this is needed at the moment see issues #242 and #243, and PR #282
env: env:
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529 ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
# By default, the new ubuntu-20.04 images use the following ANDROID_NDK_ROOT
# ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.0.8775105
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- name: "Install Android NDK 21.4.7075529" - name: Install Android NDK 21.4.7075529
run: | run: |
ANDROID_ROOT=/usr/local/lib/android ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
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@v2
- name: "Cache" - name: cache
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: |
@@ -40,26 +37,16 @@ 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@v2
with: with:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
- name: "Set default Rust version to 1.67.0" - name: Install rust android targets
run: rustup default 1.67.0
- name: "Install Rust Android targets"
run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
- name: "Build Android library" - name: Run Android tests
run: | run: |
cd bdk-android cd bdk-android
./gradlew buildAndroidLib ./gradlew test --console=rich
# There are currently no unit tests for bdk-android and the integration tests require the macOS image
# which is not working with the older NDK version we are using, so for now we just make sure that the library builds.
# - name: "Run Android unit tests"
# run: |
# cd bdk-android
# ./gradlew test --console=rich

View File

@@ -1,6 +1,5 @@
name: Test Kotlin/JVM name: Test JVM
on: on:
workflow_dispatch:
push: push:
paths: paths:
- "bdk-ffi/**" - "bdk-ffi/**"
@@ -17,7 +16,7 @@ jobs:
- name: Check out PR branch - name: Check out PR branch
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Cache - name: cache
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: |
@@ -32,9 +31,6 @@ jobs:
distribution: temurin distribution: temurin
java-version: 11 java-version: 11
- name: "Set default Rust version to 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

View File

@@ -1,148 +0,0 @@
name: Test Python
on:
workflow_dispatch:
push:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
# makes it very hard to use GitHub's javascript actions (checkout, upload-artifact, etc).
# They mount their own nodejs interpreter inside your container, but since that's not statically linked it
# tries to load glibc and fails because it requires a more recent version.
jobs:
build-manylinux2014-x86_64-wheel:
name: "Build and test Manylinux 2014 x86_64 wheels"
runs-on: ubuntu-20.04
defaults:
run:
working-directory: bdk-python
container:
image: quay.io/pypa/manylinux2014_x86_64
env:
PLAT: manylinux2014_x86_64
PYBIN: "/opt/python/${{ matrix.python }}/bin"
strategy:
matrix:
python:
- cp38-cp38
- cp39-cp39
- cp310-cp310
steps:
- name: "Checkout"
uses: actions/checkout@v2
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install requirements"
run: ${PYBIN}/pip install -r requirements.txt
- name: "Generate bdk.py"
run: bash generate.sh
- name: "Build wheel"
run: ${PYBIN}/python setup.py bdist_wheel --verbose
- name: "Install wheel"
run: ${PYBIN}/pip install ./dist/*.whl
- name: "Run tests"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# 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"
uses: actions/upload-artifact@v2
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-universal-wheel:
name: "Build and test macOS wheels"
runs-on: macos-12
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: true
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py"
run: |
python3 --version
rustup target add aarch64-apple-darwin
pip3 install --user -r requirements.txt
bash generate.sh
- name: "Build wheel"
env:
ARCHFLAGS: "-arch x86_64 -arch arm64"
run: python3 setup.py bdist_wheel --verbose
- name: "Install wheel"
run: pip3 install ./dist/*.whl
- name: "Run tests"
run: python3 -m unittest tests/test_bdk.py --verbose
build-windows-wheel:
name: "Build and test Windows wheels"
runs-on: windows-2022
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v2
with:
submodules: true
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py"
run: |
python --version
pip install --user -r requirements.txt
bash generate.sh
- name: "Build wheel"
run: python setup.py bdist_wheel --verbose
# TODO: On Windows the pip install ./dist/*.whl step fails with the following error:
# Run pip install ./dist/*.whl
# WARNING: Requirement './dist/*.whl' looks like a filename, but the file does not exist
# ERROR: *.whl is not a valid wheel filename.*.whl is not a valid wheel name
# So we skip the installing and the tests and simply test that the wheel builds
# - name: Install wheel
# run: pip install ./dist/*.whl
# - name: Run tests
# run: python -m unittest tests/test_bdk.py --verbose

View File

@@ -1,6 +1,5 @@
name: Test Swift name: Test Swift
on: on:
workflow_dispatch:
push: push:
paths: paths:
- "bdk-ffi/**" - "bdk-ffi/**"
@@ -14,12 +13,9 @@ jobs:
build: build:
runs-on: macos-12 runs-on: macos-12
steps: steps:
- name: Checkout - name: Checkout branch
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: Install Rust targets - name: Install Rust targets
run: | run: |
rustup install nightly-x86_64-apple-darwin rustup install nightly-x86_64-apple-darwin
@@ -28,13 +24,13 @@ jobs:
- name: Run bdk-ffi-bindgen - name: Run bdk-ffi-bindgen
working-directory: bdk-ffi working-directory: bdk-ffi
run: cargo run --bin uniffi-bindgen generate src/bdk.udl --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit --no-format run: cargo run --package bdk-ffi-bindgen -- --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit
- name: Build bdk-ffi for x86_64-apple-darwin - name: Build bdk-ffi for x86_64-apple-darwin
run: cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-darwin run: cargo build --profile release-smaller --target x86_64-apple-darwin
- 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 --profile release-smaller --target aarch64-apple-darwin
- name: Create lipo-ios-sim and lipo-macos - name: Create lipo-ios-sim and lipo-macos
run: | run: |

View File

@@ -7,88 +7,7 @@ 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).
## [v0.27.1] ## [Unreleased]
- Update BDK to latest version 0.27.1 [#312]
- APIs changed
- `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296]
- `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296]
- APIs added
- New `Transaction` structure that can be created from or serialized to consensus encoded bytes. [#296]
- Add Wallet.get_internal_address() API [#304]
- Add `AddressIndex::Peek(index)` and `AddressIndex::Reset(index)` APIs [#305]
[#296]: https://github.com/bitcoindevkit/bdk-ffi/pull/296
[#304]: https://github.com/bitcoindevkit/bdk-ffi/pull/304
[#305]: https://github.com/bitcoindevkit/bdk-ffi/pull/305
[#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312
## [v0.26.0]
- Update BDK to latest version 0.26.0 [#288]
- APIs changed
- 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]
- APIs added
- Added RpcConfig, BlockchainConfig::Rpc, and Auth [#125]
- Added Descriptor type in [#260] with the following methods:
- Default constructor requires a descriptor in String format and a Network
- new_bip44 constructor returns a Descriptor with structure pkh(key/44'/{0,1}'/0'/{0,1}/*)
- new_bip44_public constructor returns a Descriptor with structure pkh(key/{0,1}/*)
- new_bip49 constructor returns a Descriptor with structure sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))
- new_bip49_public constructor returns a Descriptor with structure sh(wpkh(key/{0,1}/*))
- new_bip84 constructor returns a Descriptor with structure wpkh(key/84'/{0,1}'/0'/{0,1}/*)
- new_bip84_public constructor returns a Descriptor with structure wpkh(key/{0,1}/*)
- as_string returns the public version of the output descriptor
- as_string_private returns the private version of the output descriptor if available, otherwise return the public version
[#125]: https://github.com/bitcoindevkit/bdk-ffi/pull/125
[#260]: https://github.com/bitcoindevkit/bdk-ffi/pull/260
[#279]: https://github.com/bitcoindevkit/bdk-ffi/pull/279
[#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288
## [v0.25.0]
- Update BDK to latest version 0.25.0 [#272]
- APIs Added:
- from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]
[#247]: https://github.com/bitcoindevkit/bdk-ffi/pull/247
[#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272
## [v0.11.0]
- Update BDK to latest version 0.24.0 [#221]
- APIs changed
- The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String.
- APIs added
- Added Mnemonic struct [#219] with following methods:
- new(word_count: WordCount) generates and returns Mnemonic with random entropy
- from_string(mnemonic: String) converts string Mnemonic to Mnemonic type with error
- from_entropy(entropy: Vec<u8>) generates and returns Mnemonic with given entropy
- as_string() view Mnemonic as string
- APIs removed
- generate_mnemonic(word_count: WordCount)
[#219]: https://github.com/bitcoindevkit/bdk-ffi/pull/219
[#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221
## [v0.10.0]
- Update BDK to latest version 0.23.0 [#204]
- Update uniffi-rs to latest version 0.21.0 [#216]
- Breaking Changes
- Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209]
- `TxBuilder.add_recipient()` now takes a `Script` instead of an `Address` [#192]
- `AddressAmount` is now `ScriptAmount` [#192]
- APIs Added
- Added `TxBuilderResult` with PSBT and TransactionDetails [#209]
- `Address` and `Script` structs have been added [#192]
- Add `PartiallySignedBitcoinTransaction.extract_tx()` function [#192]
- Add `secret_bytes()` method on the `DescriptorSecretKey` [#199]
- Add `PartiallySignedBitcoinTransaction.combine()` method [#200]
[#192]: https://github.com/bitcoindevkit/bdk-ffi/pull/192
[#199]: https://github.com/bitcoindevkit/bdk-ffi/pull/199
[#200]: https://github.com/bitcoindevkit/bdk-ffi/pull/200
[#204]: https://github.com/bitcoindevkit/bdk-ffi/pull/204
[#209]: https://github.com/bitcoindevkit/bdk-ffi/pull/209
[#216]: https://github.com/bitcoindevkit/bdk-ffi/pull/216
## [v0.9.0] ## [v0.9.0]
- Breaking Changes - Breaking Changes
@@ -185,11 +104,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [v0.2.0] ## [v0.2.0]
[v0.27.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.26.0...v0.27.1 [unreleased]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.9.0...HEAD
[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.11.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.10.0...v0.11.0
[v0.10.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.9.0...v0.10.0
[v0.9.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.8.0...v0.9.0 [v0.9.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.8.0...v0.9.0
[v0.8.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.7.0...v0.8.0 [v0.8.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.7.0...v0.8.0
[v0.7.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.6.0...v0.7.0 [v0.7.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.6.0...v0.7.0

548
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[workspace] [workspace]
members = ["bdk-ffi"] members = ["bdk-ffi", "bdk-ffi-bindgen"]
default-members = ["bdk-ffi"] default-members = ["bdk-ffi", "bdk-ffi-bindgen"]
exclude = ["api-docs", "bdk-android", "bdk-jvm", "bdk-python", "bdk-swift"] exclude = ["api-docs", "bdk-android", "bdk-jvm", "bdk-python", "bdk-swift"]
[profile.release-smaller] [profile.release-smaller]

View File

@@ -8,7 +8,8 @@
</p> </p>
The workspace in this repository creates the `libbdkffi` multi-language library for the Rust-based The workspace in this repository creates the `libbdkffi` multi-language library for the Rust-based
[bdk] library from the [Bitcoin Dev Kit] project. [bdk] library from the [Bitcoin Dev Kit] project. The `bdk-ffi-bindgen` package builds a tool for
generating the actual language binding code used to access the `libbdkffi` library.
Each supported language and the platform(s) it's packaged for has its own directory. The Rust code in this project is in the bdk-ffi directory and is a wrapper around the [bdk] library to expose its APIs in a uniform way using the [mozilla/uniffi-rs] bindings generator for each supported target language. Each supported language and the platform(s) it's packaged for has its own directory. The Rust code in this project is in the bdk-ffi directory and is a wrapper around the [bdk] library to expose its APIs in a uniform way using the [mozilla/uniffi-rs] bindings generator for each supported target language.
@@ -22,6 +23,13 @@ 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] | |
## Language bindings generator tool
Use the `bdk-ffi-bindgen` tool to generate language binding code for the above supported languages.
To run `bdk-ffi-bindgen` and see the available options use the command:
```shell
cargo run -p bdk-ffi-bindgen -- --help
```
## Contributing ## Contributing
### Adding new structs and functions ### Adding new structs and functions

View File

@@ -24,14 +24,12 @@ enum class Network {
* *
* @property index Child index of this address. * @property index Child index of this address.
* @property address Address. * @property address Address.
* @property keychain Type of keychain.
* *
* @sample org.bitcoindevkit.addressInfoSample * @sample org.bitcoindevkit.addressInfoSample
*/ */
data class AddressInfo ( data class AddressInfo (
var index: UInt, var index: UInt,
var address: Address, var address: String
var keychain: KeychainKind
) )
/** /**
@@ -250,7 +248,6 @@ sealed class BlockchainConfig {
* @property confirmationTime If the transaction is confirmed, [BlockTime] contains height and timestamp of the block containing the transaction. This property is null for unconfirmed transactions. * @property confirmationTime If the transaction is confirmed, [BlockTime] contains height and timestamp of the block containing the transaction. This property is null for unconfirmed transactions.
*/ */
data class TransactionDetails ( data class TransactionDetails (
var transaction?: Transaction,
var fee: ULong?, var fee: ULong?,
var received: ULong, var received: ULong,
var sent: ULong, var sent: ULong,
@@ -291,60 +288,8 @@ class Blockchain(
* @param transactionBytes The transaction bytes, bitcoin consensus encoded. * @param transactionBytes The transaction bytes, bitcoin consensus encoded.
*/ */
class Transaction(transactionBytes: List<UByte>) { class Transaction(transactionBytes: List<UByte>) {
/** Computes the txid. */
fun txid(): String {}
/**
* Returns the "weight" of this transaction, as defined by BIP141.
*
* For transactions with an empty witness, this is simply the consensus-serialized size times four.
* For transactions with a witness, this is the non-witness consensus-serialized size multiplied by three
* plus the with-witness consensus-serialized size.
*/
fun weight(): ULong {}
/** Returns the regular byte-wise consensus-serialized size of this transaction. */
fun size(): ULong {}
/**
* Returns the "virtual size" (vsize) of this transaction.
*
* Will be ceil(weight / 4.0). Note this implements the virtual size as per BIP141, which is different to
* what is implemented in Bitcoin Core. The computation should be the same for any remotely sane transaction.
*/
fun vsize(): ULong {}
/** Return the transaction bytes, bitcoin consensus encoded. */ /** Return the transaction bytes, bitcoin consensus encoded. */
fun serialize(): List<UByte> {} fun serialize(): List<UByte> {}
/** Is this a coin base transaction? */
fun isCoinBase(): Boolean {}
/**
* Returns true if the transaction itself opted in to be BIP-125-replaceable (RBF).
* This does not cover the case where a transaction becomes replaceable due to ancestors being RBF.
*/
fun isExplicitlyRbf(): Boolean {}
/** Returns true if this transactions nLockTime is enabled (BIP-65). */
fun isLockTimeEnabled(): Boolean {}
/** The protocol version, is currently expected to be 1 or 2 (BIP 68). */
fun version(): Int {}
/**
* Block height or timestamp. Transaction cannot be included in a block until this height/time.
* Relevant BIPs
* BIP-65 OP_CHECKLOCKTIMEVERIFY
* BIP-113 Median time-past as endpoint for lock-time calculations
*/
fun lockTime(): UInt {}
/** List of transaction inputs. */
fun input(): List<TxIn> {}
/** List of transaction outputs. */
fun output(): List<TxOut> {}
} }
/** /**
@@ -369,9 +314,6 @@ class PartiallySignedTransaction(psbtBase64: String) {
* In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)` * In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
*/ */
fun combine(other: PartiallySignedTransaction): PartiallySignedTransaction fun combine(other: PartiallySignedTransaction): PartiallySignedTransaction
/** Serialize the PSBT data structure as a String of JSON. */
fun jsonSerialize(): String
} }
/** /**
@@ -389,29 +331,11 @@ data class OutPoint (
* A transaction output, which defines new coins to be created from old ones. * A transaction output, which defines new coins to be created from old ones.
* *
* @property value The value of the output, in satoshis. * @property value The value of the output, in satoshis.
* @property scriptPubkey The script which must be satisfied for the output to be spent. * @property address The address of the output.
*/ */
data class TxOut ( data class TxOut (
var value: ULong, var value: ULong,
var scriptPubkey: Script var address: String
)
/**
* Bitcoin transaction input.
*
* It contains the location of the previous transactions output, that it spends and set of scripts that satisfy its spending conditions.
*
* @property previousOutput The reference to the previous output that is being used an an input.
* @property scriptSig The script which pushes values on the stack which will cause the referenced outputs script to be accepted.
* @property sequence The sequence number, which suggests to miners which of two conflicting transactions should be preferred, or 0xFFFFFFFF to ignore this feature. This is generally never used since the miner behaviour cannot be enforced.
* @property witness Witness data: an array of byte-arrays. Note that this field is not (de)serialized with the rest of the TxIn in Encodable/Decodable, as it is (de)serialized at the end of the full Transaction. It is (de)serialized with the rest of the TxIn in other (de)serialization routines.
*
*/
data class TxIn (
var previousOutput: OutPoint,
var scriptSig: Script,
var sequence: UInt,
var witness: List<List<UByte>>
) )
/** /**
@@ -492,23 +416,11 @@ class Wallet(
/** 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 {}
/** /** Sign a transaction with all the wallets signers. */
* Sign a transaction with all the wallet's signers, in the order specified by every signer's fun sign(psbt: PartiallySignedTransaction): Boolean {}
* `SignerOrdering`.
*
* The `SignOptions` can be used to tweak the behavior of the software signers, and the way
* the transaction is finalized at the end. Note that it can't be guaranteed that *every*
* signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
* in this library will.
*
* @param psbt PSBT to be signed
* @param signOptions signing options
* @return true if the PSBT was finalized, or false otherwise
*/
fun sign(psbt: PartiallySignedTransaction, signOptions: SignOptions?): Boolean {}
/** Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually. */ /** Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually. */
fun listTransactions(includeRaw: Boolean): List<TransactionDetails> {} fun listTransactions(): List<TransactionDetails> {}
/** Get the Bitcoin network the wallet is using. */ /** Get the Bitcoin network the wallet is using. */
fun network(): Network {} fun network(): Network {}
@@ -613,29 +525,6 @@ class TxBuilder() {
fun finish(wallet: Wallet): TxBuilderResult {} fun finish(wallet: Wallet): TxBuilderResult {}
} }
/**
* Options for a software signer.
*
* Adjust the behavior of our software signers and the way a transaction is finalized.
*
* @property trustWitnessUtxo Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been provided. Defaults to `false`.
* @property assumeHeight Whether the wallet should assume a specific height has been reached when trying to finalize a transaction.
* @property allowAllSighashes Whether the signer should use the sighash_type set in the PSBT when signing, no matter what its value is. Defaults to `false`.
* @property removePartialSigs Whether to remove partial signatures from the PSBT inputs while finalizing PSBT. Defaults to `true`.
* @property tryFinalize Whether to try finalizing the PSBT after the inputs are signed. Defaults to `true`.
* @property signWithTapInternalKey Whether we should try to sign a taproot transaction with the taproot internal key or not. This option is ignored if we're signing a non-taproot PSBT. Defaults to `true`.
* @property allowGrinding Whether we should grind ECDSA signature to ensure signing with low r or not. Defaults to `true`.
*/
data class SignOptions (
var trustWitnessUtxo: Boolean,
var assumeHeight: UInt?,
var allowAllSighashes: Boolean,
var removePartialSigs: Boolean,
var tryFinalize: Boolean,
var signWithTapInternalKey: Boolean,
var allowGrinding: Boolean
)
/** /**
* A object holding a ScriptPubKey and an amount. * A object holding a ScriptPubKey and an amount.
* *
@@ -834,62 +723,8 @@ class Script(rawOutputScript: List<UByte>)
* @param address The address in string format. * @param address The address in string format.
*/ */
class Address(address: String) { class Address(address: String) {
/** Construct an [`Address`] from an output script. */
fun fromScript(script: Script, network: Network): Address {}
/** Return the Payload */
fun payload(): Payload
/** Return the Network. */
fun network(): Network
/** Return the ScriptPubKey. */ /** Return the ScriptPubKey. */
fun scriptPubkey(): Script fun scriptPubkey(): Script
/**
* Creates a URI string bitcoin:address optimized to be encoded in QR codes.
*
* If the address is bech32, both the schema and the address become uppercase. If the address is base58, the schema is lowercase and the address is left mixed case.
*
* Quoting BIP 173 "inside QR codes uppercase SHOULD be used, as those permit the use of alphanumeric mode, which is 45% more compact than the normal byte mode."
*/
fun toQrUri(): String
/** Return the address as a string. */
fun asString(): String
}}
/**
* The method used to produce an address.
*/
sealed class Payload {
/** P2PKH address. */
data class PubkeyHash(
val pubkeyHash: List<UByte>
) : Payload()
/** P2SH address. */
data class ScriptHash(
val scriptHash: List<UByte>
) : Payload()
/** Segwit address. */
data class WitnessProgram(
val version: WitnessVersion,
val program: List<UByte>
) : Payload()
}
/**
* Version of the witness program.
*
* Helps limit possible versions of the witness according to the specification. If a plain u8 type
* was used instead it would mean that the version may be > 16, which would be incorrect.
* First byte of scriptPubkey in transaction output for transactions starting with opcodes ranging
* from 0 to 16 (inclusive).
*/
enum class WitnessVersion {
V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16
} }
/** /**

View File

@@ -87,7 +87,7 @@ fun addressInfoSample() {
val newAddress: AddressInfo = wallet.getAddress(AddressIndex.New) val newAddress: AddressInfo = wallet.getAddress(AddressIndex.New)
println("New address at index ${newAddress.index} is ${newAddress.address.asString()}") println("New address at index ${newAddress.index} is ${newAddress.address}")
} }
fun blockchainSample() { fun blockchainSample() {

View File

@@ -19,8 +19,8 @@ import org.bitcoindevkit.*
// ... // ...
val externalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET) val externalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)", Network.TESTNET) val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
val databaseConfig = DatabaseConfig.Memory val databaseConfig = DatabaseConfig.Memory

View File

@@ -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.27.1

View File

@@ -54,7 +54,7 @@ class AndroidLibTest {
@Test @Test
fun memoryWalletNewAddress() { fun memoryWalletNewAddress() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig) val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val address = wallet.getAddress(AddressIndex.New).address.asString() val address = wallet.getAddress(AddressIndex.New).address
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address) assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address)
} }

View File

@@ -21,7 +21,8 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
val buildAndroidAarch64Binary by tasks.register<Exec>("buildAndroidAarch64Binary") { val buildAndroidAarch64Binary by tasks.register<Exec>("buildAndroidAarch64Binary") {
workingDir("${projectDir}/../../bdk-ffi") workingDir("${projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-linux-android") val cargoArgs: MutableList<String> =
mutableListOf("build", "--profile", "release-smaller", "--target", "aarch64-linux-android")
executable("cargo") executable("cargo")
args(cargoArgs) args(cargoArgs)
@@ -35,9 +36,10 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
environment( environment(
// add build toolchain to PATH // add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), Pair("PATH",
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"), "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("AR", "llvm-ar"),
Pair("CFLAGS", "-D__ANDROID_API__=21"),
Pair("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", "aarch64-linux-android21-clang"), Pair("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", "aarch64-linux-android21-clang"),
Pair("CC", "aarch64-linux-android21-clang") Pair("CC", "aarch64-linux-android21-clang")
) )
@@ -51,7 +53,8 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
val buildAndroidX86_64Binary by tasks.register<Exec>("buildAndroidX86_64Binary") { val buildAndroidX86_64Binary by tasks.register<Exec>("buildAndroidX86_64Binary") {
workingDir("${project.projectDir}/../../bdk-ffi") workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-linux-android") val cargoArgs: MutableList<String> =
mutableListOf("build", "--profile", "release-smaller", "--target", "x86_64-linux-android")
executable("cargo") executable("cargo")
args(cargoArgs) args(cargoArgs)
@@ -65,9 +68,10 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
environment( environment(
// add build toolchain to PATH // add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), Pair("PATH",
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"), "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("AR", "llvm-ar"),
Pair("CFLAGS", "-D__ANDROID_API__=21"),
Pair("CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER", "x86_64-linux-android21-clang"), Pair("CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER", "x86_64-linux-android21-clang"),
Pair("CC", "x86_64-linux-android21-clang") Pair("CC", "x86_64-linux-android21-clang")
) )
@@ -81,7 +85,8 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
val buildAndroidArmv7Binary by tasks.register<Exec>("buildAndroidArmv7Binary") { val buildAndroidArmv7Binary by tasks.register<Exec>("buildAndroidArmv7Binary") {
workingDir("${project.projectDir}/../../bdk-ffi") workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "armv7-linux-androideabi") val cargoArgs: MutableList<String> =
mutableListOf("build", "--profile", "release-smaller", "--target", "armv7-linux-androideabi")
executable("cargo") executable("cargo")
args(cargoArgs) args(cargoArgs)
@@ -95,10 +100,12 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
environment( environment(
// add build toolchain to PATH // add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"), Pair("PATH",
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"), "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("AR", "llvm-ar"),
Pair("CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER", "armv7a-linux-androideabi21-clang"), Pair("CFLAGS", "-D__ANDROID_API__=21"),
Pair("CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER",
"armv7a-linux-androideabi21-clang"),
Pair("CC", "armv7a-linux-androideabi21-clang") Pair("CC", "armv7a-linux-androideabi21-clang")
) )
@@ -138,10 +145,17 @@ internal class UniFfiAndroidPlugin : Plugin<Project> {
dependsOn(moveNativeAndroidLibs) dependsOn(moveNativeAndroidLibs)
workingDir("${project.projectDir}/../../bdk-ffi") workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("run", "--bin", "uniffi-bindgen", "generate", "src/bdk.udl", "--language", "kotlin", "--out-dir", "../bdk-android/lib/src/main/kotlin", "--no-format")
executable("cargo") executable("cargo")
args(cargoArgs) args(
"run",
"--package",
"bdk-ffi-bindgen",
"--",
"--language",
"kotlin",
"--out-dir",
"../bdk-android/lib/src/main/kotlin"
)
doLast { doLast {
println("Android bindings file successfully created") println("Android bindings file successfully created")

View File

@@ -0,0 +1,10 @@
[package]
name = "bdk-ffi-bindgen"
version = "0.2.0"
edition = "2021"
[dependencies]
anyhow = "1.0.45" # remove after upgrading to next version of uniffi
structopt = "0.3"
uniffi_bindgen = "0.21.0"
camino = "1.0.9"

138
bdk-ffi-bindgen/src/main.rs Normal file
View File

@@ -0,0 +1,138 @@
use camino::Utf8Path;
use std::fmt;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use structopt::StructOpt;
#[derive(Debug, Eq, PartialEq)]
pub enum Language {
Kotlin,
Python,
Swift,
}
impl fmt::Display for Language {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Language::Kotlin => write!(f, "kotlin"),
Language::Swift => write!(f, "swift"),
Language::Python => write!(f, "python"),
}
}
}
#[derive(Debug)]
pub enum Error {
UnsupportedLanguage,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl FromStr for Language {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"kotlin" => Ok(Language::Kotlin),
"python" => Ok(Language::Python),
"swift" => Ok(Language::Swift),
_ => Err(Error::UnsupportedLanguage),
}
}
}
fn generate_bindings(opt: &Opt) -> anyhow::Result<(), anyhow::Error> {
let path: &Utf8Path = Utf8Path::from_path(&opt.udl_file).unwrap();
let out_dir: &Utf8Path = Utf8Path::from_path(&opt.out_dir).unwrap();
uniffi_bindgen::generate_bindings(
path,
None,
vec![opt.language.to_string().as_str()],
Some(out_dir),
None,
false,
)?;
Ok(())
}
fn fixup_python_lib_path(
out_dir: &Path,
lib_name: &Path,
) -> Result<(), Box<dyn std::error::Error>> {
use std::fs;
use std::io::Write;
const LOAD_INDIRECT_DEF: &str = "def loadIndirect():";
let bindings_file = out_dir.join("bdk.py");
let mut data = fs::read_to_string(&bindings_file)?;
let pos = data
.find(LOAD_INDIRECT_DEF)
.unwrap_or_else(|| panic!("loadIndirect not found in `{}`", bindings_file.display()));
let range = pos..pos + LOAD_INDIRECT_DEF.len();
let replacement = format!(
r#"
def loadIndirect():
import glob
return getattr(ctypes.cdll, glob.glob(os.path.join(os.path.dirname(os.path.abspath(__file__)), '{}.*'))[0])
def _loadIndirectOld():"#,
&lib_name.to_str().expect("lib name")
);
data.replace_range(range, &replacement);
let mut file = fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(&bindings_file)?;
file.write_all(data.as_bytes())?;
Ok(())
}
#[derive(Debug, StructOpt)]
#[structopt(
name = "bdk-ffi-bindgen",
about = "A tool to generate bdk-ffi language bindings"
)]
struct Opt {
/// UDL file
#[structopt(env = "BDKFFI_BINDGEN_UDL", short, long, default_value("src/bdk.udl"), parse(try_from_str = PathBuf::from_str))]
udl_file: PathBuf,
/// Language to generate bindings for
#[structopt(env = "BDKFFI_BINDGEN_LANGUAGE", short, long, possible_values(&["kotlin","swift","python"]), parse(try_from_str = Language::from_str))]
language: Language,
/// Output directory to put generated language bindings
#[structopt(env = "BDKFFI_BINDGEN_OUTPUT_DIR", short, long, parse(try_from_str = PathBuf::from_str))]
out_dir: PathBuf,
/// Python fix up lib path
#[structopt(env = "BDKFFI_BINDGEN_PYTHON_FIXUP_PATH", short, long, parse(try_from_str = PathBuf::from_str))]
python_fixup_path: Option<PathBuf>,
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let opt = Opt::from_args();
println!("Input UDL file is {:?}", opt.udl_file);
println!("Chosen language is {}", opt.language);
println!("Output directory is {:?}", opt.out_dir);
generate_bindings(&opt)?;
if opt.language == Language::Python {
if let Some(path) = opt.python_fixup_path {
println!("Fixing up python lib path, {:?}", &path);
fixup_python_lib_path(&opt.out_dir, &path)?;
}
}
Ok(())
}

View File

@@ -1,30 +1,21 @@
[package] [package]
name = "bdk-ffi" name = "bdk-ffi"
version = "0.28.0" version = "0.27.0"
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 = ["staticlib", "cdylib"]
#crate-type = ["staticlib", "cdylib"]
#crate-type = ["cdylib"]
name = "bdkffi" name = "bdkffi"
[[bin]]
name = "uniffi-bindgen"
path = "uniffi-bindgen.rs"
[features]
default = ["uniffi/cli"]
[dependencies] [dependencies]
bdk = { version = "0.28", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] } bdk = { version = "0.27.1", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled", "rpc"] }
uniffi = { version = "0.23.0" } uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] }
uniffi = { version = "0.21.0", features = ["builtin-bindgen"] }
[build-dependencies] [build-dependencies]
uniffi = { version = "0.23.0", features = ["build"] } uniffi_build = { version = "0.21.0", features = ["builtin-bindgen"] }
[dev-dependencies] [dev-dependencies]
uniffi = { version = "0.23.0", features = ["bindgen-tests"] }
assert_matches = "1.5.0" assert_matches = "1.5.0"

View File

@@ -1,3 +1,3 @@
fn main() { fn main() {
uniffi::generate_scaffolding("./src/bdk.udl").unwrap(); uniffi_build::generate_scaffolding("src/bdk.udl").unwrap();
} }

View File

@@ -50,8 +50,7 @@ enum BdkError {
dictionary AddressInfo { dictionary AddressInfo {
u32 index; u32 index;
Address address; string address;
KeychainKind keychain;
}; };
[Enum] [Enum]
@@ -95,7 +94,6 @@ interface DatabaseConfig {
}; };
dictionary TransactionDetails { dictionary TransactionDetails {
Transaction? transaction;
u64? fee; u64? fee;
u64 received; u64 received;
u64 sent; u64 sent;
@@ -188,16 +186,9 @@ dictionary OutPoint {
u32 vout; u32 vout;
}; };
dictionary TxIn {
OutPoint previous_output;
Script script_sig;
u32 sequence;
sequence<sequence<u8>> witness;
};
dictionary TxOut { dictionary TxOut {
u64 value; u64 value;
Script script_pubkey; string address;
}; };
enum KeychainKind { enum KeychainKind {
@@ -231,10 +222,10 @@ interface Wallet {
Balance get_balance(); Balance get_balance();
[Throws=BdkError] [Throws=BdkError]
boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options); boolean sign([ByRef] PartiallySignedTransaction psbt);
[Throws=BdkError] [Throws=BdkError]
sequence<TransactionDetails> list_transactions(boolean include_raw); sequence<TransactionDetails> list_transactions();
Network network(); Network network();
@@ -252,43 +243,11 @@ interface FeeRate {
float as_sat_per_vb(); float as_sat_per_vb();
}; };
dictionary SignOptions {
boolean trust_witness_utxo;
u32? assume_height;
boolean allow_all_sighashes;
boolean remove_partial_sigs;
boolean try_finalize;
boolean sign_with_tap_internal_key;
boolean allow_grinding;
};
interface Transaction { interface Transaction {
[Throws=BdkError] [Throws=BdkError]
constructor(sequence<u8> transaction_bytes); constructor(sequence<u8> transaction_bytes);
string txid(); sequence<u8> serialize();
u64 weight();
u64 size();
u64 vsize();
sequence<u8> serialize();
boolean is_coin_base();
boolean is_explicitly_rbf();
boolean is_lock_time_enabled();
i32 version();
u32 lock_time();
sequence<TxIn> input();
sequence<TxOut> output();
}; };
interface PartiallySignedTransaction { interface PartiallySignedTransaction {
@@ -307,8 +266,6 @@ interface PartiallySignedTransaction {
u64? fee_amount(); u64? fee_amount();
FeeRate? fee_rate(); FeeRate? fee_rate();
string json_serialize();
}; };
dictionary TxBuilderResult { dictionary TxBuilderResult {
@@ -448,47 +405,7 @@ interface Address {
[Throws=BdkError] [Throws=BdkError]
constructor(string address); constructor(string address);
[Name=from_script, Throws=BdkError]
constructor(Script script, Network network);
Payload payload();
Network network();
Script script_pubkey(); Script script_pubkey();
string to_qr_uri();
string as_string();
};
[Enum]
interface Payload {
PubkeyHash(sequence<u8> pubkey_hash);
ScriptHash(sequence<u8> script_hash);
WitnessProgram(WitnessVersion version, sequence<u8> program);
};
enum WitnessVersion {
"V0",
"V1",
"V2",
"V3",
"V4",
"V5",
"V6",
"V7",
"V8",
"V9",
"V10",
"V11",
"V12",
"V13",
"V14",
"V15",
"V16"
}; };
interface Script { interface Script {

View File

@@ -13,14 +13,10 @@ use crate::descriptor::Descriptor;
use crate::keys::DerivationPath; use crate::keys::DerivationPath;
use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic}; use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::psbt::PartiallySignedTransaction; use crate::psbt::PartiallySignedTransaction;
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::blockdata::script::Script as BdkScript;
use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn;
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::Decodable; use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::psbt::serialize::Serialize; use bdk::bitcoin::psbt::serialize::Serialize;
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, Network, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
}; };
@@ -29,17 +25,14 @@ use bdk::database::any::{SledDbConfiguration, 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;
use bdk::LocalUtxo as BdkLocalUtxo;
use bdk::TransactionDetails as BdkTransactionDetails;
use bdk::{Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind}; use bdk::{Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind};
use std::convert::From; use std::convert::From;
use std::fmt; use std::fmt;
use std::fmt::Debug;
use std::io::Cursor; use std::io::Cursor;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
uniffi::include_scaffolding!("bdk"); uniffi_macros::include_scaffolding!("bdk");
/// A output script and an amount of satoshis. /// A output script and an amount of satoshis.
pub struct ScriptAmount { pub struct ScriptAmount {
@@ -49,20 +42,17 @@ pub struct ScriptAmount {
/// A derived address and the index it was found at. /// A derived address and the index it was found at.
pub struct AddressInfo { pub struct AddressInfo {
/// Child index of this address. /// Child index of this address
pub index: u32, pub index: u32,
/// Address. /// Address
pub address: Arc<Address>, pub address: String,
/// Type of keychain.
pub keychain: KeychainKind,
} }
impl From<BdkAddressInfo> for AddressInfo { impl From<BdkAddressInfo> for AddressInfo {
fn from(address_info: BdkAddressInfo) -> Self { fn from(x: bdk::wallet::AddressInfo) -> AddressInfo {
AddressInfo { AddressInfo {
index: address_info.index, index: x.index,
address: Arc::new(Address::from(address_info.address)), address: x.address.to_string(),
keychain: address_info.keychain,
} }
} }
} }
@@ -89,14 +79,14 @@ pub enum AddressIndex {
/// Use with caution, if an index is given that is less than the current descriptor index /// Use with caution, if an index is given that is less than the current descriptor index
/// then the returned address and subsequent addresses returned by calls to `AddressIndex::New` /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
/// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
/// value earlier than the [`Blockchain`] stop_gap (default is 20) then a /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a
/// larger stop_gap should be used to monitor for all possibly used addresses. /// larger stop_gap should be used to monitor for all possibly used addresses.
Reset { index: u32 }, Reset { index: u32 },
} }
impl From<AddressIndex> for BdkAddressIndex { impl From<AddressIndex> for BdkAddressIndex {
fn from(address_index: AddressIndex) -> Self { fn from(x: AddressIndex) -> BdkAddressIndex {
match address_index { match x {
AddressIndex::New => BdkAddressIndex::New, AddressIndex::New => BdkAddressIndex::New,
AddressIndex::LastUnused => BdkAddressIndex::LastUnused, AddressIndex::LastUnused => BdkAddressIndex::LastUnused,
AddressIndex::Peek { index } => BdkAddressIndex::Peek(index), AddressIndex::Peek { index } => BdkAddressIndex::Peek(index),
@@ -108,7 +98,6 @@ impl From<AddressIndex> for BdkAddressIndex {
/// A wallet transaction /// A wallet transaction
#[derive(Debug, Clone, PartialEq, Eq, Default)] #[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TransactionDetails { pub struct TransactionDetails {
pub transaction: Option<Arc<Transaction>>,
/// Transaction id. /// Transaction id.
pub txid: String, pub txid: String,
/// Received value (sats) /// Received value (sats)
@@ -127,18 +116,14 @@ pub struct TransactionDetails {
pub confirmation_time: Option<BlockTime>, pub confirmation_time: Option<BlockTime>,
} }
impl From<BdkTransactionDetails> for TransactionDetails { impl From<&bdk::TransactionDetails> for TransactionDetails {
fn from(tx_details: BdkTransactionDetails) -> Self { fn from(x: &bdk::TransactionDetails) -> TransactionDetails {
let optional_tx: Option<Arc<Transaction>> =
tx_details.transaction.map(|tx| Arc::new(tx.into()));
TransactionDetails { TransactionDetails {
transaction: optional_tx, fee: x.fee,
fee: tx_details.fee, txid: x.txid.to_string(),
txid: tx_details.txid.to_string(), received: x.received,
received: tx_details.received, sent: x.sent,
sent: tx_details.sent, confirmation_time: x.confirmation_time.clone(),
confirmation_time: tx_details.confirmation_time,
} }
} }
} }
@@ -153,10 +138,10 @@ pub struct OutPoint {
} }
impl From<&OutPoint> for BdkOutPoint { impl From<&OutPoint> for BdkOutPoint {
fn from(outpoint: &OutPoint) -> Self { fn from(x: &OutPoint) -> BdkOutPoint {
BdkOutPoint { BdkOutPoint {
txid: Txid::from_str(&outpoint.txid).unwrap(), txid: Txid::from_str(&x.txid).unwrap(),
vout: outpoint.vout, vout: x.vout,
} }
} }
} }
@@ -190,23 +175,11 @@ impl From<BdkBalance> for Balance {
} }
/// A transaction output, which defines new coins to be created from old ones. /// A transaction output, which defines new coins to be created from old ones.
#[derive(Debug, Clone)]
pub struct TxOut { pub struct TxOut {
/// The value of the output, in satoshis. /// The value of the output, in satoshis.
value: u64, value: u64,
/// The address of the output. /// The address of the output.
script_pubkey: Arc<Script>, address: String,
}
impl From<&BdkTxOut> for TxOut {
fn from(tx_out: &BdkTxOut) -> Self {
TxOut {
value: tx_out.value,
script_pubkey: Arc::new(Script {
script: tx_out.script_pubkey.clone(),
}),
}
}
} }
pub struct LocalUtxo { pub struct LocalUtxo {
@@ -216,21 +189,27 @@ pub struct LocalUtxo {
is_spent: bool, is_spent: bool,
} }
impl From<BdkLocalUtxo> for LocalUtxo { // This trait is used to convert the bdk TxOut type with field `script_pubkey: Script`
fn from(local_utxo: BdkLocalUtxo) -> Self { // into the bdk-ffi TxOut type which has a field `address: String` instead
trait NetworkLocalUtxo {
fn from_utxo(x: &bdk::LocalUtxo, network: Network) -> LocalUtxo;
}
impl NetworkLocalUtxo for LocalUtxo {
fn from_utxo(x: &bdk::LocalUtxo, network: Network) -> LocalUtxo {
LocalUtxo { LocalUtxo {
outpoint: OutPoint { outpoint: OutPoint {
txid: local_utxo.outpoint.txid.to_string(), txid: x.outpoint.txid.to_string(),
vout: local_utxo.outpoint.vout, vout: x.outpoint.vout,
}, },
txout: TxOut { txout: TxOut {
value: local_utxo.txout.value, value: x.txout.value,
script_pubkey: Arc::new(Script { address: BdkAddress::from_script(&x.txout.script_pubkey, network)
script: local_utxo.txout.script_pubkey, .unwrap()
}), .to_string(),
}, },
keychain: local_utxo.keychain, keychain: x.keychain,
is_spent: local_utxo.is_spent, is_spent: x.is_spent,
} }
} }
} }
@@ -253,38 +232,14 @@ impl BdkProgress for ProgressHolder {
} }
} }
impl Debug for ProgressHolder { impl fmt::Debug for ProgressHolder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ProgressHolder").finish_non_exhaustive() f.debug_struct("ProgressHolder").finish_non_exhaustive()
} }
} }
#[derive(Debug, Clone)]
pub struct TxIn {
pub previous_output: OutPoint,
pub script_sig: Arc<Script>,
pub sequence: u32,
pub witness: Vec<Vec<u8>>,
}
impl From<&BdkTxIn> for TxIn {
fn from(tx_in: &BdkTxIn) -> Self {
TxIn {
previous_output: OutPoint {
txid: tx_in.previous_output.txid.to_string(),
vout: tx_in.previous_output.vout,
},
script_sig: Arc::new(Script {
script: tx_in.script_sig.clone(),
}),
sequence: tx_in.sequence.0,
witness: tx_in.witness.to_vec(),
}
}
}
/// A Bitcoin transaction. /// A Bitcoin transaction.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug)]
pub struct Transaction { pub struct Transaction {
internal: BdkTransaction, internal: BdkTransaction,
} }
@@ -296,64 +251,13 @@ impl Transaction {
Ok(Transaction { internal: tx }) Ok(Transaction { internal: tx })
} }
fn txid(&self) -> String {
self.internal.txid().to_string()
}
fn weight(&self) -> u64 {
self.internal.weight() as u64
}
fn size(&self) -> u64 {
self.internal.size() as u64
}
fn vsize(&self) -> u64 {
self.internal.vsize() as u64
}
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {
self.internal.serialize() self.internal.serialize()
} }
fn is_coin_base(&self) -> bool {
self.internal.is_coin_base()
}
fn is_explicitly_rbf(&self) -> bool {
self.internal.is_explicitly_rbf()
}
fn is_lock_time_enabled(&self) -> bool {
self.internal.is_lock_time_enabled()
}
fn version(&self) -> i32 {
self.internal.version
}
fn lock_time(&self) -> u32 {
self.internal.lock_time.0
}
fn input(&self) -> Vec<TxIn> {
self.internal.input.iter().map(|x| x.into()).collect()
}
fn output(&self) -> Vec<TxOut> {
self.internal.output.iter().map(|x| x.into()).collect()
}
}
impl From<BdkTransaction> for Transaction {
fn from(tx: BdkTransaction) -> Self {
Transaction { internal: tx }
}
} }
/// A Bitcoin address. /// A Bitcoin address.
#[derive(Debug, PartialEq, Eq)] struct Address {
pub struct Address {
address: BdkAddress, address: BdkAddress,
} }
@@ -364,67 +268,11 @@ impl Address {
.map_err(|e| BdkError::Generic(e.to_string())) .map_err(|e| BdkError::Generic(e.to_string()))
} }
/// alternative constructor
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
BdkAddress::from_script(&script.script, network)
.map(|a| Address { address: a })
.map_err(|e| BdkError::Generic(e.to_string()))
}
fn payload(&self) -> Payload {
match &self.address.payload.clone() {
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
pubkey_hash: pubkey_hash.to_vec(),
},
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
script_hash: script_hash.to_vec(),
},
BdkPayload::WitnessProgram { version, program } => Payload::WitnessProgram {
version: *version,
program: program.clone(),
},
}
}
fn network(&self) -> Network {
self.address.network
}
fn script_pubkey(&self) -> Arc<Script> { fn script_pubkey(&self) -> Arc<Script> {
Arc::new(Script { Arc::new(Script {
script: self.address.script_pubkey(), script: self.address.script_pubkey(),
}) })
} }
fn to_qr_uri(&self) -> String {
self.address.to_qr_uri()
}
fn as_string(&self) -> String {
self.address.to_string()
}
}
impl From<BdkAddress> for Address {
fn from(address: BdkAddress) -> Self {
Address { address }
}
}
/// The method used to produce an address.
#[derive(Debug)]
pub enum Payload {
/// P2PKH address.
PubkeyHash { pubkey_hash: Vec<u8> },
/// P2SH address.
ScriptHash { script_hash: Vec<u8> },
/// Segwit address.
WitnessProgram {
/// The witness program version.
version: WitnessVersion,
/// The witness program.
program: Vec<u8>,
},
} }
/// A Bitcoin script. /// A Bitcoin script.
@@ -440,12 +288,6 @@ impl 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,
@@ -467,11 +309,7 @@ uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::Transaction; use super::Transaction;
use crate::Network::Regtest;
use crate::{Address, Payload};
use assert_matches::assert_matches;
use bdk::bitcoin::hashes::hex::FromHex; use bdk::bitcoin::hashes::hex::FromHex;
use bdk::bitcoin::util::address::WitnessVersion;
// 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]
@@ -481,17 +319,4 @@ mod test {
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.
#[test]
fn test_address_witness_program() {
let address =
Address::new("bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string()).unwrap();
let payload = address.payload();
assert_matches!(payload, Payload::WitnessProgram { version, program } => {
assert_eq!(version,WitnessVersion::V0);
assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
});
assert_eq!(address.network(), Regtest);
}
} }

View File

@@ -1,8 +1,6 @@
use bdk::bitcoin::hashes::hex::ToHex; use bdk::bitcoin::hashes::hex::ToHex;
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction; use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoincore_rpc::jsonrpc::serde_json;
use bdk::psbt::PsbtUtils; use bdk::psbt::PsbtUtils;
use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@@ -36,7 +34,7 @@ impl PartiallySignedTransaction {
/// 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.internal.lock().unwrap().clone().extract_tx();
Arc::new(tx.into()) Arc::new(Transaction { internal: tx })
} }
/// Combines this PartiallySignedTransaction with other PSBT as described by BIP 174. /// Combines this PartiallySignedTransaction with other PSBT as described by BIP 174.
@@ -68,12 +66,6 @@ impl PartiallySignedTransaction {
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.internal.lock().unwrap().fee_rate().map(Arc::new)
} }
/// Serialize the PSBT data structure as a String of JSON.
pub(crate) fn json_serialize(&self) -> String {
let psbt = self.internal.lock().unwrap();
serde_json::to_string(psbt.deref()).unwrap()
}
} }
// 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.

View File

@@ -3,10 +3,7 @@ use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Sequ
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;
use bdk::{ use bdk::{FeeRate, SignOptions, SyncOptions as BdkSyncOptions, Wallet as BdkWallet};
FeeRate, LocalUtxo as BdkLocalUtxo, SignOptions as BdkSignOptions,
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
};
use std::collections::HashSet; use std::collections::HashSet;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use std::str::FromStr;
@@ -17,8 +14,8 @@ use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor; use crate::descriptor::Descriptor;
use crate::psbt::PartiallySignedTransaction; use crate::psbt::PartiallySignedTransaction;
use crate::{ use crate::{
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder, AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, NetworkLocalUtxo, OutPoint, Progress,
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult, ProgressHolder, RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
}; };
#[derive(Debug)] #[derive(Debug)]
@@ -113,34 +110,17 @@ impl Wallet {
self.get_wallet().get_balance().map(|b| b.into()) self.get_wallet().get_balance().map(|b| b.into())
} }
/// Sign a transaction with all the wallet's signers, in the order specified by every signer's /// Sign a transaction with all the wallets signers.
/// [`SignerOrdering`]. This function returns the `Result` type with an encapsulated `bool` that pub(crate) fn sign(&self, psbt: &PartiallySignedTransaction) -> Result<bool, BdkError> {
/// has the value true if the PSBT was finalized, or false otherwise.
///
/// The [`SignOptions`] can be used to tweak the behavior of the software signers, and the way
/// the transaction is finalized at the end. Note that it can't be guaranteed that *every*
/// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
/// in this library will.
pub(crate) fn sign(
&self,
psbt: &PartiallySignedTransaction,
sign_options: Option<SignOptions>,
) -> Result<bool, BdkError> {
let mut psbt = psbt.internal.lock().unwrap(); let mut psbt = psbt.internal.lock().unwrap();
self.get_wallet().sign( self.get_wallet().sign(&mut psbt, SignOptions::default())
&mut psbt,
sign_options.map(SignOptions::into).unwrap_or_default(),
)
} }
/// Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually. /// Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually.
pub(crate) fn list_transactions( pub(crate) fn list_transactions(&self) -> Result<Vec<TransactionDetails>, BdkError> {
&self, let transaction_details = self.get_wallet().list_transactions(true)?;
include_raw: bool,
) -> Result<Vec<TransactionDetails>, BdkError> {
let transaction_details = self.get_wallet().list_transactions(include_raw)?;
Ok(transaction_details Ok(transaction_details
.into_iter() .iter()
.map(TransactionDetails::from) .map(TransactionDetails::from)
.collect()) .collect())
} }
@@ -148,83 +128,11 @@ impl Wallet {
/// Return the list of unspent outputs of this wallet. Note that this method only operates on the internal database, /// Return the list of unspent outputs of this wallet. Note that this method only operates on the internal database,
/// which first needs to be Wallet.sync manually. /// which first needs to be Wallet.sync manually.
pub(crate) fn list_unspent(&self) -> Result<Vec<LocalUtxo>, BdkError> { pub(crate) fn list_unspent(&self) -> Result<Vec<LocalUtxo>, BdkError> {
let unspents: Vec<BdkLocalUtxo> = self.get_wallet().list_unspent()?; let unspents = self.get_wallet().list_unspent()?;
Ok(unspents.into_iter().map(LocalUtxo::from).collect()) Ok(unspents
} .iter()
} .map(|u| LocalUtxo::from_utxo(u, self.network()))
.collect())
/// Options for a software signer
///
/// Adjust the behavior of our software signers and the way a transaction is finalized
#[derive(Debug, Clone, Default)]
pub struct SignOptions {
/// Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been
/// provided
///
/// Defaults to `false` to mitigate the "SegWit bug" which should trick the wallet into
/// paying a fee larger than expected.
///
/// Some wallets, especially if relatively old, might not provide the `non_witness_utxo` for
/// SegWit transactions in the PSBT they generate: in those cases setting this to `true`
/// should correctly produce a signature, at the expense of an increased trust in the creator
/// of the PSBT.
///
/// For more details see: <https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd>
pub trust_witness_utxo: bool,
/// Whether the wallet should assume a specific height has been reached when trying to finalize
/// a transaction
///
/// The wallet will only "use" a timelock to satisfy the spending policy of an input if the
/// timelock height has already been reached. This option allows overriding the "current height" to let the
/// wallet use timelocks in the future to spend a coin.
pub assume_height: Option<u32>,
/// Whether the signer should use the `sighash_type` set in the PSBT when signing, no matter
/// what its value is
///
/// Defaults to `false` which will only allow signing using `SIGHASH_ALL`.
pub allow_all_sighashes: bool,
/// Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.
///
/// Defaults to `true` which will remove partial signatures during finalization.
pub remove_partial_sigs: bool,
/// Whether to try finalizing the PSBT after the inputs are signed.
///
/// Defaults to `true` which will try finalizing PSBT after inputs are signed.
pub try_finalize: bool,
// Specifies which Taproot script-spend leaves we should sign for. This option is
// ignored if we're signing a non-taproot PSBT.
//
// Defaults to All, i.e., the wallet will sign all the leaves it has a key for.
// TODO pub tap_leaves_options: TapLeavesOptions,
/// Whether we should try to sign a taproot transaction with the taproot internal key
/// or not. This option is ignored if we're signing a non-taproot PSBT.
///
/// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
pub sign_with_tap_internal_key: bool,
/// Whether we should grind ECDSA signature to ensure signing with low r
/// or not.
/// Defaults to `true`, i.e., we always grind ECDSA signature to sign with low r.
pub allow_grinding: bool,
}
impl From<SignOptions> for BdkSignOptions {
fn from(sign_options: SignOptions) -> Self {
BdkSignOptions {
trust_witness_utxo: sign_options.trust_witness_utxo,
assume_height: sign_options.assume_height,
allow_all_sighashes: sign_options.allow_all_sighashes,
remove_partial_sigs: sign_options.remove_partial_sigs,
try_finalize: sign_options.try_finalize,
tap_leaves_options: Default::default(),
sign_with_tap_internal_key: sign_options.sign_with_tap_internal_key,
allow_grinding: sign_options.allow_grinding,
}
} }
} }
@@ -465,7 +373,7 @@ impl TxBuilder {
psbt: Arc::new(PartiallySignedTransaction { psbt: Arc::new(PartiallySignedTransaction {
internal: Mutex::new(psbt), internal: Mutex::new(psbt),
}), }),
transaction_details: TransactionDetails::from(tx_details), transaction_details: TransactionDetails::from(&tx_details),
}) })
} }
} }
@@ -655,8 +563,7 @@ mod test {
wallet wallet
.get_address(AddressIndex::Peek { index: 2 }) .get_address(AddressIndex::Peek { index: 2 })
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj" "bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj"
); );
@@ -664,38 +571,34 @@ mod test {
wallet wallet
.get_address(AddressIndex::Peek { index: 1 }) .get_address(AddressIndex::Peek { index: 1 })
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
// new index still 0 // new index still 0
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::New) .get_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv" "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
); );
// new index now 1 // new index now 1
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::New) .get_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
// new index now 2 // new index now 2
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::New) .get_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj" "bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj"
); );
@@ -704,8 +607,7 @@ mod test {
wallet wallet
.get_address(AddressIndex::Peek { index: 1 }) .get_address(AddressIndex::Peek { index: 1 })
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
@@ -714,18 +616,13 @@ mod test {
wallet wallet
.get_address(AddressIndex::Reset { index: 0 }) .get_address(AddressIndex::Reset { index: 0 })
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv" "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
); );
// new index 1 again // new index 1 again
assert_eq!( assert_eq!(
wallet wallet.get_address(AddressIndex::New).unwrap().address,
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
} }
@@ -750,55 +647,49 @@ mod test {
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::New) .get_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv" "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
); );
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::New) .get_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
assert_eq!( assert_eq!(
wallet wallet
.get_address(AddressIndex::LastUnused) .get_address(crate::AddressIndex::LastUnused)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a" "bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
); );
assert_eq!( assert_eq!(
wallet wallet
.get_internal_address(AddressIndex::New) .get_internal_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qpmz73cyx00r4a5dea469j40ax6d6kqyd67nnpj" "bcrt1qpmz73cyx00r4a5dea469j40ax6d6kqyd67nnpj"
); );
assert_eq!( assert_eq!(
wallet wallet
.get_internal_address(AddressIndex::New) .get_internal_address(crate::AddressIndex::New)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k" "bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
); );
assert_eq!( assert_eq!(
wallet wallet
.get_internal_address(AddressIndex::LastUnused) .get_internal_address(crate::AddressIndex::LastUnused)
.unwrap() .unwrap()
.address .address,
.as_string(),
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k" "bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
); );
} }

View File

@@ -6,5 +6,10 @@ class TestBdk(unittest.TestCase):
def test_some_enum(self): def test_some_enum(self):
network = Network.TESTNET network = Network.TESTNET
def test_some_dict(self):
a = AddressInfo(index=42, address="testaddress")
self.assertEqual(42, a.index)
self.assertEqual("testaddress", a.address)
if __name__=='__main__': if __name__=='__main__':
unittest.main() unittest.main()

View File

@@ -1,5 +1,8 @@
uniffi::build_foreign_language_testcases!( uniffi_macros::build_foreign_language_testcases!(
"tests/bindings/test.kts", ["src/bdk.udl",],
"tests/bindings/test.swift", [
"tests/bindings/test.py", "tests/bindings/test.kts",
"tests/bindings/test.swift",
"tests/bindings/test.py"
]
); );

View File

@@ -1,3 +0,0 @@
fn main() {
uniffi::uniffi_bindgen_main()
}

View File

@@ -19,8 +19,8 @@ import org.bitcoindevkit.*
// ... // ...
val externalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET) val externalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)", Network.TESTNET) val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
val databaseConfig = DatabaseConfig.Memory val databaseConfig = DatabaseConfig.Memory

View File

@@ -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.27.1

View File

@@ -46,7 +46,7 @@ class JvmLibTest {
@Test @Test
fun memoryWalletNewAddress() { fun memoryWalletNewAddress() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig) val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val address = wallet.getAddress(AddressIndex.New).address.asString() val address = wallet.getAddress(AddressIndex.New).address
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address) assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address)
} }

View File

@@ -90,10 +90,17 @@ internal class UniFfiJvmPlugin : Plugin<Project> {
dependsOn(moveNativeJvmLibs) dependsOn(moveNativeJvmLibs)
workingDir("${project.projectDir}/../../bdk-ffi") workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("run", "--bin", "uniffi-bindgen", "generate", "src/bdk.udl", "--language", "kotlin", "--out-dir", "../bdk-jvm/lib/src/main/kotlin", "--no-format")
executable("cargo") executable("cargo")
args(cargoArgs) args(
"run",
"--package",
"bdk-ffi-bindgen",
"--",
"--language",
"kotlin",
"--out-dir",
"../bdk-jvm/lib/src/main/kotlin"
)
doLast { doLast {
println("JVM bindings file successfully created") println("JVM bindings file successfully created")

View File

@@ -1,2 +0,0 @@
include ./src/bdkpython/libbdkffi.dylib
include ./src/bdkpython/libbdkffi.so

View File

@@ -11,10 +11,10 @@ pip install bdkpython
## Run the tests ## Run the tests
```shell ```shell
pip install --requirement requirements.txt pip3 install --requirement requirements.txt
bash ./generate.sh bash ./generate.sh
python setup.py bdist_wheel --verbose python3 setup.py --verbose bdist_wheel
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl --force-reinstall pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl
python -m unittest --verbose tests/test_bdk.py python -m unittest --verbose tests/test_bdk.py
``` ```
@@ -23,11 +23,11 @@ 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 first
bash generate.sh bash generate.sh
# Build the wheel # Build the wheel
python setup.py --verbose bdist_wheel python3 setup.py --verbose bdist_wheel
``` ```
## Run tox to build and test locally ## Run tox to build and test locally
@@ -35,7 +35,7 @@ python setup.py --verbose bdist_wheel
# install dev requirements # install dev requirements
pip install --requirement requirements-dev.txt pip install --requirement requirements-dev.txt
# build bindings glue code (located at ./src/bdkpython/bdk.py) # build bindings glue code (located at .bdk-python/src/bdkpython/bdk.py)
source ./generate.sh source ./generate.sh
# build and test # build and test

View File

@@ -1,24 +1,11 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail set -euo pipefail
OS=$(uname -s)
SCRIPT_DIR=$(dirname "$(realpath $0)")
PY_SRC="${SCRIPT_DIR}/src/bdkpython/"
echo "Generating bdk.py..." echo "Generating bdk.py..."
cd ../bdk-ffi/ # GENERATE_PYTHON_BINDINGS_OUT="$PY_SRC" GENERATE_PYTHON_BINDINGS_FIXUP_LIB_PATH=bdkffi cargo run --manifest-path ./bdk-ffi/Cargo.toml --release --bin generate --features generate-python
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format # BDKFFI_BINDGEN_PYTHON_FIXUP_PATH=bdkffi cargo run --manifest-path ./bdk-ffi/Cargo.toml --package bdk-ffi-bindgen -- --language python --udl-file ./bdk-ffi/src/bdk.udl --out-dir ./src/bdkpython/
BDKFFI_BINDGEN_OUTPUT_DIR="$PY_SRC" BDKFFI_BINDGEN_PYTHON_FIXUP_PATH=bdkffi cargo run --manifest-path ../bdk-ffi/Cargo.toml --package bdk-ffi-bindgen -- --language python --udl-file ../bdk-ffi/src/bdk.udl
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!"

View File

@@ -1,4 +1,3 @@
semantic-version==2.9.0 semantic-version==2.9.0
setuptools-rust==1.1.2
typing_extensions==4.0.1 typing_extensions==4.0.1
setuptools==67.4.0
wheel==0.38.4

View File

@@ -1,6 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
import os
from setuptools import setup from setuptools import setup
from setuptools_rust import Binding, RustExtension
LONG_DESCRIPTION = """# bdkpython LONG_DESCRIPTION = """# bdkpython
The Python language bindings for the [Bitcoin Dev Kit](https://github.com/bitcoindevkit). The Python language bindings for the [Bitcoin Dev Kit](https://github.com/bitcoindevkit).
@@ -49,21 +52,23 @@ balance = wallet.get_balance()
print(f"Wallet balance is: {balance.total}") print(f"Wallet balance is: {balance.total}")
""" """
rust_ext = RustExtension(
target="bdkpython.bdkffi",
path="../bdk-ffi/Cargo.toml",
binding=Binding.NoBinding,
)
setup( setup(
name="bdkpython", name='bdkpython',
version="0.28.3", version='0.27.1',
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',
include_package_data = True, rust_extensions=[rust_ext],
zip_safe=False, zip_safe=False,
packages=["bdkpython"], packages=['bdkpython'],
package_dir={"bdkpython": "./src/bdkpython"}, package_dir={'bdkpython': './src/bdkpython'},
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
# See issue #350 for more information
has_ext_modules=lambda: True,
) )

View File

@@ -27,7 +27,7 @@ class TestSimpleBip84Wallet(unittest.TestCase):
database_config=db_config database_config=db_config
) )
address_info = wallet.get_address(bdk.AddressIndex.LAST_UNUSED()) address_info = wallet.get_address(bdk.AddressIndex.LAST_UNUSED())
address = address_info.address.as_string() address = address_info.address
# print(f"New address is {address}") # print(f"New address is {address}")
assert address == "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", f"Wrong address {address}, should be tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e" assert address == "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", f"Wrong address {address}, should be tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e"
@@ -43,21 +43,6 @@ class TestSimpleBip84Wallet(unittest.TestCase):
# print(f"Balance is {balance.total} sat") # print(f"Balance is {balance.total} sat")
assert balance.total > 0, "Balance is 0, send testnet coins to tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e" assert balance.total > 0, "Balance is 0, send testnet coins to tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e"
def test_output_address_from_script_pubkey(self):
wallet = bdk.Wallet(
descriptor=descriptor,
change_descriptor=None,
network=bdk.Network.TESTNET,
database_config=db_config,
)
wallet.sync(blockchain, None)
first_tx = list(wallet.list_transactions(True))[0]
assert first_tx.txid == '35d3de8dd429ec4c9684168c1fbb9a4fb6db6f2ce89be214a024657a73ef4908'
output1, output2 = list(first_tx.transaction.output())
assert bdk.Address.from_script(output1.script_pubkey, bdk.Network.TESTNET).as_string() == 'tb1qw6ly2te8k9vy2mwj3g6gx82hj7hc8f5q3vry8t'
assert bdk.Address.from_script(output2.script_pubkey, bdk.Network.TESTNET).as_string() == 'tb1qzsvpnmme78yl60j7ldh9aqvhvxr4mz7mjpmh22'
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@@ -10,7 +10,7 @@ deps =
-rrequirements.txt -rrequirements.txt
-rrequirements-dev.txt -rrequirements-dev.txt
commands = commands =
python3 setup.py build --verbose python3 setup.py -v build
python3 setup.py install --verbose python3 setup.py -v install
pytest --verbose --override-ini console_output_style=count pytest --verbose --override-ini console_output_style=count
python3 setup.py bdist_wheel --verbose python3 setup.py --verbose bdist_wheel

View File

@@ -10,6 +10,6 @@ final class BitcoinDevKitTests: XCTestCase {
let databaseConfig = DatabaseConfig.memory let databaseConfig = DatabaseConfig.memory
let wallet = try Wallet.init(descriptor: desc, changeDescriptor: nil, network: Network.regtest, databaseConfig: databaseConfig) let wallet = try Wallet.init(descriptor: desc, changeDescriptor: nil, network: Network.regtest, databaseConfig: databaseConfig)
let addressInfo = try wallet.getAddress(addressIndex: AddressIndex.new) let addressInfo = try wallet.getAddress(addressIndex: AddressIndex.new)
XCTAssertEqual(addressInfo.address.asString(), "bcrt1qzg4mckdh50nwdm9hkzq06528rsu73hjxytqkxs") XCTAssertEqual(addressInfo.address, "bcrt1qzg4mckdh50nwdm9hkzq06528rsu73hjxytqkxs")
} }
} }

View File

@@ -13,7 +13,7 @@ rustup target add aarch64-apple-darwin x86_64-apple-darwin
pushd bdk-ffi pushd bdk-ffi
mkdir -p Sources/BitcoinDevKit mkdir -p Sources/BitcoinDevKit
cargo run --bin uniffi-bindgen generate src/bdk.udl --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit --no-format cargo run --package bdk-ffi-bindgen -- --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit
popd popd
cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-darwin cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-darwin