diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..2c89533
Binary files /dev/null and b/.DS_Store differ
diff --git a/bdk-python/.github/ISSUE_TEMPLATE/bug_report.md b/bdk-python/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..3d2de18
--- /dev/null
+++ b/bdk-python/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,38 @@
+---
+name: 🐞 Bug
+about: File a bug/issue
+title: '[BUG:]
'
+labels: bug
+---
+
+
+
+### Current Behavior:
+
+
+### Expected Behavior:
+
+
+### Steps To Reproduce:
+
+
+### Environment:
+
+
+### Anything else:
+
diff --git a/bdk-python/.github/ISSUE_TEMPLATE/feature_request.md b/bdk-python/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000..6fd56fd
--- /dev/null
+++ b/bdk-python/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,23 @@
+---
+name: 🚀 Feature Request
+about: Request a feature
+title: '[Feature Request:] '
+labels: enhancement
+---
+
+### Is your proposal related to a problem?
+
+
+### Describe the solution you'd like
+
+
+### Additional context
+
diff --git a/bdk-python/.github/pull_request_template.md b/bdk-python/.github/pull_request_template.md
new file mode 100644
index 0000000..c44596a
--- /dev/null
+++ b/bdk-python/.github/pull_request_template.md
@@ -0,0 +1,24 @@
+
+
+## Description
+
+
+## Notes to the reviewers
+
+
+## Checklists
+
+## All Submissions:
+* [ ] I've signed all my commits
+* [ ] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
+
+#### New Features:
+* [ ] I've added tests for the new feature
+* [ ] I've added docs for the new feature
+* [ ] I've updated `CHANGELOG.md`
+
+#### Bugfixes:
+* [ ] This pull request breaks the existing API
+* [ ] I've added tests to reproduce the issue which are now passing
+* [ ] I'm linking the issue being fixed by this PR
diff --git a/bdk-python/.github/workflows/build.yml b/bdk-python/.github/workflows/build.yml
new file mode 100644
index 0000000..e4e8293
--- /dev/null
+++ b/bdk-python/.github/workflows/build.yml
@@ -0,0 +1,109 @@
+name: Build wheels
+on: [push, pull_request]
+
+# 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
+ 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
+ strategy:
+ matrix:
+ python:
+ - '3.7'
+ - '3.8'
+ - '3.9'
+ - '3.10'
+ steps:
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python }}
+ - run: python3 --version
+ - name: checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: true
+ - 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: dist/*.whl
+
+ build-windows-wheel:
+ name: 'Build windows wheel'
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ python:
+ - '3.7'
+ - '3.8'
+ - '3.9'
+ - '3.10'
+ steps:
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python }}
+ - run: python --version
+ - name: checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: true
+ - run: pip install --user -r requirements.txt
+ - run: ./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: dist/*.whl
diff --git a/bdk-python/.github/workflows/publish.yml b/bdk-python/.github/workflows/publish.yml
new file mode 100644
index 0000000..aeb16e6
--- /dev/null
+++ b/bdk-python/.github/workflows/publish.yml
@@ -0,0 +1,141 @@
+name: Build and publish wheels on PyPI
+on: [workflow_dispatch]
+
+# 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
+ 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
+ strategy:
+ matrix:
+ python:
+ - '3.7'
+ - '3.8'
+ - '3.9'
+ - '3.10'
+ steps:
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python }}
+ - run: python3 --version
+ - name: checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: true
+ - 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: dist/*.whl
+
+ build-windows-wheel:
+ name: 'Build windows wheel'
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ python:
+ - '3.7'
+ - '3.8'
+ - '3.9'
+ - '3.10'
+ steps:
+ - uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python }}
+ - run: python --version
+ - name: checkout
+ uses: actions/checkout@v2
+ with:
+ submodules: true
+ - run: pip install --user -r requirements.txt
+ - run: ./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: dist/*.whl
+
+ publish-pypi:
+ name: 'Publish on PyPI'
+ runs-on: ubuntu-latest
+ needs: [build-manylinux2014-x86_64-wheel, build-macos-universal-wheel, build-windows-wheel]
+ # needs: [build-macos-universal-wheel]
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+
+ - name: 'Download artifacts in dist/ directory'
+ uses: actions/download-artifact@v2
+ with:
+ path: dist/
+
+ # - name: Display structure of downloaded files
+ # run: ls -R
+
+ # - name: 'Publish on test PyPI'
+ # uses: pypa/gh-action-pypi-publish@release/v1
+ # with:
+ # user: __token__
+ # password: ${{ secrets.TEST_PYPI_API_TOKEN }}
+ # repository_url: https://test.pypi.org/legacy/
+ # packages_dir: dist/*/
+
+ - name: 'Publish on PyPI'
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ user: __token__
+ password: ${{ secrets.PYPI_API_TOKEN }}
+ packages_dir: dist/*/
\ No newline at end of file
diff --git a/bdk-python/.gitignore b/bdk-python/.gitignore
new file mode 100644
index 0000000..726b07a
--- /dev/null
+++ b/bdk-python/.gitignore
@@ -0,0 +1,16 @@
+.tox/
+dist/
+bdkpython.egg-info/
+__pycache__/
+libbdkffi.dylib
+.idea/
+.DS_Store
+
+*.swp
+
+src/bdkpython/bdk.py
+src/bdkpython/*.so
+*.whl
+build/
+
+testing-setup-py-simple-example.py
diff --git a/bdk-python/.gitmodules b/bdk-python/.gitmodules
new file mode 100644
index 0000000..c582725
--- /dev/null
+++ b/bdk-python/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "bdk-ffi"]
+ path = bdk-ffi
+ url = https://github.com/bitcoindevkit/bdk-ffi.git
diff --git a/bdk-python/LICENSE b/bdk-python/LICENSE
new file mode 100644
index 0000000..c3f44ca
--- /dev/null
+++ b/bdk-python/LICENSE
@@ -0,0 +1,14 @@
+This software is licensed under [Apache 2.0](LICENSE-APACHE) or
+[MIT](LICENSE-MIT), at your option.
+
+Some files retain their own copyright notice, however, for full authorship
+information, see version control history.
+
+Except as otherwise noted in individual files, all files in this repository are
+licensed under the Apache License, Version 2.0 or the MIT license , at your option.
+
+You may not use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of this software or any files in this repository except in
+accordance with one or both of these licenses.
diff --git a/bdk-python/LICENSE-APACHE b/bdk-python/LICENSE-APACHE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/bdk-python/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/bdk-python/LICENSE-MIT b/bdk-python/LICENSE-MIT
new file mode 100644
index 0000000..0e0676a
--- /dev/null
+++ b/bdk-python/LICENSE-MIT
@@ -0,0 +1,17 @@
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/bdk-python/README.md b/bdk-python/README.md
new file mode 100644
index 0000000..c89f245
--- /dev/null
+++ b/bdk-python/README.md
@@ -0,0 +1,53 @@
+# bdk-python
+The Python language bindings for the [bitcoindevkit](https://github.com/bitcoindevkit).
+
+See the [package on PyPI](https://pypi.org/project/bdkpython/).
+
+
+## Install from PyPI
+Install the latest release using
+```shell
+pip install bdkpython
+```
+
+
+## Run the tests
+```shell
+pip3 install --requirement requirements.txt
+bash ./generate.sh
+python3 setup.py --verbose bdist_wheel
+pip3 install ./dist/bdkpython--py3-none-any.whl
+python -m unittest --verbose tests/test_bdk.py
+```
+
+
+## Build the package
+```shell
+# Install dependencies
+pip install --requirement requirements.txt
+
+# Generate the bindings first
+bash generate.sh
+
+# Build the wheel
+python3 setup.py --verbose bdist_wheel
+```
+
+
+## Run tox to build and test locally
+```shell
+# install dev requirements
+pip install --requirement requirements-dev.txt
+
+# build bindings glue code (located at ./src/bdkpython/bdk.py)
+source ./generate.sh
+
+# build and test
+tox -vv
+```
+
+
+## Install locally
+```shell
+pip install ./dist/bdkpython--py3-none-any.whl
+```
diff --git a/bdk-python/bdk-ffi/.editorconfig b/bdk-python/bdk-ffi/.editorconfig
new file mode 100644
index 0000000..4f1c5cd
--- /dev/null
+++ b/bdk-python/bdk-ffi/.editorconfig
@@ -0,0 +1,29 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.rs]
+indent_size = 4
+
+[*.kt]
+indent_size = 4
+
+[*.gradle]
+indent_size = 4
+
+[tests/**/*.rs]
+charset = utf-8
+end_of_line = unset
+indent_size = unset
+indent_style = unset
+trim_trailing_whitespace = unset
+insert_final_newline = unset
diff --git a/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/bug_report.md b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000..0708e29
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,26 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: 'bug'
+assignees: ''
+
+---
+
+**Describe the bug**
+
+
+**To Reproduce**
+
+
+**Expected behavior**
+
+
+**Build environment**
+ - BDK tag/commit:
+ - OS+version:
+ - Rust/Cargo version:
+ - Rust/Cargo target:
+
+**Additional context**
+
diff --git a/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/minor_release.md b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/minor_release.md
new file mode 100644
index 0000000..0514d56
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/minor_release.md
@@ -0,0 +1,101 @@
+---
+name: Minor Release
+about: Create a new minor release [for release managers only]
+title: 'Release MAJOR.MINOR+1.0'
+labels: 'release'
+assignees: ''
+
+---
+
+## Create a new minor release
+
+### Summary
+
+<--release summary to be used in announcements-->
+
+### Commit
+
+<--latest commit ID to include in this release-->
+
+### Changelog
+
+<--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
+
+### Checklist
+
+Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
+branch **development** version is *MAJOR.MINOR.0*.
+
+#### On the day of the feature freeze
+
+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/
diff --git a/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/patch_release.md b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/patch_release.md
new file mode 100644
index 0000000..b292668
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/patch_release.md
@@ -0,0 +1,69 @@
+---
+name: Patch Release
+about: Create a new patch release [for release managers only]
+title: 'Release MAJOR.MINOR.PATCH+1'
+labels: 'release'
+assignees: ''
+
+---
+
+## Create a new patch release
+
+### Summary
+
+<--release summary to be used in announcements-->
+
+### Commit
+
+<--latest commit ID to include in this release-->
+
+### Changelog
+
+<--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
+
+### Checklist
+
+Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
+branch **development** version is *MAJOR.MINOR.PATCH*.
+
+### On the day of the patch release
+
+Change the `master` branch to the new PATCH+1 version:
+
+- [ ] Switch to the `master` branch.
+- [ ] Create a new PR branch called `bump_dev_MAJOR_MINOR_PATCH+1`, eg. `bump_dev_0_22_1`.
+- [ ] Bump the `bump_dev_MAJOR_MINOR` branch to the next development PATCH+1 version.
+ - Change the `Cargo.toml` version value to `MAJOR.MINOR.PATCH+1`.
+ - The commit message should be "Bump version to MAJOR.MINOR.PATCH+1".
+- [ ] Create PR and merge the `bump_dev_MAJOR_MINOR_PATCH+1` branch to `master`.
+ - 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/
diff --git a/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/summer_project.md b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/summer_project.md
new file mode 100644
index 0000000..a693283
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/ISSUE_TEMPLATE/summer_project.md
@@ -0,0 +1,77 @@
+---
+name: Summer of Bitcoin Project
+about: Template to suggest a new https://www.summerofbitcoin.org/ project.
+title: ''
+labels: 'summer-of-bitcoin'
+assignees: ''
+
+---
+
+
+
+**Description**
+
+
+**Expected Outcomes**
+
+
+**Resources**
+
+
+
+
+
+
+**Skills Required**
+
+
+
+
+
+
+
+**Mentor(s)**
+
+
+**Difficulty**
+
+
+**Competency Test (optional)**
+
+
+
+
+
+
+
diff --git a/bdk-python/bdk-ffi/.github/pull_request_template.md b/bdk-python/bdk-ffi/.github/pull_request_template.md
new file mode 100644
index 0000000..42afd7e
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/pull_request_template.md
@@ -0,0 +1,34 @@
+
+
+### Description
+
+
+
+### Notes to the reviewers
+
+
+
+### Changelog notice
+
+
+
+
+### Checklists
+
+#### All Submissions:
+
+* [ ] I've signed all my commits
+* [ ] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md)
+* [ ] I ran `cargo fmt` and `cargo clippy` before committing
+
+#### New Features:
+
+* [ ] I've added tests for the new feature
+* [ ] I've added docs for the new feature
+
+#### Bugfixes:
+
+* [ ] This pull request breaks the existing API
+* [ ] I've added tests to reproduce the issue which are now passing
+* [ ] I'm linking the issue being fixed by this PR
diff --git a/bdk-python/bdk-ffi/.github/workflows/audit.yml b/bdk-python/bdk-ffi/.github/workflows/audit.yml
new file mode 100644
index 0000000..6143cca
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/workflows/audit.yml
@@ -0,0 +1,19 @@
+name: Audit
+
+on:
+ push:
+ paths:
+ - '**/Cargo.toml'
+ - '**/Cargo.lock'
+ schedule:
+ - cron: '0 0 * * 0' # Once per week
+
+jobs:
+
+ security_audit:
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions-rs/audit-check@v1
+ with:
+ token: ${{ secrets.GITHUB_TOKEN }}
\ No newline at end of file
diff --git a/bdk-python/bdk-ffi/.github/workflows/cont_integration.yml b/bdk-python/bdk-ffi/.github/workflows/cont_integration.yml
new file mode 100644
index 0000000..4422c0d
--- /dev/null
+++ b/bdk-python/bdk-ffi/.github/workflows/cont_integration.yml
@@ -0,0 +1,61 @@
+on: [push, pull_request]
+
+name: CI
+
+jobs:
+
+ build-test:
+ name: Build and test
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ rust:
+ - version: 1.63.0 # STABLE
+ clippy: true
+ - version: 1.61.0 # MSRV
+ steps:
+ - name: checkout
+ uses: actions/checkout@v2
+ - name: Generate cache key
+ run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
+ - name: cache
+ uses: actions/cache@v2
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ target
+ key: ${{ runner.os }}-cargo-${{ hashFiles('.cache_key') }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
+ - name: Set default toolchain
+ run: rustup default ${{ matrix.rust.version }}
+ - name: Set profile
+ run: rustup set profile minimal
+ - name: Add clippy
+ if: ${{ matrix.rust.clippy }}
+ run: rustup component add clippy
+ - name: Update toolchain
+ run: rustup update
+ - name: Build
+ run: cargo build
+ - name: Clippy
+ if: ${{ matrix.rust.clippy }}
+ run: cargo clippy --all-targets -- -D warnings
+ - name: Test
+ run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test
+
+ fmt:
+ name: Rust fmt
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Set default toolchain
+ run: rustup default nightly
+ - name: Set profile
+ run: rustup set profile minimal
+ - name: Add rustfmt
+ run: rustup component add rustfmt
+ - name: Update toolchain
+ run: rustup update
+ - name: Check fmt
+ run: cargo fmt --all -- --config format_code_in_doc_comments=true --check
diff --git a/bdk-python/bdk-ffi/.gitignore b/bdk-python/bdk-ffi/.gitignore
new file mode 100644
index 0000000..c91c338
--- /dev/null
+++ b/bdk-python/bdk-ffi/.gitignore
@@ -0,0 +1,17 @@
+target
+build
+Cargo.lock
+/bindings/bdk-kotlin/local.properties
+.gradle
+wallet_db
+bdk_ffi_test
+local.properties
+*.log
+*.dylib
+*.so
+.DS_Store
+testdb
+xcuserdata
+.lsp
+.clj-kondo
+.idea/
diff --git a/bdk-python/bdk-ffi/CHANGELOG.md b/bdk-python/bdk-ffi/CHANGELOG.md
new file mode 100644
index 0000000..721b0c3
--- /dev/null
+++ b/bdk-python/bdk-ffi/CHANGELOG.md
@@ -0,0 +1,116 @@
+# Changelog
+All notable changes to this project prior to release **0.9.0** are documented in this file. Future
+changelog information can be found in each release's git tag and can be viewed with `git tag -ln100 "v*"`.
+Changelog info is also documented on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases)
+page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [Unreleased]
+
+## [v0.9.0]
+- Breaking Changes
+ - Rename `get_network()` method on `Wallet` interface to `network()` [#185]
+ - Rename `get_transactions()` method on `Wallet` interface to `list_transactions()` [#185]
+ - Remove `generate_extended_key`, returned ExtendedKeyInfo [#154]
+ - Remove `restore_extended_key`, returned ExtendedKeyInfo [#154]
+ - Remove dictionary `ExtendedKeyInfo {mnenonic, xprv, fingerprint}` [#154]
+ - Remove interface `Transaction` [#190]
+ - Changed `Wallet` interface `list_transaction()` to return array of `TransactionDetails` [#190]
+ - Update `bdk` dependency version to 0.22 [#193]
+- APIs Added [#154]
+ - `generate_mnemonic()`, returns string mnemonic
+ - `interface DescriptorSecretKey`
+ - `new(Network, string_mnenoinc, password)`, contructs DescriptorSecretKey
+ - `derive(DerivationPath)`, derives and returns child DescriptorSecretKey
+ - `extend(DerivationPath)`, extends and returns DescriptorSecretKey
+ - `as_public()`, returns DescriptorSecretKey as DescriptorPublicKey
+ - `as_string()`, returns DescriptorSecretKey as String
+ - `interface DescriptorPublicKey`
+ - `derive(DerivationPath)` derives and returns child DescriptorPublicKey
+ - `extend(DerivationPath)` extends and returns DescriptorPublicKey
+ - `as_string()` returns DescriptorPublicKey as String
+ - Add to `interface Blockchain` the `get_height()` and `get_block_hash()` methods [#184]
+ - Add to `interface TxBuilder` the `set_recipients(recipient: Vec)` method [#186]
+ - Add to `dictionary TransactionDetails` the `confirmation_time` field [#190]
+- Interfaces Added [#154]
+ - `DescriptorSecretKey`
+ - `DescriptorPublicKey`
+ - `DerivationPath`
+
+[#154]: https://github.com/bitcoindevkit/bdk-ffi/pull/154
+[#184]: https://github.com/bitcoindevkit/bdk-ffi/pull/184
+[#185]: https://github.com/bitcoindevkit/bdk-ffi/pull/185
+[#193]: https://github.com/bitcoindevkit/bdk-ffi/pull/193
+
+## [v0.8.0]
+- Update BDK to version 0.20.0 [#169]
+- APIs Added
+ - `TxBuilder.add_data(data: Vec)` [#163]
+ - `Wallet.list_unspent()` returns `Vec` [#158]
+ - Add coin control methods on TxBuilder [#164]
+
+[#163]: https://github.com/bitcoindevkit/bdk-ffi/pull/163
+[#158]: https://github.com/bitcoindevkit/bdk-ffi/pull/158
+[#164]: https://github.com/bitcoindevkit/bdk-ffi/pull/164
+[#169]: https://github.com/bitcoindevkit/bdk-ffi/pull/169
+[#190]: https://github.com/bitcoindevkit/bdk-ffi/pull/190
+
+## [v0.7.0]
+- Update BDK to version 0.19.0
+ - fixes sqlite-db issue causing wrong balance
+ - adds experimental taproot descriptor and PSBT support
+- APIs Removed
+ - `Wallet.get_new_address()`, returned String, [#137]
+ - `Wallet.get_last_unused_address()`, returned String [#137]
+- APIs Added
+ - `Wallet.get_address(AddressIndex)`, returns `AddressInfo` [#137]
+- APIs Changed
+ - `Wallet.sign(PartiallySignedBitcoinTransaction)` now returns a bool, true if finalized [#161]
+
+[#137]: https://github.com/bitcoindevkit/bdk-ffi/pull/137
+[#161]: https://github.com/bitcoindevkit/bdk-ffi/pull/161
+
+## [v0.6.0]
+- Update BDK to version 0.18.0
+- Add BumpFeeTxBuilder to bump the fee on an unconfirmed tx created by the Wallet
+- Change TxBuilder.build() to TxBuilder.finish() to align with bdk function name
+
+## [v0.5.0]
+- Fix Wallet.broadcast function, now returns a tx id as a hex string
+- Remove creating a new spending Transaction via the PartiallySignedBitcoinTransaction constructor
+- Add TxBuilder for creating new spending PartiallySignedBitcoinTransaction
+- Add TxBuilder .add_recipient, .fee_rate, and .build functions
+- Add TxBuilder .drain_wallet and .drain_to functions
+- Update generate cli tool to generate all binding languages and rename to bdk-ffi-bindgen
+
+## [v0.4.0]
+- Add dual license MIT and Apache 2.0
+- Add sqlite database support
+- Fix memory database configuration enum, remove junk field
+
+## [v0.3.1]
+- Remove hard coded sync progress value (was always returning 21.0)
+
+## [v0.3.0]
+- Move bdk-kotlin bindings and ios example to separate repos
+- Add bin to generate Python bindings
+- Add `PartiallySignedBitcoinTransaction::deserialize` function as named constructor to decode from a string per [BIP 0174]
+- Add `PartiallySignedBitcoinTransaction::serialize` function to encode to a string per [BIP 0174]
+- Remove `PartiallySignedBitcoinTransaction.details` struct field
+
+[BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding
+
+## [v0.2.0]
+
+[unreleased]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.9.0...HEAD
+[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.7.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.6.0...v0.7.0
+[v0.6.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.5.0...v0.6.0
+[v0.5.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.4.0...v0.5.0
+[v0.4.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.3.1...v0.4.0
+[v0.3.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.3.0...v0.3.1
+[v0.3.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.2.0...v0.3.0
+[v0.2.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.0.0...v0.2.0
diff --git a/bdk-python/bdk-ffi/Cargo.toml b/bdk-python/bdk-ffi/Cargo.toml
new file mode 100644
index 0000000..63cd96f
--- /dev/null
+++ b/bdk-python/bdk-ffi/Cargo.toml
@@ -0,0 +1,31 @@
+[package]
+name = "bdk-ffi"
+version = "0.11.0"
+authors = ["Steve Myers ", "Sudarsan Balaji "]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+
+[workspace]
+members = [".","bdk-ffi-bindgen"]
+default-members = [".", "bdk-ffi-bindgen"]
+
+[lib]
+crate-type = ["staticlib", "cdylib"]
+name = "bdkffi"
+
+[dependencies]
+bdk = { version = "0.24", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
+
+uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] }
+uniffi = { version = "0.21.0", features = ["builtin-bindgen"] }
+
+[build-dependencies]
+uniffi_build = { version = "0.21.0", features = ["builtin-bindgen"] }
+
+[profile.release-smaller]
+inherits = "release"
+opt-level = 'z' # Optimize for size.
+lto = true # Enable Link Time Optimization
+codegen-units = 1 # Reduce number of codegen units to increase optimizations.
+panic = 'abort' # Abort on panic
+strip = true # Strip symbols from binary*
diff --git a/bdk-python/bdk-ffi/DEVELOPMENT_CYCLE.md b/bdk-python/bdk-ffi/DEVELOPMENT_CYCLE.md
new file mode 100644
index 0000000..00c4094
--- /dev/null
+++ b/bdk-python/bdk-ffi/DEVELOPMENT_CYCLE.md
@@ -0,0 +1,35 @@
+# Development Cycle
+
+This project follows a regular releasing schedule similar to the one [used by the Rust language]
+except releases always follow the latest [`bdk`] release by one to two weeks. In short, this means
+that a new release is made at a regular cadence, with all the feature/bugfixes that made it to
+`master` in time. This ensures that we don't keep delaying releases waiting for
+"just one more little thing".
+
+After making a new `bdk-ffi` release tag all downstream language bindings should also be updated.
+
+This project uses [Semantic Versioning], but is currently at MAJOR version zero (0.y.z) meaning it
+is still in initial development. Anything MAY change at any time. The public API SHOULD NOT be
+considered stable. Until we reach version `1.0.0` we will do our best to document any breaking API
+changes in the changelog info attached to each release tag.
+
+We decided to maintain a faster release cycle while the library is still in "beta", i.e. before
+release `1.0.0`: since we are constantly adding new features and, even more importantly, fixing
+issues, we want developers to have access to those updates as fast as possible. For this reason we
+will make a release **every 4 weeks**.
+
+Once the project reaches a more mature state (>= `1.0.0`), we will very likely switch to longer
+release cycles of **6 weeks**.
+
+The "feature freeze" will happen when [`bdk`] releases a release candidate. This project will then
+be updated and tested with [`bdk`] release candidates until a final release is published. This
+means a new branch will be created originating from the `master` tip at that time, and in that
+branch we will stop adding new features and only focus on ensuring the ones we've added are working
+properly.
+
+To create a new release a release manager will create a new issue using a `Release` template and
+follow the template instructions.
+
+[used by the Rust language]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
+[Semantic Versioning]: https://semver.org/
+[`bdk`]: https://github.com/bitcoindevkit/bdk
diff --git a/bdk-python/bdk-ffi/LICENSE b/bdk-python/bdk-ffi/LICENSE
new file mode 100644
index 0000000..9c61848
--- /dev/null
+++ b/bdk-python/bdk-ffi/LICENSE
@@ -0,0 +1,14 @@
+This software is licensed under [Apache 2.0](LICENSE-APACHE) or
+[MIT](LICENSE-MIT), at your option.
+
+Some files retain their own copyright notice, however, for full authorship
+information, see version control history.
+
+Except as otherwise noted in individual files, all files in this repository are
+licensed under the Apache License, Version 2.0 or the MIT license , at your option.
+
+You may not use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of this software or any files in this repository except in
+accordance with one or both of these licenses.
\ No newline at end of file
diff --git a/bdk-python/bdk-ffi/LICENSE-APACHE b/bdk-python/bdk-ffi/LICENSE-APACHE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/bdk-python/bdk-ffi/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/bdk-python/bdk-ffi/LICENSE-MIT b/bdk-python/bdk-ffi/LICENSE-MIT
new file mode 100644
index 0000000..9d982a4
--- /dev/null
+++ b/bdk-python/bdk-ffi/LICENSE-MIT
@@ -0,0 +1,16 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/bdk-python/bdk-ffi/README.md b/bdk-python/bdk-ffi/README.md
new file mode 100644
index 0000000..c47fd5c
--- /dev/null
+++ b/bdk-python/bdk-ffi/README.md
@@ -0,0 +1,75 @@
+# Native language bindings for BDK
+
+
+
+
+
+
+
+
+The workspace in this repository creates the `libbdkffi` multi-language library for the rust based
+[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 has its own repository that includes this project as a [git submodule].
+The rust code in this project is a wrapper around the [bdk] library to expose it's APIs in a
+uniform way using the [mozilla/uniffi-rs] bindings generator for each supported target language.
+
+## Supported target languages and platforms
+
+The below repositories include instructions for using, building, and publishing the native
+language binding for [bdk] supported by this project.
+
+| Language | Platform | Repository |
+| -------- | ------------ | ------------ |
+| Kotlin | jvm | [bdk-kotlin] |
+| Kotlin | android | [bdk-kotlin] |
+| Swift | iOS, macOS | [bdk-swift] |
+| Python | linux, macOS | [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
+```
+
+[bdk]: https://github.com/bitcoindevkit/bdk
+[Bitcoin Dev Kit]: https://github.com/bitcoindevkit
+[git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
+[uniffi-rs]: https://github.com/mozilla/uniffi-rs
+
+[bdk-kotlin]: https://github.com/bitcoindevkit/bdk-kotlin
+[bdk-swift]: https://github.com/bitcoindevkit/bdk-swift
+[bdk-python]: https://github.com/bitcoindevkit/bdk-python
+
+## Contributing
+
+### Adding new structs and functions
+
+See the [UniFFI User Guide](https://mozilla.github.io/uniffi-rs/)
+
+#### For pass by value objects
+
+1. create new rust struct with only fields that are supported UniFFI types
+1. update mapping `bdk.udl` file with new `dictionary`
+
+#### For pass by reference values
+
+1. create wrapper rust struct/impl with only fields that are `Sync + Send`
+1. update mapping `bdk.udl` file with new `interface`
+
+## Goals
+
+1. Language bindings should feel idiomatic in target languages/platforms
+1. Adding new targets should be easy
+1. Getting up and running should be easy
+1. Contributing should be easy
+1. Get it right, then automate
+
+## Thanks
+
+This project is made possible thanks to the wonderful work by the [mozilla/uniffi-rs] team.
+
+[mozilla/uniffi-rs]: https://github.com/mozilla/uniffi-rs
diff --git a/bdk-python/bdk-ffi/bdk-ffi-bindgen/Cargo.toml b/bdk-python/bdk-ffi/bdk-ffi-bindgen/Cargo.toml
new file mode 100644
index 0000000..87ee0bc
--- /dev/null
+++ b/bdk-python/bdk-ffi/bdk-ffi-bindgen/Cargo.toml
@@ -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"
diff --git a/bdk-python/bdk-ffi/bdk-ffi-bindgen/src/main.rs b/bdk-python/bdk-ffi/bdk-ffi-bindgen/src/main.rs
new file mode 100644
index 0000000..8a87fc5
--- /dev/null
+++ b/bdk-python/bdk-ffi/bdk-ffi-bindgen/src/main.rs
@@ -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 {
+ 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> {
+ 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,
+}
+
+fn main() -> Result<(), Box> {
+ 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(())
+}
diff --git a/bdk-python/bdk-ffi/build.rs b/bdk-python/bdk-ffi/build.rs
new file mode 100644
index 0000000..153077f
--- /dev/null
+++ b/bdk-python/bdk-ffi/build.rs
@@ -0,0 +1,3 @@
+fn main() {
+ uniffi_build::generate_scaffolding("src/bdk.udl").unwrap();
+}
diff --git a/bdk-python/bdk-ffi/src/bdk.udl b/bdk-python/bdk-ffi/src/bdk.udl
new file mode 100644
index 0000000..e45fe87
--- /dev/null
+++ b/bdk-python/bdk-ffi/src/bdk.udl
@@ -0,0 +1,337 @@
+namespace bdk {
+
+};
+
+[Error]
+enum BdkError {
+ "InvalidU32Bytes",
+ "Generic",
+ "MissingCachedScripts",
+ "ScriptDoesntHaveAddressForm",
+ "NoRecipients",
+ "NoUtxosSelected",
+ "OutputBelowDustLimit",
+ "InsufficientFunds",
+ "BnBTotalTriesExceeded",
+ "BnBNoExactMatch",
+ "UnknownUtxo",
+ "TransactionNotFound",
+ "TransactionConfirmed",
+ "IrreplaceableTransaction",
+ "FeeRateTooLow",
+ "FeeTooLow",
+ "FeeRateUnavailable",
+ "MissingKeyOrigin",
+ "Key",
+ "ChecksumMismatch",
+ "SpendingPolicyRequired",
+ "InvalidPolicyPathError",
+ "Signer",
+ "InvalidNetwork",
+ "InvalidProgressValue",
+ "ProgressUpdateError",
+ "InvalidOutpoint",
+ "Descriptor",
+ "Encode",
+ "Miniscript",
+ "MiniscriptPsbt",
+ "Bip32",
+ "Secp256k1",
+ "Json",
+ "Hex",
+ "Psbt",
+ "PsbtParse",
+ "Electrum",
+ "Esplora",
+ "Sled",
+ "Rusqlite",
+};
+
+dictionary AddressInfo {
+ u32 index;
+ string address;
+};
+
+enum AddressIndex {
+ "New",
+ "LastUnused",
+};
+
+enum Network {
+ "Bitcoin",
+ "Testnet",
+ "Signet",
+ "Regtest",
+};
+
+dictionary SledDbConfiguration {
+ string path;
+ string tree_name;
+};
+
+dictionary SqliteDbConfiguration {
+ string path;
+};
+
+dictionary Balance {
+ u64 immature;
+ u64 trusted_pending;
+ u64 untrusted_pending;
+ u64 confirmed;
+ u64 spendable;
+ u64 total;
+};
+
+[Enum]
+interface DatabaseConfig {
+ Memory();
+ Sled(SledDbConfiguration config);
+ Sqlite(SqliteDbConfiguration config);
+};
+
+dictionary TransactionDetails {
+ u64? fee;
+ u64 received;
+ u64 sent;
+ string txid;
+ BlockTime? confirmation_time;
+};
+
+dictionary BlockTime {
+ u32 height;
+ u64 timestamp;
+};
+
+enum WordCount {
+ "Words12",
+ "Words15",
+ "Words18",
+ "Words21",
+ "Words24",
+};
+
+dictionary ElectrumConfig {
+ string url;
+ string? socks5;
+ u8 retry;
+ u8? timeout;
+ u64 stop_gap;
+};
+
+dictionary EsploraConfig {
+ string base_url;
+ string? proxy;
+ u8? concurrency;
+ u64 stop_gap;
+ u64? timeout;
+};
+
+[Enum]
+interface BlockchainConfig {
+ Electrum(ElectrumConfig config);
+ Esplora(EsploraConfig config);
+};
+
+interface Blockchain {
+ [Throws=BdkError]
+ constructor(BlockchainConfig config);
+
+ [Throws=BdkError]
+ void broadcast([ByRef] PartiallySignedTransaction psbt);
+
+ [Throws=BdkError]
+ u32 get_height();
+
+ [Throws=BdkError]
+ string get_block_hash(u32 height);
+};
+
+callback interface Progress {
+ void update(f32 progress, string? message);
+};
+
+dictionary OutPoint {
+ string txid;
+ u32 vout;
+};
+
+dictionary TxOut {
+ u64 value;
+ string address;
+};
+
+enum KeychainKind {
+ "External",
+ "Internal",
+};
+
+dictionary LocalUtxo {
+ OutPoint outpoint;
+ TxOut txout;
+ KeychainKind keychain;
+ boolean is_spent;
+};
+
+dictionary ScriptAmount {
+ Script script;
+ u64 amount;
+};
+
+interface Wallet {
+ [Throws=BdkError]
+ constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config);
+
+ [Throws=BdkError]
+ AddressInfo get_address(AddressIndex address_index);
+
+ [Throws=BdkError]
+ Balance get_balance();
+
+ [Throws=BdkError]
+ boolean sign([ByRef] PartiallySignedTransaction psbt);
+
+ [Throws=BdkError]
+ sequence list_transactions();
+
+ Network network();
+
+ [Throws=BdkError]
+ void sync([ByRef] Blockchain blockchain, Progress? progress);
+
+ [Throws=BdkError]
+ sequence list_unspent();
+};
+
+interface FeeRate {
+ [Name=from_sat_per_vb]
+ constructor(float sat_per_vb);
+
+ float as_sat_per_vb();
+};
+
+interface PartiallySignedTransaction {
+ [Throws=BdkError]
+ constructor(string psbt_base64);
+
+ string serialize();
+
+ string txid();
+
+ sequence extract_tx();
+
+ [Throws=BdkError]
+ PartiallySignedTransaction combine(PartiallySignedTransaction other);
+
+ u64? fee_amount();
+
+ FeeRate? fee_rate();
+};
+
+dictionary TxBuilderResult {
+ PartiallySignedTransaction psbt;
+ TransactionDetails transaction_details;
+};
+
+interface TxBuilder {
+ constructor();
+
+ TxBuilder add_recipient(Script script, u64 amount);
+
+ TxBuilder add_unspendable(OutPoint unspendable);
+
+ TxBuilder add_utxo(OutPoint outpoint);
+
+ TxBuilder add_utxos(sequence outpoints);
+
+ TxBuilder do_not_spend_change();
+
+ TxBuilder manually_selected_only();
+
+ TxBuilder only_spend_change();
+
+ TxBuilder unspendable(sequence unspendable);
+
+ TxBuilder fee_rate(float sat_per_vbyte);
+
+ TxBuilder fee_absolute(u64 fee_amount);
+
+ TxBuilder drain_wallet();
+
+ TxBuilder drain_to(string address);
+
+ TxBuilder enable_rbf();
+
+ TxBuilder enable_rbf_with_sequence(u32 nsequence);
+
+ TxBuilder add_data(sequence data);
+
+ TxBuilder set_recipients(sequence recipients);
+
+ [Throws=BdkError]
+ TxBuilderResult finish([ByRef] Wallet wallet);
+};
+
+interface BumpFeeTxBuilder {
+ constructor(string txid, float new_fee_rate);
+
+ BumpFeeTxBuilder allow_shrinking(string address);
+
+ BumpFeeTxBuilder enable_rbf();
+
+ BumpFeeTxBuilder enable_rbf_with_sequence(u32 nsequence);
+
+ [Throws=BdkError]
+ PartiallySignedTransaction finish([ByRef] Wallet wallet);
+};
+
+interface Mnemonic {
+ constructor(WordCount word_count);
+
+ [Name=from_string, Throws=BdkError]
+ constructor(string mnemonic);
+
+ [Name=from_entropy, Throws=BdkError]
+ constructor(sequence entropy);
+
+ string as_string();
+};
+
+interface DerivationPath {
+ [Throws=BdkError]
+ constructor(string path);
+};
+
+interface DescriptorSecretKey {
+ constructor(Network network, Mnemonic mnemonic, string? password);
+
+ [Throws=BdkError]
+ DescriptorSecretKey derive(DerivationPath path);
+
+ DescriptorSecretKey extend(DerivationPath path);
+
+ DescriptorPublicKey as_public();
+
+ sequence secret_bytes();
+
+ string as_string();
+};
+
+interface DescriptorPublicKey {
+ [Throws=BdkError]
+ DescriptorPublicKey derive(DerivationPath path);
+
+ DescriptorPublicKey extend(DerivationPath path);
+
+ string as_string();
+};
+
+interface Address {
+ [Throws=BdkError]
+ constructor(string address);
+
+ Script script_pubkey();
+};
+
+interface Script {
+ constructor(sequence raw_output_script);
+};
diff --git a/bdk-python/bdk-ffi/src/lib.rs b/bdk-python/bdk-ffi/src/lib.rs
new file mode 100644
index 0000000..e062281
--- /dev/null
+++ b/bdk-python/bdk-ffi/src/lib.rs
@@ -0,0 +1,1293 @@
+use bdk::bitcoin::blockdata::script::Script as BdkScript;
+use bdk::bitcoin::hashes::hex::ToHex;
+use bdk::bitcoin::secp256k1::Secp256k1;
+use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
+use bdk::bitcoin::util::psbt::serialize::Serialize;
+use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
+use bdk::bitcoin::Sequence;
+use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
+use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
+use bdk::blockchain::GetBlockHash;
+use bdk::blockchain::GetHeight;
+use bdk::blockchain::{
+ electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain,
+};
+use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress};
+use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration};
+use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
+use bdk::descriptor::DescriptorXKey;
+use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
+use bdk::keys::{
+ DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
+ DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
+};
+use bdk::miniscript::BareCtx;
+use bdk::psbt::PsbtUtils;
+use bdk::wallet::tx_builder::ChangeSpendPolicy;
+use bdk::wallet::AddressIndex as BdkAddressIndex;
+use bdk::wallet::AddressInfo as BdkAddressInfo;
+use bdk::{
+ Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind, SignOptions,
+ SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
+};
+use std::collections::HashSet;
+use std::convert::{From, TryFrom};
+use std::fmt;
+use std::ops::Deref;
+use std::str::FromStr;
+use std::sync::{Arc, Mutex, MutexGuard};
+
+uniffi_macros::include_scaffolding!("bdk");
+
+/// A output script and an amount of satoshis.
+pub struct ScriptAmount {
+ pub script: Arc