diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..d50e342
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,107 @@
+on: [push, pull_request]
+name: Build wheels
+
+# 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/.gitignore b/.gitignore
index a11b87d..b763419 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,8 @@ __pycache__/
libbdkffi.dylib
.idea/
.DS_Store
+
+*.swp
+
+src/bdkpython/bdk.py
+*.whl
diff --git a/README.md b/README.md
index 1f33e6a..55df900 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,11 @@ python -m tox
## Build the package
```shell
+# Install dependecies
+pip install -r requirements.txt
+# Generate the bindings first
+bash generate.sh
+# Build the wheel
python -m build
```
@@ -34,53 +39,3 @@ python -m build
pip install ./dist/bdkpython-0.0.1-py3-none-any.whl
```
-
-## Known issues
-Note that until the fix is merged upstream in [uniffi-rs](https://github.com/mozilla/uniffi-rs), the `loadIndirect()` function in the `bdk.py` module must be replaced with the following:
-```python
-def loadIndirect():
- if sys.platform == "linux":
- # libname = "lib{}.so"
- libname = os.path.join(os.path.dirname(__file__), "lib{}.so")
- elif sys.platform == "darwin":
- # libname = "lib{}.dylib"
- libname = os.path.join(os.path.dirname(__file__), "lib{}.dylib")
- elif sys.platform.startswith("win"):
- # As of python3.8, ctypes does not seem to search $PATH when loading DLLs.
- # We could use `os.add_dll_directory` to configure the search path, but
- # it doesn't feel right to mess with application-wide settings. Let's
- # assume that the `.dll` is next to the `.py` file and load by full path.
- libname = os.path.join(
- os.path.dirname(__file__),
- "{}.dll",
- )
- return getattr(ctypes.cdll, libname.format("bdkffi"))
-```
-
-## Support both macOS architectures
-In order to support both macOS architectures, we must modify the `loadIndirect()` method a little further:
-```python
-import platform
-def loadIndirect():
- if sys.platform == "linux":
- # libname = "lib{}.so"
- # libname = os.path.join(os.path.dirname(__file__), "lib{}.so")
- libname = os.path.join(os.path.dirname(__file__), "linux-x86_64/lib{}.so")
- elif sys.platform == "darwin":
- # libname = "lib{}.dylib"
- # libname = os.path.join(os.path.dirname(__file__), "lib{}.dylib")
- if platform.machine() == "arm64":
- libname = os.path.join(os.path.dirname(__file__), "darwin-arm64/lib{}.dylib")
- elif platform.machine() == "x86_64":
- libname = os.path.join(os.path.dirname(__file__), "darwin-x86_64/lib{}.dylib")
- elif sys.platform.startswith("win"):
- # As of python3.8, ctypes does not seem to search $PATH when loading DLLs.
- # We could use `os.add_dll_directory` to configure the search path, but
- # it doesn't feel right to mess with application-wide settings. Let's
- # assume that the `.dll` is next to the `.py` file and load by full path.
- libname = os.path.join(
- os.path.dirname(__file__),
- "{}.dll",
- )
- return getattr(ctypes.cdll, libname.format("bdkffi"))
-```
diff --git a/bdk-ffi b/bdk-ffi
index e4d53b5..68f266a 160000
--- a/bdk-ffi
+++ b/bdk-ffi
@@ -1 +1 @@
-Subproject commit e4d53b5e4b213e484bf4b76a4bf33884dd68f086
+Subproject commit 68f266a17b29a84e8c63ed90126c5c152d2f51aa
diff --git a/build.sh b/build.sh
deleted file mode 100644
index afd46bb..0000000
--- a/build.sh
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-#set -euo pipefail
-
-#pushd bdk-ffi
-echo "Confirm bdk-ffi rust library builds"
-cargo build --manifest-path ./bdk-ffi/Cargo.toml --release
-
-echo "Generate bdk-ffi Python bindings"
-# clean solution once uniffi-bindgen 0.15.3 is released
-# uniffi-bindgen generate src/bdk.udl --no-format --out-dir ../src/bdkpython/ --language python
-
-# in the meantime, set UNIFFI_BINDGEN environment variable to a local, latest version of uniffi-rs/uniffi_bindgen/Cargo.toml
-# and the BDK_PYTHON environment variable to the current directory
-#cd $UNIFFI_BINDGEN/
-#cargo run -- generate $BDK_PYTHON/src/bdk.udl --no-format --out-dir ./src/bdkpython/ --language python
-#cd -
-
-cargo run --manifest-path $UNIFFI_BINDGEN -- generate ./bdk-ffi/src/bdk.udl --no-format --out-dir ./src/bdkpython/ --language python
-cp ./bdk-ffi/target/release/libbdkffi.dylib ./src/bdkpython/
diff --git a/generate.sh b/generate.sh
new file mode 100644
index 0000000..653935d
--- /dev/null
+++ b/generate.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+SCRIPT_DIR=$(dirname "$(realpath $0)")
+PY_SRC="${SCRIPT_DIR}/src/bdkpython/"
+
+echo "Generating bdk.py..."
+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
diff --git a/nix/uniffi_0.14.1_cargo_lock.patch b/nix/uniffi_0.14.1_cargo_lock.patch
new file mode 100644
index 0000000..6c7244d
--- /dev/null
+++ b/nix/uniffi_0.14.1_cargo_lock.patch
@@ -0,0 +1,387 @@
+--- /dev/null 2021-12-15 11:22:02.342000000 +0100
++++ uniffi_bindgen/Cargo.lock 2021-12-15 16:15:16.132084011 +0100
+@@ -0,0 +1,384 @@
++# This file is automatically @generated by Cargo.
++# It is not intended for manual editing.
++version = 3
++
++[[package]]
++name = "anyhow"
++version = "1.0.51"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
++
++[[package]]
++name = "arrayvec"
++version = "0.5.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
++
++[[package]]
++name = "askama"
++version = "0.10.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
++dependencies = [
++ "askama_derive",
++ "askama_escape",
++ "askama_shared",
++]
++
++[[package]]
++name = "askama_derive"
++version = "0.10.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
++dependencies = [
++ "askama_shared",
++ "proc-macro2",
++ "syn",
++]
++
++[[package]]
++name = "askama_escape"
++version = "0.10.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "90c108c1a94380c89d2215d0ac54ce09796823cca0fd91b299cfff3b33e346fb"
++
++[[package]]
++name = "askama_shared"
++version = "0.11.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "2582b77e0f3c506ec4838a25fa8a5f97b9bed72bb6d3d272ea1c031d8bd373bc"
++dependencies = [
++ "askama_escape",
++ "nom 6.2.1",
++ "proc-macro2",
++ "quote",
++ "serde",
++ "syn",
++ "toml",
++]
++
++[[package]]
++name = "bitflags"
++version = "1.3.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
++
++[[package]]
++name = "bitvec"
++version = "0.19.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
++dependencies = [
++ "funty",
++ "radium",
++ "tap",
++ "wyz",
++]
++
++[[package]]
++name = "camino"
++version = "1.0.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "cargo-platform"
++version = "0.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "cargo_metadata"
++version = "0.13.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8"
++dependencies = [
++ "camino",
++ "cargo-platform",
++ "semver",
++ "semver-parser",
++ "serde",
++ "serde_json",
++]
++
++[[package]]
++name = "cfg-if"
++version = "1.0.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
++
++[[package]]
++name = "clap"
++version = "2.34.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
++dependencies = [
++ "bitflags",
++ "textwrap",
++ "unicode-width",
++]
++
++[[package]]
++name = "funty"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
++
++[[package]]
++name = "heck"
++version = "0.3.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
++dependencies = [
++ "unicode-segmentation",
++]
++
++[[package]]
++name = "itoa"
++version = "1.0.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
++
++[[package]]
++name = "lexical-core"
++version = "0.7.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
++dependencies = [
++ "arrayvec",
++ "bitflags",
++ "cfg-if",
++ "ryu",
++ "static_assertions",
++]
++
++[[package]]
++name = "memchr"
++version = "2.3.4"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
++
++[[package]]
++name = "nom"
++version = "5.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
++dependencies = [
++ "memchr",
++ "version_check",
++]
++
++[[package]]
++name = "nom"
++version = "6.2.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
++dependencies = [
++ "bitvec",
++ "funty",
++ "lexical-core",
++ "memchr",
++ "version_check",
++]
++
++[[package]]
++name = "paste"
++version = "1.0.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
++
++[[package]]
++name = "pest"
++version = "2.1.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
++dependencies = [
++ "ucd-trie",
++]
++
++[[package]]
++name = "proc-macro2"
++version = "1.0.34"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
++dependencies = [
++ "unicode-xid",
++]
++
++[[package]]
++name = "quote"
++version = "1.0.10"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
++dependencies = [
++ "proc-macro2",
++]
++
++[[package]]
++name = "radium"
++version = "0.5.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
++
++[[package]]
++name = "ryu"
++version = "1.0.9"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
++
++[[package]]
++name = "semver"
++version = "0.11.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
++dependencies = [
++ "semver-parser",
++ "serde",
++]
++
++[[package]]
++name = "semver-parser"
++version = "0.10.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
++dependencies = [
++ "pest",
++]
++
++[[package]]
++name = "serde"
++version = "1.0.131"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
++dependencies = [
++ "serde_derive",
++]
++
++[[package]]
++name = "serde_derive"
++version = "1.0.131"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
++dependencies = [
++ "proc-macro2",
++ "quote",
++ "syn",
++]
++
++[[package]]
++name = "serde_json"
++version = "1.0.73"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
++dependencies = [
++ "itoa",
++ "ryu",
++ "serde",
++]
++
++[[package]]
++name = "static_assertions"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
++
++[[package]]
++name = "syn"
++version = "1.0.82"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
++dependencies = [
++ "proc-macro2",
++ "quote",
++ "unicode-xid",
++]
++
++[[package]]
++name = "tap"
++version = "1.0.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
++
++[[package]]
++name = "textwrap"
++version = "0.11.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
++dependencies = [
++ "unicode-width",
++]
++
++[[package]]
++name = "toml"
++version = "0.5.8"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "ucd-trie"
++version = "0.1.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
++
++[[package]]
++name = "unicode-segmentation"
++version = "1.8.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
++
++[[package]]
++name = "unicode-width"
++version = "0.1.9"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
++
++[[package]]
++name = "unicode-xid"
++version = "0.2.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
++
++[[package]]
++name = "uniffi_bindgen"
++version = "0.14.1"
++dependencies = [
++ "anyhow",
++ "askama",
++ "cargo_metadata",
++ "clap",
++ "heck",
++ "paste",
++ "serde",
++ "toml",
++ "weedle",
++]
++
++[[package]]
++name = "version_check"
++version = "0.9.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
++
++[[package]]
++name = "weedle"
++version = "0.12.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "610950904727748ca09682e857f0d6d6437f0ca862f32f9229edba8cec8b2635"
++dependencies = [
++ "nom 5.1.2",
++]
++
++[[package]]
++name = "wyz"
++version = "0.2.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/nix/uniffi_0.15.2_cargo_lock.patch b/nix/uniffi_0.15.2_cargo_lock.patch
new file mode 100644
index 0000000..7fbc9e6
--- /dev/null
+++ b/nix/uniffi_0.15.2_cargo_lock.patch
@@ -0,0 +1,387 @@
+--- /dev/null 2021-12-15 11:22:02.342000000 +0100
++++ uniffi_bindgen/Cargo.lock 2021-12-15 15:54:49.278543090 +0100
+@@ -0,0 +1,384 @@
++# This file is automatically @generated by Cargo.
++# It is not intended for manual editing.
++version = 3
++
++[[package]]
++name = "anyhow"
++version = "1.0.51"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
++
++[[package]]
++name = "arrayvec"
++version = "0.5.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
++
++[[package]]
++name = "askama"
++version = "0.10.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "d298738b6e47e1034e560e5afe63aa488fea34e25ec11b855a76f0d7b8e73134"
++dependencies = [
++ "askama_derive",
++ "askama_escape",
++ "askama_shared",
++]
++
++[[package]]
++name = "askama_derive"
++version = "0.10.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "ca2925c4c290382f9d2fa3d1c1b6a63fa1427099721ecca4749b154cc9c25522"
++dependencies = [
++ "askama_shared",
++ "proc-macro2",
++ "syn",
++]
++
++[[package]]
++name = "askama_escape"
++version = "0.10.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "90c108c1a94380c89d2215d0ac54ce09796823cca0fd91b299cfff3b33e346fb"
++
++[[package]]
++name = "askama_shared"
++version = "0.11.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "2582b77e0f3c506ec4838a25fa8a5f97b9bed72bb6d3d272ea1c031d8bd373bc"
++dependencies = [
++ "askama_escape",
++ "nom 6.2.1",
++ "proc-macro2",
++ "quote",
++ "serde",
++ "syn",
++ "toml",
++]
++
++[[package]]
++name = "bitflags"
++version = "1.3.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
++
++[[package]]
++name = "bitvec"
++version = "0.19.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
++dependencies = [
++ "funty",
++ "radium",
++ "tap",
++ "wyz",
++]
++
++[[package]]
++name = "camino"
++version = "1.0.5"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "52d74260d9bf6944e2208aa46841b4b8f0d7ffc0849a06837b2f510337f86b2b"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "cargo-platform"
++version = "0.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "cargo_metadata"
++version = "0.13.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "081e3f0755c1f380c2d010481b6fa2e02973586d5f2b24eebb7a2a1d98b143d8"
++dependencies = [
++ "camino",
++ "cargo-platform",
++ "semver",
++ "semver-parser",
++ "serde",
++ "serde_json",
++]
++
++[[package]]
++name = "cfg-if"
++version = "1.0.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
++
++[[package]]
++name = "clap"
++version = "2.34.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
++dependencies = [
++ "bitflags",
++ "textwrap",
++ "unicode-width",
++]
++
++[[package]]
++name = "funty"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
++
++[[package]]
++name = "heck"
++version = "0.3.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
++dependencies = [
++ "unicode-segmentation",
++]
++
++[[package]]
++name = "itoa"
++version = "1.0.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
++
++[[package]]
++name = "lexical-core"
++version = "0.7.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
++dependencies = [
++ "arrayvec",
++ "bitflags",
++ "cfg-if",
++ "ryu",
++ "static_assertions",
++]
++
++[[package]]
++name = "memchr"
++version = "2.3.4"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
++
++[[package]]
++name = "nom"
++version = "5.1.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
++dependencies = [
++ "memchr",
++ "version_check",
++]
++
++[[package]]
++name = "nom"
++version = "6.2.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "9c5c51b9083a3c620fa67a2a635d1ce7d95b897e957d6b28ff9a5da960a103a6"
++dependencies = [
++ "bitvec",
++ "funty",
++ "lexical-core",
++ "memchr",
++ "version_check",
++]
++
++[[package]]
++name = "paste"
++version = "1.0.6"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
++
++[[package]]
++name = "pest"
++version = "2.1.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
++dependencies = [
++ "ucd-trie",
++]
++
++[[package]]
++name = "proc-macro2"
++version = "1.0.34"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1"
++dependencies = [
++ "unicode-xid",
++]
++
++[[package]]
++name = "quote"
++version = "1.0.10"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
++dependencies = [
++ "proc-macro2",
++]
++
++[[package]]
++name = "radium"
++version = "0.5.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
++
++[[package]]
++name = "ryu"
++version = "1.0.9"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
++
++[[package]]
++name = "semver"
++version = "0.11.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
++dependencies = [
++ "semver-parser",
++ "serde",
++]
++
++[[package]]
++name = "semver-parser"
++version = "0.10.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
++dependencies = [
++ "pest",
++]
++
++[[package]]
++name = "serde"
++version = "1.0.131"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
++dependencies = [
++ "serde_derive",
++]
++
++[[package]]
++name = "serde_derive"
++version = "1.0.131"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
++dependencies = [
++ "proc-macro2",
++ "quote",
++ "syn",
++]
++
++[[package]]
++name = "serde_json"
++version = "1.0.73"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5"
++dependencies = [
++ "itoa",
++ "ryu",
++ "serde",
++]
++
++[[package]]
++name = "static_assertions"
++version = "1.1.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
++
++[[package]]
++name = "syn"
++version = "1.0.82"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59"
++dependencies = [
++ "proc-macro2",
++ "quote",
++ "unicode-xid",
++]
++
++[[package]]
++name = "tap"
++version = "1.0.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
++
++[[package]]
++name = "textwrap"
++version = "0.11.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
++dependencies = [
++ "unicode-width",
++]
++
++[[package]]
++name = "toml"
++version = "0.5.8"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
++dependencies = [
++ "serde",
++]
++
++[[package]]
++name = "ucd-trie"
++version = "0.1.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
++
++[[package]]
++name = "unicode-segmentation"
++version = "1.8.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
++
++[[package]]
++name = "unicode-width"
++version = "0.1.9"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
++
++[[package]]
++name = "unicode-xid"
++version = "0.2.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
++
++[[package]]
++name = "uniffi_bindgen"
++version = "0.15.2"
++dependencies = [
++ "anyhow",
++ "askama",
++ "cargo_metadata",
++ "clap",
++ "heck",
++ "paste",
++ "serde",
++ "toml",
++ "weedle",
++]
++
++[[package]]
++name = "version_check"
++version = "0.9.3"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
++
++[[package]]
++name = "weedle"
++version = "0.12.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "610950904727748ca09682e857f0d6d6437f0ca862f32f9229edba8cec8b2635"
++dependencies = [
++ "nom 5.1.2",
++]
++
++[[package]]
++name = "wyz"
++version = "0.2.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
diff --git a/nix/uniffi_bindgen.nix b/nix/uniffi_bindgen.nix
new file mode 100644
index 0000000..42cf6ab
--- /dev/null
+++ b/nix/uniffi_bindgen.nix
@@ -0,0 +1,20 @@
+with import {};
+
+rustPlatform.buildRustPackage rec {
+ pname = "uniffi_bindgen";
+ version = "0.15.2";
+ src = fetchFromGitHub {
+ owner = "mozilla";
+ repo = "uniffi-rs";
+ rev = "6fa9c06a394b4e9b219fa30fc94e353d17f86e11";
+ # rev = "refs/tags/v0.14.1";
+ sha256 = "1chahy1ac1r88drpslln2p1b04cbg79ylpxzyyp92s1z7ldm5ddb"; # 0.15.2
+ # sha256 = "1mff3f3fqqzqx1yv70ff1yzdnvbd90vg2r477mzzcgisg1wfpwi0"; # 0.14.1
+ fetchSubmodules = true;
+ } + "/uniffi_bindgen/";
+
+ doCheck = false;
+ cargoSha256 = "sha256:08gg285fq8i32nf9kd8s0nn0niacd7sg8krv818nx41i18sm2cf3"; # 0.15.2
+ # cargoSha256 = "sha256:01zp3rwlni988h02dqhkhzhwccs7bhwc1alhbf6gbw3av4b0m9cf"; # 0.14.1
+ cargoPatches = [ ./uniffi_0.15.2_cargo_lock.patch ];
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..d6ba728
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+semantic-version==2.9.0
+setuptools-rust==1.1.2
+typing_extensions==4.0.1
diff --git a/setup.py b/setup.py
index 3006e53..55de5d7 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python
-from setuptools import setup, find_packages
+import os
+
+from setuptools import setup
+from setuptools_rust import Binding, RustExtension
LONG_DESCRIPTION = """# bdkpython
The Python language bindings for the [bitcoindevkit](https://github.com/bitcoindevkit).
@@ -60,17 +63,22 @@ print(f"Wallet balance is: {balance}")
```
"""
+rust_ext = RustExtension(
+ "bdkpython.bdkffi",
+ path="./bdk-ffi/Cargo.toml",
+ binding=Binding.NoBinding,
+)
+
setup(
- name='bdkpython',
- version='0.0.4',
- packages=find_packages(where="src"),
- package_dir={"": "src"},
- package_data={"bdkpython": ["*/*.dylib", "*/*.so"]},
- include_package_data=True,
- zip_safe=False,
+ name = 'bdkpython',
+ version = '0.0.4',
description="The Python language bindings for the bitcoindevkit",
long_description=LONG_DESCRIPTION,
long_description_content_type='text/markdown',
+ rust_extensions=[rust_ext],
+ zip_safe=False,
+ packages=['bdkpython'],
+ package_dir={ 'bdkpython': './src/bdkpython' },
url="https://github.com/thunderbiscuit/bdk-python",
author="Alekos Filini , Steve Myers ",
license="MIT or Apache 2.0",
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..1b59fca
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,17 @@
+with import {};
+
+mkShell {
+ name = "bdk-python-shell";
+ packages = [ ( import ./nix/uniffi_bindgen.nix ) ];
+ buildInputs = with python37.pkgs; [
+ pip
+ setuptools
+ ];
+ shellHook = ''
+ export LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH
+ alias pip="PIP_PREFIX='$(pwd)/_build/pip_packages' \pip"
+ export PYTHONPATH="$(pwd)/_build/pip_packages/lib/python3.7/site-packages:$(pwd):$PYTHONPATH"
+ export PATH="$(pwd)/_build/pip_packages/bin:$PATH"
+ unset SOURCE_DATE_EPOCH
+ '';
+}
diff --git a/src/bdkpython/bdk.py b/src/bdkpython/bdk.py
deleted file mode 100644
index b6e0679..0000000
--- a/src/bdkpython/bdk.py
+++ /dev/null
@@ -1,1891 +0,0 @@
-# This file was autogenerated by some hot garbage in the `uniffi` crate.
-# Trust me, you don't want to mess with it!
-
-# Common helper code.
-#
-# Ideally this would live in a separate .py file where it can be unittested etc
-# in isolation, and perhaps even published as a re-useable package.
-#
-# However, it's important that the details of how this helper code works (e.g. the
-# way that different builtin types are passed across the FFI) exactly match what's
-# expected by the rust code on the other side of the interface. In practice right
-# now that means coming from the exact some version of `uniffi` that was used to
-# compile the rust component. The easiest way to ensure this is to bundle the Python
-# helpers directly inline like we're doing here.
-
-import os
-import sys
-import ctypes
-import enum
-import struct
-import contextlib
-import datetime
-
-
-class RustBuffer(ctypes.Structure):
- _fields_ = [
- ("capacity", ctypes.c_int32),
- ("len", ctypes.c_int32),
- ("data", ctypes.POINTER(ctypes.c_char)),
- ]
-
- @staticmethod
- def alloc(size):
- return rust_call(_UniFFILib.ffi_bdk_b9b3_rustbuffer_alloc, size)
-
- @staticmethod
- def reserve(rbuf, additional):
- return rust_call(_UniFFILib.ffi_bdk_b9b3_rustbuffer_reserve, rbuf, additional)
-
- def free(self):
- return rust_call(_UniFFILib.ffi_bdk_b9b3_rustbuffer_free, self)
-
- def __str__(self):
- return "RustBuffer(capacity={}, len={}, data={})".format(
- self.capacity,
- self.len,
- self.data[0:self.len]
- )
-
- @contextlib.contextmanager
- def allocWithBuilder():
- """Context-manger to allocate a buffer using a RustBufferBuilder.
-
- The allocated buffer will be automatically freed if an error occurs, ensuring that
- we don't accidentally leak it.
- """
- builder = RustBufferBuilder()
- try:
- yield builder
- except:
- builder.discard()
- raise
-
- @contextlib.contextmanager
- def consumeWithStream(self):
- """Context-manager to consume a buffer using a RustBufferStream.
-
- The RustBuffer will be freed once the context-manager exits, ensuring that we don't
- leak it even if an error occurs.
- """
- try:
- s = RustBufferStream(self)
- yield s
- if s.remaining() != 0:
- raise RuntimeError("junk data left in buffer after consuming")
- finally:
- self.free()
-
-
-class ForeignBytes(ctypes.Structure):
- _fields_ = [
- ("len", ctypes.c_int32),
- ("data", ctypes.POINTER(ctypes.c_char)),
- ]
-
- def __str__(self):
- return "ForeignBytes(len={}, data={})".format(self.len, self.data[0:self.len])
-
-
-class RustBufferStream(object):
- """
- Helper for structured reading of bytes from a RustBuffer
- """
-
- def __init__(self, rbuf):
- self.rbuf = rbuf
- self.offset = 0
-
- def remaining(self):
- return self.rbuf.len - self.offset
-
- def _unpack_from(self, size, format):
- if self.offset + size > self.rbuf.len:
- raise InternalError("read past end of rust buffer")
- value = struct.unpack(format, self.rbuf.data[self.offset:self.offset+size])[0]
- self.offset += size
- return value
-
- def read(self, size):
- if self.offset + size > self.rbuf.len:
- raise InternalError("read past end of rust buffer")
- data = self.rbuf.data[self.offset:self.offset+size]
- self.offset += size
- return data
-
- def readI8(self):
- return self._unpack_from(1, ">b")
-
- def readU8(self):
- return self._unpack_from(1, ">B")
-
- def readI16(self):
- return self._unpack_from(2, ">h")
-
- def readU16(self):
- return self._unpack_from(2, ">H")
-
- def readI32(self):
- return self._unpack_from(4, ">i")
-
- def readU32(self):
- return self._unpack_from(4, ">I")
-
- def readI64(self):
- return self._unpack_from(8, ">q")
-
- def readU64(self):
- return self._unpack_from(8, ">Q")
-
- def readFloat(self):
- v = self._unpack_from(4, ">f")
- return v
-
- def readDouble(self):
- return self._unpack_from(8, ">d")
-
-
-class RustBufferBuilder(object):
- """
- Helper for structured writing of bytes into a RustBuffer.
- """
-
- def __init__(self):
- self.rbuf = RustBuffer.alloc(16)
- self.rbuf.len = 0
-
- def finalize(self):
- rbuf = self.rbuf
- self.rbuf = None
- return rbuf
-
- def discard(self):
- if self.rbuf is not None:
- rbuf = self.finalize()
- rbuf.free()
-
- @contextlib.contextmanager
- def _reserve(self, numBytes):
- if self.rbuf.len + numBytes > self.rbuf.capacity:
- self.rbuf = RustBuffer.reserve(self.rbuf, numBytes)
- yield None
- self.rbuf.len += numBytes
-
- def _pack_into(self, size, format, value):
- with self._reserve(size):
- # XXX TODO: I feel like I should be able to use `struct.pack_into` here but can't figure it out.
- for i, byte in enumerate(struct.pack(format, value)):
- self.rbuf.data[self.rbuf.len + i] = byte
-
- def write(self, value):
- with self._reserve(len(value)):
- for i, byte in enumerate(value):
- self.rbuf.data[self.rbuf.len + i] = byte
-
- def writeI8(self, v):
- self._pack_into(1, ">b", v)
-
- def writeU8(self, v):
- self._pack_into(1, ">B", v)
-
- def writeI16(self, v):
- self._pack_into(2, ">h", v)
-
- def writeU16(self, v):
- self._pack_into(2, ">H", v)
-
- def writeI32(self, v):
- self._pack_into(4, ">i", v)
-
- def writeU32(self, v):
- self._pack_into(4, ">I", v)
-
- def writeI64(self, v):
- self._pack_into(8, ">q", v)
-
- def writeU64(self, v):
- self._pack_into(8, ">Q", v)
-
- def writeFloat(self, v):
- self._pack_into(4, ">f", v)
-
- def writeDouble(self, v):
- self._pack_into(8, ">d", v)
-# A handful of classes and functions to support the generated data structures.
-# This would be a good candidate for isolating in its own ffi-support lib.
-
-class InternalError(Exception):
- pass
-
-class RustCallStatus(ctypes.Structure):
- """
- Error runtime.
- """
- _fields_ = [
- ("code", ctypes.c_int8),
- ("error_buf", RustBuffer),
- ]
-
- # These match the values from the uniffi::rustcalls module
- CALL_SUCCESS = 0
- CALL_ERROR = 1
- CALL_PANIC = 2
-
- def __str__(self):
- if self.code == RustCallStatus.CALL_SUCCESS:
- return "RustCallStatus(CALL_SUCCESS)"
- elif self.code == RustCallStatus.CALL_ERROR:
- return "RustCallStatus(CALL_ERROR)"
- elif self.code == RustCallStatus.CALL_PANIC:
- return "RustCallStatus(CALL_SUCCESS)"
- else:
- return "RustCallStatus()"
-
-def rust_call(fn, *args):
- # Call a rust function
- return rust_call_with_error(None, fn, *args)
-
-def rust_call_with_error(error_class, fn, *args):
- # Call a rust function and handle any errors
- #
- # This function is used for rust calls that return Result<> and therefore can set the CALL_ERROR status code.
- # error_class must be set to the error class that corresponds to the result.
- call_status = RustCallStatus(code=RustCallStatus.CALL_SUCCESS, error_buf=RustBuffer(0, 0, None))
-
- args_with_error = args + (ctypes.byref(call_status),)
- result = fn(*args_with_error)
- if call_status.code == RustCallStatus.CALL_SUCCESS:
- return result
- elif call_status.code == RustCallStatus.CALL_ERROR:
- if error_class is None:
- call_status.err_buf.contents.free()
- raise InternalError("rust_call_with_error: CALL_ERROR, but no error class set")
- else:
- raise error_class._lift(call_status.error_buf)
- elif call_status.code == RustCallStatus.CALL_PANIC:
- # When the rust code sees a panic, it tries to construct a RustBuffer
- # with the message. But if that code panics, then it just sends back
- # an empty buffer.
- if call_status.error_buf.len > 0:
- msg = FfiConverterString._lift(call_status.error_buf)
- else:
- msg = "Unknown rust panic"
- raise InternalError(msg)
- else:
- raise InternalError("Invalid RustCallStatus code: {}".format(
- call_status.code))
-
-# A function pointer for a callback as defined by UniFFI.
-# Rust definition `fn(handle: u64, method: u32, args: RustBuffer, buf_ptr: *mut RustBuffer) -> int`
-FOREIGN_CALLBACK_T = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_ulonglong, ctypes.c_ulong, RustBuffer, ctypes.POINTER(RustBuffer))
-# Types conforming to `Primitive` pass themselves directly over the FFI.
-class Primitive:
- @classmethod
- def _lift(cls, value):
- return value
-
- @classmethod
- def _lower(cls, value):
- return value
-
-# Helper class for new types that will always go through a RustBuffer.
-# Classes should inherit from this and implement the `_read` static method
-# and `_write` instance methods.
-class ViaFfiUsingByteBuffer:
- @classmethod
- def _lift(cls, rbuf):
- with rbuf.consumeWithStream() as stream:
- return cls._read(stream)
-
- def _lower(self):
- with RustBuffer.allocWithBuilder() as builder:
- self._write(builder)
- return builder.finalize()
-
-# Helper class for wrapper types that will always go through a RustBuffer.
-# Classes should inherit from this and implement the `_read` and `_write` static methods.
-class FfiConverterUsingByteBuffer:
- @classmethod
- def _lift(cls, rbuf):
- with rbuf.consumeWithStream() as stream:
- return cls._read(stream)
-
- @classmethod
- def _lower(cls, value):
- with RustBuffer.allocWithBuilder() as builder:
- cls._write(value, builder)
- return builder.finalize()
-
-# Helpers for structural types.
-
-class FfiConverterSequence:
- @staticmethod
- def _write(value, buf, writeItem):
- items = len(value)
- buf.writeI32(items)
- for item in value:
- writeItem(item, buf)
-
- @staticmethod
- def _read(buf, readItem):
- count = buf.readI32()
- if count < 0:
- raise InternalError("Unexpected negative sequence length")
-
- items = []
- while count > 0:
- items.append(readItem(buf))
- count -= 1
- return items
-
-class FfiConverterOptional:
- @staticmethod
- def _write(value, buf, writeItem):
- if value is None:
- buf.writeU8(0)
- return
-
- buf.writeU8(1)
- writeItem(value, buf)
-
- @staticmethod
- def _read(buf, readItem):
- flag = buf.readU8()
- if flag == 0:
- return None
- elif flag == 1:
- return readItem(buf)
- else:
- raise InternalError("Unexpected flag byte for optional type")
-
-class FfiConverterDictionary:
- @staticmethod
- def _write(items, buf, writeItem):
- buf.writeI32(len(items))
- for (key, value) in items.items():
- writeItem(key, value, buf)
-
- @staticmethod
- def _read(buf, readItem):
- count = buf.readI32()
- if count < 0:
- raise InternalError("Unexpected negative map size")
- items = {}
- while count > 0:
- key, value = readItem(buf)
- items[key] = value
- count -= 1
- return items
-
-# Contains loading, initialization code,
-# and the FFI Function declarations in a com.sun.jna.Library.
-# This is how we find and load the dynamic library provided by the component.
-# For now we just look it up by name.
-#
-# XXX TODO: This will probably grow some magic for resolving megazording in future.
-# E.g. we might start by looking for the named component in `libuniffi.so` and if
-# that fails, fall back to loading it separately from `lib${componentName}.so`.
-
-def loadIndirect():
- if sys.platform == "linux":
- # libname = "lib{}.so"
- libname = os.path.join(os.path.dirname(__file__), "lib{}.so")
- elif sys.platform == "darwin":
- # libname = "lib{}.dylib"
- libname = os.path.join(os.path.dirname(__file__), "lib{}.dylib")
- elif sys.platform.startswith("win"):
- # As of python3.8, ctypes does not seem to search $PATH when loading DLLs.
- # We could use `os.add_dll_directory` to configure the search path, but
- # it doesn't feel right to mess with application-wide settings. Let's
- # assume that the `.dll` is next to the `.py` file and load by full path.
- libname = os.path.join(
- os.path.dirname(__file__),
- "{}.dll",
- )
- return getattr(ctypes.cdll, libname.format("bdkffi"))
-
-# A ctypes library to expose the extern-C FFI definitions.
-# This is an implementation detail which will be called internally by the public API.
-
-_UniFFILib = loadIndirect()
-_UniFFILib.ffi_bdk_b9b3_OfflineWallet_object_free.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_OfflineWallet_object_free.restype = None
-_UniFFILib.bdk_b9b3_OfflineWallet_new.argtypes = (
- RustBuffer,
- RustBuffer,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_new.restype = ctypes.c_void_p
-_UniFFILib.bdk_b9b3_OfflineWallet_get_new_address.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_get_new_address.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OfflineWallet_get_last_unused_address.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_get_last_unused_address.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OfflineWallet_get_balance.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_get_balance.restype = ctypes.c_uint64
-_UniFFILib.bdk_b9b3_OfflineWallet_sign.argtypes = (
- ctypes.c_void_p,
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_sign.restype = None
-_UniFFILib.bdk_b9b3_OfflineWallet_get_transactions.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OfflineWallet_get_transactions.restype = RustBuffer
-_UniFFILib.ffi_bdk_b9b3_OnlineWallet_object_free.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_OnlineWallet_object_free.restype = None
-_UniFFILib.bdk_b9b3_OnlineWallet_new.argtypes = (
- RustBuffer,
- RustBuffer,
- RustBuffer,
- RustBuffer,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_new.restype = ctypes.c_void_p
-_UniFFILib.bdk_b9b3_OnlineWallet_get_new_address.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_get_new_address.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OnlineWallet_get_last_unused_address.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_get_last_unused_address.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OnlineWallet_get_balance.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_get_balance.restype = ctypes.c_uint64
-_UniFFILib.bdk_b9b3_OnlineWallet_sign.argtypes = (
- ctypes.c_void_p,
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_sign.restype = None
-_UniFFILib.bdk_b9b3_OnlineWallet_get_transactions.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_get_transactions.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OnlineWallet_get_network.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_get_network.restype = RustBuffer
-_UniFFILib.bdk_b9b3_OnlineWallet_sync.argtypes = (
- ctypes.c_void_p,
- ctypes.c_uint64,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_sync.restype = None
-_UniFFILib.bdk_b9b3_OnlineWallet_broadcast.argtypes = (
- ctypes.c_void_p,
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_OnlineWallet_broadcast.restype = RustBuffer
-_UniFFILib.ffi_bdk_b9b3_PartiallySignedBitcoinTransaction_object_free.argtypes = (
- ctypes.c_void_p,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_PartiallySignedBitcoinTransaction_object_free.restype = None
-_UniFFILib.bdk_b9b3_PartiallySignedBitcoinTransaction_new.argtypes = (
- ctypes.c_void_p,
- RustBuffer,
- ctypes.c_uint64,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_PartiallySignedBitcoinTransaction_new.restype = ctypes.c_void_p
-_UniFFILib.ffi_bdk_b9b3_BdkProgress_init_callback.argtypes = (
- FOREIGN_CALLBACK_T,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_BdkProgress_init_callback.restype = None
-_UniFFILib.bdk_b9b3_generate_extended_key.argtypes = (
- RustBuffer,
- RustBuffer,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_generate_extended_key.restype = RustBuffer
-_UniFFILib.bdk_b9b3_restore_extended_key.argtypes = (
- RustBuffer,
- RustBuffer,
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.bdk_b9b3_restore_extended_key.restype = RustBuffer
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_alloc.argtypes = (
- ctypes.c_int32,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_alloc.restype = RustBuffer
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_from_bytes.argtypes = (
- ForeignBytes,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_from_bytes.restype = RustBuffer
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_free.argtypes = (
- RustBuffer,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_free.restype = None
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_reserve.argtypes = (
- RustBuffer,
- ctypes.c_int32,
- ctypes.POINTER(RustCallStatus),
-)
-_UniFFILib.ffi_bdk_b9b3_rustbuffer_reserve.restype = RustBuffer
-
-# Public interface members begin here.
-
-import threading
-
-class ConcurrentHandleMap:
- """
- A map where inserting, getting and removing data is synchronized with a lock.
- """
-
- def __init__(self):
- # type Handle = int
- self._left_map = {} # type: Dict[Handle, Any]
- self._right_map = {} # type: Dict[Any, Handle]
-
- self._lock = threading.Lock()
- self._current_handle = 0
- self._stride = 1
-
-
- def insert(self, obj):
- with self._lock:
- if obj in self._right_map:
- return self._right_map[obj]
- else:
- handle = self._current_handle
- self._current_handle += self._stride
- self._left_map[handle] = obj
- self._right_map[obj] = handle
- return handle
-
- def get(self, handle):
- with self._lock:
- return self._left_map.get(handle)
-
- def remove(self, handle):
- with self._lock:
- if handle in self._left_map:
- obj = self._left_map.pop(handle)
- del self._right_map[obj]
- return obj
-
-# Magic number for the Rust proxy to call using the same mechanism as every other method,
-# to free the callback once it's dropped by Rust.
-IDX_CALLBACK_FREE = 0
-
-class FfiConverterCallbackInterface:
- _handle_map = ConcurrentHandleMap()
-
- def __init__(self, cb):
- self._foreign_callback = cb
-
- def drop(self, handle):
- self.__class__._handle_map.remove(handle)
-
- @classmethod
- def _lift(cls, handle):
- obj = cls._handle_map.get(handle)
- if not obj:
- raise InternalError("The object in the handle map has been dropped already")
-
- return obj
-
- @classmethod
- def _read(cls, buf):
- handle = buf.readU64()
- cls._lift(handle)
-
- @classmethod
- def _lower(cls, cb):
- handle = cls._handle_map.insert(cb)
- return handle
-
- @classmethod
- def _write(cls, cb, buf):
- buf.writeU64(cls._lower(cb))
-
-
-
-class Network(ViaFfiUsingByteBuffer, enum.Enum):
- BITCOIN = 1
- TESTNET = 2
- SIGNET = 3
- REGTEST = 4
-
-
- @staticmethod
- def _read(buf):
- variant = buf.readI32()
- if variant == 1:
- return Network.BITCOIN
- if variant == 2:
- return Network.TESTNET
- if variant == 3:
- return Network.SIGNET
- if variant == 4:
- return Network.REGTEST
-
- raise InternalError("Raw enum value doesn't match any cases")
-
- def _write(self, buf):
- if self is Network.BITCOIN:
- i = 1
- buf.writeI32(1)
- if self is Network.TESTNET:
- i = 2
- buf.writeI32(2)
- if self is Network.SIGNET:
- i = 3
- buf.writeI32(3)
- if self is Network.REGTEST:
- i = 4
- buf.writeI32(4)
-
-
-
-
-
-
-
-class DatabaseConfig(ViaFfiUsingByteBuffer, object):
- def __init__(self):
- raise RuntimeError("DatabaseConfig cannot be instantiated directly")
-
- # Each enum variant is a nested class of the enum itself.
- class MEMORY(object):
- def __init__(self,junk ):
-
- self.junk = junk
-
-
- def __str__(self):
- return "DatabaseConfig.MEMORY(junk={} )".format(self.junk )
-
- def __eq__(self, other):
- if not other.is_memory():
- return False
- if self.junk != other.junk:
- return False
- return True
- class SLED(object):
- def __init__(self,config ):
-
- self.config = config
-
-
- def __str__(self):
- return "DatabaseConfig.SLED(config={} )".format(self.config )
-
- def __eq__(self, other):
- if not other.is_sled():
- return False
- if self.config != other.config:
- return False
- return True
-
-
- # For each variant, we have an `is_NAME` method for easily checking
- # whether an instance is that variant.
- def is_memory(self):
- return isinstance(self, DatabaseConfig.MEMORY)
- def is_sled(self):
- return isinstance(self, DatabaseConfig.SLED)
-
-
- @classmethod
- def _read(cls, buf):
- variant = buf.readI32()
-
- if variant == 1:
- return cls.MEMORY(
- junk=FfiConverterString._read(buf),
- )
- if variant == 2:
- return cls.SLED(
- config=SledDbConfiguration._read(buf),
- )
-
- raise InternalError("Raw enum value doesn't match any cases")
-
- def _write(self, buf):
- if self.is_memory():
- buf.writeI32(1)
- FfiConverterString._write(self.junk, buf)
- if self.is_sled():
- buf.writeI32(2)
- self.config._write(buf)
-
-
-# Now, a little trick - we make each nested variant class be a subclass of the main
-# enum class, so that method calls and instance checks etc will work intuitively.
-# We might be able to do this a little more neatly with a metaclass, but this'll do.
-DatabaseConfig.MEMORY = type("DatabaseConfig.MEMORY", (DatabaseConfig.MEMORY, DatabaseConfig,), {})
-DatabaseConfig.SLED = type("DatabaseConfig.SLED", (DatabaseConfig.SLED, DatabaseConfig,), {})
-
-
-
-
-
-
-
-class Transaction(ViaFfiUsingByteBuffer, object):
- def __init__(self):
- raise RuntimeError("Transaction cannot be instantiated directly")
-
- # Each enum variant is a nested class of the enum itself.
- class UNCONFIRMED(object):
- def __init__(self,details ):
-
- self.details = details
-
-
- def __str__(self):
- return "Transaction.UNCONFIRMED(details={} )".format(self.details )
-
- def __eq__(self, other):
- if not other.is_unconfirmed():
- return False
- if self.details != other.details:
- return False
- return True
- class CONFIRMED(object):
- def __init__(self,details, confirmation ):
-
- self.details = details
- self.confirmation = confirmation
-
-
- def __str__(self):
- return "Transaction.CONFIRMED(details={}, confirmation={} )".format(self.details, self.confirmation )
-
- def __eq__(self, other):
- if not other.is_confirmed():
- return False
- if self.details != other.details:
- return False
- if self.confirmation != other.confirmation:
- return False
- return True
-
-
- # For each variant, we have an `is_NAME` method for easily checking
- # whether an instance is that variant.
- def is_unconfirmed(self):
- return isinstance(self, Transaction.UNCONFIRMED)
- def is_confirmed(self):
- return isinstance(self, Transaction.CONFIRMED)
-
-
- @classmethod
- def _read(cls, buf):
- variant = buf.readI32()
-
- if variant == 1:
- return cls.UNCONFIRMED(
- details=TransactionDetails._read(buf),
- )
- if variant == 2:
- return cls.CONFIRMED(
- details=TransactionDetails._read(buf),
- confirmation=Confirmation._read(buf),
- )
-
- raise InternalError("Raw enum value doesn't match any cases")
-
- def _write(self, buf):
- if self.is_unconfirmed():
- buf.writeI32(1)
- self.details._write(buf)
- if self.is_confirmed():
- buf.writeI32(2)
- self.details._write(buf)
- self.confirmation._write(buf)
-
-
-# Now, a little trick - we make each nested variant class be a subclass of the main
-# enum class, so that method calls and instance checks etc will work intuitively.
-# We might be able to do this a little more neatly with a metaclass, but this'll do.
-Transaction.UNCONFIRMED = type("Transaction.UNCONFIRMED", (Transaction.UNCONFIRMED, Transaction,), {})
-Transaction.CONFIRMED = type("Transaction.CONFIRMED", (Transaction.CONFIRMED, Transaction,), {})
-
-
-
-
-
-
-
-class BlockchainConfig(ViaFfiUsingByteBuffer, object):
- def __init__(self):
- raise RuntimeError("BlockchainConfig cannot be instantiated directly")
-
- # Each enum variant is a nested class of the enum itself.
- class ELECTRUM(object):
- def __init__(self,config ):
-
- self.config = config
-
-
- def __str__(self):
- return "BlockchainConfig.ELECTRUM(config={} )".format(self.config )
-
- def __eq__(self, other):
- if not other.is_electrum():
- return False
- if self.config != other.config:
- return False
- return True
- class ESPLORA(object):
- def __init__(self,config ):
-
- self.config = config
-
-
- def __str__(self):
- return "BlockchainConfig.ESPLORA(config={} )".format(self.config )
-
- def __eq__(self, other):
- if not other.is_esplora():
- return False
- if self.config != other.config:
- return False
- return True
-
-
- # For each variant, we have an `is_NAME` method for easily checking
- # whether an instance is that variant.
- def is_electrum(self):
- return isinstance(self, BlockchainConfig.ELECTRUM)
- def is_esplora(self):
- return isinstance(self, BlockchainConfig.ESPLORA)
-
-
- @classmethod
- def _read(cls, buf):
- variant = buf.readI32()
-
- if variant == 1:
- return cls.ELECTRUM(
- config=ElectrumConfig._read(buf),
- )
- if variant == 2:
- return cls.ESPLORA(
- config=EsploraConfig._read(buf),
- )
-
- raise InternalError("Raw enum value doesn't match any cases")
-
- def _write(self, buf):
- if self.is_electrum():
- buf.writeI32(1)
- self.config._write(buf)
- if self.is_esplora():
- buf.writeI32(2)
- self.config._write(buf)
-
-
-# Now, a little trick - we make each nested variant class be a subclass of the main
-# enum class, so that method calls and instance checks etc will work intuitively.
-# We might be able to do this a little more neatly with a metaclass, but this'll do.
-BlockchainConfig.ELECTRUM = type("BlockchainConfig.ELECTRUM", (BlockchainConfig.ELECTRUM, BlockchainConfig,), {})
-BlockchainConfig.ESPLORA = type("BlockchainConfig.ESPLORA", (BlockchainConfig.ESPLORA, BlockchainConfig,), {})
-
-
-
-
-
-
-class MnemonicType(ViaFfiUsingByteBuffer, enum.Enum):
- WORDS12 = 1
- WORDS15 = 2
- WORDS18 = 3
- WORDS21 = 4
- WORDS24 = 5
-
-
- @staticmethod
- def _read(buf):
- variant = buf.readI32()
- if variant == 1:
- return MnemonicType.WORDS12
- if variant == 2:
- return MnemonicType.WORDS15
- if variant == 3:
- return MnemonicType.WORDS18
- if variant == 4:
- return MnemonicType.WORDS21
- if variant == 5:
- return MnemonicType.WORDS24
-
- raise InternalError("Raw enum value doesn't match any cases")
-
- def _write(self, buf):
- if self is MnemonicType.WORDS12:
- i = 1
- buf.writeI32(1)
- if self is MnemonicType.WORDS15:
- i = 2
- buf.writeI32(2)
- if self is MnemonicType.WORDS18:
- i = 3
- buf.writeI32(3)
- if self is MnemonicType.WORDS21:
- i = 4
- buf.writeI32(4)
- if self is MnemonicType.WORDS24:
- i = 5
- buf.writeI32(5)
-
-
-
-
-
-def generate_extended_key(network,mnemonic_type,password):
- network = network
- mnemonic_type = mnemonic_type
- password = (None if password is None else password)
- _retval = rust_call_with_error(BdkError,_UniFFILib.bdk_b9b3_generate_extended_key,network._lower(),mnemonic_type._lower(),FfiConverterOptionalString._lower(password))
- return ExtendedKeyInfo._lift(_retval)
-
-
-
-def restore_extended_key(network,mnemonic,password):
- network = network
- mnemonic = mnemonic
- password = (None if password is None else password)
- _retval = rust_call_with_error(BdkError,_UniFFILib.bdk_b9b3_restore_extended_key,network._lower(),FfiConverterString._lower(mnemonic),FfiConverterOptionalString._lower(password))
- return ExtendedKeyInfo._lift(_retval)
-
-
-
-class OfflineWallet(object):
- def __init__(self, descriptor,network,database_config):
- descriptor = descriptor
- network = network
- database_config = database_config
- self._pointer = rust_call_with_error(BdkError,_UniFFILib.bdk_b9b3_OfflineWallet_new,FfiConverterString._lower(descriptor),network._lower(),database_config._lower())
-
- def __del__(self):
- # In case of partial initialization of instances.
- pointer = getattr(self, "_pointer", None)
- if pointer is not None:
- rust_call(_UniFFILib.ffi_bdk_b9b3_OfflineWallet_object_free, pointer)
-
- # Used by alternative constructors or any methods which return this type.
- @classmethod
- def _make_instance_(cls, pointer):
- # Lightly yucky way to bypass the usual __init__ logic
- # and just create a new instance with the required pointer.
- inst = cls.__new__(cls)
- inst._pointer = pointer
- return inst
-
-
-
- def get_new_address(self, ):
- _retval = rust_call(_UniFFILib.bdk_b9b3_OfflineWallet_get_new_address,self._pointer,)
- return FfiConverterString._lift(_retval)
-
- def get_last_unused_address(self, ):
- _retval = rust_call(_UniFFILib.bdk_b9b3_OfflineWallet_get_last_unused_address,self._pointer,)
- return FfiConverterString._lift(_retval)
-
- def get_balance(self, ):
- _retval = rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OfflineWallet_get_balance,self._pointer,)
- return FfiConverterUInt64._lift(_retval)
-
- def sign(self, psbt):
- psbt = psbt
- rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OfflineWallet_sign,self._pointer,psbt._lower())
-
- def get_transactions(self, ):
- _retval = rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OfflineWallet_get_transactions,self._pointer,)
- return FfiConverterSequenceEnumTransaction._lift(_retval)
-
-
-
- @classmethod
- def _read(cls, buf):
- ptr = buf.readU64()
- if ptr == 0:
- raise InternalError("Raw pointer value was null")
- return cls._lift(ptr)
-
- @classmethod
- def _write(cls, value, buf):
- if not isinstance(value, OfflineWallet):
- raise TypeError("Expected OfflineWallet instance, {} found".format(value.__class__.__name__))
- buf.writeU64(value._lower())
-
- @classmethod
- def _lift(cls, pointer):
- return cls._make_instance_(pointer)
-
- def _lower(self):
- return self._pointer
-
-
-class OnlineWallet(object):
- def __init__(self, descriptor,change_descriptor,network,database_config,blockchain_config):
- descriptor = descriptor
- change_descriptor = (None if change_descriptor is None else change_descriptor)
- network = network
- database_config = database_config
- blockchain_config = blockchain_config
- self._pointer = rust_call_with_error(BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_new,FfiConverterString._lower(descriptor),FfiConverterOptionalString._lower(change_descriptor),network._lower(),database_config._lower(),blockchain_config._lower())
-
- def __del__(self):
- # In case of partial initialization of instances.
- pointer = getattr(self, "_pointer", None)
- if pointer is not None:
- rust_call(_UniFFILib.ffi_bdk_b9b3_OnlineWallet_object_free, pointer)
-
- # Used by alternative constructors or any methods which return this type.
- @classmethod
- def _make_instance_(cls, pointer):
- # Lightly yucky way to bypass the usual __init__ logic
- # and just create a new instance with the required pointer.
- inst = cls.__new__(cls)
- inst._pointer = pointer
- return inst
-
-
-
- def get_new_address(self, ):
- _retval = rust_call(_UniFFILib.bdk_b9b3_OnlineWallet_get_new_address,self._pointer,)
- return FfiConverterString._lift(_retval)
-
- def get_last_unused_address(self, ):
- _retval = rust_call(_UniFFILib.bdk_b9b3_OnlineWallet_get_last_unused_address,self._pointer,)
- return FfiConverterString._lift(_retval)
-
- def get_balance(self, ):
- _retval = rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_get_balance,self._pointer,)
- return FfiConverterUInt64._lift(_retval)
-
- def sign(self, psbt):
- psbt = psbt
- rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_sign,self._pointer,psbt._lower())
-
- def get_transactions(self, ):
- _retval = rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_get_transactions,self._pointer,)
- return FfiConverterSequenceEnumTransaction._lift(_retval)
-
- def get_network(self, ):
- _retval = rust_call(_UniFFILib.bdk_b9b3_OnlineWallet_get_network,self._pointer,)
- return Network._lift(_retval)
-
- def sync(self, progress_update,max_address_param):
- progress_update = progress_update
- max_address_param = (None if max_address_param is None else int(max_address_param))
- rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_sync,self._pointer,FfiConverterCallbackInterfaceBdkProgress._lower(progress_update),FfiConverterOptionalUInt32._lower(max_address_param))
-
- def broadcast(self, psbt):
- psbt = psbt
- _retval = rust_call_with_error(
- BdkError,_UniFFILib.bdk_b9b3_OnlineWallet_broadcast,self._pointer,psbt._lower())
- return Transaction._lift(_retval)
-
-
-
- @classmethod
- def _read(cls, buf):
- ptr = buf.readU64()
- if ptr == 0:
- raise InternalError("Raw pointer value was null")
- return cls._lift(ptr)
-
- @classmethod
- def _write(cls, value, buf):
- if not isinstance(value, OnlineWallet):
- raise TypeError("Expected OnlineWallet instance, {} found".format(value.__class__.__name__))
- buf.writeU64(value._lower())
-
- @classmethod
- def _lift(cls, pointer):
- return cls._make_instance_(pointer)
-
- def _lower(self):
- return self._pointer
-
-
-class PartiallySignedBitcoinTransaction(object):
- def __init__(self, wallet,recipient,amount,fee_rate):
- wallet = wallet
- recipient = recipient
- amount = int(amount)
- fee_rate = (None if fee_rate is None else float(fee_rate))
- self._pointer = rust_call_with_error(BdkError,_UniFFILib.bdk_b9b3_PartiallySignedBitcoinTransaction_new,wallet._lower(),FfiConverterString._lower(recipient),FfiConverterUInt64._lower(amount),FfiConverterOptionalFloat._lower(fee_rate))
-
- def __del__(self):
- # In case of partial initialization of instances.
- pointer = getattr(self, "_pointer", None)
- if pointer is not None:
- rust_call(_UniFFILib.ffi_bdk_b9b3_PartiallySignedBitcoinTransaction_object_free, pointer)
-
- # Used by alternative constructors or any methods which return this type.
- @classmethod
- def _make_instance_(cls, pointer):
- # Lightly yucky way to bypass the usual __init__ logic
- # and just create a new instance with the required pointer.
- inst = cls.__new__(cls)
- inst._pointer = pointer
- return inst
-
-
-
-
-
- @classmethod
- def _read(cls, buf):
- ptr = buf.readU64()
- if ptr == 0:
- raise InternalError("Raw pointer value was null")
- return cls._lift(ptr)
-
- @classmethod
- def _write(cls, value, buf):
- if not isinstance(value, PartiallySignedBitcoinTransaction):
- raise TypeError("Expected PartiallySignedBitcoinTransaction instance, {} found".format(value.__class__.__name__))
- buf.writeU64(value._lower())
-
- @classmethod
- def _lift(cls, pointer):
- return cls._make_instance_(pointer)
-
- def _lower(self):
- return self._pointer
-
-class SledDbConfiguration(ViaFfiUsingByteBuffer, object):
- def __init__(self,path, tree_name ):
- self.path = path
- self.tree_name = tree_name
-
- def __str__(self):
- return "SledDbConfiguration(path={}, tree_name={} )".format(self.path, self.tree_name )
-
- def __eq__(self, other):
- if self.path != other.path:
- return False
- if self.tree_name != other.tree_name:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return SledDbConfiguration(
- path=FfiConverterString._read(buf),
- tree_name=FfiConverterString._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterString._write(self.path, buf)
- FfiConverterString._write(self.tree_name, buf)
-
-class TransactionDetails(ViaFfiUsingByteBuffer, object):
- def __init__(self,fees, received, sent, txid ):
- self.fees = fees
- self.received = received
- self.sent = sent
- self.txid = txid
-
- def __str__(self):
- return "TransactionDetails(fees={}, received={}, sent={}, txid={} )".format(self.fees, self.received, self.sent, self.txid )
-
- def __eq__(self, other):
- if self.fees != other.fees:
- return False
- if self.received != other.received:
- return False
- if self.sent != other.sent:
- return False
- if self.txid != other.txid:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return TransactionDetails(
- fees=FfiConverterOptionalUInt64._read(buf),
- received=FfiConverterUInt64._read(buf),
- sent=FfiConverterUInt64._read(buf),
- txid=FfiConverterString._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterOptionalUInt64._write(self.fees, buf)
- FfiConverterUInt64._write(self.received, buf)
- FfiConverterUInt64._write(self.sent, buf)
- FfiConverterString._write(self.txid, buf)
-
-class Confirmation(ViaFfiUsingByteBuffer, object):
- def __init__(self,height, timestamp ):
- self.height = height
- self.timestamp = timestamp
-
- def __str__(self):
- return "Confirmation(height={}, timestamp={} )".format(self.height, self.timestamp )
-
- def __eq__(self, other):
- if self.height != other.height:
- return False
- if self.timestamp != other.timestamp:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return Confirmation(
- height=FfiConverterUInt32._read(buf),
- timestamp=FfiConverterUInt64._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterUInt32._write(self.height, buf)
- FfiConverterUInt64._write(self.timestamp, buf)
-
-class ElectrumConfig(ViaFfiUsingByteBuffer, object):
- def __init__(self,url, socks5, retry, timeout, stop_gap ):
- self.url = url
- self.socks5 = socks5
- self.retry = retry
- self.timeout = timeout
- self.stop_gap = stop_gap
-
- def __str__(self):
- return "ElectrumConfig(url={}, socks5={}, retry={}, timeout={}, stop_gap={} )".format(self.url, self.socks5, self.retry, self.timeout, self.stop_gap )
-
- def __eq__(self, other):
- if self.url != other.url:
- return False
- if self.socks5 != other.socks5:
- return False
- if self.retry != other.retry:
- return False
- if self.timeout != other.timeout:
- return False
- if self.stop_gap != other.stop_gap:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return ElectrumConfig(
- url=FfiConverterString._read(buf),
- socks5=FfiConverterOptionalString._read(buf),
- retry=FfiConverterUInt8._read(buf),
- timeout=FfiConverterOptionalUInt8._read(buf),
- stop_gap=FfiConverterUInt64._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterString._write(self.url, buf)
- FfiConverterOptionalString._write(self.socks5, buf)
- FfiConverterUInt8._write(self.retry, buf)
- FfiConverterOptionalUInt8._write(self.timeout, buf)
- FfiConverterUInt64._write(self.stop_gap, buf)
-
-class EsploraConfig(ViaFfiUsingByteBuffer, object):
- def __init__(self,base_url, proxy, timeout_read, timeout_write, stop_gap ):
- self.base_url = base_url
- self.proxy = proxy
- self.timeout_read = timeout_read
- self.timeout_write = timeout_write
- self.stop_gap = stop_gap
-
- def __str__(self):
- return "EsploraConfig(base_url={}, proxy={}, timeout_read={}, timeout_write={}, stop_gap={} )".format(self.base_url, self.proxy, self.timeout_read, self.timeout_write, self.stop_gap )
-
- def __eq__(self, other):
- if self.base_url != other.base_url:
- return False
- if self.proxy != other.proxy:
- return False
- if self.timeout_read != other.timeout_read:
- return False
- if self.timeout_write != other.timeout_write:
- return False
- if self.stop_gap != other.stop_gap:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return EsploraConfig(
- base_url=FfiConverterString._read(buf),
- proxy=FfiConverterOptionalString._read(buf),
- timeout_read=FfiConverterUInt64._read(buf),
- timeout_write=FfiConverterUInt64._read(buf),
- stop_gap=FfiConverterUInt64._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterString._write(self.base_url, buf)
- FfiConverterOptionalString._write(self.proxy, buf)
- FfiConverterUInt64._write(self.timeout_read, buf)
- FfiConverterUInt64._write(self.timeout_write, buf)
- FfiConverterUInt64._write(self.stop_gap, buf)
-
-class ExtendedKeyInfo(ViaFfiUsingByteBuffer, object):
- def __init__(self,mnemonic, xprv, fingerprint ):
- self.mnemonic = mnemonic
- self.xprv = xprv
- self.fingerprint = fingerprint
-
- def __str__(self):
- return "ExtendedKeyInfo(mnemonic={}, xprv={}, fingerprint={} )".format(self.mnemonic, self.xprv, self.fingerprint )
-
- def __eq__(self, other):
- if self.mnemonic != other.mnemonic:
- return False
- if self.xprv != other.xprv:
- return False
- if self.fingerprint != other.fingerprint:
- return False
- return True
-
- @staticmethod
- def _read(buf):
- return ExtendedKeyInfo(
- mnemonic=FfiConverterString._read(buf),
- xprv=FfiConverterString._read(buf),
- fingerprint=FfiConverterString._read(buf)
- )
-
- def _write(self, buf):
- FfiConverterString._write(self.mnemonic, buf)
- FfiConverterString._write(self.xprv, buf)
- FfiConverterString._write(self.fingerprint, buf)
-
-class BdkError(ViaFfiUsingByteBuffer):
-
- # Each variant is a nested class of the error itself.
- # It just carries a string error message, so no special implementation is necessary.
- class InvalidU32Bytes(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(1)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Generic(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(2)
- message = str(self)
- FfiConverterString._write(message, buf)
- class ScriptDoesntHaveAddressForm(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(3)
- message = str(self)
- FfiConverterString._write(message, buf)
- class NoRecipients(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(4)
- message = str(self)
- FfiConverterString._write(message, buf)
- class NoUtxosSelected(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(5)
- message = str(self)
- FfiConverterString._write(message, buf)
- class OutputBelowDustLimit(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(6)
- message = str(self)
- FfiConverterString._write(message, buf)
- class InsufficientFunds(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(7)
- message = str(self)
- FfiConverterString._write(message, buf)
- class BnBTotalTriesExceeded(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(8)
- message = str(self)
- FfiConverterString._write(message, buf)
- class BnBNoExactMatch(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(9)
- message = str(self)
- FfiConverterString._write(message, buf)
- class UnknownUtxo(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(10)
- message = str(self)
- FfiConverterString._write(message, buf)
- class TransactionNotFound(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(11)
- message = str(self)
- FfiConverterString._write(message, buf)
- class TransactionConfirmed(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(12)
- message = str(self)
- FfiConverterString._write(message, buf)
- class IrreplaceableTransaction(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(13)
- message = str(self)
- FfiConverterString._write(message, buf)
- class FeeRateTooLow(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(14)
- message = str(self)
- FfiConverterString._write(message, buf)
- class FeeTooLow(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(15)
- message = str(self)
- FfiConverterString._write(message, buf)
- class FeeRateUnavailable(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(16)
- message = str(self)
- FfiConverterString._write(message, buf)
- class MissingKeyOrigin(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(17)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Key(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(18)
- message = str(self)
- FfiConverterString._write(message, buf)
- class ChecksumMismatch(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(19)
- message = str(self)
- FfiConverterString._write(message, buf)
- class SpendingPolicyRequired(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(20)
- message = str(self)
- FfiConverterString._write(message, buf)
- class InvalidPolicyPathError(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(21)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Signer(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(22)
- message = str(self)
- FfiConverterString._write(message, buf)
- class InvalidNetwork(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(23)
- message = str(self)
- FfiConverterString._write(message, buf)
- class InvalidProgressValue(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(24)
- message = str(self)
- FfiConverterString._write(message, buf)
- class ProgressUpdateError(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(25)
- message = str(self)
- FfiConverterString._write(message, buf)
- class InvalidOutpoint(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(26)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Descriptor(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(27)
- message = str(self)
- FfiConverterString._write(message, buf)
- class AddressValidator(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(28)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Encode(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(29)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Miniscript(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(30)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Bip32(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(31)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Secp256k1(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(32)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Json(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(33)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Hex(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(34)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Psbt(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(35)
- message = str(self)
- FfiConverterString._write(message, buf)
- class PsbtParse(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(36)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Electrum(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(37)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Esplora(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(38)
- message = str(self)
- FfiConverterString._write(message, buf)
- class Sled(ViaFfiUsingByteBuffer, Exception):
- def _write(self, buf):
- buf.writeI32(39)
- message = str(self)
- FfiConverterString._write(message, buf)
-
- @classmethod
- def _read(cls, buf):
- variant = buf.readI32()
- if variant == 1:
- return cls.InvalidU32Bytes(FfiConverterString._read(buf))
- if variant == 2:
- return cls.Generic(FfiConverterString._read(buf))
- if variant == 3:
- return cls.ScriptDoesntHaveAddressForm(FfiConverterString._read(buf))
- if variant == 4:
- return cls.NoRecipients(FfiConverterString._read(buf))
- if variant == 5:
- return cls.NoUtxosSelected(FfiConverterString._read(buf))
- if variant == 6:
- return cls.OutputBelowDustLimit(FfiConverterString._read(buf))
- if variant == 7:
- return cls.InsufficientFunds(FfiConverterString._read(buf))
- if variant == 8:
- return cls.BnBTotalTriesExceeded(FfiConverterString._read(buf))
- if variant == 9:
- return cls.BnBNoExactMatch(FfiConverterString._read(buf))
- if variant == 10:
- return cls.UnknownUtxo(FfiConverterString._read(buf))
- if variant == 11:
- return cls.TransactionNotFound(FfiConverterString._read(buf))
- if variant == 12:
- return cls.TransactionConfirmed(FfiConverterString._read(buf))
- if variant == 13:
- return cls.IrreplaceableTransaction(FfiConverterString._read(buf))
- if variant == 14:
- return cls.FeeRateTooLow(FfiConverterString._read(buf))
- if variant == 15:
- return cls.FeeTooLow(FfiConverterString._read(buf))
- if variant == 16:
- return cls.FeeRateUnavailable(FfiConverterString._read(buf))
- if variant == 17:
- return cls.MissingKeyOrigin(FfiConverterString._read(buf))
- if variant == 18:
- return cls.Key(FfiConverterString._read(buf))
- if variant == 19:
- return cls.ChecksumMismatch(FfiConverterString._read(buf))
- if variant == 20:
- return cls.SpendingPolicyRequired(FfiConverterString._read(buf))
- if variant == 21:
- return cls.InvalidPolicyPathError(FfiConverterString._read(buf))
- if variant == 22:
- return cls.Signer(FfiConverterString._read(buf))
- if variant == 23:
- return cls.InvalidNetwork(FfiConverterString._read(buf))
- if variant == 24:
- return cls.InvalidProgressValue(FfiConverterString._read(buf))
- if variant == 25:
- return cls.ProgressUpdateError(FfiConverterString._read(buf))
- if variant == 26:
- return cls.InvalidOutpoint(FfiConverterString._read(buf))
- if variant == 27:
- return cls.Descriptor(FfiConverterString._read(buf))
- if variant == 28:
- return cls.AddressValidator(FfiConverterString._read(buf))
- if variant == 29:
- return cls.Encode(FfiConverterString._read(buf))
- if variant == 30:
- return cls.Miniscript(FfiConverterString._read(buf))
- if variant == 31:
- return cls.Bip32(FfiConverterString._read(buf))
- if variant == 32:
- return cls.Secp256k1(FfiConverterString._read(buf))
- if variant == 33:
- return cls.Json(FfiConverterString._read(buf))
- if variant == 34:
- return cls.Hex(FfiConverterString._read(buf))
- if variant == 35:
- return cls.Psbt(FfiConverterString._read(buf))
- if variant == 36:
- return cls.PsbtParse(FfiConverterString._read(buf))
- if variant == 37:
- return cls.Electrum(FfiConverterString._read(buf))
- if variant == 38:
- return cls.Esplora(FfiConverterString._read(buf))
- if variant == 39:
- return cls.Sled(FfiConverterString._read(buf))
-
- raise InternalError("Raw enum value doesn't match any cases")
-
-
-# Declaration and FfiConverters for BdkProgress Callback Interface
-
-class BdkProgress:
- def update(progress,message):
- raise NotImplementedError
-
-
-
-def py_foreignCallbackCallbackInterfaceBdkProgress(handle, method, args, buf_ptr):
-
- def invoke_update(python_callback, args):
- rval = None
- with args.consumeWithStream() as buf:
- rval = python_callback.update(
- FfiConverterFloat._read(buf),
- FfiConverterOptionalString._read(buf)
- )
- return RustBuffer.alloc(0)
- # TODO catch errors and report them back to Rust.
- # https://github.com/mozilla/uniffi-rs/issues/351
-
-
- cb = FfiConverterCallbackInterfaceBdkProgress._lift(handle)
- if not cb:
- raise InternalError("No callback in handlemap; this is a Uniffi bug")
-
- if method == IDX_CALLBACK_FREE:
- FfiConverterCallbackInterfaceBdkProgress.drop(handle)
- # No return value.
- # See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs`
- return 0
-
- if method == 1:
- buf_ptr[0] = invoke_update(cb, args)
- # Value written to out buffer.
- # See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs`
- return 1
-
-
- # This should never happen, because an out of bounds method index won't
- # ever be used. Once we can catch errors, we should return an InternalException.
- # https://github.com/mozilla/uniffi-rs/issues/351
-
- # An unexpected error happened.
- # See docs of ForeignCallback in `uniffi/src/ffi/foreigncallbacks.rs`
- return -1
-
-# We need to keep this function reference alive:
-# if they get GC'd while in use then UniFFI internals could attempt to call a function
-# that is in freed memory.
-# That would be...uh...bad. Yeah, that's the word. Bad.
-foreignCallbackCallbackInterfaceBdkProgress = FOREIGN_CALLBACK_T(py_foreignCallbackCallbackInterfaceBdkProgress)
-
-# The FfiConverter which transforms the Callbacks in to Handles to pass to Rust.
-rust_call(lambda err: _UniFFILib.ffi_bdk_b9b3_BdkProgress_init_callback(foreignCallbackCallbackInterfaceBdkProgress, err))
-FfiConverterCallbackInterfaceBdkProgress = FfiConverterCallbackInterface(foreignCallbackCallbackInterfaceBdkProgress)
-class FfiConverterUInt8(Primitive):
- @staticmethod
- def _read(buf):
- return FfiConverterUInt8._lift(buf.readU8())
-
- @staticmethod
- def _write(value, buf):
- buf.writeU8(FfiConverterUInt8._lower(value))
-class FfiConverterUInt32(Primitive):
- @staticmethod
- def _read(buf):
- return FfiConverterUInt32._lift(buf.readU32())
-
- @staticmethod
- def _write(value, buf):
- buf.writeU32(FfiConverterUInt32._lower(value))
-class FfiConverterUInt64(Primitive):
- @staticmethod
- def _read(buf):
- return FfiConverterUInt64._lift(buf.readU64())
-
- @staticmethod
- def _write(value, buf):
- buf.writeU64(FfiConverterUInt64._lower(value))
-class FfiConverterFloat(Primitive):
- @staticmethod
- def _read(buf):
- return FfiConverterFloat._lift(buf.readFloat())
-
- @staticmethod
- def _write(value, buf):
- buf.writeFloat(FfiConverterFloat._lower(value))
-class FfiConverterString:
- @staticmethod
- def _read(buf):
- size = buf.readI32()
- if size < 0:
- raise InternalError("Unexpected negative string length")
- utf8Bytes = buf.read(size)
- return utf8Bytes.decode("utf-8")
-
- @staticmethod
- def _write(value, buf):
- utf8Bytes = value.encode("utf-8")
- buf.writeI32(len(utf8Bytes))
- buf.write(utf8Bytes)
-
- @staticmethod
- def _lift(buf):
- with buf.consumeWithStream() as stream:
- return stream.read(stream.remaining()).decode("utf-8")
-
- @staticmethod
- def _lower(value):
- with RustBuffer.allocWithBuilder() as builder:
- builder.write(value.encode("utf-8"))
- return builder.finalize()
-# Helper code for OfflineWallet class is found in ObjectTemplate.py
-# Helper code for OnlineWallet class is found in ObjectTemplate.py
-# Helper code for PartiallySignedBitcoinTransaction class is found in ObjectTemplate.py
-# Helper code for Confirmation record is found in RecordTemplate.py
-# Helper code for ElectrumConfig record is found in RecordTemplate.py
-# Helper code for EsploraConfig record is found in RecordTemplate.py
-# Helper code for ExtendedKeyInfo record is found in RecordTemplate.py
-# Helper code for SledDbConfiguration record is found in RecordTemplate.py
-# Helper code for TransactionDetails record is found in RecordTemplate.py
-# Helper code for BlockchainConfig enum is found in EnumTemplate.py
-# Helper code for DatabaseConfig enum is found in EnumTemplate.py
-# Helper code for MnemonicType enum is found in EnumTemplate.py
-# Helper code for Network enum is found in EnumTemplate.py
-# Helper code for Transaction enum is found in EnumTemplate.py
-# Helper code for BdkError error is found in ErrorTemplate.py
-
-
-class FfiConverterOptionalUInt8(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterOptional._write(value, buf, lambda v, buf: FfiConverterUInt8._write(v, buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterOptional._read(buf, lambda buf: FfiConverterUInt8._read(buf))
-
-
-class FfiConverterOptionalUInt32(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterOptional._write(value, buf, lambda v, buf: FfiConverterUInt32._write(v, buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterOptional._read(buf, lambda buf: FfiConverterUInt32._read(buf))
-
-
-class FfiConverterOptionalUInt64(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterOptional._write(value, buf, lambda v, buf: FfiConverterUInt64._write(v, buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterOptional._read(buf, lambda buf: FfiConverterUInt64._read(buf))
-
-
-class FfiConverterOptionalFloat(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterOptional._write(value, buf, lambda v, buf: FfiConverterFloat._write(v, buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterOptional._read(buf, lambda buf: FfiConverterFloat._read(buf))
-
-
-class FfiConverterOptionalString(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterOptional._write(value, buf, lambda v, buf: FfiConverterString._write(v, buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterOptional._read(buf, lambda buf: FfiConverterString._read(buf))
-
-
-class FfiConverterSequenceEnumTransaction(FfiConverterUsingByteBuffer):
- @staticmethod
- def _write(value, buf):
- FfiConverterSequence._write(value, buf, lambda v, buf: v._write(buf))
-
- @staticmethod
- def _read(buf):
- return FfiConverterSequence._read(buf, lambda buf: Transaction._read(buf))
-
-__all__ = [
- "InternalError",
- "Network",
- "DatabaseConfig",
- "Transaction",
- "BlockchainConfig",
- "MnemonicType",
- "SledDbConfiguration",
- "TransactionDetails",
- "Confirmation",
- "ElectrumConfig",
- "EsploraConfig",
- "ExtendedKeyInfo",
- "generate_extended_key",
- "restore_extended_key",
- "OfflineWallet",
- "OnlineWallet",
- "PartiallySignedBitcoinTransaction",
- "BdkError",
- "BdkProgress",
-]
-