Compare commits

...

696 Commits

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

Pull request description:

  ### Description

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

  ### Notes to the reviewers

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

  ### Changelog notice

  None, only CI changes.

  ### Checklists

  #### All Submissions:

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

ACKs for top commit:
  thunderbiscuit:
    ACK 1da01b4a0b.

Tree-SHA512: 72f7d8dbef791daebf3f4d9d92722f1f3780d173501673ca6f47af39dd2102c85944ba603e4e9213d44a294ab1cec43dff82213fe53c5dea663279473be64a15
2023-08-10 14:03:52 -05:00
Steve Myers
1da01b4a0b ci: change rust stable version to 0.71.0 2023-08-10 11:54:33 -05:00
Steve Myers
f1ba03bf50 ci: fix to work with bdk 0.28.1 and msrv 1.61.0 2023-08-10 11:28:36 -05:00
thunderbiscuit
bc182c7164 Update CI actions to their latest versions
* checkout (v3)
* setup-java (v3)
* cache (v3)
* upload-artifact (v3)
* setup-python (v4)
2023-07-05 14:03:42 -04:00
thunderbiscuit
5fc189717d Fix CI bdk-jvm 2023-07-04 16:19:55 -04:00
thunderbiscuit
849bfe79c1 Add Windows target to Kotlin/JVM published library 2023-07-04 12:32:00 -04:00
thunderbiscuit
dc79b78b2d Fix Python readme and integrate new scripts 2023-06-30 16:18:27 -04:00
thunderbiscuit
7cc08f1d6f Fix publishing Python CI workflow 2023-06-30 16:17:46 -04:00
thunderbiscuit
031fcb02da Run Python Windows tests in CI 2023-06-30 16:01:01 -04:00
thunderbiscuit
5f9b5682e5 Use macos-13 image to test and publish Python libraries 2023-06-23 14:42:36 -04:00
thunderbiscuit
d0a7315c9d Remove patch release issue template 2023-06-16 22:28:32 -04:00
thunderbiscuit
0bfc56b0e8 Fix minor release issue template 2023-06-16 22:28:09 -04:00
thunderbiscuit
3dd6c203e8 Bump snapshot and dev versions of libraries 2023-06-16 22:11:12 -04:00
thunderbiscuit
76acbf575b Add release 0.29.0 to changelog 2023-06-16 22:09:14 -04:00
thunderbiscuit
039b64de5c Update JVM readme with specific Rust version 2023-06-15 11:10:28 -04:00
thunderbiscuit
fe7e4e21c0 Update Android readme with specific Rust and NDK versions 2023-06-15 11:09:48 -04:00
thunderbiscuit
77f89afc68 Update library version to 0.29.0 2023-06-15 10:15:23 -04:00
thunderbiscuit
25033f6bd6 Add Kotlin API docs for Script.toBytes 2023-06-12 13:36:50 -04:00
thunderbiscuit
3cb2c2c394 Expose Script.to_bytes() method 2023-06-12 13:36:44 -04:00
Steve Myers
5092987b26 [swift] suppress keyword escape warnings 2023-06-06 14:17:30 -05:00
Steve Myers
aea25dbf21 Update bdk-swift local build script 2023-06-05 16:45:29 -05:00
thunderbiscuit
ed67eba910 Align JVM target version for Kotlin and Java compile tasks
This commit resolves a build error related to mismatched JVM target
versions for the Kotlin and Java compile tasks. Previously, the
'compileJava' task was targeting JVM 11, while the 'compileKotlin'
task was targeting JVM 8.

Both tasks have now been set to target JVM 11, ensuring consistency
and eliminating the build error.
2023-06-05 10:35:23 -04:00
thunderbiscuit
90606b2455 Small style cleanups in JVM Gradle plugin 2023-06-05 10:09:27 -04:00
yellowhatpro
49e8fe461e added support for x86_64-pc-windows-msvc 64-bit MSVC 2023-06-05 10:09:14 -04:00
Matthew
de88184b8c github: add feature request issue template 2023-05-30 15:27:34 -05:00
thunderbiscuit
3be2c0495f Clean up is_mine method body 2023-05-15 09:01:39 -04:00
thunderbiscuit
2c4c64515f Fix Clippy warning 2023-05-03 15:13:22 -04:00
thunderbiscuit
17323d3184 Add Kotlin API docs for isMine method 2023-05-03 14:21:37 -04:00
thunderbiscuit
b382511a9e Add is_mine method on Wallet type
Closes #354
2023-05-03 14:19:50 -04:00
Steve Myers
d3895441d3 Update bdk-swift/build-local-swift.sh for aarch64-apple-ios-sim to use release-smaller profile 2023-05-01 11:37:05 -05:00
Steve Myers
269512a673 Fix bdk-swift/build-local-swift.sh for aarch64-apple-ios-sim 2023-05-01 10:40:07 -05:00
thunderbiscuit
d27206787a Add supported Python library changes to changelog 2023-04-28 09:00:37 -04:00
thunderbiscuit
c1b1fd6f5d Update changelog for 0.28.0 release 2023-04-28 08:57:11 -04:00
thunderbiscuit
7062fbd047 Update minor_release and patch_release templates 2023-04-28 08:56:58 -04:00
thunderbiscuit
0e34a6bacf Bump snapshot and dev versions of libraries 2023-04-28 08:56:47 -04:00
thunderbiscuit
89e85a20cf Fix Python libraries' names to prepare for releasing 2023-04-25 13:53:27 -04:00
David Sterling
d8718c3f05 Update bdk-jvm README build instructions
The current build instructions for bdk-jvm are insufficient for someone to build bdk-jvm from scratch. It's not outlined that JDK 11 and Rust is required on the system.
2023-04-25 13:48:32 -04:00
thunderbiscuit
871a06d1ce Add library build task to Android test CI workflow 2023-04-24 14:17:58 -04:00
thunderbiscuit
b820d6a2ba Remove support for Python 3.6 and 3.7 2023-04-24 13:57:12 -04:00
thunderbiscuit
79d9fa2909 Use ubuntu-20.04 image for all Linux CI runs 2023-04-24 13:53:56 -04:00
thunderbiscuit
a0e0467d39 Add workflow dispatch to all test workflows 2023-04-24 13:52:42 -04:00
thunderbiscuit
f2296704e6 Pin Rust version in CI workflows to 1.67 2023-04-24 13:51:37 -04:00
thunderbiscuit
b8b60dda87 Prepare language bindings libraries for 0.28 release 2023-04-17 14:34:03 -04:00
Steve Myers
a50e19e7e0 Update bdk to 0.28 2023-04-13 10:22:53 -04:00
Steve Myers
fab9ae8ae5 Add PartiallySignedTransaction.json_serialize() function 2023-04-13 09:21:22 -04:00
thunderbiscuit
478b12c489 Add API docs for fromScript method on Address 2023-04-13 08:50:08 -04:00
andreasgriffin
63b85b9100 Add from_script method to Address type 2023-04-13 08:50:03 -04:00
Steve Myers
0e6b472793 Merge bitcoindevkit/bdk-ffi#335: Use version 21 of the Android NDK in the CI test, build, and publish workflows
beb75dd552 Use version 21 of the Android NDK in the CI test, build, and publish workflows (thunderbiscuit)

Pull request description:

  This PR reverts an update to our Android CI workflows.

  For info on why this is needed, see issues #242 and #243.

ACKs for top commit:
  notmandatory:
    ACK beb75dd552

Tree-SHA512: dfee0b1f335318b86fa490fa85e7ef5d7a032e01a78db64a186c5d75e9e77e8f0e2af58ee5407d4fe38a0aa3aabbc7b06b23189aef0dfaad1d246a354452870d
2023-04-12 21:38:07 -05:00
thunderbiscuit
beb75dd552 Use version 21 of the Android NDK in the CI test, build, and publish workflows 2023-04-05 11:10:21 -04:00
thunderbiscuit
5ee8698e0a Add Kotlin API docs for new AddressInfo type 2023-03-28 19:51:15 -04:00
thunderbiscuit
ac600a1312 Clean up type aliases and use more explicit variable names 2023-03-28 19:47:38 -04:00
thunderbiscuit
f26031db80 Update tests for new AddressInfo type 2023-03-28 15:05:42 -04:00
thunderbiscuit
e7e1a6057e Use Address type in address field on AddressInfo 2023-03-28 13:29:06 -04:00
thunderbiscuit
2b7c104f11 Clean up of docs regarding removed cli tool 2023-03-27 13:39:28 -04:00
thunderbiscuit
6bab5a159d Remove bdk-ffi-bindgen tool section in root readme 2023-03-24 12:56:06 -04:00
thunderbiscuit
b6c8b145bb Fix bdk-android publishing CI workflow 2023-03-24 12:38:32 -04:00
Steve Myers
67610abeb6 Merge bitcoindevkit/bdk-ffi#326: Add SignOptions to Wallet.sign() params
4e5537acd2 Add SignOptions to Wallet.sign() params (Steve Myers)

Pull request description:

  ### Description

  Fixes #323

  ### Notes to the reviewers

  I didn't include the `tap_leaves_options: TapLeavesOptions` because it would require more deeply nested structures and is not currently required.

  ### Changelog notice

  - Add SignOptions to Wallet.sign() params.

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [ ] I've added tests for the new feature
  * [x] I've added docs for the new feature

Top commit has no ACKs.

Tree-SHA512: e846388b93b5270dd6d1f86ebff462d1c69aa0ea8359d7e4955c88eed4dac1ce00f8da3ecf2432e6eba6e1e5b2f52e3e789918aa31a4b739a7d0a5185b5c3c0c
2023-03-24 11:12:23 -05:00
Steve Myers
4e5537acd2 Add SignOptions to Wallet.sign() params 2023-03-24 10:51:44 -05:00
Steve Myers
6be4ddaf7b Merge bitcoindevkit/bdk-ffi#325: Expose Address payload and network properties
cd10c75e96 Add to_qr_uri() method on Address type (thunderbiscuit)
cbd44249f3 Add kotlin api-docs for Address.payload() and Address.network() (Steve Myers)
20c31d5383 Expose Address payload and network properties (Steve Myers)
616cb21738 Update Cargo.lock (Steve Myers)

Pull request description:

  ### Description

  Fixes #319

  ### Notes to the reviewers

  The test data was generated with:
  ```
  bitcoin-cli -rpcwallet="regtest2" -datadir=/tmp/regtest1/bitcoind -regtest validateaddress "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
  {
    "isvalid": true,
    "address": "bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv",
    "scriptPubKey": "001404a6545885dd87b8e147cd327f2e9db362b72346",
    "isscript": false,
    "iswitness": true,
    "witness_version": 0,
    "witness_program": "04a6545885dd87b8e147cd327f2e9db362b72346"
  }
  ```

  ### Changelog notice

  Added
  - Expose Address payload and network properties.

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  thunderbiscuit:
    ACK cd10c75e96.

Tree-SHA512: 65a1d550577fd4a35cfeb8fb765002e47e0703ff40fc7a68c07b78bc1ba642d33a0efbdfa8f9322024841ba84d25c0e289294c10ae4c1b4d52eb9beffa3d0e10
2023-03-23 16:39:00 -05:00
thunderbiscuit
cd10c75e96 Add to_qr_uri() method on Address type 2023-03-23 17:03:40 -04:00
Steve Myers
cbd44249f3 Add kotlin api-docs for Address.payload() and Address.network() 2023-03-23 15:41:17 -05:00
Steve Myers
20c31d5383 Expose Address payload and network properties 2023-03-23 15:41:17 -05:00
Steve Myers
616cb21738 Update Cargo.lock 2023-03-23 15:41:17 -05:00
Steve Myers
d3a6453eda Merge bitcoindevkit/bdk-ffi#307: Expose more of the Transaction type
cba69e681a Clean up of From traits implementations (thunderbiscuit)
35d8fb3139 Clean up extract_tx method on PSBT (thunderbiscuit)
f003a6275e Clean up conversion between BDK TransactionDetails to ffi TransactionDetails (thunderbiscuit)
2f62377eec Add Eq and PartialEq traits on the Transaction type (thunderbiscuit)
81e208222a Add uniffi/cli as default feature to cargo (thunderbiscuit)
3dc6596aa2 Add include_raw boolean parameter on wallet list_transactions method (thunderbiscuit)
2342265c26 Remove unused NetworkLocalUtxo type (thunderbiscuit)
6c561228c2 Use the latest version of the Android NDK (thunderbiscuit)
e86909ab3d Clean up input and output methods on Transaction type (thunderbiscuit)
8e51756a3a Fix clippy errors (thunderbiscuit)
40263b425e Remove deprecated bdk-ffi-bindgen tool (thunderbiscuit)
9437051668 Fix fmt and clippy errors (thunderbiscuit)
7557e214c8 Add optional transaction field on the TransactionDetails type (thunderbiscuit)
40ca62086c Expose all fields on the Transaction type (thunderbiscuit)
e0506deffa Add new utility methods on Transaction type (thunderbiscuit)
d3e183a498 Add Kotlin API docs for new Transaction methods (thunderbiscuit)
1e9ecfbe52 Add weight, size, and vsize methods on the Transaction type (thunderbiscuit)

Pull request description:

  ## Description
  We've recently exposed the `Transaction` type, and I think a few methods on it would be useful. ~This is a draft PR with the first 3: `weight()`, `size()`, and `vsize()`~ _Edit: it's now much more_. I think there might be other methods we might want to expose as well. [Take a look at the docs to see them all](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html).

  Other candidates have now been added:
  1. [is_explicitly_rbf](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html#method.is_explicitly_rbf)
  2. [is_lock_time_enabled](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html#method.is_lock_time_enabled)
  3. [is_absolute_timelock_satisfied](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html#method.is_absolute_timelock_satisfied)
  4. [is_coin_base](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html#method.is_coin_base)
  5. [txid](https://docs.rs/bitcoin/0.29.2/bitcoin/blockdata/transaction/struct.Transaction.html#method.txid)

  This PR is growing in size but I decided to add all 4 fields on the `Transaction` type. This is useful because it means we can now add the `transaction` field on the `TransactionDetails` type (also added in this PR).

  I still have a few questions regarding all the translation between the ffi and bdk/rust types, some of the traits I had to remove (Eq and PartialEq on the TransactionDetails type) as well as the usage of `Option<Arc<T>>` vs `Arc<Option<T>>`. Will outline those tomorrow.

  Closes #303
  Closes #187

  ## Changelog notice
  ```md
  APIs Added
  - `Transaction` type now exposes the `.weight()`, `.size()`, `.vsize()`, `is_explicitly_rbf()`, `is_lock_time_enabled()`, `is_coin_base(), and `txid()` methods [#307]

  [#307]: https://github.com/bitcoindevkit/bdk-ffi/pull/307
  ```

  ## Checklists

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

  #### New Features:
  * [ ] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  notmandatory:
    ACK cba69e681a

Tree-SHA512: 83e860407b230b6cdca59c0d74a486e52e7ea34d655d418ddc115418551a61665cad8f1d6182858d8ed6d7d72a8558e595e61644efed6c704de8a0b6960a0df2
2023-03-23 15:40:19 -05:00
thunderbiscuit
cba69e681a Clean up of From traits implementations 2023-03-23 15:16:53 -04:00
thunderbiscuit
35d8fb3139 Clean up extract_tx method on PSBT 2023-03-23 13:14:48 -04:00
thunderbiscuit
f003a6275e Clean up conversion between BDK TransactionDetails to ffi TransactionDetails 2023-03-23 13:08:55 -04:00
thunderbiscuit
2f62377eec Add Eq and PartialEq traits on the Transaction type 2023-03-23 12:48:04 -04:00
thunderbiscuit
81e208222a Add uniffi/cli as default feature to cargo 2023-03-23 12:39:22 -04:00
thunderbiscuit
3dc6596aa2 Add include_raw boolean parameter on wallet list_transactions method 2023-03-23 12:32:54 -04:00
thunderbiscuit
2342265c26 Remove unused NetworkLocalUtxo type 2023-03-23 12:21:18 -04:00
thunderbiscuit
6c561228c2 Use the latest version of the Android NDK 2023-03-21 17:01:54 -04:00
thunderbiscuit
e86909ab3d Clean up input and output methods on Transaction type 2023-03-20 15:16:39 -04:00
thunderbiscuit
8e51756a3a Fix clippy errors 2023-03-14 08:22:05 -04:00
thunderbiscuit
40263b425e Remove deprecated bdk-ffi-bindgen tool 2023-03-13 15:04:48 -04:00
thunderbiscuit
9437051668 Fix fmt and clippy errors 2023-03-13 14:52:17 -04:00
thunderbiscuit
7557e214c8 Add optional transaction field on the TransactionDetails type 2023-03-13 14:49:07 -04:00
thunderbiscuit
40ca62086c Expose all fields on the Transaction type 2023-03-13 12:13:09 -04:00
thunderbiscuit
e0506deffa Add new utility methods on Transaction type
This PR adds the txid(), is_coin_base(), is_explicitly_rbf(),
and is_lock_time_enabled() methods.
Fixes #303
2023-03-13 08:54:37 -04:00
thunderbiscuit
d3e183a498 Add Kotlin API docs for new Transaction methods 2023-03-13 08:54:31 -04:00
thunderbiscuit
1e9ecfbe52 Add weight, size, and vsize methods on the Transaction type 2023-03-13 08:54:25 -04:00
thunderbiscuit
d48bacd29b Streamline CI workflows 2023-03-10 21:03:24 -05:00
thunderbiscuit
c1243f9e1c Update publish Python CI workflow 2023-03-01 13:43:24 -05:00
thunderbiscuit
9c6069e389 Run tests in Python CI workflow 2023-03-01 11:37:08 -05:00
thunderbiscuit
488edf8bd2 Fix Python build workflow to account for Linux/Windows 2023-03-01 10:02:45 -05:00
thunderbiscuit
90763d42a2 Fix Swift script and CI workflow 2023-02-28 12:42:54 -05:00
thunderbiscuit
44b2ef1382 Fix cargo test workflow 2023-02-28 12:04:43 -05:00
thunderbiscuit
25617d1f23 Fix cargo clippy CI workflow 2023-02-28 09:27:56 -05:00
thunderbiscuit
2fcafe2b80 Fix Rust CI workflow 2023-02-28 08:31:51 -05:00
thunderbiscuit
5728b50100 Fix formatting warning in Gradle plugins 2023-02-27 20:07:02 -05:00
thunderbiscuit
d08317775b Update Python build scripts for uniffi-rs 0.23.0 2023-02-27 20:04:32 -05:00
thunderbiscuit
c93f292b0e Upgrade uniffi-rs to 0.23.0 and migrate Gradle plugins 2023-02-27 14:43:52 -05:00
thunderbiscuit
a75c868eb2 Update minor_release and patch_release templates 2023-02-22 14:27:03 -05:00
thunderbiscuit
974ff66caf Bump snapshot and dev versions of libraries 2023-02-21 15:45:46 -05:00
thunderbiscuit
2309b19209 Update changelog for all versions since 0.10.0 2023-02-21 15:42:50 -05:00
thunderbiscuit
3128fad690 Update AddressIndex enum use in Python test and example 2023-02-18 09:53:13 -05:00
thunderbiscuit
a1b112cbbb Remove license files from bdk-python 2023-02-18 09:42:33 -05:00
thunderbiscuit
553c337241 Update JVM readme 2023-02-17 17:31:00 -05:00
thunderbiscuit
90d12a96c5 Update Android readme to add section on x86 emulators 2023-02-17 16:00:41 -05:00
thunderbiscuit
5ca1d17adb Fix Android tests to account for new AddressIndex sealed class 2023-02-17 15:49:20 -05:00
thunderbiscuit
f121372c73 Fix PartiallySignedTransaction type name in Kotlin API docs 2023-02-17 15:23:47 -05:00
Steve Myers
44a78cc459 Update bdk from 0.27 to 0.27.1 2023-02-17 09:14:28 -06:00
Steve Myers
2dbad2ddd5 Merge bitcoindevkit/bdk-ffi#308: Bump bdk version to 0.27 and bdk-ffi to 0.27.0
ec71ef58be Bump bdk version to 0.27 and bdk-ffi to 0.27.0 (thunderbiscuit)

Pull request description:

  ## Description
  This PR updates BDK to the latest version, `0.27.0`.

  ### Changelog notice
  ```txt
  - Update BDK to latest version 0.27 [#308]

  [#308](https://github.com/bitcoindevkit/bdk-ffi/pull/308)
  ```

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

ACKs for top commit:
  notmandatory:
    ACK ec71ef58be

Tree-SHA512: 2d97b2af5247a5021fb7e5db70a903ded243b8f298133da1b83f7610d4e8ffc5e8e1b65e60ae07a781334de9c1630dfc6f9d58f62ff240783c9c22afc1f8f907
2023-02-14 17:00:29 -06:00
thunderbiscuit
ec71ef58be Bump bdk version to 0.27 and bdk-ffi to 0.27.0 2023-02-14 12:45:29 -06:00
thunderbiscuit
4ca7919ca9 Clean up samples in Kotlin API docs 2023-02-02 12:26:29 -05:00
thunderbiscuit
07aa1f8950 Add new AddressIndex variants to Kotlin API docs 2023-02-02 12:26:28 -05:00
Ed Ball
d42789db9b fix: incorrect peek_address index 2023-02-02 12:26:27 -05:00
Ed Ball
10f893a4b3 test: reset_address 2023-02-02 12:26:26 -05:00
Ed Ball
13043065b6 expose: get_address reset method 2023-02-02 12:26:25 -05:00
Ed Ball
5fa0b916a2 test: more descriptive and complete peek_address tests 2023-02-02 12:26:24 -05:00
Ed Ball
7611a65620 fix jvm test AddressIndex class capitalisation 2023-02-02 12:26:23 -05:00
Ed Ball
458a162c2a remove redundant to_string from tests 2023-02-02 12:26:22 -05:00
Ed Ball
d15783dba0 add missing bdk-ffi AddressIndex Peek docstrings 2023-02-02 12:26:20 -05:00
Ed Ball
2723577a84 test: get_address peek ffi tests 2023-02-02 12:26:14 -05:00
Ed Ball
7fefb8a7b9 expose: get_address peek 2023-02-02 12:25:42 -05:00
Ed Ball
aa842c3844 fix incorrect address in get_internal_address test 2023-02-01 20:30:24 +01:00
thunderbiscuit
df019c11ec Add new getInternalAddress method to Kotlin API docs 2023-02-01 14:03:49 -05:00
Ed Ball
11d7d6b80f test: get_internal_address LastUnused 2023-02-01 14:43:22 +01:00
Ed Ball
85f8a8a526 fix: redundant problematic to_string in get_internal_address tests 2023-02-01 14:37:36 +01:00
Ed Ball
5e75c856c5 test: get internal/external address 2023-01-31 22:25:30 +01:00
Ed Ball
b854c78dde feat: expose get_internal_address 2023-01-28 19:10:54 +01:00
thunderbiscuit
f5d4750ae4 Fix Python CI release workflow 2023-01-24 13:22:58 -05:00
Steve Myers
f75ead02ff Merge bitcoindevkit/bdk-ffi#296: Add Transaction struct, update PSBT and Blockchain to use it
8e54ada436 Add Transaction struct, update PSBT and Blockchain to use it (Steve Myers)

Pull request description:

  ### Description

  Add new `Transaction` structure that can be created from transaction consensus encoded bytes. Update `PartiallySignedTransaction.extract_tx()` to return a `Transaction` instead of a the transaction bytes. Update `Blockchain.broadcast()` to take a `Transaction` parameter.

  ### Notes to the reviewers

  Fixes #157.

  ### Changelog notice

  #### Added

  - New `Transaction` structure that can be created from or serialized to consensus encoded bytes.

  #### Changed

  - `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of a the transaction bytes.
  - `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`.

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [ ] I've added tests for the new feature
  * [x] 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

ACKs for top commit:
  thunderbiscuit:
    Tested ACK 8e54ada436. I ran a script using bdk-jvm and your test vector. Looks good! Another win for the LDK/BDK integration.

Tree-SHA512: f5bfdafad93f0b4ada0756a8e68bdb12f2de680d8ae8a5083dbbeded6fc314bd79c8913f0b7f01e2eb807676092777ad8bf9466996cd51fa9587b8bb53170ca8
2023-01-23 15:47:39 -06:00
Steve Myers
8e54ada436 Add Transaction struct, update PSBT and Blockchain to use it 2023-01-23 14:30:36 -06:00
thunderbiscuit
302ad8dea8 Move Rust tests to their respective files 2023-01-19 22:59:53 -05:00
thunderbiscuit
561e93f6dd Add pycache directory to gitignore 2023-01-19 16:29:21 -05:00
thunderbiscuit
b8230799cf Fix GitHub repository link in setup.py file 2023-01-19 16:11:52 -05:00
thunderbiscuit
d2bec60046 Bump development versions for JVM, Android, and Python 2023-01-17 15:49:46 -05:00
thunderbiscuit
aadc622006 Refactor: Fix up imports 2023-01-17 15:47:48 -05:00
thunderbiscuit
202dcfa2b5 Refactor: separate database from lib.rs 2023-01-17 15:37:10 -05:00
thunderbiscuit
46bd9a1f15 Refactor: separate keys from lib.rs 2023-01-17 15:35:20 -05:00
thunderbiscuit
6fcb8985f1 Refactor: separate descriptor from lib.rs 2023-01-17 15:29:23 -05:00
thunderbiscuit
dd58a9d548 Refactor: separate blockchain from lib.rs 2023-01-17 15:29:05 -05:00
thunderbiscuit
d2a4e2adba Refactor: separate transaction builders from lib.rs 2023-01-17 15:18:55 -05:00
thunderbiscuit
cbc740c407 Refactor: separate psbt struct from lib.rs 2023-01-17 15:18:48 -05:00
thunderbiscuit
f50ecdb7e7 Refactor: separate wallet struct from lib.rs 2023-01-17 15:18:41 -05:00
Shobit Beltangdy
f01e0e30f3 expose estimate_fee api
bdk::blockchain::Blockchain contains an `estimate_fee` api. This commit adds the bindings for estimate_fee.

This will fix https://github.com/bitcoindevkit/bdk-ffi/issues/287

Tested this by adding a unit test in lib.rs. Also generated the python code and verified that it is able to invoke estimate_fee and get the fee rate
2023-01-13 16:47:12 -08:00
thunderbiscuit
5f7d8a9077 Fix typos in Kotlin API docs 2023-01-10 16:15:12 -05:00
thunderbiscuit
d77f5b84c3 Update Swift readme for 0.26.0 release 2023-01-09 21:36:19 -05:00
thunderbiscuit
6555170d28 Fix Python tests and examples for 0.26.0 release 2023-01-09 21:24:02 -05:00
thunderbiscuit
c763609b8b Update bdk-jvm readme for 0.26.0 release 2023-01-09 21:08:20 -05:00
thunderbiscuit
340fa19bb8 Update bdk-android tests and readme 2023-01-09 21:03:41 -05:00
thunderbiscuit
ff2734663e Update Kotlin API docs to reflect new descriptor templates 2023-01-09 20:48:44 -05:00
Steve Myers
f399b799e4 Add validate_domain option to ElectrumConfig 2023-01-09 14:41:49 -05:00
Steve Myers
cdde26a8ea Bump bdk-ff version to 0.26.0 and bdk version to 0.26 2023-01-03 09:07:38 -06:00
Shobit Beltangdy
34af88df6f Update Blockchain.broadcast doc to reflect no return type
This fixes #284
2022-12-18 14:32:29 -08:00
Shobit Beltangdy
12e9a18357 Update Wallet.getBalance doc to reflect Balance return type
This is a fix for issue #284
2022-12-17 09:11:56 -08:00
thunderbiscuit
bada9b82e0 Add assert_matches dev-dependency 2022-12-16 12:28:06 -05:00
thunderbiscuit
41f15fe80f Change descriptor parameter in wallet constructor to use Descriptor instead of String 2022-12-16 11:28:55 -05:00
thunderbiscuit
54953fa208 Add default string constructor for Descriptor 2022-12-16 11:28:50 -05:00
thunderbiscuit
b7ccf81c7a Add tests for templates 2022-12-16 11:28:45 -05:00
thunderbiscuit
3792a98426 Add BIP44/49/84 templates 2022-12-16 11:28:38 -05:00
thunderbiscuit
5dd79e9632 Add readme to api-docs directory 2022-12-16 11:26:25 -05:00
thunderbiscuit
9ae938ca8c Add JNA issue fix in documentation 2022-12-16 11:26:19 -05:00
thunderbiscuit
05aa7157df Clean up CI tests for bdk-android and bdk-jvm 2022-12-16 11:23:04 -05:00
thunderbiscuit
275bd94148 Add dependency on the Android plugin library building task for tests 2022-12-16 11:23:02 -05:00
thunderbiscuit
146cb039c3 Add dependency on the JVM plugin library building task for tests 2022-12-16 11:22:43 -05:00
Steve Myers
41fdadb09c Merge bitcoindevkit/bdk-ffi#125: Add RpcConfig, BlockchainConfig::Rpc, and Auth
4ed6e364e6 Add API docs for RPC blockchain config and auth (thunderbiscuit)
d0cd3b0f38 Add Auth, RpcSyncParams, and RpcConfig (Steve Myers)

Pull request description:

  Fixes #117. This adds the RPC blockchain config but I don't currently have a way to test it as part of the `bdk-kotlin` or `bdk-swift` automated testing, which would need to be able to spin up a local regtest bitcoind for the tests.

  For now this will only be manually tested.

ACKs for top commit:
  thunderbiscuit:
    ACK [4ed6e36](4ed6e364e6).

Tree-SHA512: 2f114753a683c32ec957b26e23918eb3c1de07073fd0293e06fb960f8226f09d4d9ebf89f8d04f9da5cd459619f224d732b81e21c2173afeccb8ce56cc558582
2022-12-16 10:10:06 -06:00
thunderbiscuit
4ed6e364e6 Add API docs for RPC blockchain config and auth 2022-12-16 10:36:32 -05:00
Steve Myers
d0cd3b0f38 Add Auth, RpcSyncParams, and RpcConfig 2022-12-13 15:10:28 -06:00
Steve Myers
f216417fd2 Update api-docs for TxBuilder.drain_to change 2022-12-07 15:34:32 -06:00
Steve Myers
7d1a4500ef Change TxBuilder.drain_to argument to Script instead of address String 2022-12-07 11:54:22 -06:00
thunderbiscuit
a408387bff Bump snapshot and dev libraries' versions 2022-12-07 11:59:40 -05:00
thunderbiscuit
8c62905d39 Add Swift-specific gitignore items 2022-12-06 16:22:48 -05:00
thunderbiscuit
3cd17bb908 Fix bdk-jvm and bdk-android readme files 2022-12-06 15:42:29 -05:00
thunderbiscuit
17b3712000 Update JVM and Android API docs to version 0.25 and add samples 2022-12-06 15:17:10 -05:00
thunderbiscuit
a925ddfc47 Bump bdk version to 0.25 2022-12-06 10:45:37 -05:00
thunderbiscuit
5dd5828e88 Add documentation on how to use snapshot versions of libraries 2022-11-30 12:20:48 -05:00
thunderbiscuit
2645f69853 Fix jvm and android library version defined in two places
Fixes #234
2022-11-30 12:04:25 -05:00
thunderbiscuit
f834da11c5 Fix artifact upload path in JVM CI publishing workflow 2022-11-29 17:36:00 -05:00
Steve Myers
8c934e9bfc Merge bitcoindevkit/bdk-ffi#247: Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey
427816fd9a Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey (thunderbiscuit)
29614b5b78 Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey (thunderbiscuit)

Pull request description:

  This PR adds the `from_string()` method to the `DescriptorSecretKey` and `DescriptorPublicKey` structs.

  ### Description
  Fixes #246.

  ### Notes to the reviewers
  The error thrown is coming from rust-miniscript, so I'm not sure yet how to handle that.

  ### Changelog notice
  ```txt
  APIs Added:
    - from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]

  [#247](https://github.com/bitcoindevkit/bdk-ffi/pull/247)
  ```

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added tests for the new feature

ACKs for top commit:
  notmandatory:
    ACK 427816fd9a

Tree-SHA512: a961af10549c92e1750669b148bc56c017c3929ae32199c7b71e51dca760b3dcd039ecbd68873a5175f7b02a2f1b0a94ba22018bc48d596c16d8a7d710c60fea
2022-11-29 09:01:36 -08:00
thunderbiscuit
9c0606e036 Replace AddressAmount with ScriptAmount in Kotlin API docs 2022-11-28 21:46:29 -05:00
thunderbiscuit
832387d32d Add uniffi-bindings-template link to readme 2022-11-25 12:41:02 -05:00
Steve Myers
84f5677abb Add test-swift workflow 2022-11-23 09:23:50 -08:00
Steve Myers
e790764915 Move build-local-swift.sh into bdk-swift directory, fix README 2022-11-23 09:23:07 -08:00
Steve Myers
b9bb5962ae Add build-local-swift.sh, consolidate .gitignore files 2022-11-21 13:43:47 -06:00
Steve Myers
13cbe89167 Merge bdk-swift repo into bdk-ffi/bdk-swift 2022-11-21 13:09:08 -06:00
Steve Myers
07f5b5f8ba Remove autogenerated BitcoinDevKit.swift 2022-11-21 13:08:31 -06:00
Steve Myers
a12b1f8d7a Remove unneeded .github and .gitmodules directories 2022-11-21 13:06:35 -06:00
Steve Myers
97d011acc0 Update README and remove redundant license files 2022-11-21 12:59:09 -06:00
Steve Myers
b7efb37632 Move all files to bdk-swift and deinit bdk-ffi 2022-11-21 12:10:23 -06:00
thunderbiscuit
3edda27ef2 Clean up root readme and add individual libraries' readmes 2022-11-17 11:48:24 -05:00
Steve Myers
e017d76351 Fix publish-spm to commit updated BitcoinDevKit.swift 2022-11-15 18:27:16 -06:00
thunderbiscuit
427816fd9a Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey 2022-11-15 13:22:18 -05:00
thunderbiscuit
29614b5b78 Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey 2022-11-15 13:16:54 -05:00
Steve Myers
063f69222a Update android and jvm workflows and plugins for root rust /target 2022-11-14 20:59:52 -06:00
Steve Myers
95a36bc9e2 Add MIT and Apache 2.0 licenses 2022-11-14 18:57:17 -06:00
Steve Myers
8857c851f6 Move rust workspace to top directory 2022-11-14 18:14:08 -06:00
thunderbiscuit
632f48e75a Commit Cargo.lock file 2022-11-14 13:16:45 -05:00
thunderbiscuit
6a9c2eb80e Fix audit workflow 2022-11-14 13:11:43 -05:00
thunderbiscuit
be058e11d9 Move kotlin API docs to more specific subdirectory 2022-11-14 13:10:51 -05:00
thunderbiscuit
ce9ca63bc7 Remove submodule code from CI workflows 2022-11-14 12:55:17 -05:00
thunderbiscuit
16ab09d7df Move licenses, changelog, and readme back into root directory 2022-11-14 10:54:06 -05:00
thunderbiscuit
738ed656fc Update Android and JVM CI workflows to run only on appropriate changes 2022-11-14 10:04:06 -05:00
thunderbiscuit
e6708d4c5b Move bdk-jvm and bdk-android out of subdirectory after ffi merge 2022-11-14 09:58:10 -05:00
thunderbiscuit
af77b9b9b1 Merge remote-tracking branch 'kotlinrepo/master' into ffi-merge 2022-11-14 09:45:49 -05:00
thunderbiscuit
0c1a9d7f1d Move all bdk-kotlin into subdirectory to prepare for ffi merge
Signed-off-by: thunderbiscuit <thunderbiscuit@protonmail.com>
2022-11-14 08:56:17 -05:00
Steve Myers
4f544e465b Use update ci workflows to use defaults.run.working-directory 2022-11-11 17:13:22 -06:00
thunderbiscuit
64c496f815 Run CI workflows only when relevant files are modified 2022-11-11 15:17:28 -05:00
thunderbiscuit
8bb8c00a6b Remove bdk-ffi submodule from bdk-python 2022-11-10 16:27:48 -05:00
thunderbiscuit
26ef0d4a34 Remove .github directory in bdk-python 2022-11-10 16:09:29 -05:00
thunderbiscuit
8240d8dc99 Add simplified Python CI workflow 2022-11-10 15:58:23 -05:00
thunderbiscuit
da4c792046 Fix CI paths 2022-11-10 13:34:43 -05:00
thunderbiscuit
b06528d10c Move bdk-ffi source code in subdirectory 2022-11-10 13:27:00 -05:00
thunderbiscuit
662270364b Merge remote-tracking branch 'python/master' into python-ffi-merge 2022-11-10 13:23:32 -05:00
thunderbiscuit
413ca8bdeb Move all content in bdk-python subdirectory 2022-11-10 12:57:38 -05:00
thunderbiscuit
2a97218991 Bump library development version to 0.6.0.dev0 2022-11-09 15:26:51 -05:00
thunderbiscuit
ec7b3769b5 Bump bdk-ffi submodule to v0.11.0 (bdk version 0.24.0)
Signed-off-by: thunderbiscuit <thunderbiscuit@protonmail.com>
2022-11-09 12:52:15 -05:00
thunderbiscuit
f07473e1ca Bump versions to 0.12.0-SNAPSHOT 2022-11-08 15:03:20 -05:00
thunderbiscuit
3be23ad7f9 Update API docs to version 0.11.0 2022-11-08 14:19:37 -05:00
thunderbiscuit
ffd85e6bd1 Use release-smaller profile for bdk-ffi in Gradle plugins 2022-11-08 12:24:49 -05:00
Steve Myers
073c89db4b Fix publish-spm workflow with release-smaller profile 2022-11-08 11:07:27 -06:00
thunderbiscuit
04aae0486a Bump bdk-ffi submodule to v0.11.0 2022-11-08 11:50:54 -05:00
thunderbiscuit
929147f182 Bump versions to 0.11.0-SNAPSHOT 2022-11-08 11:17:23 -05:00
Steve Myers
eb9241d315 Update bdk-ffi to 0.11.0 2022-11-08 09:55:25 -06:00
thunderbiscuit
0648075555 Bump version to 0.11.0 2022-11-08 10:11:38 -05:00
thunderbiscuit
3f81346e6b Refactor from_str() method on the Mnemonic struct to from_string() 2022-11-08 09:54:50 -05:00
Steve Myers
a25fb1348d Merge bitcoindevkit/bdk-ffi#208: Add FeeRate struct and PSBT fee_amount and fee_rate functions
ae1ea99ed3 Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction (Steve Myers)
9a381f6d32 Rename PartiallySignedBitcoinTransaction to PartiallySignedTransaction (Steve Myers)

Pull request description:

  <!-- You can erase any parts of this template not applicable to your Pull Request. -->

  ### Description

  Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction.

  ### Notes to the reviewers

  This PR is dependent on https://github.com/bitcoindevkit/bdk/pull/782.

  ### Changelog notice

  - Breaking Changes
    - Renamed PartiallySignedBitcoinTransaction to PartiallySignedTransaction to be consistent with `rust-bitcoin`
  - APIs Added
    - Add FeeRate struct
    - Add fee_amount() and fee_rate() functions on PartiallySignedTransaction

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  thunderbiscuit:
    Re-ACK [ae1ea99](ae1ea99ed3).

Tree-SHA512: 2c3f792e9ef092cd3ba233601122f4960c496d132caad54ef2f7f41d7113dd16600a863bb8fd78d2e5b978adebdb7ddd9529c21b3d46cd0b16e0db4eb90de01d
2022-11-07 14:15:35 -06:00
Steve Myers
ae1ea99ed3 Add FeeRate struct and fee_amount() and fee_rate() functions on PartiallySignedTransaction 2022-11-07 11:55:36 -06:00
Steve Myers
9a381f6d32 Rename PartiallySignedBitcoinTransaction to PartiallySignedTransaction 2022-11-07 11:55:36 -06:00
Steve Myers
3a07b4838a Merge bitcoindevkit/bdk-ffi#221: Bump bdk version to 0.24.0
29de6f2d06 Bump bdk version to 0.24.0 (thunderbiscuit)

Pull request description:

  ## Description
  This PR updates BDK to the latest version, `0.24.0`.

  ### Notes to the reviewers
  This PR is currently open only for CI testing and review. Only merge once bdk 0.24.0 is out and the PR has been updated.

  ### Changelog notice
  ```txt
  - Update BDK to latest version 0.24.0 [#221]

  [#221](https://github.com/bitcoindevkit/bdk-ffi/pull/221)
  ```

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

ACKs for top commit:
  notmandatory:
    ACK 29de6f2d06

Tree-SHA512: 256eb4387728467704f732ce1151de9569b6121916bb1d814bb48c75faf20026846e6170a384ca7e5e9ac3652bd9dfe5511e019f13c972ae755f0b37f9db8b83
2022-11-07 11:47:45 -06:00
thunderbiscuit
29de6f2d06 Bump bdk version to 0.24.0 2022-11-07 12:33:00 -05:00
Steve Myers
73ba73fd03 Merge bitcoindevkit/bdk-ffi#219: Added Mnemonic Interface
9866649fdc Added Mnemonic Interface (dhruvbaliyan)

Pull request description:

  ### Description
  This PR adds `interface Mnemonic` which will make the API to generate new DescriptorSecretKey have type-safe arguments.

  <!-- Describe the purpose of this PR, what's being adding and/or fixed -->

  ### Notes to the reviewers

  This PR doesn't have any issue linked to it, as it was discusses on a call during the implementation of `DescriptorSecretKey` (PR #154). It was discussed to make `Mnemonic` an interface and use that instead of string `Mnemonic` so that the API to generate `DescriptorSecretKey` doesn't have any potential failure (like in case it's provided with incorrect Mnemonic words).

  APIs added
  ```
  // generates and returns Mnemonic with random entropy
  Mnemonic::new(word_count: WordCount) -> Self { ... }
  // converts string Mnemonic to Mnemonic type with error (in case of incorrect string Mnemonic)
  Mnemonic::from_str(mnemonic: String) -> Result<Self, BdkError> { ... }
  // generates and returns Mnemonic with given entropy
  Mnemonic::from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {...}
  // view mnemonic as string
  Mnemonic::as_string(&self) -> String { ... }
  ```
  Along with some changes to `DescriptorSecretKey::new()` to fit these new APIs

  ### Changelog notice
  ```
  - Added Struct Mnemonic with following methods [#219]
    - new(word_count: WordCount) generates and returns Mnemonic with random entropy
    - from_str(mnemonic: String) converts string Mnemonic to Mnemonic type with error
    - from_entropy(entropy: Vec<u8>) generates and returns Mnemonic with given entropy
    - as_string() view Mnemonic as string
  - API removed [#219]
    - generate_mnemonic(word_count: WordCount)

  [#219](https://github.com/bitcoindevkit/bdk-ffi/pull/219)
  ```
  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added docs for the new feature

  #### Bugfixes:

  * [x] This pull request breaks the existing API
      * Top level function `generate_mnemonic(...)` was removed

ACKs for top commit:
  thunderbiscuit:
    ACK 9866649fdc.
  notmandatory:
    ACK 9866649fdc

Tree-SHA512: 45f9158beb6fe7bfe2a901c3f17126db855fe0b4b479ecb2a16381e06a415eed295fe6be3c840bd1d1fc8cffaf58bd97dc27bdc1e82699367a827d700e8fd09b
2022-11-07 11:27:41 -06:00
thunderbiscuit
82126ece78 Add publishing CI workflow 2022-11-03 15:22:25 -04:00
dhruvbaliyan
9866649fdc Added Mnemonic Interface 2022-11-03 22:33:38 +05:30
thunderbiscuit
4ff3f71cb8 Bump bdk-ffi submodule to v0.10.0 (bdk version 0.23.0) 2022-11-03 11:32:32 -04:00
Steve Myers
4abda332de Use the release-smaller profile in publish-spm workflow 2022-11-01 19:03:16 -05:00
Steve Myers
c2aecb0597 Merge bitcoindevkit/bdk-ffi#220: Add build profile 'release-smaller'
ba71a7a27c Add build profile 'release-smaller' (Steve Myers)

Pull request description:

  ### Description

  New profile turns on all the non-experimental rust build size optimizations.

  ### Notes to the reviewers

  This PR is the first step to fixing bitcoindevkit/bdk-swift#25.

  ### Changelog notice

  None.

  ### Checklists

  #### All Submissions:

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

ACKs for top commit:
  thunderbiscuit:
    ACK [ba71a7a](ba71a7a27c).

Tree-SHA512: b12cf3a3ad3683dccbb89f611e98246db4a604b674077a45b78e30e9e20021f443dfec68e8ab511e0bb64d84c5c7064b4078b578fc3b4c1fb2e1119680a656a6
2022-11-01 18:57:52 -05:00
Steve Myers
ba71a7a27c Add build profile 'release-smaller' 2022-10-29 22:02:59 -05:00
Steve Myers
c8436f519c Update README publishing steps 2022-10-29 19:58:33 -05:00
Steve Myers
beca56ba3c Add publish-spm github actions workflow 2022-10-29 17:43:14 -05:00
Steve Myers
036e790a75 Merge bitcoindevkit/bdk-ffi#215: Add simple kotlin, swift and python integration tests
ee6ee8139a Add simple kotlin,swift, and python integration tests (Steve Myers)

Pull request description:

  ### Description

  Add simple kotlin, swift and python integration tests. These tests confirm fixes in #216 and #214.

  ### Notes to the reviewers

  To skip integration tests use:

  `cargo test --lib`.

  Otherwise java, kotlin, swift, and python need to be installed, and you must run tests with:

  `CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test`

  ### Changelog notice

  - Integration tests added, see tests/README.md for updated instructions for running tests. #215

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

  #### Bugfixes:

  * [x] I've added tests to reproduce the issue which are now passing

ACKs for top commit:
  thunderbiscuit:
    ACK [ee6ee81](ee6ee8139a).
  waterst0ne:
    > ACK [ee6ee81](ee6ee8139a).

Tree-SHA512: 06ab14da1185de431c16b767f187bc8e7792106df54314242b26f225e3a8ddada28317b7cb8bec47b8b248d3088d0305ab777770525540c72d2815349a73728b
2022-10-27 13:38:29 -05:00
thunderbiscuit
5991b07385 Add group and version properties for nexus publishing plugin 2022-10-24 13:06:29 -04:00
Steve Myers
7ba5f3757d Updated bdk-ffi to v0.10.0 (bdk 0.23) 2022-10-21 17:18:30 -05:00
Steve Myers
ee6ee8139a Add simple kotlin,swift, and python integration tests 2022-10-21 15:14:15 -05:00
thunderbiscuit
f820b4fd6f Bump uniffi-rs dependency to 0.21.0 through latest bdk-ffi tag
Signed-off-by: thunderbiscuit <thunderbiscuit@protonmail.com>
2022-10-21 15:02:46 -04:00
Steve Myers
3bec5d2cab Merge bitcoindevkit/bdk-ffi#216: Update uniffi dependencies to 0.21.0
b9aa0a2cf1 Update uniffi dependencies to 0.21.0 (Steve Myers)

Pull request description:

  ### Description

  Update uniffi dependencies to 0.21.0

  ### Notes to the reviewers

  This is required to pickup my PR to handle swift keywords. https://github.com/mozilla/uniffi-rs/compare/v0.20.0...v0.21.0

  ### Changelog notice

  Update uniffi-rs to latest version 0.20.0 #216

  ### Checklists

  #### All Submissions:

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

ACKs for top commit:
  thunderbiscuit:
    ACK [b9aa0a2](b9aa0a2cf1).

Tree-SHA512: 8bd585a22e6df2186d3985cc4d41a86dc35644b1e8dc06c1153de04a85df2cb6b345e15c0eb26e1b87c41cb00f15acf29f1b6a5b23736ead397fa6ee0fe0af0e
2022-10-21 13:26:36 -05:00
Steve Myers
b9aa0a2cf1 Update uniffi dependencies to 0.21.0 2022-10-21 13:18:38 -05:00
thunderbiscuit
65f2c0fcf1 Bump bdk-ffi submodule to v0.10.0 tag 2022-10-21 12:30:33 -04:00
thunderbiscuit
c7d0803000 Fix use of Error as name for error enum in UDL 2022-10-21 09:30:28 -04:00
Steve Myers
1a4b9b440d Bump version to 0.10.0 2022-10-19 12:47:16 -05:00
Steve Myers
1f914c2b4d Merge bitcoindevkit/bdk-ffi#209: Change TxBuilder.finish() to return new TxBuilderResult
fadb316451 Change TxBuilder.finish() to return new TxBuilderResult (Steve Myers)

Pull request description:

  ### Description

  Change TxBuilder.finish() to return new TxBuilderResult.

  ### Notes to the reviewers

  This fixes #179 in that it return both PartiallySignedBitcoinTransaction and TransactionDetails encapsulated in a new TxBuilderResult structure. It does not calculate the fee rate which requires #208.

  ### Changelog notice

  - Breaking Changes
    - Changed `TxBuilder.finish()` to return new `TxBuilderResult`.
  - APIs Added
    - Added `TxBuilderResult` with PSBT and TransactionDetails.

  ### Checklists

  #### All Submissions:

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

  #### New Features:

  * [x] I've added tests for the new feature
  * [x] I've added docs for the new feature

ACKs for top commit:
  thunderbiscuit:
    ACK [fadb316](fadb316451).

Tree-SHA512: b8aafc53ba86bf7ab12ae3d5bb251d1ec5cb54e4b7d6bfc342155d5cd3726d9a6d114591dc740a7467afb8ef402f3d77ad51e273a27865d6e47192291b570af9
2022-10-19 12:30:06 -05:00
Steve Myers
fadb316451 Change TxBuilder.finish() to return new TxBuilderResult 2022-10-19 12:27:00 -05:00
thunderbiscuit
3fefd3c1fb Allow TxBuilder.add_recipient() to take Script 2022-10-17 17:42:36 -04:00
thunderbiscuit
2cbb314d0b Remove BdkError type alias 2022-10-17 16:43:37 -04:00
thunderbiscuit
535fc70433 Upgrade bdk dependency to v0.23 2022-10-17 16:19:35 -04:00
thunderbiscuit
10fa276bec Update uniffi-rs to 0.20.0 2022-10-17 16:03:27 -04:00
thunderbiscuit
e5e38d7f77 Fix missing comma in API docs for TransactionDetails 2022-10-05 10:26:57 -04:00
thunderbiscuit
20134bb96a Add option to build API docs into bdk-jvm website 2022-10-05 10:10:16 -04:00
thunderbiscuit
1cc9afaeb3 Rename DescriptorSecretKey.secret_bytes() to mirror upstream API 2022-10-03 14:54:01 -04:00
thunderbiscuit
6f5e621561 Remove changelog entry to follow workflow defined in #202 2022-10-03 14:54:00 -04:00
thunderbiscuit
1dd6f2d9f8 Add test for DescriptorSecretKey.secret_key_bytes() 2022-10-03 14:53:58 -04:00
thunderbiscuit
f92b45db6a Add ability to retrieve private keys as bytes
This feature is needed for compatibility with LDKLite, where the
initial entropy given to LDK is the private key of the root of
the BIP32 derivation tree.

Closes #188
2022-10-03 14:53:25 -04:00
thunderbiscuit
3a0fe79dd8 Add bindings PGP public key and documentation on how to verify signatures 2022-10-03 14:46:11 -04:00
thunderbiscuit
6598df9ed9 Add bindings PGP public key and documentation on how to verify signatures 2022-10-03 14:45:57 -04:00
thunderbiscuit
c971d54aea Fix warnings 2022-09-30 19:37:19 -04:00
thunderbiscuit
2abccafb8f Add combine() method on PSBT
Closes #198
2022-09-30 19:37:12 -04:00
Steve Myers
75d0415bec Add release templates and dev cycle docs, update changelog process 2022-09-29 11:18:27 -05:00
thunderbiscuit
4ff428a9a6 Update simple example in setup.py 2022-09-22 11:18:35 -04:00
thunderbiscuit
d539d8eaf8 Update tests for bdk-ffi v0.9.0 2022-09-22 11:02:41 -04:00
thunderbiscuit
96889b43a8 Add documentation on local testing 2022-09-22 11:02:05 -04:00
thunderbiscuit
02a572cbc6 Remove changelog
This is in line with the bdk-jvm, bdk-android, and bdk-swift libraries, who all rely on the bdk-ffi changelog.
2022-09-22 10:25:33 -04:00
thunderbiscuit
3f35a18d41 Add API docs samples for Network, BlockchainConfig, and Blockchain 2022-09-22 09:56:41 -04:00
thunderbiscuit
b9c283c89b Add samples for AddressIndex and AddressInfo 2022-09-22 09:40:39 -04:00
thunderbiscuit
3e96aad10e Use idiomatic Kotlin/Java documentation and KDoc structure 2022-09-21 09:12:50 -04:00
thunderbiscuit
a671c4f86b Move samples into tests 2022-09-21 08:01:12 -04:00
thunderbiscuit
157b1875c5 Remove unused docs patch 2022-09-21 08:01:11 -04:00
thunderbiscuit
af89ebaeea Update API docs to v0.9.0 2022-09-21 08:01:08 -04:00
thunderbiscuit
4259f260a9 Add samples for BlockchainConfig 2022-09-21 08:00:17 -04:00
thunderbiscuit
4d973e7ab6 Add temporary API docs 2022-09-21 08:00:10 -04:00
thunderbiscuit
d603932e23 Update publishing CI workflow 2022-09-20 19:43:27 -04:00
thunderbiscuit
db64f372f2 Split libraries into independent Gradle projects 2022-09-20 19:43:17 -04:00
thunderbiscuit
810e22dc9c Bump bdk-ffi submodule to v0.9.0 tag 2022-09-20 08:09:36 -04:00
thunderbiscuit
a3cbc4477f Bump SNAPSHOT version to 0.10.0-SNAPSHOT 2022-09-09 12:41:41 -04:00
thunderbiscuit
6b993b22db Merge pull request #89 from thunderbiscuit/bump-version-0.9.0
Bump version 0.9.0
2022-09-09 12:04:04 -04:00
thunderbiscuit
b8f9d199a8 Simplify tests 2022-09-08 18:21:04 -04:00
thunderbiscuit
b5ff0a7914 Bump bdk-ffi submodule version to 0.9.0 2022-09-08 16:07:41 -04:00
thunderbiscuit
485f4f72ce Bump version to 0.9.0 2022-09-08 15:18:48 -04:00
thunderbiscuit
37dddd05f6 Update changelog for 0.9.0 release 2022-09-08 15:17:35 -04:00
Steve Myers
dfb350e206 Merge bitcoindevkit/bdk-ffi#193: Update bdk dependency to 0.22
3c6075ad96 Add Balance struct and conversion from BdkBalance (thunderbiscuit)
4e15badb14 Update BDK to version 0.22 (thunderbiscuit)

Pull request description:

  The bindings do not build when attempting this upgrade because `get_balance()` now returns a `Balance` struct (this was merged in bitcoindevkit/bdk#640)

  ```sh
  error[E0308]: mismatched types
     --> src/lib.rs:433:9
      |
  432 |     fn get_balance(&self) -> Result<u64, Error> {
      |                              ------------------ expected `Result<u64, bdk::Error>` because of return type
  433 |         self.get_wallet().get_balance()
      |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found struct `Balance`
      |
      = note: expected enum `Result<u64, _>`
                 found enum `Result<Balance, _>`

  For more information about this error, try `rustc --explain E0308`.
  error: could not compile `bdk-ffi` due to previous error
  ```

  When we upgrade to `0.22.0` we could decide to add the `Balance` struct to the bindings, or simply return the total by calling `get_total()`, which returns a `u64` (same as we have now).

ACKs for top commit:
  notmandatory:
    ACK 3c6075ad96

Tree-SHA512: 13d2f83f992735f4f9619ae339d7834df08385129edf06bac830c298b433571af3f211e92a6da1f4f9646dec27dbd2c6133a035f26eac8757b7a1c94b54b463d
2022-09-08 13:58:27 -05:00
thunderbiscuit
4e14e8d22a Merge pull request #87 from bitcoindevkit/publish-to-staging
Publish bdk-jvm and bdk-android to Maven Central
2022-09-08 10:45:00 -04:00
thunderbiscuit
222d1594ca Enable full bdk-jvm and bdk-android publishing workflow 2022-09-08 09:50:13 -04:00
thunderbiscuit
3c6075ad96 Add Balance struct and conversion from BdkBalance 2022-09-08 08:35:10 -05:00
thunderbiscuit
4e15badb14 Update BDK to version 0.22 2022-09-08 08:34:56 -05:00
thunderbiscuit
3cd252f877 Remove dokka-related markdown files 2022-09-08 08:47:46 -04:00
thunderbiscuit
b259d376b0 Pick up Nexus credentials from GitHub secrets 2022-09-08 08:47:43 -04:00
thunderbiscuit
fc288bc92b Add bdk-android publishing workflow 2022-09-08 08:47:39 -04:00
thunderbiscuit
7e25684399 Add publish to staging repository task 2022-09-08 08:47:36 -04:00
thunderbiscuit
a0adc8fc74 Remove unused Dokka blocks and imports 2022-09-08 08:47:33 -04:00
thunderbiscuit
8b042ef470 Fix bdk-android gradle script signing block 2022-09-08 08:47:31 -04:00
thunderbiscuit
db4ad1a78d Sign bdk-jvm artifact in CI 2022-09-08 08:47:09 -04:00
Steve Myers
f05a6648a7 Refactor TransactionDetails to include confirmation_time (#190) 2022-09-05 14:02:29 -04:00
thunderbiscuit
297680b7c2 Merge pull request #194 from thunderbiscuit/update/uniffi-bindgen
Update uniffi-bindgen to 0.19.5
2022-09-05 13:36:07 -04:00
Steve Myers
8166f820b4 Add README info badges for MSRV and other links 2022-09-05 12:04:08 -05:00
Steve Myers
4f20966ddd Update CI test rust versions to 1.61 and 1.63 2022-09-05 11:46:26 -05:00
thunderbiscuit
d447aac9ae Update uniffi-bindgen to 0.19.5 2022-09-02 13:11:31 -04:00
thunderbiscuit
9c485a952f Bump bdk-ffi submodule to v0.8.1 tag (#78) 2022-08-30 16:29:36 -04:00
thunderbiscuit
159e7ab4af Pin version of uniffi-bindgen in bdk-ffi-bindgen tool (#189) 2022-08-29 22:08:38 -04:00
thunderbiscuit
3750a7ebd6 Add workflow to publish bdk-jvm (#76) 2022-08-29 20:25:05 -04:00
thunderbiscuit
bfe03b91b2 Add inline documentation (#171)
* Add docs for AddressInfo and AddressIndex structs

* Add docs for DatabaseConfig and ElectrumConfig

* Add docs for EsploraConfig struct

* Add docs for TransactionDetails struct

* Add docs for OutPoint struct

* Add docs for TxOut struct

* Add docs for TxBuilder
2022-08-29 15:47:37 -04:00
Pedro
3b028ecab1 Expose set_recipients API from TxBuiler (#186) 2022-08-29 09:58:46 -04:00
Kirill Zhukov
989b7339a0 Convert Gradle script plugin for generating UniFfi bindings into a composite build. 2022-08-24 11:12:44 -07:00
thunderbiscuit
d00813e1d6 Fix CI test workflow using pinned Android NDK 2022-08-19 07:53:50 -04:00
thunderbiscuit
aa004201b2 Fix method names to mirror Rust bdk API (#185)
* Fix method names to mirror Rust bdk API

* Fix method names to mirror Rust bdk API
2022-08-18 14:35:17 -04:00
thunderbiscuit
eed5554551 Merge pull request #184 from thunderbiscuit/block-height-hash
Add `get_height` and `get_block_hash` methods on blockchain
2022-08-18 14:14:03 -04:00
thunderbiscuit
88427e4a05 Update CHANGELOG.md
Co-authored-by: Steve Myers <github@notmandatory.org>
2022-08-18 14:04:31 -04:00
thunderbiscuit
8248660c52 Merge branch 'master' into block-height-hash 2022-08-18 13:43:18 -04:00
thunderbiscuit
25963ec982 Add get_height and get_block_hash methods on blockchain 2022-08-18 13:39:00 -04:00
Steve Myers
7da28658a5 Merge bitcoindevkit/bdk-ffi#154: Add child key pair generation api
5944756b78 Added tests for DescriptorSecretKey and DescriptorPublicKey (dhruvbaliyan)
58fea6b205 Added interfaces DescriptorSecretKey and DescriptorPublicKey (dhruvbaliyan)
4977cb6d68 Added interface DerivationPath (dhruvbaliyan)
930a1f1eb4 Added generate_mnemonic method (dhruvbaliyan)
973013cbdf Removed ExtendedKeyInfo & related methods (dhruvbaliyan)

Pull request description:

  Would like to know if anything can be improved. Completes #87

Top commit has no ACKs.

Tree-SHA512: a480535c8965015d860336c717ec3c394778ac08194b0336eeba4209f3e3eff2072873a190dd8c9e4fac1e2f712c7040c838dc1c1a757d53c28866f118c99c17
2022-08-18 12:14:35 -05:00
dhruvbaliyan
5944756b78 Added tests for DescriptorSecretKey and DescriptorPublicKey 2022-08-18 04:24:03 +05:30
dhruvbaliyan
58fea6b205 Added interfaces DescriptorSecretKey and DescriptorPublicKey 2022-08-18 04:24:02 +05:30
dhruvbaliyan
4977cb6d68 Added interface DerivationPath 2022-08-18 04:24:02 +05:30
dhruvbaliyan
930a1f1eb4 Added generate_mnemonic method 2022-08-18 04:24:02 +05:30
dhruvbaliyan
973013cbdf Removed ExtendedKeyInfo & related methods 2022-08-18 04:24:01 +05:30
thunderbiscuit
d38737669d Fix bdk-python link in readme (#182) 2022-08-17 17:20:20 -04:00
thunderbiscuit
fbf9792b38 Bump version to 0.3.0.dev0 2022-08-07 15:48:59 -04:00
thunderbiscuit
184dcba882 Merge pull request #23 from thunderbiscuit/bump-ffi-080
Bump bdk-ffi to v0.8.0 tag
2022-08-07 13:48:15 -04:00
thunderbiscuit
d916fbd7be Fix CHANGELOG.md
Co-authored-by: Steve Myers <github@notmandatory.org>
2022-08-07 13:26:41 -04:00
thunderbiscuit
66376f05ec Refactors to setup.py 2022-08-05 10:31:24 -04:00
thunderbiscuit
d633d6d2a9 Update changelog to reflect 0.2.0 changes 2022-08-05 10:30:23 -04:00
thunderbiscuit
7a9a6f5169 Bump bdk-ffi to v0.8.0 tag 2022-08-05 09:45:33 -04:00
thunderbiscuit
b19f776e68 Merge pull request #20 from kornpow/build/fix-tests
Fix tox build and tests
2022-08-04 15:12:47 -04:00
Sam Korn
4396ebaa72 fix tox build and tests
Signed-off-by: Sam Korn <korn94sam@gmail.com>
2022-08-04 12:13:05 -06:00
thunderbiscuit
697b58d33e Bump version to 0.9.0-SNAPSHOT 2022-08-01 22:27:05 -04:00
thunderbiscuit
b8129ccd15 Bump bdk-ffi submodule to version 0.8.0
Signed-off-by: thunderbiscuit <thunderbiscuit@protonmail.com>
2022-07-29 14:26:25 -04:00
thunderbiscuit
6896097eb7 Release/0.8 (#177)
* Update changelog to reflect 0.8.0 additions

* Bump version to 0.8.0
2022-07-29 14:08:23 -04:00
Steve Myers
7d95433c28 Merge bitcoindevkit/bdk-ffi#175: Set project MSRV to 1.57.0
6d53cbeb25 Fix fmt error (Steve Myers)
1a12f37a2f Set MSRV to 1.57.0 (Steve Myers)

Pull request description:

  ### Description

  The `master` branch is currently not passing the new github checks.

  A required dependency of `bdk-ffi-bindgen` is `uniffi_bindgen` and it depends on `os_str_bytes` v6.2.0 which has a MSRV of 1.57.0. I therefore had to make the MSRV of `bdk-ffi` also 1.57.0 and update the github actions. This PR also fixes a small `cargo fmt` warning.

  ### Notes to the reviewers

  ```shell
  % cargo +1.56.1 build
  error: package `os_str_bytes v6.2.0` cannot be built because it requires rustc 1.57.0 or newer, while the currently active rustc version is 1.56.1
  ```

  ```shell
  % cargo tree -i os_str_bytes
  os_str_bytes v6.2.0
  └── clap_lex v0.2.4
      └── clap v3.1.18
          └── uniffi_bindgen v0.19.3
              └── bdk-ffi-bindgen v0.2.0 (/Users/steve/git/notmandatory/bdk-ffi/bdk-ffi-bindgen)
  ```

  ### Checklists

  #### All Submissions:

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

Top commit has no ACKs.

Tree-SHA512: 87ad4a02d91184b421871354b1f5c31d906bf7460fe992db15666da32a65f13d8fbaf4ae53928f410a7206b195c8dff76af07210c144a4d02854ceb6af265f7e
2022-07-29 09:43:16 -07:00
Steve Myers
6d53cbeb25 Fix fmt error 2022-07-26 12:36:07 -07:00
Steve Myers
1a12f37a2f Set MSRV to 1.57.0 2022-07-26 12:35:41 -07:00
Steve Myers
04022787c4 Merge bitcoindevkit/bdk-ffi#174: Add github workflows for audit, test and fmt
46850ed471 Add github issue templates and PR template (Steve Myers)
49da6fcbae Fix clippy warnings (Steve Myers)
075510d6e4 Add github workflows for audit, test and fmt (Steve Myers)

Pull request description:

  1. Copied and updated github workflows from BDK project.
  2. Fixed clippy warnings.
  3. Added github issue templates and PR templates from BDK project.

  Fixes #88

Top commit has no ACKs.

Tree-SHA512: 7aaca6be0f05d12f4561e165ebc45b52e40200b231b55326732756d45116f371f2da4c5d7cc590cd0af9450c344530f815a357fa979a34d0181efc2149ffccb3
2022-07-26 12:25:25 -07:00
Steve Myers
46850ed471 Add github issue templates and PR template 2022-07-25 13:17:52 -07:00
Steve Myers
49da6fcbae Fix clippy warnings 2022-07-25 13:17:52 -07:00
Steve Myers
075510d6e4 Add github workflows for audit, test and fmt 2022-07-25 13:17:38 -07:00
thunderbiscuit
fa5c67cd05 Bump uniffi-rs to 0.19.3 (#173) 2022-07-25 15:15:23 -04:00
thunderbiscuit
1a20d0a6c2 Merge pull request #164 from zoedberg/coin_selection
Add coin selection methods
2022-07-21 15:39:55 -04:00
Zoe Faltibà
a3ae4635eb Post review fixes 2022-07-21 21:04:57 +02:00
Zoe Faltibà
5f12900c6d Add TxBuilder coin selection methods 2022-07-21 16:59:16 +02:00
thunderbiscuit
1a5a628a5d Merge pull request #170 from thunderbiscuit/bump/bdk-0.20.0
Update BDK to version 0.20.0
2022-07-20 11:49:21 -04:00
thunderbiscuit
d8c8261e44 Update BDK to version 0.20.0 2022-07-15 12:03:19 -04:00
thunderbiscuit
692904df1e Merge pull request #158 from zoedberg/list_unspent
Add Wallet list_unspent method
2022-07-12 12:07:52 -04:00
thunderbiscuit
2ac42b3ae0 Add list_unspent and add_data methods to changelog 2022-07-12 12:05:31 -04:00
thunderbiscuit
d50e2a6832 Bump development version to 0.2.0.dev0 2022-06-30 15:37:58 -04:00
thunderbiscuit
8df13adac7 Merge pull request #18 from thunderbiscuit/feat/ffi-0.6.0
Update library to new bdk-ffi API version 0.7.0
2022-06-30 11:39:46 -04:00
thunderbiscuit
d978993d06 Fix version number for development 2022-06-29 13:26:19 -04:00
thunderbiscuit
5862b13dac Fix changelog missing link 2022-06-29 13:25:17 -04:00
thunderbiscuit
5db9b1bc7b Bump bdk-ffi submodule to 0.7.0 tag 2022-06-23 15:21:48 -04:00
Steve Myers
fe59f29cbc Update to bdk-ffi 0.7.0 2022-06-23 11:03:45 -07:00
Steve Myers
0dfaf3fd35 Update instructions for installing required rust targets 2022-06-23 11:03:26 -07:00
Pedro
6be22daf84 Add add_data method for txbuilder op_return (#163) 2022-06-23 07:20:02 -04:00
thunderbiscuit
fad5e3cefd Fix comment for NetworkLocalUtxo trait 2022-06-22 14:48:56 -03:00
Zoe Faltibà
28a9b302d5 Post review changes 2022-06-18 15:38:39 +02:00
Zoe Faltibà
8f5ca7f0fc Add Wallet list_unspent method 2022-06-18 15:37:40 +02:00
thunderbiscuit
c4b1985076 Remove install of uniffi-bindgen in CI workflow (#65) 2022-06-17 14:49:47 -03:00
thunderbiscuit
d213266c52 Bump version to 0.8.0-SNAPSHOT (#67) 2022-06-17 14:49:15 -03:00
thunderbiscuit
29f09e7cd8 Merge pull request #63 from nicbus/nicbus/armv7
Add armeabi-v7a support
2022-06-15 16:52:20 -03:00
thunderbiscuit
860130f08c Add armv7-linux-androideabi to CI Rust android targets 2022-06-15 16:37:20 -03:00
Nicola Busanello
d8c3ddca16 add armv7 support 2022-06-15 16:25:16 -03:00
Tang Yetong
df67ded9f1 Feat: Update gitmodule to use HTTPS
Signed-off-by: Tang Yetong <tangyetong666@gmail.com>
2022-06-15 16:23:26 -03:00
thunderbiscuit
5f2297ed7c Hardcode ANDROID_NDK_ROOT to fix CI issues 2022-06-15 08:48:24 -03:00
thunderbiscuit
de9fde0d9c Migrate tests to API version 0.7.0 2022-06-14 16:52:13 -03:00
thunderbiscuit
fe045c13f4 Bump bdk-ffi version to 0.7.0 2022-06-14 16:51:22 -03:00
thunderbiscuit
b76bdfcb22 Remove unnecessary architecture enum in plugin 2022-05-18 13:35:40 -04:00
thunderbiscuit
9b8cc006ba Build both x86_64 and aarch64 binaries when building bdk-jvm on macOS 2022-05-18 13:25:58 -04:00
thunderbiscuit
c9c85875a5 Merge pull request #56 from notmandatory/bump_release_070
Bump version to 0.7.0-SNAPSHOT
2022-05-16 14:11:37 -04:00
Steve Myers
a9e868cb7e Bump version to 0.7.0-SNAPSHOT 2022-05-16 10:38:12 -07:00
Steve Myers
5622b07047 Update Package binaryTarget for release 0.3.0 2022-05-13 14:13:08 -07:00
Steve Myers
e6223be905 Update to bdk-ffi 0.6.0 2022-05-13 14:07:23 -07:00
Steve Myers
cecf973777 Update docs.patch for bdk-ffi 0.6.0 2022-05-12 15:39:52 -07:00
Steve Myers
108fcd46ec Comment out walletTxBuilderBroadcast test 2022-05-12 15:09:22 -07:00
Steve Myers
44b724ea9f Update to bdk-ffi 0.6.0 2022-05-12 15:09:14 -07:00
thunderbiscuit
03b2097173 Bring changelog up to date with bdkpython 0.1.0 2022-05-11 16:20:18 -04:00
thunderbiscuit
29821069d8 Use same wallet descriptor as for the bdk-kotlin tests 2022-05-11 16:09:59 -04:00
thunderbiscuit
3ae2f48846 Upgrade library to bdk-ffi 0.6.0 2022-05-11 16:02:49 -04:00
thunderbiscuit
cc730b00b2 Fix test workflow in readme 2022-05-11 15:19:33 -04:00
thunderbiscuit
d23dfb831b Update bdk-ffi submodule to version to 0.6.0 2022-05-11 15:18:37 -04:00
thunderbiscuit
711747efc0 Merge branch 'master' into feat/ffi-0.6.0 2022-05-06 15:31:11 -04:00
thunderbiscuit
45216c7563 Update library to new bdk-ffi API version to 0.6.0 2022-05-06 15:24:41 -04:00
thunderbiscuit
a9f42dd945 Fix dokka plugin declaration in JVM gradle build file 2022-04-17 09:27:52 -04:00
thunderbiscuit
d8cfa1110d Merge branch 'master' into gradle-plugin 2022-04-17 09:18:15 -04:00
thunderbiscuit
e41bc9a84f Remove build shell script and use Gradle plugin in CI workflow 2022-04-17 09:14:55 -04:00
thunderbiscuit
0ab14264c0 Add comment on requirement for x86_64 emulator in docs 2022-04-17 08:59:57 -04:00
thunderbiscuit
14622ef75b Fix requirement for different extensions on JVM native libraries 2022-04-17 08:54:06 -04:00
thunderbiscuit
4dc4182236 Fix docs typo in Gradle build task 2022-04-17 08:45:33 -04:00
thunderbiscuit
12e04a634b Clean up docs for custom Gradle plugins 2022-04-12 15:04:24 -04:00
thunderbiscuit
51f978e78e Add custom Gradle plugin to build bdk-android library 2022-04-12 14:41:04 -04:00
thunderbiscuit
b8e1282eba Fix dokka theme bug with AGP 2022-04-07 15:45:48 -04:00
thunderbiscuit
758608419b Temp: Start Android plugin 2022-04-07 13:50:34 -04:00
thunderbiscuit
e566c4017c Remove intermediate tasks from Bitcoindevkit group
This ensures they don't show up when using ./gradlew :jvm:tasks. The
only two tasks that will appear in the end will be buildJvmLib and
buildAndroidLib.
2022-04-05 22:17:12 -04:00
thunderbiscuit
35f097542b Add documentation for plugin 2022-04-05 21:36:06 -04:00
thunderbiscuit
06d3f96706 Add aggregate task buildJvmLib 2022-04-05 21:35:59 -04:00
thunderbiscuit
a8d0bf52d2 Add Gradle plugin MVP for building JVM library 2022-04-05 21:35:51 -04:00
Steve Myers
1bcacece65 Update docs.patch file 2022-04-05 16:45:24 -07:00
Steve Myers
25863c527f Comment out jvm test walletTxBuilderDrainWallet 2022-04-05 15:05:04 -07:00
Steve Myers
1905d8804d Add jvm walletTxBuilderDrainWallet test 2022-04-05 15:05:02 -07:00
Steve Myers
65b9a3f9b6 Fix CI caching for bdk-ffi/target 2022-04-05 15:05:00 -07:00
Steve Myers
43865b0ad0 Update bdk-ffi to v0.5.0 2022-04-05 15:04:58 -07:00
Steve Myers
907f67eb83 Update bdk-ffi and add TxBuilder tests 2022-04-05 15:04:56 -07:00
Steve Myers
f205269d97 Fix tests network and addresses to TESTNET
Must be TESTNET to match BlockchainConfig.
2022-04-05 15:04:54 -07:00
thunderbiscuit
0aa9db450d Add library version to API docs 2022-04-01 12:56:16 -04:00
Steve Myers
4f121f8289 Merge commit 'refs/pull/31/head' of github.com:bitcoindevkit/bdk-kotlin 2022-03-30 12:03:11 -07:00
thunderbiscuit
42b8db8609 Fix docs homepages module.md files 2022-03-30 14:29:09 -04:00
thunderbiscuit
61295bf7ac Merge pull request #33 from kirillzh/issue-32/publish-android-sources-and-docs
#32: Enable publishing bdk-android sources and java docs
2022-03-23 19:47:40 -04:00
Steve Myers
f99ba7f992 Add CI steps to build bdk-ffi libraries 2022-03-22 13:54:42 -05:00
Sudarsan Balaji
fa1b94da10 Merge commit 'refs/pull/34/head' of https://github.com/bitcoindevkit/bdk-kotlin 2022-03-21 20:27:45 +00:00
Kirill Zhukov
16e6a4b170 Update README and build.sh script to use latest env var naming.
ANDROID_HOME, ANDROID_SDK_HOME, and ANDROID_NDK_HOME are not used by the Android platform and SDK tools so these are considered deprecated/invalid.

Google recommends using ANDROID_SDK_ROOT and ANDROID_NDK_ROOT instead:
- https://groups.google.com/g/android-ndk/c/qZjhOaynHXc/m/2ux2ZZdxy2MJ
- https://developer.android.com/studio/command-line/variables
2022-03-20 16:52:56 -07:00
Kirill Zhukov
aea8d703e1 Enable publishing sources and javadocs for bdk-android.
This resolves bitcoindevkit#32.
Using new API from AGP 7.1.0 to generate and publish Android sources and javadocs.

https://developer.android.com/studio/releases/gradle-plugin#publish-javadoc-jar
https://developer.android.com/studio/releases/gradle-plugin#publish-sources-jar
2022-03-20 15:47:21 -07:00
Kirill Zhukov
bb9d0869ac Update AGP to 7.1.2.
AGP 7.1.0 adds maven-publish APIs for making publishing javadocs and sources for Android libraries very easy. We can use that to resolve #32.

Changelog: https://developer.android.com/studio/releases/gradle-plugin#versioning-update.
2022-03-20 15:47:19 -07:00
thunderbiscuit
aa13e113fa Add required files for API docs 0.5.1 2022-03-19 11:11:44 -04:00
thunderbiscuit
6332e78375 Add ability to generate dokka docs 2022-03-19 11:11:25 -04:00
thunderbiscuit
f1f69c6fdf Add basic CI workflow that runs tests on pull requests
Fixes #27
2022-03-18 14:10:34 -04:00
thunderbiscuit
e139e3d999 Merge pull request #26 from thunderbiscuit/fix/memory
Fix database memory test
2022-03-17 17:23:27 -04:00
thunderbiscuit
fadaef5105 Fix database memory test 2022-03-17 17:19:17 -04:00
Steve Myers
bb1e69e73f Increment version to 0.6.0-SNAPSHOT 2022-03-17 16:10:23 -05:00
Steve Myers
dc9ad20d99 Add javadocs to jvm build 2022-03-17 16:06:12 -05:00
Steve Myers
e9111f74c5 Update bdk-ffi to 0.4.1 2022-03-17 13:38:59 -05:00
thunderbiscuit
322b5b4343 Merge pull request #14 from thunderbiscuit/community
Add community related files
2022-03-15 19:08:32 -04:00
thunderbiscuit
4e4d2c64b4 Add documentation on how to skip signing task for local Maven 2022-03-15 13:47:08 -04:00
Steve Myers
a1b4d66f47 Fix README example 2022-03-15 08:59:58 -05:00
Steve Myers
a495bd9605 Update bdk-ffi to v0.4.0 2022-03-14 15:24:10 -05:00
Steve Myers
b0b44550a1 Add sqlite database option 2022-03-14 15:15:13 -05:00
Steve Myers
5b760717bf Merge commit 'refs/pull/17/head' of github.com:bitcoindevkit/bdk-kotlin 2022-03-14 13:46:28 -05:00
Steve Myers
e48a0d9b54 Merge commit 'refs/pull/16/head' of github.com:bitcoindevkit/bdk-kotlin 2022-03-14 12:59:56 -05:00
thunderbiscuit
1ff345ab1d Merge pull request #12 from thunderbiscuit/bump-version
Bump version to v0.0.6.dev
2022-03-04 09:50:55 -05:00
thunderbiscuit
7c9a624eab Add changelog 2022-03-04 09:07:27 -05:00
thunderbiscuit
8b50e8d3ad Fix version numbering to comply with PEP 440 2022-03-04 08:53:11 -05:00
thunderbiscuit
6f848254bc Add Apache 2.0 and MIT licenses 2022-03-03 16:40:51 -05:00
thunderbiscuit
680d3ccc86 Add feature request template 2022-03-03 16:28:45 -05:00
thunderbiscuit
e42e2c15e2 Add bug report template 2022-03-03 16:24:46 -05:00
thunderbiscuit
d41f787efd Add pull request template 2022-03-03 16:06:34 -05:00
thunderbiscuit
e851f42aee Bump version to v0.0.6-SNAPSHOT 2022-03-03 15:55:22 -05:00
thunderbiscuit
2ebd4979b0 Merge pull request #11 from thunderbiscuit/master
Bump bdk-ffi submodule to v0.3.0
2022-03-03 15:48:10 -05:00
Steve Myers
91b290e474 Bump version to 0.2.0 2022-03-02 20:29:38 -08:00
Steve Myers
61c75b24bd Add example project to README 2022-03-02 20:17:11 -08:00
Steve Myers
2cd5fa6934 Update bdk-ffi to 0.3.1 2022-03-02 20:04:49 -08:00
thunderbiscuit
453dc6e7ea Bump bdk-ffi submodule to v0.3.0 2022-03-01 10:37:18 -05:00
Steve Myers
1ec6d2538e Add license files 2022-02-28 22:14:17 -08:00
Steve Myers
54a28d65b8 Merge branch 'master' into release/0.4 2022-02-28 21:49:04 -08:00
Steve Myers
9123cbbaef Remove unused code 2022-02-28 21:43:19 -08:00
Steve Myers
9e35866a47 Merge commit 'refs/pull/10/head' of github.com:bitcoindevkit/bdk-kotlin 2022-02-28 21:39:16 -08:00
Steve Myers
a21b69a217 Fix jvm artifact version 2022-02-28 21:30:18 -08:00
Steve Myers
933af8c706 Fix jvm module junit dependency error 2022-02-28 21:11:25 -08:00
Steve Myers
5514dc577e Bump version to 0.4.1-SNAPSHOT 2022-02-28 20:43:23 -08:00
Steve Myers
6195ba0896 Bump version to 0.4.0 2022-02-28 20:43:21 -08:00
Steve Myers
9a3f930148 Update README for bdk-jvm and bdk-android 0.4.0 2022-02-28 20:42:55 -08:00
Steve Myers
e7e4b0f48b Update to pruned bdk-ffi v0.3.0 tag 2022-02-28 16:23:48 -08:00
thunderbiscuit
74f6d2bb9e Remove compiler option for experimental unsigned types 2022-02-28 10:28:44 -05:00
Steve Myers
6df9a98fb6 Fix tests for bdk-ffi v0.3.0, add psbt serde test 2022-02-27 22:48:59 -08:00
Steve Myers
19e88e3e67 Update bdk-ffi to v0.3.0 2022-02-27 21:51:30 -08:00
thunderbiscuit
95ef8eb3de Migrate jvm module Gradle build script to Kotlin DSL 2022-02-23 15:19:18 -05:00
thunderbiscuit
25f5bd26b4 Migrate android module Gradle build script to Kotlin DSL 2022-02-23 15:18:13 -05:00
thunderbiscuit
4e66758048 Migrate project-level Gradle build script to Kotlin DSL 2022-02-23 15:11:05 -05:00
Steve Myers
bd13eca0f3 Add uniffi-bindgen version to README 2022-02-22 21:48:18 -08:00
Caio Faustino
4656cf50b5 Add step to install uniffi-bindgen on README
This step exists in bdk-ffi readme, but is missing in this repo,
and build.sh fails without it.
2022-02-22 21:46:23 -08:00
Steve Myers
77a5353469 Merge commit 'refs/pull/5/head' of github.com:bitcoindevkit/bdk-kotlin 2022-02-22 21:38:14 -08:00
thunderbiscuit
4de866de20 Bump package version to 0.0.5 2022-02-22 21:40:11 -05:00
thunderbiscuit
472edb6e8c Add publish job to GitHub workflow 2022-02-22 14:03:08 -05:00
thunderbiscuit
7982a73aa7 Fix long description examples after API change 2022-02-16 21:59:28 -05:00
thunderbiscuit
a6943af686 Add build directory to gitignore 2022-02-16 21:59:28 -05:00
thunderbiscuit
be87629aba Fix 'build the wheel' section of readme 2022-02-16 21:59:11 -05:00
thunderbiscuit
c364b20dd9 Merge pull request #2 from afilini/setuptools-rust
Build wheels using setuptools-rust
2022-02-16 20:26:33 -05:00
Alekos Filini
acb8380b61 Build wheels in GitHub Actions 2022-02-15 17:11:09 +01:00
Alekos Filini
d2bbecc5f5 Build wheels using setuptools-rust
Build wheels in a more "standard" way using setuptools-rust, which makes
our life easier when dealing with multiple different platforms.

Also use the new bdk-ffi's `generate` binary instead of relying on
uniffi's bindgen cli.
2022-02-15 16:48:38 +01:00
thunderbiscuit
9ef075c67e Add Devkit Wallet link 2022-02-07 16:36:27 -05:00
Steve Myers
c917a77639 Fix pull request template 2022-02-04 14:32:18 -06:00
Steve Myers
e26d7b9c9c Add a Github feature request template 2022-02-04 14:02:38 -06:00
Steve Myers
ba51cbf64e Allow creating a blank Github issue 2022-02-04 14:02:28 -06:00
Steve Myers
62db844911 Add Github bug template and issue config and PR template 2022-02-04 11:39:52 -06:00
Steve Myers
530031e088 Bump jvm and android versions to 0.3.2 2022-02-03 20:02:28 -06:00
Steve Myers
f601a17daa Fix jvm darwin-aarch64 jpa resources path 2022-02-03 19:39:13 -06:00
Steve Myers
438f05a39a Bump jvm and android versions to 0.3.1 2022-01-30 21:25:25 -06:00
Steve Myers
7b060f2e7e Bump android and jvm versions to 0.3.0 2022-01-28 23:49:06 -06:00
Steve Myers
68dea8b258 Update build.sh to support building mac aarch64 (m1) targets, update bdk-ffi 2022-01-28 23:47:11 -06:00
Steve Myers
9bb629d0a8 Update README.md with links to padawan and tatooine 2022-01-24 10:35:59 -08:00
Steve Myers
2a658d2ff6 Remove demo 2022-01-24 10:35:56 -08:00
Sudarsan Balaji
6c1de427ff Merge pull request #1 from bitcoindevkit/fix_publish
Update SDK and dependency versions
2022-01-24 18:28:19 +00:00
Sudarsan Balaji
6967ee0ace Add a note on submodule usage 2022-01-24 18:22:53 +00:00
Sudarsan Balaji
7ab48613c3 Add a note on NDK version 2022-01-24 18:19:17 +00:00
Steve Myers
67ecd89d5f Update gradle compilerArgs to use -Xopt-in 2021-12-21 13:11:57 -08:00
Steve Myers
cd55d01f72 Upgrade gradle and sdk and dependency versions 2021-12-18 10:45:08 -08:00
Steve Myers
e4a7e4efa1 remove demo/gradle 2021-12-17 12:15:07 -08:00
Steve Myers
e409856d62 Update README.md 2021-12-14 21:34:16 -08:00
Steve Myers
d0be3bd6da Bump version to 0.2.0 2021-12-13 23:00:26 -08:00
Steve Myers
0f42ba7590 Remove non-kotlin related files, add bdk-ffi as submodule, update build.sh 2021-12-13 22:15:37 -08:00
thunderbiscuit
964b7ae5f0 Update project url 2021-12-13 19:45:48 -05:00
thunderbiscuit
d946e53c60 Bump package version to 0.0.4 2021-12-13 19:44:10 -05:00
thunderbiscuit
3aef401092 Add supported architectures to readme 2021-12-13 19:43:39 -05:00
thunderbiscuit
662c425743 Enable subdirectories for native libraries in package 2021-12-13 12:17:25 -05:00
thunderbiscuit
65bd7ea428 Update loadIndirect function fix documentation 2021-12-13 12:15:30 -05:00
thunderbiscuit
9f3194d315 Bump package version to 0.0.3-dev 2021-12-11 19:30:55 -05:00
thunderbiscuit
5e82625b76 Add .so file type to package data copy task
This fix enables building for the x86_64 architecture
2021-12-11 19:29:01 -05:00
thunderbiscuit
c750af1b9a Add authors and long description to PyPI release 2021-12-07 14:56:15 -05:00
thunderbiscuit
5e376db385 Add MVP Python package structure 2021-12-07 10:25:42 -05:00
thunderbiscuit
45cdd6911a Add build script 2021-12-07 10:18:14 -05:00
thunderbiscuit
f898bc0351 Add build and install instructions to readme 2021-12-07 10:12:30 -05:00
thunderbiscuit
5fd491a4e7 Add gitignore 2021-12-07 10:10:30 -05:00
thunderbiscuit
145c526fc1 Add git submodule bdk-ffi 2021-12-06 13:13:34 -05:00
thunderbiscuit
247340632b Add readme 2021-12-06 13:04:15 -05:00
thunderbiscuit
58f189f987 Initial empty commit 2021-12-06 12:59:07 -05:00
Steve Myers
f2b857a609 Change bdkFFI xcframework download url to bitcoindevkit repo release 2021-12-03 12:35:58 -08:00
Steve Myers
e450668b9d Update .gitmodule to https url 2021-12-03 11:35:58 -08:00
Steve Myers
a33e856b48 Add M1 target support to build.sh 2021-12-03 10:55:39 -08:00
Steve Myers
250df250ff Update README 2021-11-24 15:14:47 -08:00
Steve Myers
dcefae806d Bump version to 0.1.3 2021-11-24 14:31:21 -08:00
Steve Myers
05a6a21e9e Update README with usage and publishing instructions 2021-11-24 14:30:33 -08:00
Steve Myers
ee56748348 Update to lastest bdk-ffi master branch 2021-11-24 12:31:59 -08:00
Steve Myers
09ce971708 Remove swift related files and -s option in build.sh
Build script and files to create a bdkFFI binary xcframework and BitcoinDevKit swift package
have been moved to the bdk-swift repo.
2021-11-24 12:23:19 -08:00
Steve Myers
aa84f5583e Bump version to 0.1.2 2021-11-24 00:17:34 -08:00
Steve Myers
18a2efa8da Add missing BitcoinDevKit.swift 2021-11-24 00:10:26 -08:00
Steve Myers
14c10b6631 Fix bdkFFI url 2021-11-23 23:57:24 -08:00
Steve Myers
a74f5caaff Fix bdkFFI checksum 2021-11-23 23:41:00 -08:00
Steve Myers
71496cd56a Simplify build.sh and add template bdkFFI.xcframework to repo 2021-11-23 22:50:42 -08:00
Steve Myers
2ccd89ed2e Fix build.sh cargo build loop and xcframework module.modulemap 2021-11-23 21:46:11 -08:00
Steve Myers
38403e00b4 Initial Commit 2021-11-23 11:51:51 -08:00
Steve Myers
743ba939ca Fix IOSBdkAppSample to work with git hosted BitcoinDevKit swift package 2021-11-23 10:05:19 -08:00
Steve Myers
af101d0b41 Update build.sh to create swift xcframework 2021-11-23 10:05:19 -08:00
Steve Myers
581787a775 Pin anyhow version to "=1.0.45"
This change can be removed after upgrading to the next version of uniffi.
See: https://github.com/mozilla/uniffi-rs/issues/1109
2021-11-22 15:59:12 -08:00
thunderbiscuit
9fa6fd5133 Refactor transaction 'id' property to 'txid' 2021-11-12 12:50:40 -05:00
Steve Myers
3f28be0854 Bump version to 0.1.3-dev 2021-11-08 18:14:44 -08:00
Steve Myers
02dd2af0d3 Remove kotlin jvm testFixtures and dup test code 2021-11-08 18:14:39 -08:00
Steve Myers
0d68d2341b Bump version to 0.1.2 2021-11-08 18:14:33 -08:00
Sudarsan Balaji
9131c37d8e Re-add test fixtures 2021-11-08 18:14:28 -08:00
Sudarsan Balaji
597d0685ae Remove debug version of android package 2021-11-08 18:14:22 -08:00
Sudarsan Balaji
df5bb9b722 Update email 2021-11-08 18:14:17 -08:00
Steve Myers
62d7d6fbd5 Configure publishing for jvm and android artifacts to maven central 2021-11-08 18:14:11 -08:00
Sudarsan Balaji
5512cee539 Merge pull request #75 from bitcoindevkit/update-readme-with-deployed-package-versions
Update README with latest published package information
2021-11-06 05:48:53 +05:30
Sudarsan Balaji
613f25a79e Update README with latest published package information 2021-11-06 05:48:27 +05:30
Sudarsan Balaji
52529b7d05 Merge pull request #73 from bitcoindevkit/publish-a-package
Publish android and kotlin packages
2021-11-06 01:31:42 +05:30
Sudarsan Balaji
5ecfab3c0e Add some notes on consuming published packages 2021-11-06 01:30:36 +05:30
Sudarsan Balaji
39554e11be Update jvm package artifact id 2021-11-06 01:23:21 +05:30
Sudarsan Balaji
152e2147e6 Remove armv7 ABI target instead of i686 2021-11-06 00:45:03 +05:30
Sudarsan Balaji
a4e32e7833 Stop publishing on build 2021-11-06 00:23:06 +05:30
Sudarsan Balaji
fb3bfbde70 Stop copying over i686 2021-11-06 00:22:58 +05:30
Sudarsan Balaji
cfde899b2c Add publish configuration 2021-11-06 00:22:45 +05:30
Sudarsan Balaji
dc7339a174 Add publish configuration 2021-11-06 00:22:38 +05:30
Sudarsan Balaji
931461e10d Ignore unnecessary files 2021-11-05 23:52:08 +05:30
Steve Myers
1edc4ec878 Merge pull request #70 from notmandatory/fix_build
Fix build.sh kotlin copy for android, also a rust fmt fix
2021-11-04 17:47:52 -07:00
Steve Myers
4e5741f55d Fix build.sh kotlin copy for android 2021-11-04 17:44:02 -07:00
Sudarsan Balaji
b2bdb5c818 Merge pull request #69 from bitcoindevkit/return-transaction-details-on-broadcast
Return transaction details on broadcast
2021-11-05 01:19:04 +05:30
Sudarsan Balaji
bfe38d9890 Use From trait for conversion 2021-11-05 01:13:45 +05:30
Sudarsan Balaji
87a8af9457 Use From trait for conversion 2021-11-05 01:08:50 +05:30
Sudarsan Balaji
e738126bed Fix demo 2021-11-05 00:45:50 +05:30
Sudarsan Balaji
de47771c12 Update Wallet::broadcast API 2021-11-05 00:45:40 +05:30
Sudarsan Balaji
578771ffe1 Return transaction on broadcast 2021-11-05 00:45:27 +05:30
Sudarsan Balaji
683a817c55 Simplify 2021-11-05 00:45:16 +05:30
Sudarsan Balaji
d190008f2c Add details to PSBT 2021-11-05 00:45:02 +05:30
Sudarsan Balaji
f4e9af18b5 Add a way to convert TransactionDetails to Transaction 2021-11-05 00:44:40 +05:30
Sudarsan Balaji
620d65e217 Allow cloning transaction 2021-11-05 00:43:26 +05:30
Sudarsan Balaji
202f6c71e6 Merge pull request #67 from bitcoindevkit/allow-passing-a-fee-rate-when-creating-a-transaction
Add optional fee rate to a transaction
2021-11-04 23:30:11 +05:30
Sudarsan Balaji
ba12b632b4 Add optional fee rate to a transaction 2021-11-04 23:29:22 +05:30
Sudarsan Balaji
850ef7208d Merge pull request #65 from bitcoindevkit/allow-getting-last-unused-wallet-address
Allow getting last unused wallet address
2021-11-04 22:48:55 +05:30
Sudarsan Balaji
1888c2e2a1 Expose Wallet::getLastUnusedAddress 2021-11-04 22:45:00 +05:30
Sudarsan Balaji
076de31dcc Add a way to get last unused address 2021-11-04 22:44:38 +05:30
Sudarsan Balaji
498fabf97d Merge pull request #52 from notmandatory/add-more-features-to-ios-example
Add more features to iOS example
2021-11-02 21:59:59 +05:30
Sudarsan Balaji
862029a0ba Ignore xc user data 2021-11-02 21:48:29 +05:30
Sudarsan Balaji
12628a62d8 Ignore unnecessary files 2021-11-02 18:43:05 +05:30
Steve Myers
b6835364b3 Fix androidTest package and proguard and manifest 2021-11-01 20:08:07 -07:00
Steve Myers
ae2294c83b Delete generated swift files, update lib name 2021-11-01 19:36:52 -07:00
Steve Myers
a8f69fbd2b Rename kotlin package to org.bitcoindevkit, rust lib to bdkffi 2021-11-01 19:07:27 -07:00
Sudarsan Balaji
fa1c6ffa33 Merge pull request #40 from notmandatory/add-documentation-for-swift-bindings
Add sections and more info to README
2021-10-30 00:29:24 +05:30
Sudarsan Balaji
99affffd32 Fix heading levels 2021-10-30 00:28:26 +05:30
Sudarsan Balaji
fea6a3d1ee Add sections and more info 2021-10-30 00:27:02 +05:30
Steve Myers
cafc15197c Update README android setup 2021-10-28 15:34:17 -07:00
Steve Myers
2fc37eef61 Fix build.sh and test.sh help 2021-10-28 14:22:45 -07:00
Steve Myers
fec67b7622 Update bdk dependency to 0.13.0 2021-10-28 14:21:57 -07:00
Sudarsan Balaji
b7703e30f9 Merge pull request #35 from notmandatory/add-swift-language-bindings
Add swift language bindings
2021-10-28 23:01:11 +05:30
Sudarsan Balaji
28d13b57d6 Update uniffi to 0.14.1
which supports callback interface in Swift
2021-10-28 23:00:23 +05:30
Sudarsan Balaji
95074b4834 Revert "Remove callback interface"
This reverts commit f04c1f7fa8.
2021-10-28 01:51:16 +05:30
Sudarsan Balaji
f5be0fae3d Add swiftmodule 2021-10-28 00:37:42 +05:30
Sudarsan Balaji
a946a0cb44 Generate bindings for swift 2021-10-28 00:35:22 +05:30
Sudarsan Balaji
8406ff04b7 Copy kotlin libs only when building kotlin 2021-10-28 00:35:09 +05:30
Sudarsan Balaji
f04c1f7fa8 Remove callback interface 2021-10-28 00:33:10 +05:30
Sudarsan Balaji
925d92c4b8 Merge pull request #32 from notmandatory/fix-identifier-case-in-udl
Use snake_case for identifier
2021-10-21 23:43:28 +05:30
Sudarsan Balaji
6fc53fdfe7 Use snake_case for identifier 2021-10-21 23:42:38 +05:30
Sudarsan Balaji
9757b9900e Merge pull request #31 from notmandatory/change-aar-outputs
Export source files with aar
2021-10-21 23:27:04 +05:30
Sudarsan Balaji
33f37ae593 Export source files with aar 2021-10-21 23:26:34 +05:30
Sudarsan Balaji
6a25dbfb05 Merge pull request #30 from notmandatory/allow-creating-a-wallet-with-a-change-descriptor
Allow creating a wallet with a change descriptor
2021-10-21 14:54:21 +05:30
Sudarsan Balaji
d833ebadfc Update consumers of OnlineWallet::new with change descriptor 2021-10-21 14:53:51 +05:30
Sudarsan Balaji
091f5df97d Add change descriptor to Wallet 2021-10-21 14:50:52 +05:30
Sudarsan Balaji
cda099a2f2 Merge pull request #29 from notmandatory/allow-restoring-extended-key-from-mnemonic
Allow restoring extended key from mnemonic
2021-10-21 14:45:11 +05:30
Sudarsan Balaji
3b9df0d110 Ensure restoration of extended key from mnemonic 2021-10-21 14:44:29 +05:30
Sudarsan Balaji
852f7a6468 Allow restoring extended keys from mnemonic 2021-10-21 14:40:26 +05:30
Sudarsan Balaji
79e691e4f3 Merge pull request #28 from notmandatory/allow-generating-key
Allow creating extended keys
2021-10-21 14:37:18 +05:30
Sudarsan Balaji
be24f18d84 Show how to generate extended keys 2021-10-21 14:35:55 +05:30
Sudarsan Balaji
e20a41a186 Allow generating extended keys 2021-10-21 14:35:40 +05:30
Sudarsan Balaji
360d2c9005 Upgrade to gradle 7.2 2021-10-21 14:35:14 +05:30
Steve Myers
fd03eb95eb Change descriptor to wpkh with tprv key 2021-10-18 16:51:18 -07:00
Steve Myers
db4f2db748 Fix demo gradle warning 2021-10-18 14:49:10 -07:00
Steve Myers
e9f00dcb75 Move bdk-kotlin test-fixtures tests to jvm module 2021-10-18 14:15:36 -07:00
Sudarsan Balaji
5ece17d67a Merge pull request #21 from notmandatory/list-incomplete-transactions
List both confirmed and unconfirmed transactions
2021-10-18 17:35:14 +05:30
Sudarsan Balaji
e64b1f67c1 List both confirmed and unconfirmed transactions 2021-10-18 15:48:30 +05:30
Steve Myers
c9e8368694 Add android aar build and connected device test 2021-10-17 14:51:05 -07:00
Steve Myers
f556f611b0 Move kotlin tests to fest-fixtures submodule 2021-10-17 14:51:04 -07:00
Steve Myers
0b500d8e05 Remove and ignore generated code and binary libs 2021-10-17 14:51:02 -07:00
Sudarsan Balaji
b91d96278b Merge pull request #19 from notmandatory/improve-console-output
Simplify messages
2021-10-17 04:12:38 +05:30
Sudarsan Balaji
6122051431 Simplify messages 2021-10-17 04:11:43 +05:30
Sudarsan Balaji
9b4419088c Merge pull request #18 from notmandatory/allow-listing-transactions
Allow listing confirmed transactions
2021-10-17 03:19:42 +05:30
Sudarsan Balaji
b47c3c482d Apply formatting 2021-10-17 02:52:45 +05:30
Sudarsan Balaji
50dc701ec4 Avoid superflous printlns 2021-10-17 02:51:46 +05:30
Sudarsan Balaji
87437fbddc Stop printing to console when confirming 2021-10-17 02:45:38 +05:30
Sudarsan Balaji
25977408df Keep syncing until confirmation 2021-10-17 02:38:51 +05:30
Sudarsan Balaji
9d3b31b56e Return only confirmed transactions in Wallet::getTransactions 2021-10-17 02:36:43 +05:30
Sudarsan Balaji
d343bce815 Allow listing confirmed transactions 2021-10-17 02:28:26 +05:30
Sudarsan Balaji
69efddafec Merge pull request #14 from notmandatory/allow-signing-partially-signed-transactions
Allow signing partially signed transactions
2021-10-16 20:28:03 +05:30
Sudarsan Balaji
ca0a2cba15 Share Wallet::getBalance and Wallet::sign 2021-10-16 20:25:58 +05:30
Sudarsan Balaji
58d774a3f3 Fix formatting 2021-10-16 20:19:56 +05:30
Sudarsan Balaji
320771d7f8 Add sign and broadcast to wallet 2021-10-16 20:19:34 +05:30
Sudarsan Balaji
9d6229df58 Simplify logger 2021-10-16 20:10:07 +05:30
Sudarsan Balaji
33a291f760 Merge pull request #13 from notmandatory/allow-creating-a-wallet-transaction
Allow creating partially signed bitcoin transactions
2021-10-16 16:44:49 +05:30
Sudarsan Balaji
d4c832b8de Allow creating partially signed bitcoin transactions 2021-10-16 16:42:35 +05:30
Sudarsan Balaji
0b3fda9da8 Merge pull request #12 from notmandatory/add-demo-application
Add demo application
2021-10-16 14:46:50 +05:30
Sudarsan Balaji
3f620ecf19 Add demo application in kotlin 2021-10-16 14:45:32 +05:30
Sudarsan Balaji
85d803afcf Merge pull request #11 from notmandatory/unify-offline-operations
Share OfflineWalletOperations
2021-10-16 14:22:37 +05:30
Sudarsan Balaji
2dab31209e Share OfflineWalletOperations 2021-10-16 14:19:29 +05:30
Sudarsan Balaji
95980c5e14 Merge branch 'uniffi' of https://github.com/notmandatory/bdk-ffi into uniffi 2021-10-15 21:27:46 +05:30
Steve Myers
31db42ae0e Reorganize bdk-kotlin into jvm sub-module 2021-10-14 22:05:21 -07:00
artfuldev
830cbd852e Fix electrum testnet url 2021-10-15 03:56:17 +05:30
artfuldev
c15c69fb08 Add OnlineWallet::getBalance() 2021-10-15 03:40:33 +05:30
artfuldev
5ab47ef815 Remove testdb before every test 2021-10-15 03:05:46 +05:30
artfuldev
9ba0625824 Remove unnecessary Mutex wrapper 2021-10-15 03:00:49 +05:30
artfuldev
2907eb074d Test a callback 2021-10-15 01:54:32 +05:30
artfuldev
40a4b58757 Add OnlineWallet::getNetwork 2021-10-15 00:48:53 +05:30
artfuldev
0fc04fc34e Add online wallet 2021-10-15 00:43:17 +05:30
Steve Myers
038c9ef23c Change order of Network param 2021-10-14 11:17:52 -07:00
Steve Myers
fffb2e2cbc Add Network enum as wallet constructor param 2021-10-14 10:58:16 -07:00
Sudarsan Balaji
58ef298a42 Add a test for sled 2021-10-14 04:29:50 +05:30
Sudarsan Balaji
6f01c38a71 Allow using configs for database 2021-10-14 04:23:17 +05:30
Sudarsan Balaji
23c17ca841 Use a thread-safe MemoryDatabase 2021-10-14 03:53:22 +05:30
Sudarsan Balaji
a66e8eb8ed Add name to authors 2021-10-14 00:15:25 +05:30
Sudarsan Balaji
42582158bf Add test for exception being thrown 2021-10-14 00:06:17 +05:30
Sudarsan Balaji
1864a3e6ba Add JNA debug_load to gradle script 2021-10-14 00:06:05 +05:30
Sudarsan Balaji
07b35bb20f Add a little bit of error handling 2021-10-14 00:05:50 +05:30
Sudarsan Balaji
a8a2de9d24 Stop running gradle build
which also runs tests
2021-10-14 00:05:29 +05:30
Sudarsan Balaji
da24bb2bfc Ignore more files
mac-specific
local sled database
2021-10-14 00:05:04 +05:30
Sudarsan Balaji
9ea2494940 Use settings from rust-fmt 2021-10-14 00:04:44 +05:30
Sudarsan Balaji
5459ad3e7e Add editorconfig 2021-10-13 13:42:55 +05:30
Steve Myers
b94620819c Update README, build.sh and test.sh, rust fmt 2021-10-12 18:22:02 -07:00
Steve Myers
290db0105f [WIP] reorganize and remove old stuff 2021-10-12 15:24:11 -07:00
Sudarsan Balaji
a7f7ab0ef9 Ignore testdb 2021-10-13 03:06:49 +05:30
Sudarsan Balaji
87a4e09862 Add some more steps to run 2021-10-13 03:05:55 +05:30
Sudarsan Balaji
121e2b34b5 [WIP] first passing test! 2021-10-13 03:04:48 +05:30
Sudarsan Balaji
3ccf780ed3 [WIP] kotlin tests work! 2021-10-13 03:02:49 +05:30
Sudarsan Balaji
a92aa66358 [WIP] Add generated and test files 2021-10-13 02:05:46 +05:30
Sudarsan Balaji
84d28a0476 [WIP] Add get new address API to Wallet 2021-10-13 01:45:22 +05:30
Steve Myers
cdb90aa35c wip compiles now 2021-10-12 11:53:11 -07:00
Steve Myers
aa63457d9c WIP -- NOT WORKING 2021-10-12 10:27:33 -07:00
Steve Myers
6f46e2deb6 [wip] swift 2021-10-02 18:22:30 -07:00
Steve Myers
c11e17b5e2 Upgrade bdk dependency to 0.11 2021-09-28 17:03:25 -07:00
Steve Myers
e5a74344f3 Remove local.properties and add to .gitignore 2021-07-07 10:42:42 -07:00
Steve Myers
24e71b5a39 Update build.sh to install jvm darwin-x86-64 dylib 2021-07-05 14:25:09 -07:00
Steve Myers
b437b78668 Add Wallet.listTransactions() 2021-07-04 22:10:32 -07:00
Steve Myers
cd813a14b1 Add Wallet.balance() 2021-07-04 15:54:23 -07:00
Steve Myers
adadcbc982 Return FfiResult errors as FfiError enum short values 2021-07-03 20:40:17 -07:00
Steve Myers
8443265142 Add FfiResultVoid type 2021-07-03 19:24:29 -07:00
Steve Myers
d00cc73261 Remove unneeded pointers from FfiResult types 2021-07-03 19:07:49 -07:00
Steve Myers
62f18bdc2c Reorganized code into wallet mod/package 2021-07-03 10:16:02 -07:00
Steve Myers
f8365cc939 Rename kotlin src directories to kotlin 2021-07-02 21:36:46 -07:00
Steve Myers
273cad8318 Refactor to return results by value, add wallet list_unspent and related types 2021-07-02 21:28:26 -07:00
Steve Myers
f5dd87b02a Add LibTest getTestDataDir to fix sled test on android 2021-06-26 18:55:49 -07:00
Steve Myers
1249a4c491 Add kotlin BlockchainConfig and DatabaseConfig 2021-06-25 23:40:38 -07:00
Steve Myers
757113c002 Simplify Kotlin Wallet api 2021-06-24 15:00:00 -07:00
Steve Myers
110dfbd13c Update build.sh to publish to local maven repo 2021-06-23 14:20:04 -07:00
Steve Myers
9fd29871ca Fix Kotlin jar: native library path 2021-06-23 14:13:33 -07:00
Steve Myers
c921120216 Update Results return Error enum instead of String 2021-06-22 16:49:25 -07:00
Steve Myers
d248bca299 Add classes to wrap LibJna native types 2021-06-22 11:53:09 -07:00
Steve Myers
90c4fd3328 Add jna lib to jvm jar resources 2021-06-21 15:08:39 -07:00
Steve Myers
e6fabc81b3 Rename Lib to LibJna, add LibBase abstract class 2021-06-21 14:55:56 -07:00
Steve Myers
adb54e3b87 Add slf4j logging for kotlin jvm and android 2021-06-20 23:39:42 -07:00
Steve Myers
f1c1524e61 Add kotlin test-fixtures module used by jvm and android 2021-06-20 20:26:13 -07:00
Steve Myers
a830d9b082 Rename gradle modules to jvm and android 2021-06-20 18:48:48 -07:00
Steve Myers
9e5aac759d Return results as opaque structs from ffi calls 2021-06-20 15:48:06 -07:00
Steve Myers
87c823d497 Free rust allocated string from Kotlin in local and android emulator tests 2021-06-15 15:21:14 -07:00
Steve Myers
610d393923 Add kotlin/aar android device tests 2021-06-14 22:38:29 -07:00
Steve Myers
bec53bd836 Update jar test LD_LIBRARY_PATH to use libs/x86_64_linux 2021-06-14 14:24:20 -07:00
Steve Myers
4682fb3ec8 Execute bdk_ffi_test via valgrind 2021-06-14 14:18:16 -07:00
Steve Myers
e266634560 Rename bdk-kotlin companion project, fix gradle warnings 2021-06-14 13:59:56 -07:00
Steve Myers
a37bae5b9d Remove unneeded test structs and functions, cleanup tests 2021-06-10 17:22:33 -07:00
Steve Myers
a5ad4cd0a5 Fix kotlin wallet struct access via JNA opaque pointer 2021-06-10 13:41:46 -07:00
Steve Myers
8deb39ac76 Add missing kotlin files 2021-06-09 16:00:40 -07:00
Steve Myers
8aa18fbf20 Test new, print, and free Config works 2021-06-08 18:15:20 -07:00
122 changed files with 11001 additions and 1039 deletions

View File

@@ -1,29 +0,0 @@
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

26
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,26 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''
---
**Describe the bug**
<!-- A clear and concise description of what the bug is. -->
**To Reproduce**
<!-- Steps or code to reproduce the behavior. -->
**Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
**Build environment**
- BDK tag/commit: <!-- e.g. v0.13.0, 3a07614 -->
- OS+version: <!-- e.g. ubuntu 20.04.01, macOS 12.0.1, windows -->
- Rust/Cargo version: <!-- e.g. 1.56.0 -->
- Rust/Cargo target: <!-- e.g. x86_64-apple-darwin, x86_64-unknown-linux-gnu, etc. -->
**Additional context**
<!-- Add any other context about the problem here. -->

View File

@@ -0,0 +1,17 @@
---
name: Enhancement request
about: Request a new feature or change to an existing feature
title: ''
labels: 'enhancement'
assignees: ''
---
**Describe the enhancement**
<!-- A clear and concise description of what you would like added or changed. -->
**Use case**
<!-- Tell us how you or others will use this new feature or change to an existing feature. -->
**Additional context**
<!-- Add any other context about the enhancement here. -->

87
.github/ISSUE_TEMPLATE/minor_release.md vendored Normal file
View File

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

View File

@@ -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: ''
---
<!--
## Overview
Project ideas are scoped for a university-level student with a basic background in CS and bitcoin
fundamentals - achievable over 12-weeks. Below are just a few types of ideas:
- Low-hanging fruit: Relatively short projects with clear goals; requires basic technical knowledge
and minimal familiarity with the codebase.
- Core development: These projects derive from the ongoing work from the core of your development
team. The list of features and bugs is never-ending, and help is always welcome.
- Risky/Exploratory: These projects push the scope boundaries of your development effort. They
might require expertise in an area not covered by your current development team. They might take
advantage of a new technology. There is a reasonable chance that the project might be less
successful, but the potential rewards make it worth the attempt.
- Infrastructure/Automation: These projects are the code that your organization uses to get its
development work done; for example, projects that improve the automation of releases, regression
tests and automated builds. This is a category where a Summer of Bitcoin student can be really
helpful, doing work that the development team has been putting off while they focus on core
development.
- Quality Assurance/Testing: Projects that work on and test your project's software development
process. Additionally, projects that involve a thorough test and review of individual PRs.
- Fun/Peripheral: These projects might not be related to the current core development focus, but
create new innovations and new perspectives for your project.
-->
**Description**
<!-- Description: 3-7 sentences describing the project background and tasks to be done. -->
**Expected Outcomes**
<!-- Short bullet list describing what is to be accomplished -->
**Resources**
<!-- 2-3 reading materials for candidate to learn about the repo, project, scope etc -->
<!-- Recommended reading such as a developer/contributor guide -->
<!-- [Another example a paper citation](https://arxiv.org/pdf/1802.08091.pdf) -->
<!-- [Another example an existing issue](https://github.com/opencv/opencv/issues/11013) -->
<!-- [An existing related module](https://github.com/opencv/opencv_contrib/tree/master/modules/optflow) -->
**Skills Required**
<!-- 3-4 technical skills that the candidate should know -->
<!-- hands on experience with git -->
<!-- mastery plus experience coding in C++ -->
<!-- basic knowledge in matrix and tensor computations, college course work in cryptography -->
<!-- strong mathematical background -->
<!-- Bonus - has experience with React Native. Best if you have also worked with OSSFuzz -->
**Mentor(s)**
<!-- names of mentor(s) for this project go here -->
**Difficulty**
<!-- Easy, Medium, Hard -->
**Competency Test (optional)**
<!-- 2-3 technical tasks related to the project idea or repository youd like a candidate to
perform in order to demonstrate competency, good first bugs, warm-up exercises -->
<!-- ex. Read the instructions here to get Bitcoin core running on your machine -->
<!-- ex. pick an issue labeled as “newcomer” in the repository, and send a merge request to the
repository. You can also suggest some other improvement that we did not think of yet, or
something that you find interesting or useful -->
<!-- ex. fixes for coding style are usually easy to do, and are good issues for first time
contributions for those learning how to interact with the project. After you are done with the
coding style issue, try making a different contribution. -->
<!-- ex. setup a full Debian packaging development environment and learn the basics of Debian
packaging. Then identify and package the missing dependencies to package Specter Desktop -->
<!-- ex. write a pull parser for CSV files. You'll be judged by the decisions to store the parser
state and how flexible it is to wrap this parser in other scenarios. -->
<!-- ex. Stretch Goal: Implement some basic metaprogram/app to prove you're very familiar with BDK.
Be prepared to make adjustments as we judge your solution. -->

34
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,34 @@
<!-- Erase any parts of this template not applicable to your Pull Request. -->
### Description
<!-- Describe the purpose of this PR, what's being adding and/or fixed -->
### Notes to the reviewers
<!-- In this section you can include notes directed to the reviewers, like explaining why some parts
of the PR were done in a specific way -->
### Changelog notice
<!-- Notice the release manager should include in the release tag message changelog -->
<!-- See https://keepachangelog.com/en/1.0.0/ for examples -->
### 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

19
.github/workflows/audit.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Audit
on:
push:
paths:
- '**/Cargo.toml'
- '**/Cargo.lock'
schedule:
- cron: '0 0 * * 0' # Once per week
jobs:
security_audit:
name: Security audit
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions-rs/audit-check@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}

85
.github/workflows/cont_integration.yml vendored Normal file
View File

@@ -0,0 +1,85 @@
name: Rust layer CI
on:
push:
paths:
- "bdk-ffi/**"
pull_request:
paths:
- "bdk-ffi/**"
jobs:
build-test:
name: Build and test
runs-on: ubuntu-20.04
strategy:
matrix:
rust:
- version: 1.71.0 # STABLE
clippy: true
- version: 1.61.0 # MSRV
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Generate cache key
run: echo "${{ matrix.rust.version }} ${{ matrix.features }}" | tee .cache_key
- name: Cache
uses: actions/cache@v3
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: Pin dependencies for MSRV
if: matrix.rust.version == '1.61.0'
run: |
cargo update -p hashlink --precise "0.8.1"
cargo update -p tokio --precise "1.29.1"
cargo update -p flate2 --precise "1.0.26"
- name: Build
run: cargo build
- name: Clippy
if: ${{ matrix.rust.clippy }}
run: cargo clippy --all-targets --features "uniffi/bindgen-tests" -- -D warnings
- name: Test
run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test --features uniffi/bindgen-tests
fmt:
name: Rust fmt
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- 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

60
.github/workflows/publish-android.yaml vendored Normal file
View File

@@ -0,0 +1,60 @@
name: Publish bdk-android to Maven Central
on: [workflow_dispatch]
# The default Android NDK on the ubuntu-22.04 image is 25.2.9519653
# We replace the default environment variable ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.2.9519653
# with an older version of the NDK (21.4.7075529) using the fix proposed here: https://github.com/actions/runner-images/issues/5930
# For information on why this is needed at the moment see issues #242 and #243, and PR #282
env:
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: "Install Android NDK 21.4.7075529"
run: |
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch"
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install Rust Android targets"
run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
- name: "Build bdk-android library"
run: |
cd bdk-android
./gradlew buildAndroidLib
- name: "Publish to Maven Local and Maven Central"
env:
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }}
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.NEXUS_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.NEXUS_PASSWORD }}
run: |
cd bdk-android
./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

132
.github/workflows/publish-jvm.yaml vendored Normal file
View File

@@ -0,0 +1,132 @@
name: Publish bdk-jvm to Maven Central
on: [workflow_dispatch]
jobs:
build-macOS-native-libs:
name: "Create M1 and x86_64 native binaries"
runs-on: macos-12
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install aarch64 Rust target"
run: rustup target add aarch64-apple-darwin
- name: "Build bdk-jvm library"
run: |
cd bdk-jvm
./gradlew buildJvmLib
- name: "Upload macOS native libraries for reuse in publishing job"
uses: actions/upload-artifact@v3
with:
name: artifact-macos
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/
build-windows-native-lib:
name: "Create Windows native binaries"
runs-on: windows-2022
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v3
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install x86_64-pc-windows-msvc Rust target"
run: rustup target add x86_64-pc-windows-msvc
- name: "Build bdk-jvm library"
run: |
cd bdk-jvm
./gradlew buildJvmLib
- name: "Upload Windows native libraries for reuse in publishing job"
uses: actions/upload-artifact@v3
with:
name: artifact-windows
path: D:\a\bdk-ffi\bdk-ffi\bdk-jvm\lib\src\main\resources\
build-full-library:
name: Create full bdk-jvm library
needs: [build-macOS-native-libs, build-windows-native-lib]
runs-on: ubuntu-20.04
steps:
- name: "Checkout publishing branch"
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Build bdk-jvm library"
run: |
cd bdk-jvm
./gradlew buildJvmLib
- name: "Download macOS native binaries from previous job"
uses: actions/download-artifact@v3
with:
name: artifact-macos
path: ./bdk-jvm/lib/src/main/resources/
- name: "Download Windows native libraries from previous job"
uses: actions/download-artifact@v3
with:
name: artifact-windows
path: ./bdk-jvm/lib/src/main/resources/
- name: "Upload library code and binaries"
uses: actions/upload-artifact@v3
with:
name: artifact-full
path: ./bdk-jvm/lib/
- name: "Publish to Maven Central"
env:
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.PGP_KEY_ID }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.PGP_PASSPHRASE }}
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.NEXUS_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.NEXUS_PASSWORD }}
run: |
cd bdk-jvm
./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository

184
.github/workflows/publish-python.yaml vendored Normal file
View File

@@ -0,0 +1,184 @@
name: Publish bdkpython to PyPI
on: [workflow_dispatch]
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
# 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-wheels:
name: "Build Manylinux 2014 x86_64 wheel"
runs-on: ubuntu-20.04
defaults:
run:
working-directory: bdk-python
container:
image: quay.io/pypa/manylinux2014_x86_64
env:
PLAT: manylinux2014_x86_64
PYBIN: "/opt/python/${{ matrix.python }}/bin"
strategy:
matrix:
python: # Update this list whenever the docker image is updated (check /opt/python/)
- cp38-cp38
- cp39-cp39
- cp310-cp310
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-linux.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- uses: actions/upload-artifact@v3
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-arm64-wheels:
name: "Build macOS arm64 wheel"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-arm64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
- name: "Upload artifacts"
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-x86_64-wheels:
name: "Build macOS x86_64 wheel"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-x86_64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
- uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheels:
name: "Build Windows wheel"
runs-on: windows-2022
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-windows.sh
- name: "Build wheel"
run: python setup.py bdist_wheel --verbose
- name: "Upload artifacts"
uses: actions/upload-artifact@v3
with:
name: bdkpython-win-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
publish-pypi:
name: "Publish on PyPI"
runs-on: ubuntu-20.04
defaults:
run:
working-directory: bdk-python
needs: [build-manylinux2014-x86_64-wheels, build-macos-arm64-wheels, build-macos-x86_64-wheels, build-windows-wheels]
steps:
- name: "Checkout"
uses: actions/checkout@v3
- name: "Download artifacts in dist/ directory"
uses: actions/download-artifact@v3
with:
path: dist/
# - 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/*/

65
.github/workflows/test-android.yaml vendored Normal file
View File

@@ -0,0 +1,65 @@
name: Test Android
on:
workflow_dispatch:
push:
paths:
- "bdk-ffi/**"
- "bdk-android/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-android/**"
# The default Android NDK on the ubuntu-22.04 image is 25.2.9519653
# We replace the default environment variable ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.2.9519653
# with an older version of the NDK (21.4.7075529) using the fix proposed here: https://github.com/actions/runner-images/issues/5930
# For information on why this is needed at the moment see issues #242 and #243, and PR #282
env:
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: "Install Android NDK 21.4.7075529"
run: |
ANDROID_ROOT=/usr/local/lib/android
ANDROID_SDK_ROOT=${ANDROID_ROOT}/sdk
SDKMANAGER=${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager
echo "y" | $SDKMANAGER "ndk;21.4.7075529"
- name: "Check out PR branch"
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Install Rust Android targets"
run: rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
- name: "Build Android library"
run: |
cd bdk-android
./gradlew buildAndroidLib
# There are currently no unit tests for bdk-android and the integration tests require the macOS image
# which is not working with the older NDK version we are using, so for now we just make sure that the library builds.
# - name: "Run Android unit tests"
# run: |
# cd bdk-android
# ./gradlew test --console=rich

41
.github/workflows/test-jvm.yaml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: Test Kotlin/JVM
on:
workflow_dispatch:
push:
paths:
- "bdk-ffi/**"
- "bdk-jvm/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-jvm/**"
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: "Check out PR branch"
uses: actions/checkout@v3
- name: "Cache"
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
./target
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
- name: "Set up JDK"
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 11
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: "Run JVM tests"
run: |
cd bdk-jvm
./gradlew test

189
.github/workflows/test-python.yaml vendored Normal file
View File

@@ -0,0 +1,189 @@
name: Test Python
on:
workflow_dispatch:
push:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-python/**"
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
# makes it very hard to use GitHub's javascript actions (checkout, upload-artifact, etc).
# They mount their own nodejs interpreter inside your container, but since that's not statically linked it
# tries to load glibc and fails because it requires a more recent version.
jobs:
build-manylinux2014-x86_64-wheels:
name: "Build and test Manylinux 2014 x86_64 wheels"
runs-on: ubuntu-20.04
defaults:
run:
working-directory: bdk-python
container:
image: quay.io/pypa/manylinux2014_x86_64
env:
PLAT: manylinux2014_x86_64
PYBIN: "/opt/python/${{ matrix.python }}/bin"
strategy:
matrix:
python:
- cp38-cp38
- cp39-cp39
- cp310-cp310
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-linux.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: ${PYBIN}/python setup.py bdist_wheel --plat-name manylinux_2_17_x86_64 --verbose
- name: "Install wheel"
run: ${PYBIN}/pip install ./dist/*.whl
- name: "Run tests"
run: ${PYBIN}/python -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
path: /home/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-arm64-wheels:
name: "Build and test macOS arm64 wheels"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-arm64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_arm64 --verbose
# You can't install the arm64 wheel on the CI, so we skip these steps and simply test that the wheel builds
# - name: "Install wheel and run tests"
# run: |
# pip3 install ./dist/*.whl
# python3 -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-arm64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-macos-x86_64-wheels:
name: "Build and test macOS x86_64 wheels"
runs-on: macos-13
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-macos-x86_64.sh
- name: "Build wheel"
# Specifying the plat-name argument is necessary to build a wheel with the correct name,
# see issue #350 for more information
run: python3 setup.py bdist_wheel --plat-name macosx_11_0_x86_64 --verbose
- name: "Install wheel"
run: pip3 install ./dist/*.whl
- name: "Run tests"
run: python3 -m unittest tests/test_bdk.py --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-macos-x86_64-${{ matrix.python }}
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-python/dist/*.whl
build-windows-wheels:
name: "Build and test Windows wheels"
runs-on: windows-2022
defaults:
run:
working-directory: bdk-python
strategy:
matrix:
python:
- "3.8"
- "3.9"
- "3.10"
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
submodules: true
- name: "Install Python"
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
- name: "Generate bdk.py and binaries"
run: bash ./scripts/generate-windows.sh
- name: "Build wheel"
run: python setup.py bdist_wheel --verbose
- name: "Upload artifact test"
uses: actions/upload-artifact@v3
with:
name: bdkpython-windows-${{ matrix.python }}
path: D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl
- name: "Install dependencies"
run: Get-ChildItem 'D:\a\bdk-ffi\bdk-ffi\bdk-python\dist\*.whl' | ForEach-Object {pip install $_.FullName}
shell: powershell
- name: "Run tests"
run: python -m unittest tests/test_bdk.py --verbose

55
.github/workflows/test-swift.yaml vendored Normal file
View File

@@ -0,0 +1,55 @@
name: Test Swift
on:
workflow_dispatch:
push:
paths:
- "bdk-ffi/**"
- "bdk-swift/**"
pull_request:
paths:
- "bdk-ffi/**"
- "bdk-swift/**"
jobs:
build:
runs-on: macos-12
steps:
- name: Checkout
uses: actions/checkout@v3
- name: "Set default Rust version to 1.67.0"
run: rustup default 1.67.0
- name: Install Rust targets
run: |
rustup install nightly-x86_64-apple-darwin
rustup component add rust-src --toolchain nightly-x86_64-apple-darwin
rustup target add aarch64-apple-darwin x86_64-apple-darwin
- name: Run bdk-ffi-bindgen
working-directory: bdk-ffi
run: cargo run --bin uniffi-bindgen generate src/bdk.udl --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit --no-format
- name: Build bdk-ffi for x86_64-apple-darwin
run: cargo build --package bdk-ffi --profile release-smaller --target x86_64-apple-darwin
- name: Build bdk-ffi for aarch64-apple-darwin
run: cargo build --package bdk-ffi --profile release-smaller --target aarch64-apple-darwin
- name: Create lipo-macos
run: |
mkdir -p target/lipo-macos/release-smaller
lipo target/aarch64-apple-darwin/release-smaller/libbdkffi.a target/x86_64-apple-darwin/release-smaller/libbdkffi.a -create -output target/lipo-macos/release-smaller/libbdkffi.a
- name: Create bdkFFI.xcframework
working-directory: bdk-swift
run: |
mv Sources/BitcoinDevKit/bdk.swift Sources/BitcoinDevKit/BitcoinDevKit.swift
cp Sources/BitcoinDevKit/bdkFFI.h bdkFFI.xcframework/macos-arm64_x86_64/bdkFFI.framework/Headers
cp ../target/lipo-macos/release-smaller/libbdkffi.a bdkFFI.xcframework/macos-arm64_x86_64/bdkFFI.framework/bdkFFI
rm Sources/BitcoinDevKit/bdkFFI.h
rm Sources/BitcoinDevkit/bdkFFI.modulemap
- name: Run Swift tests
working-directory: bdk-swift
run: swift test

23
.gitignore vendored
View File

@@ -1,7 +1,5 @@
target
build
Cargo.lock
/bindings/bdk-kotlin/local.properties
.gradle
wallet_db
bdk_ffi_test
@@ -15,3 +13,24 @@ xcuserdata
.lsp
.clj-kondo
.idea/
.editorconfig
bdk.kt
# Swift related
/.build
/.swiftpm
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
bdkFFI.xcframework.zip
bdkFFI
libbdkffi.a
bdkFFI.h
BitcoinDevKit.swift
bdk.swift
.build
# Python related
__pycache__

View File

@@ -1,13 +1,184 @@
# Changelog
All notable changes to this project will be documented in this file.
Changelog information can also be found in each release's git tag (which can be viewed with `git tag -ln100 "v*"`), as well as on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases) page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
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]
## [0.30.0]
This release has a new API and a few internal optimizations and refactorings.
- APIs Added
- Add BIP-86 descriptor templates [#388]
[#388]: https://github.com/bitcoindevkit/bdk-ffi/pull/388
## [0.29.0]
This release has a number of new APIs, and adds support for Windows in bdk-jvm.
Changelog
- Add support for Windows in bdk-jvm [#336]
- Add support for older version of Linux distros in bdk-jvm [#345]
- APIs added
- Expose `is_mine()` method on the `Wallet` type [#355]
- Expose `to_bytes()` method on the `Script` type [#369]
[#336]: https://github.com/bitcoindevkit/bdk-ffi/pull/336
[#345]: https://github.com/bitcoindevkit/bdk-ffi/pull/345
[#355]: https://github.com/bitcoindevkit/bdk-ffi/pull/355
[#369]: https://github.com/bitcoindevkit/bdk-ffi/pull/369
## [v0.28.0]
- Update BDK to version 0.28.0 [#341]
- Drop support of pypy releases of Python libraries [#351]
- Drop support for Python 3.6 and 3.7 [#351]
- Drop support for very old Linux versions that do not support the manylinux_2_17_x86_64 platform tag [#351]
- APIs changed:
- Expose Address payload and network properties. [#325]
- Add SignOptions to Wallet.sign() params. [#326]
- address field on `AddressInfo` type is now of type `Address` [#333]
- new PartiallySignedTransaction.json_serialize() function to get JSON serialized value of all PSBT fields. [#334]
- Add from_script constructor to `Address` type [#337]
[#325]: https://github.com/bitcoindevkit/bdk-ffi/pull/325
[#326]: https://github.com/bitcoindevkit/bdk-ffi/pull/326
[#333]: https://github.com/bitcoindevkit/bdk-ffi/pull/333
[#334]: https://github.com/bitcoindevkit/bdk-ffi/pull/334
[#337]: https://github.com/bitcoindevkit/bdk-ffi/pull/337
[#341]: https://github.com/bitcoindevkit/bdk-ffi/pull/341
[#351]: https://github.com/bitcoindevkit/bdk-ffi/pull/351
## [v0.27.1]
- Update BDK to version 0.27.1 [#312]
- APIs changed
- `PartiallySignedTransaction.extract_tx()` returns a `Transaction` instead of the transaction bytes. [#296]
- `Blockchain.broadcast()` takes a `Transaction` instead of a `PartiallySignedTransaction`. [#296]
- APIs added
- New `Transaction` structure that can be created from or serialized to consensus encoded bytes. [#296]
- Add Wallet.get_internal_address() API [#304]
- Add `AddressIndex::Peek(index)` and `AddressIndex::Reset(index)` APIs [#305]
[#296]: https://github.com/bitcoindevkit/bdk-ffi/pull/296
[#304]: https://github.com/bitcoindevkit/bdk-ffi/pull/304
[#305]: https://github.com/bitcoindevkit/bdk-ffi/pull/305
[#312]: https://github.com/bitcoindevkit/bdk-ffi/pull/312
## [v0.26.0]
- Update BDK to version 0.26.0 [#288]
- APIs changed
- The descriptor and change_descriptor arguments on the wallet constructor now take a `Descriptor` instead of a `String`. [#260]
- TxBuilder.drain_to() argument is now `Script` instead of address `String`. [#279]
- APIs added
- Added RpcConfig, BlockchainConfig::Rpc, and Auth [#125]
- Added Descriptor type in [#260] with the following methods:
- Default constructor requires a descriptor in String format and a Network
- new_bip44 constructor returns a Descriptor with structure pkh(key/44'/{0,1}'/0'/{0,1}/*)
- new_bip44_public constructor returns a Descriptor with structure pkh(key/{0,1}/*)
- new_bip49 constructor returns a Descriptor with structure sh(wpkh(key/49'/{0,1}'/0'/{0,1}/*))
- new_bip49_public constructor returns a Descriptor with structure sh(wpkh(key/{0,1}/*))
- new_bip84 constructor returns a Descriptor with structure wpkh(key/84'/{0,1}'/0'/{0,1}/*)
- new_bip84_public constructor returns a Descriptor with structure wpkh(key/{0,1}/*)
- as_string returns the public version of the output descriptor
- as_string_private returns the private version of the output descriptor if available, otherwise return the public version
[#125]: https://github.com/bitcoindevkit/bdk-ffi/pull/125
[#260]: https://github.com/bitcoindevkit/bdk-ffi/pull/260
[#279]: https://github.com/bitcoindevkit/bdk-ffi/pull/279
[#288]: https://github.com/bitcoindevkit/bdk-ffi/pull/288
## [v0.25.0]
- Update BDK to version 0.25.0 [#272]
- APIs Added:
- from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247]
[#247]: https://github.com/bitcoindevkit/bdk-ffi/pull/247
[#272]: https://github.com/bitcoindevkit/bdk-ffi/pull/272
## [v0.11.0]
- Update BDK to version 0.24.0 [#221]
- APIs changed
- The constructor on the DescriptorSecretKey type now takes a Mnemonic instead of a String.
- APIs added
- Added Mnemonic struct [#219] with following methods:
- new(word_count: WordCount) generates and returns Mnemonic with random entropy
- from_string(mnemonic: String) converts string Mnemonic to Mnemonic type with error
- from_entropy(entropy: Vec<u8>) generates and returns Mnemonic with given entropy
- as_string() view Mnemonic as string
- APIs removed
- generate_mnemonic(word_count: WordCount)
[#219]: https://github.com/bitcoindevkit/bdk-ffi/pull/219
[#221]: https://github.com/bitcoindevkit/bdk-ffi/pull/221
## [v0.10.0]
- Update BDK to version 0.23.0 [#204]
- Update uniffi-rs to latest version 0.21.0 [#216]
- Breaking Changes
- Changed `TxBuilder.finish()` to return new `TxBuilderResult` [#209]
- `TxBuilder.add_recipient()` now takes a `Script` instead of an `Address` [#192]
- `AddressAmount` is now `ScriptAmount` [#192]
- APIs Added
- Added `TxBuilderResult` with PSBT and TransactionDetails [#209]
- `Address` and `Script` structs have been added [#192]
- Add `PartiallySignedBitcoinTransaction.extract_tx()` function [#192]
- Add `secret_bytes()` method on the `DescriptorSecretKey` [#199]
- Add `PartiallySignedBitcoinTransaction.combine()` method [#200]
[#192]: https://github.com/bitcoindevkit/bdk-ffi/pull/192
[#199]: https://github.com/bitcoindevkit/bdk-ffi/pull/199
[#200]: https://github.com/bitcoindevkit/bdk-ffi/pull/200
[#204]: https://github.com/bitcoindevkit/bdk-ffi/pull/204
[#209]: https://github.com/bitcoindevkit/bdk-ffi/pull/209
[#216]: https://github.com/bitcoindevkit/bdk-ffi/pull/216
## [v0.9.0]
- 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)`, constructs 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<AddressAmount>)` 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<u8>)` [#163]
- `Wallet.list_unspent()` returns `Vec<LocalUtxo>` [#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
@@ -23,13 +194,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#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
@@ -38,17 +207,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 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]
@@ -57,9 +223,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[BIP 0174]:https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#encoding
## [v0.2.0]
[unreleased]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.7.0...HEAD
[v0.30.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.29.0...v0.30.0
[v0.29.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.28.0...v0.29.0
[v0.28.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.27.1...v0.28.0
[v0.27.1]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.26.0...v0.27.1
[v0.26.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.25.0...v0.26.0
[v0.25.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.11.0...v0.25.0
[v0.11.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.10.0...v0.11.0
[v0.10.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.9.0...v0.10.0
[v0.9.0]: https://github.com/bitcoindevkit/bdk-ffi/compare/v0.8.0...v0.9.0
[v0.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

1593
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,12 @@
[package]
name = "bdk-ffi"
version = "0.7.0"
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
edition = "2018"
[workspace]
members = [".","bdk-ffi-bindgen"]
default-members = [".", "bdk-ffi-bindgen"]
members = ["bdk-ffi"]
default-members = ["bdk-ffi"]
exclude = ["api-docs", "bdk-android", "bdk-jvm", "bdk-python", "bdk-swift"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
crate-type = ["staticlib", "cdylib"]
name = "bdkffi"
[dependencies]
bdk = { version = "0.19", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
uniffi_macros = { version = "0.16.0", features = ["builtin-bindgen"] }
uniffi = { version = "0.16.0", features = ["builtin-bindgen"] }
[build-dependencies]
uniffi_build = { version = "0.16.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

35
DEVELOPMENT_CYCLE.md Normal file
View File

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

14
PGP-BDK-BINDINGS.asc Normal file
View File

@@ -0,0 +1,14 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYw6xkRYJKwYBBAHaRw8BAQdAg+VLXuidDqeP015H/QMlESJyQeIntTUoQkbk
+IFu+jO0M2JpdGNvaW5kZXZraXQtYmluZGluZ3MgPGJpbmRpbmdzQGJpdGNvaW5k
ZXZraXQub3JnPoiTBBMWCgA7FiEEiK2TrEWJ/QkP87jRJ2jEPogDxqMFAmMOsZEC
GwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQJ2jEPogDxqPQTgEA292D
RQaxDTJ4k91D0w50Vrd0NSNUwlsERz9XJ64abWABAP99vGMmq2pfrngTQqjLgLe8
0YhQ+VML2x/B0LSN6MgNuDgEYw6xkRIKKwYBBAGXVQEFAQEHQEkUJv+/Wzx7nNiX
eti3HkeT6ZNAuCExPE4F7jxHNQ1TAwEIB4h4BBgWCgAgFiEEiK2TrEWJ/QkP87jR
J2jEPogDxqMFAmMOsZECGwwACgkQJ2jEPogDxqObPQEA/B0xNew03KM0JP630efG
QT/3Caq/jx86pLwnB7XqWI8BAOKmqrOEiwCBjhaIpzC3/1M+aZuPRUL3V91uPxpM
jFAJ
=vvmK
-----END PGP PUBLIC KEY BLOCK-----

177
README.md
View File

@@ -1,68 +1,163 @@
# 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.
<p>
<a href="https://github.com/bitcoindevkit/bdk-ffi/blob/master/LICENSE"><img alt="MIT or Apache-2.0 Licensed" src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg"/></a>
<a href="https://github.com/bitcoindevkit/bdk-ffi/actions?query=workflow%3ACI"><img alt="CI Status" src="https://github.com/bitcoindevkit/bdk-ffi/workflows/CI/badge.svg"></a>
<a href="https://blog.rust-lang.org/2022/05/19/Rust-1.61.0.html"><img alt="Rustc Version 1.61.0+" src="https://img.shields.io/badge/rustc-1.61.0%2B-lightgrey.svg"/></a>
<a href="https://discord.gg/d7NkDKm"><img alt="Chat on Discord" src="https://img.shields.io/discord/753336465005608961?logo=discord"></a>
</p>
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.
The workspace in this repository creates the `libbdkffi` multi-language library for the Rust-based
[bdk] library from the [Bitcoin Dev Kit] project.
Each supported language and the platform(s) it's packaged for has its own directory. The Rust code in this project is in the bdk-ffi directory and is a wrapper around the [bdk] library to expose its APIs in a uniform way using the [mozilla/uniffi-rs] bindings generator for each supported target language.
## Supported target languages and platforms
The below directories (a separate repository in the case of bdk-swift) include instructions for using, building, and publishing the native language binding for [bdk] supported by this project.
The below repositories include instructions for using, building, and publishing the native
language binding for [bdk] supported by this project.
| Language | Platform | Published Package | Building Documentation | API Docs |
| -------- |-----------------------|-------------------------------|------------------------|-----------------------|
| Kotlin | JVM | [bdk-jvm (Maven Central)] | [Readme bdk-jvm] | [Kotlin JVM API Docs] |
| Kotlin | Android | [bdk-android (Maven Central)] | [Readme bdk-android] | [Android API Docs] |
| Swift | iOS, macOS | [bdk-swift (GitHub)] | [Readme bdk-swift] | |
| Python | linux, macOS, Windows | [bdk-python (PyPI)] | [Readme bdk-python] | |
| Language | Platform | Repository |
| -------- | ------------ | ------------ |
| Kotlin | jvm | [bdk-kotlin] |
| Kotlin | android | [bdk-kotlin] |
| Swift | iOS, macOS | [bdk-swift] |
| Python | linux, macOS | [bdk-python] |
## Minimum Supported Rust Version (MSRV)
## Language bindings generator tool
This library should compile with any combination of features with Rust 1.61.0.
To build with the MSRV you will need to pin dependencies as follows:
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
# required for sqlite feature, hashlink 0.8.2 has MSRV 1.61.0
cargo update -p hashlink --precise "0.8.1"
# tokio 1.30.0 has MSRV 1.63.0
cargo update -p tokio --precise "1.29.1"
# flate2 1.0.27 and up do not work with Rust 1.61.0, but 1.0.26 does
cargo update -p flate2 --precise "1.0.26"
```
[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/thunderbiscuit/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
2. Update mapping `bdk.udl` file with new `dictionary`
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`
#### For pass by reference values
1. Create wrapper rust struct/impl with only fields that are `Sync + Send`
2. 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
2. Adding new targets should be easy
3. Getting up and running should be easy
4. Contributing should be easy
5. Get it right, then automate
## Using the libraries
### bdk-android
```kotlin
// build.gradle.kts
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
}
```
### bdk-jvm
```kotlin
// build.gradle.kts
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version>")
}
```
_Note:_ We also publish snapshot versions of bdk-jvm and bdk-android. See the specific readmes for instructions on how to use those.
### bdk-python
```shell
pip3 install bdkpython
```
### bdk-swift
Add bdk-swift to your dependencies in XCode.
## Developing language bindings using uniffi-rs
If you are interested in better understanding the base structure we use here in order to build your own Rust-to-Kotlin/Swift/Python language bindings, check out the [uniffi-bindings-template](https://github.com/thunderbiscuit/uniffi-bindings-template) repository. We maintain it as an example and starting point for other projects that wish to leverage the tech stack used in producing the BDK language bindings.
## Verifying Signatures
Both libraries and all their corresponding artifacts are signed with a PGP key you can find in the
root of this repository. To verify the signatures follow the below steps:
1. Import the PGP key in your keyring.
```shell
# Navigate to the root of the repository and import the ./PGP-BDK-BINDINGS.asc public key
gpg --import ./PGP-BDK-BINDINGS.asc
# Alternatively, you can import the key directly from a public key server
gpg --keyserver keyserver.ubuntu.com --receive-key 2768C43E8803C6A3
# Verify that the correct key was imported
gpg --list-keys
# You should see the below output
pub ed25519 2022-08-31 [SC]
88AD93AC4589FD090FF3B8D12768C43E8803C6A3
uid [ unknown] bitcoindevkit-bindings <bindings@bitcoindevkit.org>
sub cv25519 2022-08-31 [E]
```
2. Download the binary artifacts and corresponding signature files.
- from [bdk-jvm]
- `bdk-jvm-<version>.jar`
- `bdk-jvm-<version>.jar.asc`
- from [bdk-android]
- `bdk-android-<version>.aar`
- `bdk-android-<version>.aar.asc`
3. Verify the signatures.
```shell
gpg --verify bdk-jvm-<version>.jar.asc
gpg --verify bdk-android-<version>.aar.asc
# you should see a "Good signature" result
gpg: Good signature from "bitcoindevkit-bindings <bindings@bitcoindevkit.org>" [unknown]
```
### PGP Metadata
Full key ID: `88AD 93AC 4589 FD09 0FF3 B8D1 2768 C43E 8803 C6A3`
Fingerprint: `2768C43E8803C6A3`
Name: `bitcoindevkit-bindings`
Email: `bindings@bitcoindevkit.org`
## Thanks
This project is made possible thanks to the wonderful work by the [mozilla/uniffi-rs] team.
[Kotlin]: https://kotlinlang.org/
[Android Studio]: https://developer.android.com/studio/
[`bdk`]: https://github.com/bitcoindevkit/bdk
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
["Getting Started (Developer)"]: https://github.com/bitcoindevkit/bdk-ffi#getting-started-developer
[bdk-jvm]: https://search.maven.org/artifact/org.bitcoindevkit/bdk-jvm/0.11.0/jar
[bdk-android]: https://search.maven.org/artifact/org.bitcoindevkit/bdk-android/0.11.0/aar
[bdk-jvm (Maven Central)]: https://central.sonatype.dev/artifact/org.bitcoindevkit/bdk-jvm/0.11.0
[bdk-android (Maven Central)]: https://central.sonatype.dev/artifact/org.bitcoindevkit/bdk-android/0.11.0
[bdk-swift (GitHub)]: https://github.com/bitcoindevkit/bdk-swift
[bdk-python (PyPI)]: https://pypi.org/project/bdkpython/
[mozilla/uniffi-rs]: https://github.com/mozilla/uniffi-rs
[bdk]: https://github.com/bitcoindevkit/bdk
[Bitcoin Dev Kit]: https://github.com/bitcoindevkit
[uniffi-rs]: https://github.com/mozilla/uniffi-rs
[Readme bdk-jvm]: https://github.com/bitcoindevkit/bdk-ffi/tree/master/bdk-jvm
[Readme bdk-android]: https://github.com/bitcoindevkit/bdk-ffi/tree/master/bdk-android
[Readme bdk-swift]: https://github.com/bitcoindevkit/bdk-swift
[Readme bdk-python]: https://github.com/bitcoindevkit/bdk-ffi/tree/master/bdk-python
[Kotlin JVM API Docs]: https://bitcoindevkit.org/jvm/
[Android API Docs]: https://bitcoindevkit.org/android/

6
api-docs/README.md Normal file
View File

@@ -0,0 +1,6 @@
# API documentation
The Bitcoin Dev Kit language bindings make use of the [uniffi-rs](https://github.com/mozilla/uniffi-rs) library to produce their bindings. While efforts are ongoing to allow inline documentation on the Rust side to be ported to the bindings code, this is not currently possible.
This directory contains our temporary solution to this problem. A set of files mimicking the bindings libraries in their function signatures, but without any implementation. This allows for documentation build tools to produce API docs similarly to how we would like them to be if they could be inlined.
You can find the resulting API documentation websites in the ["API Reference" section of the sidebar](https://bitcoindevkit.org/getting-started/) under the "Docs" tab on the bitcoindevkit official website.

View File

@@ -0,0 +1,4 @@
# Module bdk-android
The [bitcoindevkit](https://bitcoindevkit.org/) language bindings library for Android.
# Package org.bitcoindevkit

View File

@@ -0,0 +1,4 @@
# Module bdk-jvm
The [bitcoindevkit](https://bitcoindevkit.org/) language bindings library for Kotlin and Java on the JVM.
# Package org.bitcoindevkit

View File

@@ -0,0 +1,46 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.7.10"
// API docs
id("org.jetbrains.dokka") version "1.7.10"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
}
// tasks.withType<org.jetbrains.dokka.gradle.DokkaTask>().configureEach {
// dokkaSourceSets {
// named("main") {
// moduleName.set("bdk-android")
// moduleVersion.set("0.11.0")
// includes.from("Module1.md")
// samples.from("src/test/kotlin/org/bitcoindevkit/Samples.kt")
// }
// }
// }
tasks.withType<org.jetbrains.dokka.gradle.DokkaTask>().configureEach {
dokkaSourceSets {
named("main") {
moduleName.set("bdk-jvm")
moduleVersion.set("0.11.0")
includes.from("Module2.md")
samples.from("src/test/kotlin/org/bitcoindevkit/Samples.kt")
}
}
}

View File

@@ -0,0 +1,8 @@
./gradlew dokkaHtml
cd build/dokka/html
git init .
git add .
git switch --create gh-pages
git commit -m "Deploy"
git remote add origin git@github.com:bitcoindevkit/bdk-kotlin.git
git push --set-upstream origin gh-pages --force

View File

@@ -0,0 +1 @@
kotlin.code.style=official

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
api-docs/kotlin/gradlew vendored Executable file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
api-docs/kotlin/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1 @@
rootProject.name = "BDK Android and BDK JVM API Docs"

View File

@@ -0,0 +1,934 @@
package org.bitcoindevkit
/**
* The cryptocurrency to act on.
*
* @sample org.bitcoindevkit.networkSample
*/
enum class Network {
/** Bitcoin's mainnet. */
BITCOIN,
/** Bitcoins testnet. */
TESTNET,
/** Bitcoins signet. */
SIGNET,
/** Bitcoins regtest. */
REGTEST,
}
/**
* A derived address and the index it was found at.
*
* @property index Child index of this address.
* @property address Address.
* @property keychain Type of keychain.
*
* @sample org.bitcoindevkit.addressInfoSample
*/
data class AddressInfo (
var index: UInt,
var address: Address,
var keychain: KeychainKind
)
/**
* The address index selection strategy to use to derive an address from the wallets external descriptor.
*
* If youre unsure which one to use, use `AddressIndex.New`.
*
* @sample org.bitcoindevkit.addressIndexSample
*/
sealed class AddressIndex {
/** Return a new address after incrementing the current descriptor index. */
object New: AddressIndex(),
/**
* Return the address for the current descriptor index if it has not been used in a received transaction.
* Otherwise return a new address as with `AddressIndex.NEW`. Use with caution, if the wallet
* has not yet detected an address has been used it could return an already used address.
* This function is primarily meant for situations where the caller is untrusted;
* for example when deriving donation addresses on-demand for a public web page.
*/
object LastUnused: AddressIndex(),
/**
* Return the address for a specific descriptor index. Does not change the current descriptor
* index used by [AddressIndex.New] and [AddressIndex.LastUsed].
* Use with caution, if an index is given that is less than the current descriptor index
* then the returned address may have already been used.
*/
data class Peek(val index: UInt): AddressIndex(),
/**
* Return the address for a specific descriptor index and reset the current descriptor index
* used by [AddressIndex.New] and [AddressIndex.LastUsed] to this value.
* Use with caution, if an index is given that is less than the current descriptor index
* then the returned address and subsequent addresses returned by calls to [AddressIndex.New]
* and [AddressIndex.LastUsed] may have already been used. Also if the index is reset to a
* value earlier than the [Blockchain] stopGap (default is 20) then a
* larger stopGap should be used to monitor for all possibly used addresses.
*/
data class Reset(val index: UInt): AddressIndex()
}
/**
* Balance differentiated in various categories.
*
* @property immature All coinbase outputs not yet matured.
* @property trustedPending Unconfirmed UTXOs generated by a wallet tx.
* @property untrustedPending Unconfirmed UTXOs received from an external wallet.
* @property confirmed Confirmed and immediately spendable balance.
* @property spendable The sum of trustedPending and confirmed coins.
* @property total The whole balance visible to the wallet.
*
* @sample org.bitcoindevkit.balanceSample
*/
data class Balance (
var immature: ULong,
var trustedPending: ULong,
var untrustedPending: ULong,
var confirmed: ULong,
var spendable: ULong,
var total: ULong
)
/**
* Type that can contain any of the database configurations defined by the library.
*
* @sample org.bitcoindevkit.memoryDatabaseConfigSample
* @sample org.bitcoindevkit.sqliteDatabaseConfigSample
*/
sealed class DatabaseConfig {
/** Configuration for an in-memory database. */
object Memory : DatabaseConfig()
/** Configuration for a Sled database. */
data class Sled(val config: SledDbConfiguration) : DatabaseConfig()
/** Configuration for a SQLite database. */
data class Sqlite(val config: SqliteDbConfiguration) : DatabaseConfig()
}
/**
* Configuration type for a SQLite database.
*
* @property path Main directory of the DB.
*
* @sample org.bitcoindevkit.sqliteDatabaseConfigSample
*/
data class SqliteDbConfiguration(
var path: String,
)
/**
* Configuration type for a SledDB database.
*
* @property path Main directory of the DB.
* @property treeName Name of the database tree, a separated namespace for the data.
*/
data class SledDbConfiguration(
var path: String,
var treeName: String,
)
/**
* Configuration for an Electrum blockchain.
*
* @property url URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port, e.g. `ssl://electrum.blockstream.info:60002`.
* @property socks5 URL of the socks5 proxy server or a Tor service.
* @property retry Request retry count.
* @property timeout Request timeout (seconds).
* @property stopGap Stop searching addresses for transactions after finding an unused gap of this length.
* @property validateDomain Validate the domain when using SSL.
*
* @sample org.bitcoindevkit.electrumBlockchainConfigSample
*/
data class ElectrumConfig(
var url: String,
var socks5: String?,
var retry: UByte,
var timeout: UByte?,
var stopGap: ULong,
var validateDomain: Boolean
)
/**
* Configuration for an Esplora blockchain.
*
* @property baseUrl Base URL of the esplora service, e.g. `https://blockstream.info/api/`.
* @property proxy Optional URL of the proxy to use to make requests to the Esplora server.
* @property concurrency Number of parallel requests sent to the esplora service (default: 4).
* @property stopGap Stop searching addresses for transactions after finding an unused gap of this length.
* @property timeout Socket timeout.
*
* @sample org.bitcoindevkit.esploraBlockchainConfigSample
*/
data class EsploraConfig(
var baseUrl: String,
var proxy: String?,
var concurrency: UByte?,
var stopGap: ULong,
var timeout: ULong?
)
/**
* Authentication mechanism for RPC connection to full node.
*/
sealed class Auth {
/** No authentication */
object None: Auth()
/** Authentication with username and password, usually [Auth.Cookie] should be preferred */
data class UserPass(val username: String, val password: String): Auth()
/** Authentication with a cookie file */
data class Cookie(val file: String): Auth()
}
/**
* Sync parameters for Bitcoin Core RPC.
*
* In general, BDK tries to sync `scriptPubKey`s cached in `Database` with
* `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining
* how the `importdescriptors` RPC calls are to be made.
*
* @property startScriptCount The minimum number of scripts to scan for on initial sync.
* @property startTime Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).
* @property forceStartTime Forces every sync to use `start_time` as import timestamp.
* @property pollRateSec RPC poll rate (in seconds) to get state updates.
*/
data class RcpSyncParams(
val startScriptCount: ULong,
val startTime: Ulong,
val forceStartTime: Boolean,
val pollRateSec: ULong,
)
/**
* RpcBlockchain configuration options
*
* @property url The bitcoin node url.
* @property auth The bicoin node authentication mechanism.
* @property network The network we are using (it will be checked the bitcoin node network matches this).
* @property walletName The wallet name in the bitcoin node.
* @property syncParams Sync parameters.
*/
data class RpcConfig(
val url: String,
val auth: Auth,
val network: Network,
val walletName: String,
val syncParams: RcpSyncParams?,
)
/**
* Type that can contain any of the blockchain configurations defined by the library.
*
* @sample org.bitcoindevkit.electrumBlockchainConfigSample
*/
sealed class BlockchainConfig {
/** Electrum client. */
data class Electrum(val config: ElectrumConfig) : BlockchainConfig()
/** Esplora client. */
data class Esplora(val config: EsploraConfig) : BlockchainConfig()
/** Bitcoin Core RPC client. */
data class Rpc(val config: RpcConfig) : BlockchainConfig()
}
/**
* A wallet transaction.
*
* @property fee Fee value (sats) if available. The availability of the fee depends on the backend. Its never None with an Electrum server backend, but it could be None with a Bitcoin RPC node without txindex that receive funds while offline.
* @property received Received value (sats) Sum of owned outputs of this transaction.
* @property sent Sent value (sats) Sum of owned inputs of this transaction.
* @property txid Transaction id.
* @property confirmationTime If the transaction is confirmed, [BlockTime] contains height and timestamp of the block containing the transaction. This property is null for unconfirmed transactions.
*/
data class TransactionDetails (
var transaction?: Transaction,
var fee: ULong?,
var received: ULong,
var sent: ULong,
var txid: String,
var confirmationTime: BlockTime?
)
/**
* A blockchain backend.
*
* @constructor Create the new blockchain client.
*
* @param config The blockchain configuration required.
*
* @sample org.bitcoindevkit.blockchainSample
*/
class Blockchain(
config: BlockchainConfig
) {
/** Broadcast a transaction. */
fun broadcast(transaction: Transaction) {}
/** Estimate the fee rate required to confirm a transaction in a given target of blocks. */
fun estimateFee(target: ULong): FeeRate {}
/** Get the current height of the blockchain. */
fun getHeight(): UInt {}
/** Get the block hash of a given block. */
fun getBlockHash(height: UInt): String {}
}
/**
* A bitcoin transaction.
*
* @constructor Build a new Bitcoin Transaction.
*
* @param transactionBytes The transaction bytes, bitcoin consensus encoded.
*/
class Transaction(transactionBytes: List<UByte>) {
/** Computes the txid. */
fun txid(): String {}
/**
* Returns the "weight" of this transaction, as defined by BIP141.
*
* For transactions with an empty witness, this is simply the consensus-serialized size times four.
* For transactions with a witness, this is the non-witness consensus-serialized size multiplied by three
* plus the with-witness consensus-serialized size.
*/
fun weight(): ULong {}
/** Returns the regular byte-wise consensus-serialized size of this transaction. */
fun size(): ULong {}
/**
* Returns the "virtual size" (vsize) of this transaction.
*
* Will be ceil(weight / 4.0). Note this implements the virtual size as per BIP141, which is different to
* what is implemented in Bitcoin Core. The computation should be the same for any remotely sane transaction.
*/
fun vsize(): ULong {}
/** Return the transaction bytes, bitcoin consensus encoded. */
fun serialize(): List<UByte> {}
/** Is this a coin base transaction? */
fun isCoinBase(): Boolean {}
/**
* Returns true if the transaction itself opted in to be BIP-125-replaceable (RBF).
* This does not cover the case where a transaction becomes replaceable due to ancestors being RBF.
*/
fun isExplicitlyRbf(): Boolean {}
/** Returns true if this transactions nLockTime is enabled (BIP-65). */
fun isLockTimeEnabled(): Boolean {}
/** The protocol version, is currently expected to be 1 or 2 (BIP 68). */
fun version(): Int {}
/**
* Block height or timestamp. Transaction cannot be included in a block until this height/time.
* Relevant BIPs
* BIP-65 OP_CHECKLOCKTIMEVERIFY
* BIP-113 Median time-past as endpoint for lock-time calculations
*/
fun lockTime(): UInt {}
/** List of transaction inputs. */
fun input(): List<TxIn> {}
/** List of transaction outputs. */
fun output(): List<TxOut> {}
}
/**
* A partially signed bitcoin transaction.
*
* @constructor Build a new Partially Signed Bitcoin Transaction.
*
* @param psbtBase64 The PSBT in base64 format.
*/
class PartiallySignedTransaction(psbtBase64: String) {
/** Return the PSBT in string format, using a base64 encoding. */
fun serialize(): String {}
/** Get the txid of the PSBT. */
fun txid(): String {}
/** Extract the transaction. */
fun extractTx(): Transaction {}
/**
* Combines this PartiallySignedTransaction with another PSBT as described by BIP 174.
* In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
*/
fun combine(other: PartiallySignedTransaction): PartiallySignedTransaction
/** Serialize the PSBT data structure as a String of JSON. */
fun jsonSerialize(): String
}
/**
* A reference to a transaction output.
*
* @property txid The referenced transactions txid.
* @property vout The index of the referenced output in its transactions vout.
*/
data class OutPoint (
var txid: String,
var vout: UInt
)
/**
* A transaction output, which defines new coins to be created from old ones.
*
* @property value The value of the output, in satoshis.
* @property scriptPubkey The script which must be satisfied for the output to be spent.
*/
data class TxOut (
var value: ULong,
var scriptPubkey: Script
)
/**
* Bitcoin transaction input.
*
* It contains the location of the previous transactions output, that it spends and set of scripts that satisfy its spending conditions.
*
* @property previousOutput The reference to the previous output that is being used an an input.
* @property scriptSig The script which pushes values on the stack which will cause the referenced outputs script to be accepted.
* @property sequence The sequence number, which suggests to miners which of two conflicting transactions should be preferred, or 0xFFFFFFFF to ignore this feature. This is generally never used since the miner behaviour cannot be enforced.
* @property witness Witness data: an array of byte-arrays. Note that this field is not (de)serialized with the rest of the TxIn in Encodable/Decodable, as it is (de)serialized at the end of the full Transaction. It is (de)serialized with the rest of the TxIn in other (de)serialization routines.
*
*/
data class TxIn (
var previousOutput: OutPoint,
var scriptSig: Script,
var sequence: UInt,
var witness: List<List<UByte>>
)
/**
* An unspent output owned by a [Wallet].
*
* @property outpoint Reference to a transaction output.
* @property txout Transaction output.
* @property keychain Type of keychain.
* @property isSpent Whether this UTXO is spent or not.
*/
data class LocalUtxo (
var outpoint: OutPoint,
var txout: TxOut,
var keychain: KeychainKind,
var isSpent: Boolean
)
/**
* Types of keychains.
*/
enum class KeychainKind {
/** External. */
EXTERNAL,
/** Internal, usually used for change outputs. */
INTERNAL,
}
/**
* Block height and timestamp of a block.
*
* @property height Confirmation block height.
* @property timestamp Confirmation block timestamp.
*/
data class BlockTime (
var height: UInt,
var timestamp: ULong,
)
/**
* A Bitcoin wallet.
* The Wallet acts as a way of coherently interfacing with output descriptors and related transactions. Its main components are:
* 1. Output descriptors from which it can derive addresses.
* 2. A Database where it tracks transactions and utxos related to the descriptors.
* 3. Signers that can contribute signatures to addresses instantiated from the descriptors.
*
* @constructor Create a BDK wallet.
*
* @param descriptor The main (or "external") descriptor.
* @param changeDescriptor? The change (or "internal") descriptor.
* @param network The network to act on.
* @param databaseConfig The database configuration.
*
* @sample org.bitcoindevkit.walletSample
*/
class Wallet(
descriptor: Descriptor,
changeDescriptor: Descriptor?,
network: Network,
databaseConfig: DatabaseConfig,
) {
/**
* Return a derived address using the external descriptor, see [AddressIndex] for available address index
* selection strategies. If none of the keys in the descriptor are derivable (i.e. the descriptor does not end
* with a * character) then the same address will always be returned for any [AddressIndex].
*/
fun getAddress(addressIndex: AddressIndex): AddressInfo {}
/**
* Return a derived address using the internal (change) descriptor.
* If the wallet doesn't have an internal descriptor it will use the external descriptor.
* See [AddressIndex] for available address index selection strategies. If none of the keys
* in the descriptor are derivable (i.e. does not end with /\*) then the same address will always
* be returned for any [AddressIndex].
*/
fun getInternalAddress(addressIndex: AddressIndex): AddressInfo {}
/** Return whether or not a script is part of this wallet (either internal or external). */
fun isMine(script: Script): Boolean {}
/** Return the wallet's balance, across different categories. See [Balance] for the categories. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
fun getBalance(): Balance {}
/**
* Sign a transaction with all the wallet's signers, in the order specified by every signer's
* `SignerOrdering`.
*
* The `SignOptions` can be used to tweak the behavior of the software signers, and the way
* the transaction is finalized at the end. Note that it can't be guaranteed that *every*
* signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
* in this library will.
*
* @param psbt PSBT to be signed
* @param signOptions signing options
* @return true if the PSBT was finalized, or false otherwise
*/
fun sign(psbt: PartiallySignedTransaction, signOptions: SignOptions?): Boolean {}
/** Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually. */
fun listTransactions(includeRaw: Boolean): List<TransactionDetails> {}
/** Get the Bitcoin network the wallet is using. */
fun network(): Network {}
/** Sync the internal database with the blockchain. */
fun sync(blockchain: Blockchain, progress: Progress?) {}
/** Return the list of unspent outputs of this wallet. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
fun listUnspent(): List<LocalUtxo> {}
}
/**
* Class that logs at level INFO every update received (if any).
*/
class Progress {
/** Send a new progress update. The progress value should be in the range 0.0 - 100.0, and the message value is an optional text message that can be displayed to the user. */
fun update(progress: Float, message: String?) {}
}
/**
* A transaction builder.
*
* After creating the TxBuilder, you set options on it until finally calling `.finish` to consume the builder and generate the transaction.
*
* Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added.
*
* @sample org.bitcoindevkit.txBuilderResultSample1
* @sample org.bitcoindevkit.txBuilderResultSample2
*/
class TxBuilder() {
/** Add data as an output using OP_RETURN. */
fun addData(data: List<UByte>): TxBuilder {}
/** Add a recipient to the internal list. */
fun addRecipient(script: Script, amount: ULong): TxBuilder {}
/** Set the list of recipients by providing a list of [ScriptAmount]. */
fun setRecipients(recipients: List<ScriptAmount>): TxBuilder {}
/** Add a utxo to the internal list of unspendable utxos. Its important to note that the "must-be-spent" utxos added with [TxBuilder.addUtxo] have priority over this. See the Rust docs of the two linked methods for more details. */
fun addUnspendable(unspendable: OutPoint): TxBuilder {}
/** Add an outpoint to the internal list of UTXOs that must be spent. These have priority over the "unspendable" utxos, meaning that if a utxo is present both in the "utxos" and the "unspendable" list, it will be spent. */
fun addUtxo(outpoint: OutPoint): TxBuilder {}
/**
* Add the list of outpoints to the internal list of UTXOs that must be spent. If an error
* occurs while adding any of the UTXOs then none of them are added and the error is returned.
* These have priority over the "unspendable" utxos, meaning that if a utxo is present both
* in the "utxos" and the "unspendable" list, it will be spent.
*/
fun addUtxos(outpoints: List<OutPoint>): TxBuilder {}
/** Do not spend change outputs. This effectively adds all the change outputs to the "unspendable" list. See [TxBuilder.unspendable]. */
fun doNotSpendChange(): TxBuilder {}
/** Only spend utxos added by [add_utxo]. The wallet will not add additional utxos to the transaction even if they are needed to make the transaction valid. */
fun manuallySelectedOnly(): TxBuilder {}
/** Only spend change outputs. This effectively adds all the non-change outputs to the "unspendable" list. See [TxBuilder.unspendable]. */
fun onlySpendChange(): TxBuilder {}
/**
* Replace the internal list of unspendable utxos with a new list. Its important to note that the "must-be-spent" utxos
* added with [TxBuilder.addUtxo] have priority over these. See the Rust docs of the two linked methods for more details.
*/
fun unspendable(unspendable: List<OutPoint>): TxBuilder {}
/** Set a custom fee rate. */
fun feeRate(satPerVbyte: Float): TxBuilder {}
/** Set an absolute fee. */
fun feeAbsolute(feeAmount: ULong): TxBuilder {}
/** Spend all the available inputs. This respects filters like [TxBuilder.unspendable] and the change policy. */
fun drainWallet(): TxBuilder {}
/**
* Sets the address to drain excess coins to. Usually, when there are excess coins they are
* sent to a change address generated by the wallet. This option replaces the usual change address
* with an arbitrary ScriptPubKey of your choosing. Just as with a change output, if the
* drain output is not needed (the excess coins are too small) it will not be included in the resulting
* transaction. The only difference is that it is valid to use [drainTo] without setting any ordinary recipients
* with [addRecipient] (but it is perfectly fine to add recipients as well). If you choose not to set any
* recipients, you should either provide the utxos that the transaction should spend via [addUtxos], or set
* [drainWallet] to spend all of them. When bumping the fees of a transaction made with this option,
* you probably want to use [BumpFeeTxBuilder.allowShrinking] to allow this output to be reduced to pay for the extra fees.
*/
fun drainTo(script: Script): TxBuilder {}
/** Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`. */
fun enableRbf(): TxBuilder {}
/**
* Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors
* contain an "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence`
* is higher than `0xFFFFFFFD` an error will be thrown, since it would not be a valid nSequence to signal RBF.
*/
fun enableRbfWithSequence(nsequence: UInt): TxBuilder {}
/** Finish building the transaction. Returns a [TxBuilderResult]. */
fun finish(wallet: Wallet): TxBuilderResult {}
}
/**
* Options for a software signer.
*
* Adjust the behavior of our software signers and the way a transaction is finalized.
*
* @property trustWitnessUtxo Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been provided. Defaults to `false`.
* @property assumeHeight Whether the wallet should assume a specific height has been reached when trying to finalize a transaction.
* @property allowAllSighashes Whether the signer should use the sighash_type set in the PSBT when signing, no matter what its value is. Defaults to `false`.
* @property removePartialSigs Whether to remove partial signatures from the PSBT inputs while finalizing PSBT. Defaults to `true`.
* @property tryFinalize Whether to try finalizing the PSBT after the inputs are signed. Defaults to `true`.
* @property signWithTapInternalKey Whether we should try to sign a taproot transaction with the taproot internal key or not. This option is ignored if we're signing a non-taproot PSBT. Defaults to `true`.
* @property allowGrinding Whether we should grind ECDSA signature to ensure signing with low r or not. Defaults to `true`.
*/
data class SignOptions (
var trustWitnessUtxo: Boolean,
var assumeHeight: UInt?,
var allowAllSighashes: Boolean,
var removePartialSigs: Boolean,
var tryFinalize: Boolean,
var signWithTapInternalKey: Boolean,
var allowGrinding: Boolean
)
/**
* A object holding a ScriptPubKey and an amount.
*
* @property script The ScriptPubKey.
* @property amount The amount.
*/
data class ScriptAmount (
var script: Script,
var amount: ULong
)
/**
* The BumpFeeTxBuilder is used to bump the fee on a transaction that has been broadcast and has its RBF flag set to true.
*/
class BumpFeeTxBuilder() {
/**
* Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this scriptPubKey
* in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output
* to shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is
* preserved then it is currently not guaranteed to be in the same position as it was originally. Returns an error
* if scriptPubkey cant be found among the recipients of the transaction we are bumping.
*/
fun allowShrinking(address: String): BumpFeeTxBuilder {}
/** Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`. */
fun enableRbf(): BumpFeeTxBuilder {}
/**
* Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors
* contain an "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence`
* is higher than `0xFFFFFFFD` an error will be thrown, since it would not be a valid nSequence to signal RBF.
*/
fun enableRbfWithSequence(nsequence: UInt): BumpFeeTxBuilder {}
/** Finish building the transaction. Returns a [TxBuilderResult]. */
fun finish(wallet: Wallet): TxBuilderResult {}
}
/**
* A BIP-32 derivation path.
*
* @param path The derivation path. Must start with `m`. Use this type to derive or extend a [DescriptorSecretKey]
* or [DescriptorPublicKey].
*/
class DerivationPath(path: String) {}
/**
* An extended secret key.
*
* @param network The network this DescriptorSecretKey is to be used on.
* @param mnemonic The mnemonic.
* @param password The optional passphrase that can be provided as per BIP-39.
*
* @sample org.bitcoindevkit.descriptorSecretKeyDeriveSample
* @sample org.bitcoindevkit.descriptorSecretKeyExtendSample
*/
class DescriptorSecretKey(network: Network, mnemonic: Mnemonic, password: String?) {
/** Build a DescriptorSecretKey from a String */
fun fromString(secretKey: String): DescriptorSecretKey {}
/** Derive a private descriptor at a given path. */
fun derive(path: DerivationPath): DescriptorSecretKey {}
/** Extend the private descriptor with a custom path. */
fun extend(path: DerivationPath): DescriptorSecretKey {}
/** Return the public version of the descriptor. */
fun asPublic(): DescriptorPublicKey {}
/** Return the raw private key as bytes. */
fun secretBytes(): List<UByte>
/** Return the private descriptor as a string. */
fun asString(): String {}
}
/**
* An extended public key.
*
* @param network The network this DescriptorPublicKey is to be used on.
* @param mnemonic The mnemonic.
* @param password The optional passphrase that can be provided as per BIP-39.
*/
class DescriptorPublicKey(network: Network, mnemonic: String, password: String?) {
/** Build a DescriptorPublicKey from a String */
fun fromString(publicKey: String): DescriptorPublicKey {}
/** Derive a public descriptor at a given path. */
fun derive(path: DerivationPath): DescriptorPublicKey
/** Extend the public descriptor with a custom path. */
fun extend(path: DerivationPath): DescriptorPublicKey
/** Return the public descriptor as a string. */
fun asString(): String
}
/**
* A output descriptor.
*
* @param descriptor The descriptor in string format.
* @param network The network this descriptor is to be used on.
*
* @sample org.bitcoindevkit.descriptorTemplates1
* @sample org.bitcoindevkit.descriptorTemplates2
*/
class Descriptor(descriptor: String, network: Network) {
/**
* BIP44 template. Expands to pkh(key/44'/{0,1}'/0'/{0,1}/\*)
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip44(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP44 public template. Expands to pkh(key/{0,1}/\*)
* This assumes that the key used has already been derived with m/44'/0'/0' for Mainnet or m/44'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip44Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/**
* BIP49 template. Expands to sh(wpkh(key/49'/{0,1}'/0'/{0,1}/\*))
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip49(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP49 public template. Expands to sh(wpkh(key/{0,1}/\*))
* This assumes that the key used has already been derived with m/49'/0'/0' for Mainnet or m/49'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip49Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/**
* BIP84 template. Expands to wpkh(key/84'/{0,1}'/0'/{0,1}/\*)
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip84(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP84 public template. Expands to wpkh(key/{0,1}/\*)
* This assumes that the key used has already been derived with m/84'/0'/0' for Mainnet or m/84'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip84Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/**
* BIP86 template. Expands to wpkh(key/86'/{0,1}'/0'/{0,1}/\*)
* Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).
*/
fun newBip86(secretKey: DescriptorSecretKey, keychain: KeychainKind, network: Network) {}
/**
* BIP86 public template. Expands to wpkh(key/{0,1}/\*)
* This assumes that the key used has already been derived with m/86'/0'/0' for Mainnet or m/86'/1'/0' for Testnet.
* This template requires the parent fingerprint to populate correctly the metadata of PSBTs.
*/
fun newBip86Public(publicKey: DescriptorPublicKey, fingerprint: String, keychain: KeychainKind, network: Network) {}
/** Return the public version of the output descriptor. */
fun asString(): String {}
/** Return the private version of the output descriptor if available, otherwise return the public version. */
fun asStringPrivate(): String {}
}
/**
* An enum describing entropy length (aka word count) in the mnemonic.
*/
enum class WordCount {
/** 12 words mnemonic (128 bits entropy). */
WORDS12,
/** 15 words mnemonic (160 bits entropy). */
WORDS15,
/** 18 words mnemonic (192 bits entropy). */
WORDS18,
/** 21 words mnemonic (224 bits entropy). */
WORDS21,
/** 24 words mnemonic (256 bits entropy). */
WORDS24,
}
/**
* The value returned from calling the `.finish()` method on the [TxBuilder] or [BumpFeeTxBuilder].
*
* @property psbt The PSBT
* @property transactionDetails The transaction details.
*
* @sample org.bitcoindevkit.txBuilderResultSample1
* @sample org.bitcoindevkit.txBuilderResultSample2
*/
data class TxBuilderResult (
var psbt: PartiallySignedTransaction,
var transactionDetails: TransactionDetails
)
/**
* A bitcoin script.
*/
class Script(rawOutputScript: List<UByte>) {
/** Return the script as bytes. */
fun toBytes(): List<UByte> {}
}
/**
* A bitcoin address.
*
* @param address The address in string format.
*/
class Address(address: String) {
/** Construct an [`Address`] from an output script. */
fun fromScript(script: Script, network: Network): Address {}
/** Return the Payload */
fun payload(): Payload
/** Return the Network. */
fun network(): Network
/** Return the ScriptPubKey. */
fun scriptPubkey(): Script
/**
* Creates a URI string bitcoin:address optimized to be encoded in QR codes.
*
* If the address is bech32, both the schema and the address become uppercase. If the address is base58, the schema is lowercase and the address is left mixed case.
*
* Quoting BIP 173 "inside QR codes uppercase SHOULD be used, as those permit the use of alphanumeric mode, which is 45% more compact than the normal byte mode."
*/
fun toQrUri(): String
/** Return the address as a string. */
fun asString(): String
}}
/**
* The method used to produce an address.
*/
sealed class Payload {
/** P2PKH address. */
data class PubkeyHash(
val pubkeyHash: List<UByte>
) : Payload()
/** P2SH address. */
data class ScriptHash(
val scriptHash: List<UByte>
) : Payload()
/** Segwit address. */
data class WitnessProgram(
val version: WitnessVersion,
val program: List<UByte>
) : Payload()
}
/**
* Version of the witness program.
*
* Helps limit possible versions of the witness according to the specification. If a plain u8 type
* was used instead it would mean that the version may be > 16, which would be incorrect.
* First byte of scriptPubkey in transaction output for transactions starting with opcodes ranging
* from 0 to 16 (inclusive).
*/
enum class WitnessVersion {
V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16
}
/**
* Mnemonic phrases are a human-readable version of the private keys. Supported number of words are 12, 15, 18, 21 and 24.
*
* @constructor Generates Mnemonic with a random entropy.
* @param mnemonic The mnemonic as a string of space-separated words.
*
* @sample org.bitcoindevkit.mnemonicSample
*/
class Mnemonic(mnemonic: String) {
/* Returns Mnemonic as string */
fun asString(): String
/* Parse a Mnemonic from a given string. */
fun fromString(): Mnemonic
/*
* Create a new Mnemonic in the specified language from the given entropy. Entropy must be a
* multiple of 32 bits (4 bytes) and 128-256 bits in length.
*/
fun fromEntropy(): Mnemonic
}

View File

@@ -0,0 +1,281 @@
package org.bitcoindevkit
fun networkSample() {
val wallet = Wallet(
descriptor = descriptor,
changeDescriptor = changeDescriptor,
network = Network.TESTNET,
databaseConfig = DatabaseConfig.Memory
)
}
fun balanceSample() {
object LogProgress : Progress {
override fun update(progress: Float, message: String?) {}
}
val memoryDatabaseConfig = DatabaseConfig.Memory
private val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
"ssl://electrum.blockstream.info:60002",
null,
5u,
null,
200u
)
)
val wallet = Wallet(descriptor, null, Network.TESTNET, memoryDatabaseConfig)
val blockchain = Blockchain(blockchainConfig)
wallet.sync(blockchain, LogProgress)
val balance: Balance = wallet.getBalance()
println("Total wallet balance is ${balance.total}")
}
fun electrumBlockchainConfigSample() {
val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
url = "ssl://electrum.blockstream.info:60002",
socks5 = null,
retry = 5u,
timeout = null,
stopGap = 200u
)
)
}
fun esploraBlockchainConfigSample() {
val esploraURL: String = "http://10.0.2.2:3002"
val esploraConfig: EsploraConfig = EsploraConfig(
baseUrl = esploraURL,
proxy = null,
concurrency = 4u,
stopGap = 20UL,
timeout = null
)
val blockchainConfig = BlockchainConfig.Esplora(config = esploraConfig)
}
fun memoryDatabaseConfigSample() {
val memoryDatabaseConfig = DatabaseConfig.Memory
}
fun sqliteDatabaseConfigSample() {
val databaseConfig = DatabaseConfig.Sqlite(SqliteDbConfiguration("bdk-sqlite"))
}
fun addressIndexSample() {
val wallet: Wallet = Wallet(
descriptor = descriptor,
changeDescriptor = changeDescriptor,
network = Network.TESTNET,
databaseConfig = DatabaseConfig.Memory
)
fun peekAddress100(): AddressInfo {
return wallet.getAddress(AddressIndex.Peek(100u))
}
}
fun addressInfoSample() {
val wallet: Wallet = Wallet(
descriptor = descriptor,
changeDescriptor = changeDescriptor,
network = Network.TESTNET,
databaseConfig = DatabaseConfig.Memory
)
val newAddress: AddressInfo = wallet.getAddress(AddressIndex.New)
println("New address at index ${newAddress.index} is ${newAddress.address.asString()}")
}
fun blockchainSample() {
val blockchainConfig: BlockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
electrumURL,
null,
5u,
null,
10u
)
)
val blockchain: Blockchain = Blockchain(blockchainConfig)
val feeRate: FeeRate = blockchain.estimateFee(3u)
val (psbt, txDetails) = TxBuilder()
.addRecipient(faucetAddress.scriptPubkey(), 1000uL)
.feeRate(feeRate.asSatPerVb())
.finish(wallet)
wallet.sign(psbt)
blockchain.broadcast(psbt)
}
fun txBuilderResultSample1() {
val faucetAddress = Address("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
// TxBuilderResult is a data class, which means you can use destructuring declarations on it to
// open it up into its component parts
val (psbt, txDetails) = TxBuilder()
.addRecipient(faucetAddress.scriptPubkey(), 1000uL)
.feeRate(1.2f)
.finish(wallet)
println("Txid is ${txDetails.txid}")
wallet.sign(psbt)
}
fun txBuilderResultSample2() {
val faucetAddress = Address("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
val txBuilderResult: TxBuilderResult = TxBuilder()
.addRecipient(faucetAddress.scriptPubkey(), 1000uL)
.feeRate(1.2f)
.finish(wallet)
val psbt = txBuilderResult.psbt
val txDetails = txBuilderResult.transactionDetails
println("Txid is ${txDetails.txid}")
wallet.sign(psbt)
}
fun descriptorSecretKeyExtendSample() {
// The `DescriptorSecretKey.extend()` method allows you to extend a key to any given path.
// val mnemonic: String = generateMnemonic(WordCount.WORDS12)
val mnemonic: Mnemonic = Mnemonic("scene change clap smart together mind wheel knee clip normal trial unusual")
// the initial DescriptorSecretKey will always be at the "master" node,
// i.e. the derivation path is empty
val bip32RootKey: DescriptorSecretKey = DescriptorSecretKey(
network = Network.TESTNET,
mnemonic = mnemonic,
password = ""
)
println(bip32RootKey.asString())
// tprv8ZgxMBicQKsPfM8Trx2apvdEkmxbJkYY3ZsmcgKb2bfnLNcBhtCstqQTeFesMRLEJXpjGDinAUJUHprXMwph8dQBdS1HAoxEis8Knimxovf/*
// the derive method will also automatically apply the wildcard (*) to your path,
// i.e the following will generate the typical testnet BIP84 external wallet path
// m/84h/1h/0h/0/*
val bip84ExternalPath: DerivationPath = DerivationPath("m/84h/1h/0h/0")
val externalExtendedKey: DescriptorSecretKey = bip32RootKey.extend(bip84ExternalPath).asString()
println(externalExtendedKey)
// tprv8ZgxMBicQKsPfM8Trx2apvdEkmxbJkYY3ZsmcgKb2bfnLNcBhtCstqQTeFesMRLEJXpjGDinAUJUHprXMwph8dQBdS1HAoxEis8Knimxovf/84'/1'/0'/0/*
// to create the descriptor you'll need to use this extended key in a descriptor function,
// i.e. wpkh(), tr(), etc.
val externalDescriptor = "wpkh($externalExtendedKey)"
}
fun descriptorSecretKeyDeriveSample() {
// The DescriptorSecretKey.derive() method allows you to derive an extended key for a given
// node in the derivation tree (for example to create an xpub for a particular account)
val mnemonic: Mnemonic = Mnemonic("scene change clap smart together mind wheel knee clip normal trial unusual")
val bip32RootKey: DescriptorSecretKey = DescriptorSecretKey(
network = Network.TESTNET,
mnemonic = mnemonic,
password = ""
)
val bip84Account0: DerivationPath = DerivationPath("m/84h/1h/0h")
val xpubAccount0: DescriptorSecretKey = bip32RootKey.derive(bip84Account0)
println(xpubAccount0.asString())
// [5512949b/84'/1'/0']tprv8ghw3FWfWTeLCEXcr8f8Q8Lz4QPCELYv3jhBXjAm7XagA6R5hreeWLTJeLBfMj7Ni6Q3PdV1o8NbvNBHE59W97EkRJSU4JkvTQjaNUmQubE/*
val internalPath: DerivationPath = DerivationPath("m/0")
val externalExtendedKey = xpubAccount0.extend(internalPath).asString()
println(externalExtendedKey)
// [5512949b/84'/1'/0']tprv8ghw3FWfWTeLCEXcr8f8Q8Lz4QPCELYv3jhBXjAm7XagA6R5hreeWLTJeLBfMj7Ni6Q3PdV1o8NbvNBHE59W97EkRJSU4JkvTQjaNUmQubE/0/*
// to create the descriptor you'll need to use this extended key in a descriptor function,
// i.e. wpkh(), tr(), etc.
val externalDescriptor = "wpkh($externalExtendedKey)"
}
fun createTransaction() {
val wallet = BdkWallet(
descriptor = externalDescriptor,
changeDescriptor = internalDescriptor,
network = Network.TESTNET,
databaseConfig = memoryDatabaseConfig,
)
val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
"ssl://electrum.blockstream.info:60002",
null,
5u,
null,
200u
)
)
val paymentAddress: Address = Address("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
val (psbt, txDetails) = TxBuilder()
.addRecipient(faucetAddress.scriptPubkey(), 1000uL)
.feeRate(1.2f)
.finish(wallet)
wallet.sign(psbt)
blockchain.broadcast(psbt)
}
fun walletSample() {
val externalDescriptor = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEfVULesmhEfZYyBXdE/84h/1h/0h/0/*)"
val internalDescriptor = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEfVULesmhEfZYyBXdE/84h/1h/0h/1/*)"
val sqliteDatabaseConfig = DatabaseConfig.Sqlite(SqliteDbConfiguration("bdk-sqlite"))
val wallet = Wallet(
descriptor = externalDescriptor,
changeDescriptor = internalDescriptor,
network = Network.TESTNET,
databaseConfig = sqliteDatabaseConfig,
)
}
fun mnemonicSample() {
val mnemonic0: Mnemonic = Mnemonic(WordCount.WORDS12)
val mnemonic1: Mnemonic = Mnemonic.fromString("scene change clap smart together mind wheel knee clip normal trial unusual")
val entropy: List<UByte> = listOf<UByte>(0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u)
val mnemonic2: Mnemonic = Mnemonic.fromEntropy(entropy)
println(mnemonic0.asString(), mnemonic1.asString(), mnemonic2.asString())
}
fun descriptorTemplates1() {
// Bip84 private descriptor
val recoveryPhrase: String = "scene change clap smart together mind wheel knee clip normal trial unusual"
val mnemonic = Mnemonic.fromString(recoveryPhrase)
val bip32ExtendedRootKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
val bip84ExternalDescriptor: Descriptor = Descriptor.newBip84(bip32ExtendedRootKey, KeychainKind.EXTERNAL, Network.TESTNET)
}
fun descriptorTemplates2() {
// Bip49 public descriptor
// assume we already have the xpub for m/49'/0'/1' created on an external device that only shared the xpub with the wallet
// using the template requires the parent fingerprint to populate correctly the metadata of PSBTs, which the external device would provide
// the xpub (tpub for testnet): tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR
// the fingerprint: d1d04177
val descriptorPublicKey: DescriptorPublicKey = DescriptorPublicKey.fromString("tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR")
val bip49PublicDescriptor: Descriptor = Descriptor.newBip49Public(
publicKey = descriptorPublicKey,
fingerprint = "d1d04177",
keychain = KeychainKind.EXTERNAL,
network = Network.TESTNET,
)
println(bip49PublicDescriptor.asString()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
println(bip49PublicDescriptor.asStringPrivate()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
// Creating it starting from the full xprv derived from a mnemonic will give you the same public descriptor
val mnemonic = Mnemonic.fromString("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect")
val bip32ExtendedRootKey: DescriptorSecretKey = DescriptorSecretKey(Network.TESTNET, mnemonic, null)
val bip49PrivateDescriptor: Descriptor = Descriptor.newBip49(bip32ExtendedRootKey, KeychainKind.EXTERNAL, Network.TESTNET)
println(bip49PrivateDescriptor.asString()) // sh(wpkh([d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/0/*))#a7lxzefl
}

120
bdk-android/README.md Normal file
View File

@@ -0,0 +1,120 @@
# bdk-android
This project builds an .aar package for the Android platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the [`bdk-ffi`] project which is included in the root of this repository.
## How to Use
To use the Kotlin language bindings for [`bdk`] in your Android project add the following to your gradle dependencies:
```kotlin
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version>")
}
```
You may then import and use the `org.bitcoindevkit` library in your Kotlin code. For example:
```kotlin
import org.bitcoindevkit.*
// ...
val externalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)", Network.TESTNET)
val databaseConfig = DatabaseConfig.Memory
val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
)
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
val newAddress = wallet.getAddress(AddressIndex.LastUnused)
```
### Snapshot releases
To use a snapshot release, specify the snapshot repository url in the `repositories` block and use the snapshot version in the `dependencies` block:
```kotlin
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
implementation("org.bitcoindevkit:bdk-android:<version-SNAPSHOT>")
}
```
### Example Projects
* [Devkit Wallet](https://github.com/thunderbiscuit/devkit-wallet)
* [Padawan Wallet](https://github.com/thunderbiscuit/padawan-wallet)
### How to build
_Note that Kotlin version `1.6.10` or later is required to build the library._
1. Clone this repository.
```shell
git clone https://github.com/bitcoindevkit/bdk-ffi
```
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
3. Install Rust (note that we are currently building using Rust 1.67.0):
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default 1.67.0
```
4. Install required targets
```sh
rustup target add x86_64-linux-android aarch64-linux-android armv7-linux-androideabi
```
5. Install Android SDK and Build-Tools for API level 30+
6. Setup `$ANDROID_SDK_ROOT` and `$ANDROID_NDK_ROOT` path variables (which are required by the
build tool), for example (note that currently, NDK version 21.4.7075529 is required):
```shell
export ANDROID_SDK_ROOT=~/Android/Sdk
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.4.7075529
```
7. Build kotlin bindings
```sh
# build Android library
cd bdk-android
./gradlew buildAndroidLib
```
8. Start android emulator (must be x86_64) and run tests
```sh
./gradlew connectedAndroidTest
```
## How to publish to your local Maven repo
```shell
cd bdk-android
./gradlew publishToMavenLocal --exclude-task signMavenPublication
```
Note that the commands assume you don't need the local libraries to be signed. If you do wish to sign them, simply set your `~/.gradle/gradle.properties` signing key values like so:
```properties
signing.gnupg.keyName=<YOUR_GNUPG_ID>
signing.gnupg.passphrase=<YOUR_GNUPG_PASSPHRASE>
```
and use the `publishToMavenLocal` task without excluding the signing task:
```shell
./gradlew publishToMavenLocal
```
## Known issues
### JNA dependency
Depending on the JVM version you use, you might not have the JNA dependency on your classpath. The exception thrown will be
```shell
class file for com.sun.jna.Pointer not found
```
The solution is to add JNA as a dependency like so:
```kotlin
dependencies {
// ...
implementation("net.java.dev.jna:jna:5.12.1")
}
```
### x86 emulators
For some older versions of macOS, Android Studio will recommend users install the x86 version of the emulator by default. This will not work with the bdk-android library, as we do not support 32-bit architectures. Make sure you install an x86_64 emulator to work with bdk-android.
[`bdk`]: https://github.com/bitcoindevkit/bdk
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi

View File

@@ -0,0 +1,36 @@
buildscript {
repositories {
google()
}
dependencies {
classpath("com.android.tools.build:gradle:7.1.2")
}
}
plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
}
// library version is defined in gradle.properties
val libraryVersion: String by project
// These properties are required here so that the nexus publish-plugin
// finds a staging profile with the correct group (group is otherwise set as "")
// and knows whether to publish to a SNAPSHOT repository or not
// https://github.com/gradle-nexus/publish-plugin#applying-the-plugin
group = "org.bitcoindevkit"
version = libraryVersion
nexusPublishing {
repositories {
create("sonatype") {
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
val ossrhUsername: String? by project
val ossrhPassword: String? by project
username.set(ossrhUsername)
password.set(ossrhPassword)
}
}
}

View File

@@ -0,0 +1,5 @@
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
android.enableJetifier=true
kotlin.code.style=official
libraryVersion=0.31.0

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
bdk-android/gradlew vendored Executable file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
bdk-android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,117 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
// library version is defined in gradle.properties
val libraryVersion: String by project
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android") version "1.6.10"
id("maven-publish")
id("signing")
// Custom plugin to generate the native libs and bindings file
id("org.bitcoindevkit.plugins.generate-android-bindings")
}
repositories {
mavenCentral()
google()
}
android {
compileSdk = 31
defaultConfig {
minSdk = 21
targetSdk = 31
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(file("proguard-android-optimize.txt"), file("proguard-rules.pro"))
}
}
publishing {
singleVariant("release") {
withSourcesJar()
withJavadocJar()
}
}
}
dependencies {
implementation("net.java.dev.jna:jna:5.8.0@aar")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7")
implementation("androidx.appcompat:appcompat:1.4.0")
implementation("androidx.core:core-ktx:1.7.0")
api("org.slf4j:slf4j-api:1.7.30")
androidTestImplementation("com.github.tony19:logback-android:2.0.0")
androidTestImplementation("androidx.test.ext:junit:1.1.3")
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
androidTestImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1")
}
afterEvaluate {
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "org.bitcoindevkit"
artifactId = "bdk-android"
version = libraryVersion
from(components["release"])
pom {
name.set("bdk-android")
description.set("Bitcoin Dev Kit Kotlin language bindings.")
url.set("https://bitcoindevkit.org")
licenses {
license {
name.set("APACHE 2.0")
url.set("https://github.com/bitcoindevkit/bdk/blob/master/LICENSE-APACHE")
}
license {
name.set("MIT")
url.set("https://github.com/bitcoindevkit/bdk/blob/master/LICENSE-MIT")
}
}
developers {
developer {
id.set("notmandatory")
name.set("Steve Myers")
email.set("notmandatory@noreply.github.org")
}
developer {
id.set("artfuldev")
name.set("Sudarsan Balaji")
email.set("sudarsan.balaji@artfuldev.com")
}
}
scm {
connection.set("scm:git:github.com/bitcoindevkit/bdk-ffi.git")
developerConnection.set("scm:git:ssh://github.com/bitcoindevkit/bdk-ffi.git")
url.set("https://github.com/bitcoindevkit/bdk-ffi/tree/master")
}
}
}
}
}
}
signing {
val signingKeyId: String? by project
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}
// This task dependency ensures that we build the bindings
// binaries before running the tests
tasks.withType<KotlinCompile> {
dependsOn("buildAndroidLib")
}

28
bdk-android/lib/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,28 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
# for JNA
-dontwarn java.awt.*
-keep class com.sun.jna.* { *; }
-keep class org.bitcoindevkit.* { *; }
-keepclassmembers class * extends org.bitcoindevkit.* { public *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }

View File

@@ -0,0 +1,14 @@
<configuration>
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
<tagEncoder>
<pattern>%logger{12}</pattern>
</tagEncoder>
<encoder>
<pattern>[%-20thread] %msg</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="logcat" />
</root>
</configuration>

View File

@@ -0,0 +1,81 @@
package org.bitcoindevkit
import org.junit.Assert.*
import org.junit.Test
import android.app.Application
import android.content.Context.MODE_PRIVATE
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.runner.RunWith
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class AndroidLibTest {
private fun getTestDataDir(): String {
val context = ApplicationProvider.getApplicationContext<Application>()
return context.getDir("bdk-test", MODE_PRIVATE).toString()
}
private fun cleanupTestDataDir(testDataDir: String) {
File(testDataDir).deleteRecursively()
}
class LogProgress : Progress {
private val log: Logger = LoggerFactory.getLogger(AndroidLibTest::class.java)
override fun update(progress: Float, message: String?) {
log.debug("Syncing...")
}
}
private val descriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
private val databaseConfig = DatabaseConfig.Memory
private val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
"ssl://electrum.blockstream.info:60002",
null,
5u,
null,
100u,
true,
)
)
@Test
fun memoryWalletNewAddress() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val address = wallet.getAddress(AddressIndex.New).address.asString()
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address)
}
@Test
fun memoryWalletSyncGetBalance() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val blockchain = Blockchain(blockchainConfig)
wallet.sync(blockchain, LogProgress())
val balance: Balance = wallet.getBalance()
assertTrue(balance.total > 0u)
}
@Test
fun sqliteWalletSyncGetBalance() {
val testDataDir = getTestDataDir() + "/bdk-wallet.sqlite"
val databaseConfig = DatabaseConfig.Sqlite(SqliteDbConfiguration(testDataDir))
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val blockchain = Blockchain(blockchainConfig)
wallet.sync(blockchain, LogProgress())
val balance: Balance = wallet.getBalance()
assertTrue(balance.total > 0u)
cleanupTestDataDir(testDataDir)
}
}

View File

@@ -0,0 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.bitcoindevkit">
<uses-permission android:name="android.permission.INTERNET" />
</manifest>

View File

@@ -0,0 +1,17 @@
# Readme
The purpose of this directory is to host the Gradle plugin that adds tasks for building the native binaries required by `bdk-android`, and building the language bindings files.
The plugin is applied to the `build.gradle.kts` file in `bdk-android` through the `plugins` block:
```kotlin
// bdk-android
plugins {
id("org.bitcoindevkit.plugins.generate-android-bindings")
}
```
It adds a series of tasks which are brought together into an aggregate task called `buildAndroidLib`.
This aggregate task:
1. Builds the native libraries using `bdk-ffi`
2. Places them in the correct resource directories
3. Builds the bindings file

View File

@@ -0,0 +1,13 @@
plugins {
id("java-gradle-plugin")
`kotlin-dsl`
}
gradlePlugin {
plugins {
create("uniFfiAndroidBindings") {
id = "org.bitcoindevkit.plugins.generate-android-bindings"
implementationClass = "org.bitcoindevkit.plugins.UniFfiAndroidPlugin"
}
}
}

View File

@@ -0,0 +1,8 @@
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
// include(":plugins")

View File

@@ -0,0 +1,14 @@
package org.bitcoindevkit.plugins
val operatingSystem: OS = when {
System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC
System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX
else -> OS.OTHER
}
enum class OS {
MAC,
LINUX,
OTHER,
}

View File

@@ -0,0 +1,166 @@
package org.bitcoindevkit.plugins
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Exec
import org.gradle.kotlin.dsl.environment
import org.gradle.kotlin.dsl.getValue
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register
internal class UniFfiAndroidPlugin : Plugin<Project> {
override fun apply(target: Project): Unit = target.run {
val llvmArchPath = when (operatingSystem) {
OS.MAC -> "darwin-x86_64"
OS.LINUX -> "linux-x86_64"
OS.OTHER -> throw Error("Cannot build Android library from current architecture")
}
// arm64-v8a is the most popular hardware architecture for Android
val buildAndroidAarch64Binary by tasks.register<Exec>("buildAndroidAarch64Binary") {
workingDir("${projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-linux-android")
executable("cargo")
args(cargoArgs)
// if ANDROID_NDK_ROOT is not set then set it to github actions default
if (System.getenv("ANDROID_NDK_ROOT") == null) {
environment(
Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle")
)
}
environment(
// add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"),
Pair("AR", "llvm-ar"),
Pair("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", "aarch64-linux-android21-clang"),
Pair("CC", "aarch64-linux-android21-clang")
)
doLast {
println("Native library for bdk-android on aarch64 built successfully")
}
}
// the x86_64 version of the library is mostly used by emulators
val buildAndroidX86_64Binary by tasks.register<Exec>("buildAndroidX86_64Binary") {
workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-linux-android")
executable("cargo")
args(cargoArgs)
// if ANDROID_NDK_ROOT is not set then set it to github actions default
if (System.getenv("ANDROID_NDK_ROOT") == null) {
environment(
Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle")
)
}
environment(
// add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"),
Pair("AR", "llvm-ar"),
Pair("CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER", "x86_64-linux-android21-clang"),
Pair("CC", "x86_64-linux-android21-clang")
)
doLast {
println("Native library for bdk-android on x86_64 built successfully")
}
}
// armeabi-v7a version of the library for older 32-bit Android hardware
val buildAndroidArmv7Binary by tasks.register<Exec>("buildAndroidArmv7Binary") {
workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "armv7-linux-androideabi")
executable("cargo")
args(cargoArgs)
// if ANDROID_NDK_ROOT is not set then set it to github actions default
if (System.getenv("ANDROID_NDK_ROOT") == null) {
environment(
Pair("ANDROID_NDK_ROOT", "${System.getenv("ANDROID_SDK_ROOT")}/ndk-bundle")
)
}
environment(
// add build toolchain to PATH
Pair("PATH", "${System.getenv("PATH")}:${System.getenv("ANDROID_NDK_ROOT")}/toolchains/llvm/prebuilt/$llvmArchPath/bin"),
Pair("CFLAGS", "-D__ANDROID_MIN_SDK_VERSION__=21"),
Pair("AR", "llvm-ar"),
Pair("CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER", "armv7a-linux-androideabi21-clang"),
Pair("CC", "armv7a-linux-androideabi21-clang")
)
doLast {
println("Native library for bdk-android on armv7 built successfully")
}
}
// move the native libs build by cargo from target/<architecture>/release/
// to their place in the bdk-android library
// the task only copies the available binaries built using the buildAndroid<architecture>Binary tasks
val moveNativeAndroidLibs by tasks.register<Copy>("moveNativeAndroidLibs") {
dependsOn(buildAndroidAarch64Binary)
into("${project.projectDir}/../lib/src/main/jniLibs/")
into("arm64-v8a") {
from("${project.projectDir}/../../target/aarch64-linux-android/release-smaller/libbdkffi.so")
}
into("x86_64") {
from("${project.projectDir}/../../target/x86_64-linux-android/release-smaller/libbdkffi.so")
}
into("armeabi-v7a") {
from("${project.projectDir}/../../target/armv7-linux-androideabi/release-smaller/libbdkffi.so")
}
doLast {
println("Native binaries for Android moved to ./lib/src/main/jniLibs/")
}
}
// generate the bindings using the bdk-ffi-bindgen tool located in the bdk-ffi submodule
val generateAndroidBindings by tasks.register<Exec>("generateAndroidBindings") {
dependsOn(moveNativeAndroidLibs)
workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("run", "--bin", "uniffi-bindgen", "generate", "src/bdk.udl", "--language", "kotlin", "--out-dir", "../bdk-android/lib/src/main/kotlin", "--no-format")
executable("cargo")
args(cargoArgs)
doLast {
println("Android bindings file successfully created")
}
}
// create an aggregate task which will run the required tasks to build the Android libs in order
// the task will also appear in the printout of the ./gradlew tasks task with group and description
tasks.register("buildAndroidLib") {
group = "Bitcoindevkit"
description = "Aggregate task to build Android library"
dependsOn(
buildAndroidAarch64Binary,
buildAndroidX86_64Binary,
buildAndroidArmv7Binary,
moveNativeAndroidLibs,
generateAndroidBindings
)
}
}
}

View File

@@ -0,0 +1,4 @@
rootProject.name = "bdk-android"
include(":lib")
includeBuild("plugins")

View File

@@ -1,11 +0,0 @@
[package]
name = "bdk-ffi-bindgen"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "=1.0.45" # remove after upgrading to next version of uniffi
structopt = "0.3"
uniffi_bindgen = "0.16.0"

View File

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

28
bdk-ffi/Cargo.toml Normal file
View File

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

3
bdk-ffi/build.rs Normal file
View File

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

510
bdk-ffi/src/bdk.udl Normal file
View File

@@ -0,0 +1,510 @@
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",
"Rpc",
"HardenedIndex"
};
dictionary AddressInfo {
u32 index;
Address address;
KeychainKind keychain;
};
[Enum]
interface AddressIndex {
New();
LastUnused();
Peek(u32 index);
Reset(u32 index);
};
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 {
Transaction? transaction;
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;
boolean validate_domain;
};
dictionary EsploraConfig {
string base_url;
string? proxy;
u8? concurrency;
u64 stop_gap;
u64? timeout;
};
[Enum]
interface Auth {
None();
UserPass(string username, string password);
Cookie(string file);
};
dictionary RpcSyncParams {
u64 start_script_count;
u64 start_time;
boolean force_start_time;
u64 poll_rate_sec;
};
dictionary RpcConfig {
string url;
Auth auth;
Network network;
string wallet_name;
RpcSyncParams? sync_params;
};
[Enum]
interface BlockchainConfig {
Electrum(ElectrumConfig config);
Esplora(EsploraConfig config);
Rpc(RpcConfig config);
};
interface Blockchain {
[Throws=BdkError]
constructor(BlockchainConfig config);
[Throws=BdkError]
void broadcast([ByRef] Transaction transaction);
[Throws=BdkError]
FeeRate estimate_fee(u64 target);
[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 TxIn {
OutPoint previous_output;
Script script_sig;
u32 sequence;
sequence<sequence<u8>> witness;
};
dictionary TxOut {
u64 value;
Script script_pubkey;
};
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(Descriptor descriptor, Descriptor? change_descriptor, Network network, DatabaseConfig database_config);
Network network();
[Throws=BdkError]
AddressInfo get_address(AddressIndex address_index);
[Throws=BdkError]
AddressInfo get_internal_address(AddressIndex address_index);
[Throws=BdkError]
boolean is_mine(Script script);
[Throws=BdkError]
sequence<LocalUtxo> list_unspent();
[Throws=BdkError]
sequence<TransactionDetails> list_transactions(boolean include_raw);
[Throws=BdkError]
Balance get_balance();
[Throws=BdkError]
boolean sign([ByRef] PartiallySignedTransaction psbt, SignOptions? sign_options);
[Throws=BdkError]
void sync([ByRef] Blockchain blockchain, Progress? progress);
};
interface FeeRate {
[Name=from_sat_per_vb]
constructor(float sat_per_vb);
float as_sat_per_vb();
};
dictionary SignOptions {
boolean trust_witness_utxo;
u32? assume_height;
boolean allow_all_sighashes;
boolean remove_partial_sigs;
boolean try_finalize;
boolean sign_with_tap_internal_key;
boolean allow_grinding;
};
interface Transaction {
[Throws=BdkError]
constructor(sequence<u8> transaction_bytes);
string txid();
u64 weight();
u64 size();
u64 vsize();
sequence<u8> serialize();
boolean is_coin_base();
boolean is_explicitly_rbf();
boolean is_lock_time_enabled();
i32 version();
u32 lock_time();
sequence<TxIn> input();
sequence<TxOut> output();
};
interface PartiallySignedTransaction {
[Throws=BdkError]
constructor(string psbt_base64);
string serialize();
string txid();
Transaction extract_tx();
[Throws=BdkError]
PartiallySignedTransaction combine(PartiallySignedTransaction other);
u64? fee_amount();
FeeRate? fee_rate();
string json_serialize();
};
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<OutPoint> outpoints);
TxBuilder do_not_spend_change();
TxBuilder manually_selected_only();
TxBuilder only_spend_change();
TxBuilder unspendable(sequence<OutPoint> unspendable);
TxBuilder fee_rate(float sat_per_vbyte);
TxBuilder fee_absolute(u64 fee_amount);
TxBuilder drain_wallet();
TxBuilder drain_to(Script script);
TxBuilder enable_rbf();
TxBuilder enable_rbf_with_sequence(u32 nsequence);
TxBuilder add_data(sequence<u8> data);
TxBuilder set_recipients(sequence<ScriptAmount> recipients);
[Throws=BdkError]
TxBuilderResult finish([ByRef] Wallet wallet);
};
interface BumpFeeTxBuilder {
constructor(string txid, float new_fee_rate);
BumpFeeTxBuilder allow_shrinking(Script script_pubkey);
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<u8> entropy);
string as_string();
};
interface DerivationPath {
[Throws=BdkError]
constructor(string path);
};
interface DescriptorSecretKey {
constructor(Network network, Mnemonic mnemonic, string? password);
[Name=from_string, Throws=BdkError]
constructor(string secret_key);
[Throws=BdkError]
DescriptorSecretKey derive(DerivationPath path);
[Throws=BdkError]
DescriptorSecretKey extend(DerivationPath path);
DescriptorPublicKey as_public();
sequence<u8> secret_bytes();
string as_string();
};
interface DescriptorPublicKey {
[Name=from_string, Throws=BdkError]
constructor(string public_key);
[Throws=BdkError]
DescriptorPublicKey derive(DerivationPath path);
[Throws=BdkError]
DescriptorPublicKey extend(DerivationPath path);
string as_string();
};
interface Descriptor {
[Throws=BdkError]
constructor(string descriptor, Network network);
[Name=new_bip44]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip44_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
[Name=new_bip49]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip49_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
[Name=new_bip84]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip84_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
[Name=new_bip86]
constructor(DescriptorSecretKey secret_key, KeychainKind keychain, Network network);
[Name=new_bip86_public]
constructor(DescriptorPublicKey public_key, string fingerprint, KeychainKind keychain, Network network);
string as_string();
string as_string_private();
};
interface Address {
[Throws=BdkError]
constructor(string address, Network network);
[Name=from_script, Throws=BdkError]
constructor(Script script, Network network);
Payload payload();
Network network();
Script script_pubkey();
string to_qr_uri();
boolean is_valid_for_network(Network network);
string as_string();
};
[Enum]
interface Payload {
PubkeyHash(string pubkey_hash);
ScriptHash(string script_hash);
WitnessProgram(WitnessVersion version, sequence<u8> program);
};
enum WitnessVersion {
"V0",
"V1",
"V2",
"V3",
"V4",
"V5",
"V6",
"V7",
"V8",
"V9",
"V10",
"V11",
"V12",
"V13",
"V14",
"V15",
"V16"
};
interface Script {
constructor(sequence<u8> raw_output_script);
sequence<u8> to_bytes();
};

201
bdk-ffi/src/blockchain.rs Normal file
View File

@@ -0,0 +1,201 @@
// use crate::BlockchainConfig;
use crate::Network;
use crate::{BdkError, Transaction};
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
use bdk::blockchain::rpc::Auth as BdkAuth;
use bdk::blockchain::rpc::RpcSyncParams as BdkRpcSyncParams;
use bdk::blockchain::Blockchain as BdkBlockchain;
use bdk::blockchain::GetBlockHash;
use bdk::blockchain::GetHeight;
use bdk::blockchain::{
electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig,
rpc::RpcConfig as BdkRpcConfig, ConfigurableBlockchain,
};
use bdk::FeeRate;
use std::convert::{From, TryFrom};
use std::path::PathBuf;
use std::sync::{Arc, Mutex, MutexGuard};
pub(crate) struct Blockchain {
inner_mutex: Mutex<AnyBlockchain>,
}
impl Blockchain {
pub(crate) fn new(blockchain_config: BlockchainConfig) -> Result<Self, BdkError> {
let any_blockchain_config = match blockchain_config {
BlockchainConfig::Electrum { config } => {
AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
retry: config.retry,
socks5: config.socks5,
timeout: config.timeout,
url: config.url,
stop_gap: usize::try_from(config.stop_gap).unwrap(),
validate_domain: config.validate_domain,
})
}
BlockchainConfig::Esplora { config } => {
AnyBlockchainConfig::Esplora(EsploraBlockchainConfig {
base_url: config.base_url,
proxy: config.proxy,
concurrency: config.concurrency,
stop_gap: usize::try_from(config.stop_gap).unwrap(),
timeout: config.timeout,
})
}
BlockchainConfig::Rpc { config } => AnyBlockchainConfig::Rpc(BdkRpcConfig {
url: config.url,
auth: config.auth.into(),
network: config.network.into(),
wallet_name: config.wallet_name,
sync_params: config.sync_params.map(|p| p.into()),
}),
};
let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?;
Ok(Self {
inner_mutex: Mutex::new(blockchain),
})
}
pub(crate) fn get_blockchain(&self) -> MutexGuard<AnyBlockchain> {
self.inner_mutex.lock().expect("blockchain")
}
pub(crate) fn broadcast(&self, transaction: &Transaction) -> Result<(), BdkError> {
let tx = &transaction.inner;
self.get_blockchain().broadcast(tx)
}
pub(crate) fn estimate_fee(&self, target: u64) -> Result<Arc<FeeRate>, BdkError> {
let result: Result<FeeRate, bdk::Error> =
self.get_blockchain().estimate_fee(target as usize);
result.map(Arc::new)
}
pub(crate) fn get_height(&self) -> Result<u32, BdkError> {
self.get_blockchain().get_height()
}
pub(crate) fn get_block_hash(&self, height: u32) -> Result<String, BdkError> {
self.get_blockchain()
.get_block_hash(u64::from(height))
.map(|hash| hash.to_string())
}
}
/// Configuration for an ElectrumBlockchain
pub struct ElectrumConfig {
/// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with ssl:// or tcp:// and include a port
/// e.g. ssl://electrum.blockstream.info:60002
pub url: String,
/// URL of the socks5 proxy server or a Tor service
pub socks5: Option<String>,
/// Request retry count
pub retry: u8,
/// Request timeout (seconds)
pub timeout: Option<u8>,
/// Stop searching addresses for transactions after finding an unused gap of this length
pub stop_gap: u64,
/// Validate the domain when using SSL
pub validate_domain: bool,
}
/// Configuration for an EsploraBlockchain
pub struct EsploraConfig {
/// Base URL of the esplora service
/// e.g. https://blockstream.info/api/
pub base_url: String,
/// Optional URL of the proxy to use to make requests to the Esplora server
/// The string should be formatted as: <protocol>://<user>:<password>@host:<port>.
/// Note that the format of this value and the supported protocols change slightly between the
/// sync version of esplora (using ureq) and the async version (using reqwest). For more
/// details check with the documentation of the two crates. Both of them are compiled with
/// the socks feature enabled.
/// The proxy is ignored when targeting wasm32.
pub proxy: Option<String>,
/// Number of parallel requests sent to the esplora service (default: 4)
pub concurrency: Option<u8>,
/// Stop searching addresses for transactions after finding an unused gap of this length.
pub stop_gap: u64,
/// Socket timeout.
pub timeout: Option<u64>,
}
pub enum Auth {
/// No authentication
None,
/// Authentication with username and password, usually [Auth::Cookie] should be preferred
UserPass {
/// Username
username: String,
/// Password
password: String,
},
/// Authentication with a cookie file
Cookie {
/// Cookie file
file: String,
},
}
impl From<Auth> for BdkAuth {
fn from(auth: Auth) -> Self {
match auth {
Auth::None => BdkAuth::None,
Auth::UserPass { username, password } => BdkAuth::UserPass { username, password },
Auth::Cookie { file } => BdkAuth::Cookie {
file: PathBuf::from(file),
},
}
}
}
/// Sync parameters for Bitcoin Core RPC.
///
/// In general, BDK tries to sync `scriptPubKey`s cached in `Database` with
/// `scriptPubKey`s imported in the Bitcoin Core Wallet. These parameters are used for determining
/// how the `importdescriptors` RPC calls are to be made.
pub struct RpcSyncParams {
/// The minimum number of scripts to scan for on initial sync.
pub start_script_count: u64,
/// Time in unix seconds in which initial sync will start scanning from (0 to start from genesis).
pub start_time: u64,
/// Forces every sync to use `start_time` as import timestamp.
pub force_start_time: bool,
/// RPC poll rate (in seconds) to get state updates.
pub poll_rate_sec: u64,
}
impl From<RpcSyncParams> for BdkRpcSyncParams {
fn from(params: RpcSyncParams) -> Self {
BdkRpcSyncParams {
start_script_count: params.start_script_count as usize,
start_time: params.start_time,
force_start_time: params.force_start_time,
poll_rate_sec: params.poll_rate_sec,
}
}
}
/// RpcBlockchain configuration options
pub struct RpcConfig {
/// The bitcoin node url
pub url: String,
/// The bitcoin node authentication mechanism
pub auth: Auth,
/// The network we are using (it will be checked the bitcoin node network matches this)
pub network: Network,
/// The wallet name in the bitcoin node, consider using [crate::wallet::wallet_name_from_descriptor] for this
pub wallet_name: String,
/// Sync parameters
pub sync_params: Option<RpcSyncParams>,
}
/// Type that can contain any of the blockchain configurations defined by the library.
pub enum BlockchainConfig {
/// Electrum client
Electrum { config: ElectrumConfig },
/// Esplora client
Esplora { config: EsploraConfig },
/// Bitcoin Core RPC client
Rpc { config: RpcConfig },
}

14
bdk-ffi/src/database.rs Normal file
View File

@@ -0,0 +1,14 @@
use bdk::database::any::{SledDbConfiguration, SqliteDbConfiguration};
/// Type that can contain any of the database configurations defined by the library
/// This allows storing a single configuration that can be loaded into an AnyDatabaseConfig
/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
/// will find this particularly useful.
pub enum DatabaseConfig {
/// Memory database has no config
Memory,
/// Simple key-value embedded database based on sled
Sled { config: SledDbConfiguration },
/// Sqlite embedded database using rusqlite
Sqlite { config: SqliteDbConfiguration },
}

440
bdk-ffi/src/descriptor.rs Normal file
View File

@@ -0,0 +1,440 @@
use crate::Network;
use crate::{BdkError, DescriptorPublicKey, DescriptorSecretKey};
use bdk::bitcoin::bip32::Fingerprint;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::descriptor::{ExtendedDescriptor, IntoWalletDescriptor};
use bdk::keys::{
DescriptorPublicKey as BdkDescriptorPublicKey, DescriptorSecretKey as BdkDescriptorSecretKey,
KeyMap,
};
use bdk::template::{
Bip44, Bip44Public, Bip49, Bip49Public, Bip84, Bip84Public, Bip86, Bip86Public,
DescriptorTemplate,
};
use bdk::KeychainKind;
use std::str::FromStr;
use std::sync::Arc;
#[derive(Debug)]
pub(crate) struct Descriptor {
pub(crate) extended_descriptor: ExtendedDescriptor,
pub(crate) key_map: KeyMap,
}
impl Descriptor {
pub(crate) fn new(descriptor: String, network: Network) -> Result<Self, BdkError> {
let secp = Secp256k1::new();
let (extended_descriptor, key_map) =
descriptor.into_wallet_descriptor(&secp, network.into())?;
Ok(Self {
extended_descriptor,
key_map,
})
}
pub(crate) fn new_bip44(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip44(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip44_public(
public_key: Arc<DescriptorPublicKey>,
fingerprint: String,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = &public_key.inner;
match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) =
Bip44Public(derivable_key, fingerprint, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip49(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip49(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip49_public(
public_key: Arc<DescriptorPublicKey>,
fingerprint: String,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = &public_key.inner;
match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) =
Bip49Public(derivable_key, fingerprint, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip84(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip84(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip84_public(
public_key: Arc<DescriptorPublicKey>,
fingerprint: String,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = &public_key.inner;
match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) =
Bip84Public(derivable_key, fingerprint, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86(
secret_key: Arc<DescriptorSecretKey>,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let derivable_key = &secret_key.inner;
match derivable_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) = Bip86(derivable_key, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
}
}
pub(crate) fn new_bip86_public(
public_key: Arc<DescriptorPublicKey>,
fingerprint: String,
keychain_kind: KeychainKind,
network: Network,
) -> Self {
let fingerprint = Fingerprint::from_str(fingerprint.as_str()).unwrap();
let derivable_key = &public_key.inner;
match derivable_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derivable_key = descriptor_x_key.xkey;
let (extended_descriptor, key_map, _) =
Bip86Public(derivable_key, fingerprint, keychain_kind)
.build(network.into())
.unwrap();
Self {
extended_descriptor,
key_map,
}
}
BdkDescriptorPublicKey::Single(_) => {
unreachable!()
}
BdkDescriptorPublicKey::MultiXPub(_) => {
unreachable!()
}
}
}
pub(crate) fn as_string_private(&self) -> String {
let descriptor = &self.extended_descriptor;
let key_map = &self.key_map;
descriptor.to_string_with_secret(key_map)
}
pub(crate) fn as_string(&self) -> String {
self.extended_descriptor.to_string()
}
}
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
// crate.
#[cfg(test)]
mod test {
use crate::database::DatabaseConfig;
use crate::*;
use assert_matches::assert_matches;
use bdk::descriptor::DescriptorError::Key;
use bdk::keys::KeyError::InvalidNetwork;
fn get_descriptor_secret_key() -> DescriptorSecretKey {
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None)
}
#[test]
fn test_descriptor_templates() {
let master: Arc<DescriptorSecretKey> = Arc::new(get_descriptor_secret_key());
println!("Master: {:?}", master.as_string());
// tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h
let handmade_public_44 = master
.derive(Arc::new(
DerivationPath::new("m/44h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 44: {}", handmade_public_44.as_string());
// Public 44: [d1d04177/44'/1'/0']tpubDCoPjomfTqh1e7o1WgGpQtARWtkueXQAepTeNpWiitS3Sdv8RKJ1yvTrGHcwjDXp2SKyMrTEca4LoN7gEUiGCWboyWe2rz99Kf4jK4m2Zmx/*
let handmade_public_49 = master
.derive(Arc::new(
DerivationPath::new("m/49h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 49: {}", handmade_public_49.as_string());
// Public 49: [d1d04177/49'/1'/0']tpubDC65ZRvk1NDddHrVAUAZrUPJ772QXzooNYmPywYF9tMyNLYKf5wpKE7ZJvK9kvfG3FV7rCsHBNXy1LVKW95jrmC7c7z4hq7a27aD2sRrAhR/*
let handmade_public_84 = master
.derive(Arc::new(
DerivationPath::new("m/84h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 84: {}", handmade_public_84.as_string());
// Public 84: [d1d04177/84'/1'/0']tpubDDNxbq17egjFk2edjv8oLnzxk52zny9aAYNv9CMqTzA4mQDiQq818sEkNe9Gzmd4QU8558zftqbfoVBDQorG3E4Wq26tB2JeE4KUoahLkx6/*
let handmade_public_86 = master
.derive(Arc::new(
DerivationPath::new("m/86h/1h/0h".to_string()).unwrap(),
))
.unwrap()
.as_public();
println!("Public 86: {}", handmade_public_86.as_string());
// Public 86: [d1d04177/86'/1'/0']tpubDCJzjbcGbdEfXMWaL6QmgVmuSfXkrue7m2YNoacWwyc7a2XjXaKojRqNEbo41CFL3PyYmKdhwg2fkGpLX4SQCbQjCGxAkWHJTw9WEeenrJb/*
let template_private_44 =
Descriptor::new_bip44(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_49 =
Descriptor::new_bip49(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_84 =
Descriptor::new_bip84(master.clone(), KeychainKind::External, Network::Testnet);
let template_private_86 =
Descriptor::new_bip86(master, KeychainKind::External, Network::Testnet);
// the extended public keys are the same when creating them manually as they are with the templates
println!("Template 49: {}", template_private_49.as_string());
println!("Template 44: {}", template_private_44.as_string());
println!("Template 84: {}", template_private_84.as_string());
println!("Template 86: {}", template_private_86.as_string());
let template_public_44 = Descriptor::new_bip44_public(
handmade_public_44,
"d1d04177".to_string(),
KeychainKind::External,
Network::Testnet,
);
let template_public_49 = Descriptor::new_bip49_public(
handmade_public_49,
"d1d04177".to_string(),
KeychainKind::External,
Network::Testnet,
);
let template_public_84 = Descriptor::new_bip84_public(
handmade_public_84,
"d1d04177".to_string(),
KeychainKind::External,
Network::Testnet,
);
let template_public_86 = Descriptor::new_bip86_public(
handmade_public_86,
"d1d04177".to_string(),
KeychainKind::External,
Network::Testnet,
);
println!("Template public 49: {}", template_public_49.as_string());
println!("Template public 44: {}", template_public_44.as_string());
println!("Template public 84: {}", template_public_84.as_string());
println!("Template public 86: {}", template_public_86.as_string());
// when using a public key, both as_string and as_string_private return the same string
assert_eq!(
template_public_44.as_string_private(),
template_public_44.as_string()
);
assert_eq!(
template_public_49.as_string_private(),
template_public_49.as_string()
);
assert_eq!(
template_public_84.as_string_private(),
template_public_84.as_string()
);
assert_eq!(
template_public_86.as_string_private(),
template_public_86.as_string()
);
// when using as_string on a private key, we get the same result as when using it on a public key
assert_eq!(
template_private_44.as_string(),
template_public_44.as_string()
);
assert_eq!(
template_private_49.as_string(),
template_public_49.as_string()
);
assert_eq!(
template_private_84.as_string(),
template_public_84.as_string()
);
assert_eq!(
template_private_86.as_string(),
template_public_86.as_string()
);
}
#[test]
fn test_descriptor_from_string() {
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet);
let descriptor2 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Bitcoin);
// Creating a Descriptor using an extended key that doesn't match the network provided will throw and InvalidNetwork Error
assert!(descriptor1.is_ok());
assert_matches!(
descriptor2.unwrap_err(),
bdk::Error::Descriptor(Key(InvalidNetwork))
)
}
#[test]
fn test_wallet_from_descriptor() {
let descriptor1 = Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap();
let wallet1 = Wallet::new(
Arc::new(Descriptor::new("wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)".to_string(), Network::Testnet).unwrap()),
None,
Network::Testnet,
DatabaseConfig::Memory
);
let wallet2 = Wallet::new(
Arc::new(descriptor1),
None,
Network::Bitcoin,
DatabaseConfig::Memory,
);
// Creating a wallet using a Descriptor with an extended key that doesn't match the network provided in the wallet constructor will throw and InvalidNetwork Error
assert!(wallet1.is_ok());
assert_matches!(
wallet2.unwrap_err(),
bdk::Error::Descriptor(Key(InvalidNetwork))
)
}
}

375
bdk-ffi/src/keys.rs Normal file
View File

@@ -0,0 +1,375 @@
use crate::BdkError;
use crate::Network;
use bdk::bitcoin::bip32::DerivationPath as BdkDerivationPath;
use bdk::bitcoin::secp256k1::Secp256k1;
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
use bdk::keys::{
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
};
use bdk::miniscript::descriptor::{DescriptorXKey, Wildcard};
use bdk::miniscript::BareCtx;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
/// Mnemonic phrases are a human-readable version of the private keys.
/// Supported number of words are 12, 15, 18, 21 and 24.
pub(crate) struct Mnemonic {
inner: BdkMnemonic,
}
impl Mnemonic {
/// Generates Mnemonic with a random entropy
pub(crate) fn new(word_count: WordCount) -> Self {
let generated_key: GeneratedKey<_, BareCtx> =
BdkMnemonic::generate((word_count, Language::English)).unwrap();
let mnemonic = BdkMnemonic::parse_in(Language::English, generated_key.to_string()).unwrap();
Mnemonic { inner: mnemonic }
}
/// Parse a Mnemonic with given string
pub(crate) fn from_string(mnemonic: String) -> Result<Self, BdkError> {
BdkMnemonic::from_str(&mnemonic)
.map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
/// Create a new Mnemonic in the specified language from the given entropy.
/// Entropy must be a multiple of 32 bits (4 bytes) and 128-256 bits in length.
pub(crate) fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
BdkMnemonic::from_entropy(entropy.as_slice())
.map(|m| Mnemonic { inner: m })
.map_err(|e| BdkError::Generic(e.to_string()))
}
/// Returns Mnemonic as string
pub(crate) fn as_string(&self) -> String {
self.inner.to_string()
}
}
pub(crate) struct DerivationPath {
inner_mutex: Mutex<BdkDerivationPath>,
}
impl DerivationPath {
pub(crate) fn new(path: String) -> Result<Self, BdkError> {
BdkDerivationPath::from_str(&path)
.map(|x| DerivationPath {
inner_mutex: Mutex::new(x),
})
.map_err(|e| BdkError::Generic(e.to_string()))
}
}
#[derive(Debug)]
pub(crate) struct DescriptorSecretKey {
pub(crate) inner: BdkDescriptorSecretKey,
}
impl DescriptorSecretKey {
pub(crate) fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
let mnemonic = mnemonic.inner.clone();
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: None,
xkey: xkey.into_xprv(network.into()).unwrap(),
derivation_path: BdkDerivationPath::master(),
wildcard: Wildcard::Unhardened,
});
Self {
inner: descriptor_secret_key,
}
}
pub(crate) fn from_string(private_key: String) -> Result<Self, BdkError> {
let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self {
inner: descriptor_secret_key,
})
}
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let derived_xprv = descriptor_x_key.xkey.derive_priv(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(&secp), path),
};
let derived_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: Some(key_source),
xkey: derived_xprv,
derivation_path: BdkDerivationPath::default(),
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
inner: derived_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(),
)),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
}
}
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_secret_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_secret_key {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
origin: descriptor_x_key.origin.clone(),
xkey: descriptor_x_key.xkey,
derivation_path: extended_path,
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
inner: extended_descriptor_secret_key,
}))
}
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(),
)),
BdkDescriptorSecretKey::MultiXPrv(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
}
}
pub(crate) fn as_public(&self) -> Arc<DescriptorPublicKey> {
let secp = Secp256k1::new();
let descriptor_public_key = self.inner.to_public(&secp).unwrap();
Arc::new(DescriptorPublicKey {
inner: descriptor_public_key,
})
}
/// Get the private key as bytes.
pub(crate) fn secret_bytes(&self) -> Vec<u8> {
let inner = &self.inner;
let secret_bytes: Vec<u8> = match inner {
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
}
BdkDescriptorSecretKey::Single(_) => {
unreachable!()
}
BdkDescriptorSecretKey::MultiXPrv(_) => {
unreachable!()
}
};
secret_bytes
}
pub(crate) fn as_string(&self) -> String {
self.inner.to_string()
}
}
#[derive(Debug)]
pub(crate) struct DescriptorPublicKey {
pub(crate) inner: BdkDescriptorPublicKey,
}
impl DescriptorPublicKey {
pub(crate) fn from_string(public_key: String) -> Result<Self, BdkError> {
let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Self {
inner: descriptor_public_key,
})
}
pub(crate) fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let secp = Secp256k1::new();
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let derived_xpub = descriptor_x_key.xkey.derive_pub(&secp, &path)?;
let key_source = match descriptor_x_key.origin.clone() {
Some((fingerprint, origin_path)) => (fingerprint, origin_path.extend(path)),
None => (descriptor_x_key.xkey.fingerprint(), path),
};
let derived_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
origin: Some(key_source),
xkey: derived_xpub,
derivation_path: BdkDerivationPath::default(),
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
inner: derived_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot derive from a single key".to_string(),
)),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot derive from a multi key".to_string(),
)),
}
}
pub(crate) fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
let descriptor_public_key = &self.inner;
let path = path.inner_mutex.lock().unwrap().deref().clone();
match descriptor_public_key {
BdkDescriptorPublicKey::XPub(descriptor_x_key) => {
let extended_path = descriptor_x_key.derivation_path.extend(path);
let extended_descriptor_public_key = BdkDescriptorPublicKey::XPub(DescriptorXKey {
origin: descriptor_x_key.origin.clone(),
xkey: descriptor_x_key.xkey,
derivation_path: extended_path,
wildcard: descriptor_x_key.wildcard,
});
Ok(Arc::new(Self {
inner: extended_descriptor_public_key,
}))
}
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
"Cannot extend from a single key".to_string(),
)),
BdkDescriptorPublicKey::MultiXPub(_) => Err(BdkError::Generic(
"Cannot extend from a multi key".to_string(),
)),
}
}
pub(crate) fn as_string(&self) -> String {
self.inner.to_string()
}
}
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
// crate.
#[cfg(test)]
mod test {
use crate::keys::{DerivationPath, DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::BdkError;
use crate::Network;
use std::sync::Arc;
fn get_inner() -> DescriptorSecretKey {
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None)
}
fn derive_dsk(
key: &DescriptorSecretKey,
path: &str,
) -> Result<Arc<DescriptorSecretKey>, BdkError> {
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
key.derive(path)
}
fn extend_dsk(
key: &DescriptorSecretKey,
path: &str,
) -> Result<Arc<DescriptorSecretKey>, BdkError> {
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
key.extend(path)
}
fn derive_dpk(
key: &DescriptorPublicKey,
path: &str,
) -> Result<Arc<DescriptorPublicKey>, BdkError> {
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
key.derive(path)
}
fn extend_dpk(
key: &DescriptorPublicKey,
path: &str,
) -> Result<Arc<DescriptorPublicKey>, BdkError> {
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
key.extend(path)
}
#[test]
fn test_generate_descriptor_secret_key() {
let master_dsk = get_inner();
assert_eq!(master_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
assert_eq!(master_dsk.as_public().as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
}
#[test]
fn test_derive_self() {
let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177]tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
let derived_dpk: &DescriptorPublicKey = &derive_dpk(master_dpk, "m").unwrap();
assert_eq!(derived_dpk.as_string(), "[d1d04177]tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/*");
}
#[test]
fn test_derive_descriptors_keys() {
let master_dsk = get_inner();
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
let derived_dpk: &DescriptorPublicKey = &derive_dpk(master_dpk, "m/0").unwrap();
assert_eq!(derived_dpk.as_string(), "[d1d04177/0]tpubD9oaCiP1MPmQdndm7DCD3D3QU34pWd6BbKSRedoZF1UJcNhEk3PJwkALNYkhxeTKL29oGNR7psqvT1KZydCGqUDEKXN6dVQJY2R8ooLPy8m/*");
}
#[test]
fn test_extend_descriptor_keys() {
let master_dsk = get_inner();
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
let extended_dpk: &DescriptorPublicKey = &extend_dpk(master_dpk, "m/0").unwrap();
assert_eq!(extended_dpk.as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*");
let wif = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
let extended_key = DescriptorSecretKey::from_string(wif.to_string()).unwrap();
let result = extended_key.derive(Arc::new(DerivationPath::new("m/0".to_string()).unwrap()));
dbg!(&result);
assert!(result.is_err());
}
#[test]
fn test_from_str_inner() {
let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
let private_descriptor_key2 = DescriptorSecretKey::from_string(key2.to_string()).unwrap();
dbg!(private_descriptor_key1);
dbg!(private_descriptor_key2);
// Should error out because you can't produce a DescriptorSecretKey from an xpub
let key0 = "tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi";
assert!(DescriptorSecretKey::from_string(key0.to_string()).is_err());
}
#[test]
fn test_derive_and_extend_inner() {
let master_dsk = get_inner();
// derive DescriptorSecretKey with path "m/0" from master
let derived_dsk: &DescriptorSecretKey = &derive_dsk(&master_dsk, "m/0").unwrap();
assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
// extend derived_dsk with path "m/0"
let extended_dsk: &DescriptorSecretKey = &extend_dsk(derived_dsk, "m/0").unwrap();
assert_eq!(extended_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
}
#[test]
fn test_derive_hardened_path_using_public() {
let master_dpk = get_inner().as_public();
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
assert!(derived_dpk.is_err());
}
}

544
bdk-ffi/src/lib.rs Normal file
View File

@@ -0,0 +1,544 @@
mod blockchain;
mod database;
mod descriptor;
mod keys;
mod psbt;
mod wallet;
use crate::blockchain::{
Auth, Blockchain, BlockchainConfig, ElectrumConfig, EsploraConfig, RpcConfig, RpcSyncParams,
};
use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor;
use crate::keys::DerivationPath;
use crate::keys::{DescriptorPublicKey, DescriptorSecretKey, Mnemonic};
use crate::psbt::PartiallySignedTransaction;
use crate::wallet::SignOptions;
use crate::wallet::{BumpFeeTxBuilder, TxBuilder, Wallet};
use bdk::bitcoin::address::{NetworkUnchecked, Payload as BdkPayload, WitnessVersion};
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::blockdata::transaction::TxIn as BdkTxIn;
use bdk::bitcoin::blockdata::transaction::TxOut as BdkTxOut;
use bdk::bitcoin::consensus::encode::serialize;
use bdk::bitcoin::consensus::Decodable;
use bdk::bitcoin::network::constants::Network as BdkNetwork;
use bdk::bitcoin::{
Address as BdkAddress, OutPoint as BdkOutPoint, Transaction as BdkTransaction, Txid,
};
use bdk::blockchain::Progress as BdkProgress;
use bdk::database::any::SledDbConfiguration;
use bdk::database::any::SqliteDbConfiguration;
use bdk::keys::bip39::WordCount;
use bdk::wallet::AddressIndex as BdkAddressIndex;
use bdk::wallet::AddressInfo as BdkAddressInfo;
use bdk::LocalUtxo as BdkLocalUtxo;
use bdk::TransactionDetails as BdkTransactionDetails;
use bdk::{Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind};
use std::convert::From;
use std::fmt;
use std::fmt::Debug;
use std::io::Cursor;
use std::str::FromStr;
use std::sync::Arc;
uniffi::include_scaffolding!("bdk");
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Script(pub(crate) BdkScriptBuf);
impl Script {
pub fn new(raw_output_script: Vec<u8>) -> Self {
let script: BdkScriptBuf = raw_output_script.into();
Script(script)
}
pub fn to_bytes(&self) -> Vec<u8> {
self.0.to_bytes()
}
}
impl From<BdkScriptBuf> for Script {
fn from(script: BdkScriptBuf) -> Self {
Script(script)
}
}
/// A output script and an amount of satoshis.
pub struct ScriptAmount {
pub script: Arc<Script>,
pub amount: u64,
}
/// A derived address and the index it was found at.
pub struct AddressInfo {
/// Child index of this address.
pub index: u32,
/// Address.
pub address: Arc<Address>,
/// Type of keychain.
pub keychain: KeychainKind,
}
impl From<BdkAddressInfo> for AddressInfo {
fn from(address_info: BdkAddressInfo) -> Self {
AddressInfo {
index: address_info.index,
address: Arc::new(Address::from(address_info.address)),
keychain: address_info.keychain,
}
}
}
/// The address index selection strategy to use to derived an address from the wallet's external
/// descriptor.
pub enum AddressIndex {
/// Return a new address after incrementing the current descriptor index.
New,
/// Return the address for the current descriptor index if it has not been used in a received
/// transaction. Otherwise return a new address as with AddressIndex::New.
/// Use with caution, if the wallet has not yet detected an address has been used it could
/// return an already used address. This function is primarily meant for situations where the
/// caller is untrusted; for example when deriving donation addresses on-demand for a public
/// web page.
LastUnused,
/// Return the address for a specific descriptor index. Does not change the current descriptor
/// index used by `AddressIndex::New` and `AddressIndex::LastUsed`.
/// Use with caution, if an index is given that is less than the current descriptor index
/// then the returned address may have already been used.
Peek { index: u32 },
/// Return the address for a specific descriptor index and reset the current descriptor index
/// used by `AddressIndex::New` and `AddressIndex::LastUsed` to this value.
/// Use with caution, if an index is given that is less than the current descriptor index
/// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
/// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
/// value earlier than the [`Blockchain`] stop_gap (default is 20) then a
/// larger stop_gap should be used to monitor for all possibly used addresses.
Reset { index: u32 },
}
impl From<AddressIndex> for BdkAddressIndex {
fn from(address_index: AddressIndex) -> Self {
match address_index {
AddressIndex::New => BdkAddressIndex::New,
AddressIndex::LastUnused => BdkAddressIndex::LastUnused,
AddressIndex::Peek { index } => BdkAddressIndex::Peek(index),
AddressIndex::Reset { index } => BdkAddressIndex::Reset(index),
}
}
}
/// A wallet transaction
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct TransactionDetails {
pub transaction: Option<Arc<Transaction>>,
/// Transaction id.
pub txid: String,
/// Received value (sats)
/// Sum of owned outputs of this transaction.
pub received: u64,
/// Sent value (sats)
/// Sum of owned inputs of this transaction.
pub sent: u64,
/// Fee value (sats) if confirmed.
/// The availability of the fee depends on the backend. It's never None with an Electrum
/// Server backend, but it could be None with a Bitcoin RPC node without txindex that receive
/// funds while offline.
pub fee: Option<u64>,
/// If the transaction is confirmed, contains height and timestamp of the block containing the
/// transaction, unconfirmed transaction contains `None`.
pub confirmation_time: Option<BlockTime>,
}
impl From<BdkTransactionDetails> for TransactionDetails {
fn from(tx_details: BdkTransactionDetails) -> Self {
let optional_tx: Option<Arc<Transaction>> =
tx_details.transaction.map(|tx| Arc::new(tx.into()));
TransactionDetails {
transaction: optional_tx,
fee: tx_details.fee,
txid: tx_details.txid.to_string(),
received: tx_details.received,
sent: tx_details.sent,
confirmation_time: tx_details.confirmation_time,
}
}
}
/// A reference to a transaction output.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct OutPoint {
/// The referenced transaction's txid.
txid: String,
/// The index of the referenced output in its transaction's vout.
vout: u32,
}
impl From<&OutPoint> for BdkOutPoint {
fn from(outpoint: &OutPoint) -> Self {
BdkOutPoint {
txid: Txid::from_str(&outpoint.txid).unwrap(),
vout: outpoint.vout,
}
}
}
pub struct Balance {
// All coinbase outputs not yet matured
pub immature: u64,
/// Unconfirmed UTXOs generated by a wallet tx
pub trusted_pending: u64,
/// Unconfirmed UTXOs received from an external wallet
pub untrusted_pending: u64,
/// Confirmed and immediately spendable balance
pub confirmed: u64,
/// Get sum of trusted_pending and confirmed coins
pub spendable: u64,
/// Get the whole balance visible to the wallet
pub total: u64,
}
impl From<BdkBalance> for Balance {
fn from(bdk_balance: BdkBalance) -> Self {
Balance {
immature: bdk_balance.immature,
trusted_pending: bdk_balance.trusted_pending,
untrusted_pending: bdk_balance.untrusted_pending,
confirmed: bdk_balance.confirmed,
spendable: bdk_balance.get_spendable(),
total: bdk_balance.get_total(),
}
}
}
/// A transaction output, which defines new coins to be created from old ones.
#[derive(Debug, Clone)]
pub struct TxOut {
/// The value of the output, in satoshis.
value: u64,
/// The address of the output.
script_pubkey: Arc<Script>,
}
impl From<&BdkTxOut> for TxOut {
fn from(tx_out: &BdkTxOut) -> Self {
TxOut {
value: tx_out.value,
script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
}
}
}
pub struct LocalUtxo {
outpoint: OutPoint,
txout: TxOut,
keychain: KeychainKind,
is_spent: bool,
}
impl From<BdkLocalUtxo> for LocalUtxo {
fn from(local_utxo: BdkLocalUtxo) -> Self {
LocalUtxo {
outpoint: OutPoint {
txid: local_utxo.outpoint.txid.to_string(),
vout: local_utxo.outpoint.vout,
},
txout: TxOut {
value: local_utxo.txout.value,
script_pubkey: Arc::new(Script(local_utxo.txout.script_pubkey)),
},
keychain: local_utxo.keychain,
is_spent: local_utxo.is_spent,
}
}
}
/// Trait that logs at level INFO every update received (if any).
pub trait Progress: Send + Sync + 'static {
/// Send a new progress update. The progress value should be in the range 0.0 - 100.0, and the message value is an
/// optional text message that can be displayed to the user.
fn update(&self, progress: f32, message: Option<String>);
}
struct ProgressHolder {
progress: Box<dyn Progress>,
}
impl BdkProgress for ProgressHolder {
fn update(&self, progress: f32, message: Option<String>) -> Result<(), BdkError> {
self.progress.update(progress, message);
Ok(())
}
}
impl Debug for ProgressHolder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ProgressHolder").finish_non_exhaustive()
}
}
#[derive(Debug, Clone)]
pub struct TxIn {
pub previous_output: OutPoint,
pub script_sig: Arc<Script>,
pub sequence: u32,
pub witness: Vec<Vec<u8>>,
}
impl From<&BdkTxIn> for TxIn {
fn from(tx_in: &BdkTxIn) -> Self {
TxIn {
previous_output: OutPoint {
txid: tx_in.previous_output.txid.to_string(),
vout: tx_in.previous_output.vout,
},
script_sig: Arc::new(Script(tx_in.script_sig.clone())),
sequence: tx_in.sequence.0,
witness: tx_in.witness.to_vec(),
}
}
}
/// A Bitcoin transaction.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Transaction {
inner: BdkTransaction,
}
impl Transaction {
fn new(transaction_bytes: Vec<u8>) -> Result<Self, BdkError> {
let mut decoder = Cursor::new(transaction_bytes);
let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
Ok(Transaction { inner: tx })
}
fn txid(&self) -> String {
self.inner.txid().to_string()
}
fn weight(&self) -> u64 {
self.inner.weight().to_wu()
}
fn size(&self) -> u64 {
self.inner.size() as u64
}
fn vsize(&self) -> u64 {
self.inner.vsize() as u64
}
fn serialize(&self) -> Vec<u8> {
serialize(&self.inner)
}
fn is_coin_base(&self) -> bool {
self.inner.is_coin_base()
}
fn is_explicitly_rbf(&self) -> bool {
self.inner.is_explicitly_rbf()
}
fn is_lock_time_enabled(&self) -> bool {
self.inner.is_lock_time_enabled()
}
fn version(&self) -> i32 {
self.inner.version
}
fn lock_time(&self) -> u32 {
self.inner.lock_time.to_consensus_u32()
}
fn input(&self) -> Vec<TxIn> {
self.inner.input.iter().map(|x| x.into()).collect()
}
fn output(&self) -> Vec<TxOut> {
self.inner.output.iter().map(|x| x.into()).collect()
}
}
impl From<BdkTransaction> for Transaction {
fn from(tx: BdkTransaction) -> Self {
Transaction { inner: tx }
}
}
/// A Bitcoin address.
#[derive(Debug, PartialEq, Eq)]
pub struct Address {
inner: BdkAddress,
}
impl Address {
pub fn new(address: String, network: Network) -> Result<Self, BdkError> {
let parsed_address = address
.parse::<bdk::bitcoin::Address<NetworkUnchecked>>()
.map_err(|e| BdkError::Generic(e.to_string()))?;
let network_checked_address = parsed_address
.require_network(network.into())
.map_err(|e| BdkError::Generic(e.to_string()))?;
Ok(Address {
inner: network_checked_address,
})
}
/// alternative constructor
fn from_script(script: Arc<Script>, network: Network) -> Result<Self, BdkError> {
BdkAddress::from_script(&script.0, network.into())
.map(|a| Address { inner: a })
.map_err(|e| BdkError::Generic(e.to_string()))
}
fn payload(&self) -> Payload {
match &self.inner.payload.clone() {
BdkPayload::PubkeyHash(pubkey_hash) => Payload::PubkeyHash {
pubkey_hash: pubkey_hash.to_string(),
},
BdkPayload::ScriptHash(script_hash) => Payload::ScriptHash {
script_hash: script_hash.to_string(),
},
BdkPayload::WitnessProgram(witness_program) => Payload::WitnessProgram {
version: witness_program.version(),
program: Vec::from(witness_program.program().as_bytes()),
},
_ => panic!("Unsupported address payload type"),
}
}
fn network(&self) -> Network {
self.inner.network.into()
}
fn script_pubkey(&self) -> Arc<Script> {
Arc::new(Script(self.inner.script_pubkey()))
}
fn to_qr_uri(&self) -> String {
self.inner.to_qr_uri()
}
pub fn is_valid_for_network(&self, network: Network) -> bool {
let address_str = self.inner.to_string();
if let Ok(unchecked_address) = address_str.parse::<BdkAddress<NetworkUnchecked>>() {
unchecked_address.is_valid_for_network(network.into())
} else {
false
}
}
fn as_string(&self) -> String {
self.inner.to_string()
}
}
impl From<BdkAddress> for Address {
fn from(address: BdkAddress) -> Self {
Address { inner: address }
}
}
/// The method used to produce an address.
#[derive(Debug)]
pub enum Payload {
/// P2PKH address.
PubkeyHash { pubkey_hash: String },
/// P2SH address.
ScriptHash { script_hash: String },
/// Segwit address.
WitnessProgram {
/// The witness program version.
version: WitnessVersion,
/// The witness program.
program: Vec<u8>,
},
}
#[derive(Clone, Debug)]
enum RbfValue {
Default,
Value(u32),
}
/// The result after calling the TxBuilder finish() function. Contains unsigned PSBT and
/// transaction details.
pub struct TxBuilderResult {
pub(crate) psbt: Arc<PartiallySignedTransaction>,
pub transaction_details: TransactionDetails,
}
#[derive(PartialEq, Debug)]
pub enum Network {
Bitcoin,
Testnet,
Signet,
Regtest,
}
impl From<Network> for BdkNetwork {
fn from(network: Network) -> Self {
match network {
Network::Bitcoin => BdkNetwork::Bitcoin,
Network::Testnet => BdkNetwork::Testnet,
Network::Signet => BdkNetwork::Signet,
Network::Regtest => BdkNetwork::Regtest,
}
}
}
impl From<BdkNetwork> for Network {
fn from(network: BdkNetwork) -> Self {
match network {
BdkNetwork::Bitcoin => Network::Bitcoin,
BdkNetwork::Testnet => Network::Testnet,
BdkNetwork::Signet => Network::Signet,
BdkNetwork::Regtest => Network::Regtest,
_ => panic!("Network {} not supported", network),
}
}
}
uniffi::deps::static_assertions::assert_impl_all!(Wallet: Sync, Send);
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
// crate.
#[cfg(test)]
mod test {
use crate::Network::Regtest;
use crate::{Address, Payload};
use assert_matches::assert_matches;
use bdk::bitcoin::address::WitnessVersion;
use bdk::bitcoin::hashes::hex::FromHex;
use bdk::bitcoin::Network;
// Verify that bdk-ffi Transaction can be created from valid bytes and serialized back into the same bytes.
// #[test]
// fn test_transaction_serde() {
// let test_tx_bytes = Vec::from_hex("020000000001031cfbc8f54fbfa4a33a30068841371f80dbfe166211242213188428f437445c91000000006a47304402206fbcec8d2d2e740d824d3d36cc345b37d9f65d665a99f5bd5c9e8d42270a03a8022013959632492332200c2908459547bf8dbf97c65ab1a28dec377d6f1d41d3d63e012103d7279dfb90ce17fe139ba60a7c41ddf605b25e1c07a4ddcb9dfef4e7d6710f48feffffff476222484f5e35b3f0e43f65fc76e21d8be7818dd6a989c160b1e5039b7835fc00000000171600140914414d3c94af70ac7e25407b0689e0baa10c77feffffffa83d954a62568bbc99cc644c62eb7383d7c2a2563041a0aeb891a6a4055895570000000017160014795d04cc2d4f31480d9a3710993fbd80d04301dffeffffff06fef72f000000000017a91476fd7035cd26f1a32a5ab979e056713aac25796887a5000f00000000001976a914b8332d502a529571c6af4be66399cd33379071c588ac3fda0500000000001976a914fc1d692f8de10ae33295f090bea5fe49527d975c88ac522e1b00000000001976a914808406b54d1044c429ac54c0e189b0d8061667e088ac6eb68501000000001976a914dfab6085f3a8fb3e6710206a5a959313c5618f4d88acbba20000000000001976a914eb3026552d7e3f3073457d0bee5d4757de48160d88ac0002483045022100bee24b63212939d33d513e767bc79300051f7a0d433c3fcf1e0e3bf03b9eb1d70220588dc45a9ce3a939103b4459ce47500b64e23ab118dfc03c9caa7d6bfc32b9c601210354fd80328da0f9ae6eef2b3a81f74f9a6f66761fadf96f1d1d22b1fd6845876402483045022100e29c7e3a5efc10da6269e5fc20b6a1cb8beb92130cc52c67e46ef40aaa5cac5f0220644dd1b049727d991aece98a105563416e10a5ac4221abac7d16931842d5c322012103960b87412d6e169f30e12106bdf70122aabb9eb61f455518322a18b920a4dfa887d30700").unwrap();
// let new_tx_from_bytes = Transaction::new(test_tx_bytes.clone()).unwrap();
// let serialized_tx_to_bytes = new_tx_from_bytes.serialize();
// assert_eq!(test_tx_bytes, serialized_tx_to_bytes);
// }
// Verify that bdk-ffi Address.payload includes expected WitnessProgram variant, version and program bytes.
#[test]
fn test_address_witness_program() {
let address = Address::new(
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv".to_string(),
Network::Regtest.into(),
)
.unwrap();
let payload = address.payload();
assert_matches!(payload, Payload::WitnessProgram { version, program } => {
assert_eq!(version, WitnessVersion::V0);
assert_eq!(program, Vec::from_hex("04a6545885dd87b8e147cd327f2e9db362b72346").unwrap());
});
assert_eq!(address.network(), Regtest);
}
}

119
bdk-ffi/src/psbt.rs Normal file
View File

@@ -0,0 +1,119 @@
use bdk::bitcoin::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
use bdk::bitcoincore_rpc::jsonrpc::serde_json;
use bdk::psbt::PsbtUtils;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use crate::{BdkError, FeeRate, Transaction};
#[derive(Debug)]
pub(crate) struct PartiallySignedTransaction {
pub(crate) inner: Mutex<BdkPartiallySignedTransaction>,
}
impl PartiallySignedTransaction {
pub(crate) fn new(psbt_base64: String) -> Result<Self, BdkError> {
let psbt: BdkPartiallySignedTransaction =
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
Ok(PartiallySignedTransaction {
inner: Mutex::new(psbt),
})
}
pub(crate) fn serialize(&self) -> String {
let psbt = self.inner.lock().unwrap().clone();
psbt.to_string()
}
pub(crate) fn txid(&self) -> String {
let tx = self.inner.lock().unwrap().clone().extract_tx();
let txid = tx.txid();
txid.to_string()
}
/// Return the transaction.
pub(crate) fn extract_tx(&self) -> Arc<Transaction> {
let tx = self.inner.lock().unwrap().clone().extract_tx();
Arc::new(tx.into())
}
/// Combines this PartiallySignedTransaction with other PSBT as described by BIP 174.
///
/// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
pub(crate) fn combine(
&self,
other: Arc<PartiallySignedTransaction>,
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let other_psbt = other.inner.lock().unwrap().clone();
let mut original_psbt = self.inner.lock().unwrap().clone();
original_psbt.combine(other_psbt)?;
Ok(Arc::new(PartiallySignedTransaction {
inner: Mutex::new(original_psbt),
}))
}
/// The total transaction fee amount, sum of input amounts minus sum of output amounts, in Sats.
/// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_amount(&self) -> Option<u64> {
self.inner.lock().unwrap().fee_amount()
}
/// The transaction's fee rate. This value will only be accurate if calculated AFTER the
/// `PartiallySignedTransaction` is finalized and all witness/signature data is added to the
/// transaction.
/// If the PSBT is missing a TxOut for an input returns None.
pub(crate) fn fee_rate(&self) -> Option<Arc<FeeRate>> {
self.inner.lock().unwrap().fee_rate().map(Arc::new)
}
/// Serialize the PSBT data structure as a String of JSON.
pub(crate) fn json_serialize(&self) -> String {
let psbt = self.inner.lock().unwrap();
serde_json::to_string(psbt.deref()).unwrap()
}
}
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
// crate.
#[cfg(test)]
mod test {
use crate::wallet::{TxBuilder, Wallet};
use crate::Network;
use bdk::wallet::get_funded_wallet;
use std::sync::Mutex;
#[test]
fn test_psbt_fee() {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet {
inner_mutex: Mutex::new(funded_wallet),
};
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap()
.script_pubkey();
let tx_builder = TxBuilder::new()
.fee_rate(2.0)
.drain_wallet()
.drain_to(drain_to_script.clone());
//dbg!(&tx_builder);
assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
assert!(tx_builder_result.psbt.fee_rate().is_some());
assert_eq!(
tx_builder_result.psbt.fee_rate().unwrap().as_sat_per_vb(),
2.682927
);
assert!(tx_builder_result.psbt.fee_amount().is_some());
assert_eq!(tx_builder_result.psbt.fee_amount().unwrap(), 220);
}
}

865
bdk-ffi/src/wallet.rs Normal file
View File

@@ -0,0 +1,865 @@
use bdk::bitcoin::blockdata::script::ScriptBuf as BdkScriptBuf;
use bdk::bitcoin::script::PushBytesBuf;
use bdk::bitcoin::{OutPoint as BdkOutPoint, Sequence, Txid};
use bdk::database::any::AnyDatabase;
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
use bdk::wallet::tx_builder::ChangeSpendPolicy;
use bdk::{
FeeRate, LocalUtxo as BdkLocalUtxo, SignOptions as BdkSignOptions,
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
};
use std::collections::HashSet;
use std::convert::TryFrom;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::{Arc, Mutex, MutexGuard};
use crate::blockchain::Blockchain;
use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor;
use crate::psbt::PartiallySignedTransaction;
use crate::Network;
use crate::{
AddressIndex, AddressInfo, Balance, BdkError, LocalUtxo, OutPoint, Progress, ProgressHolder,
RbfValue, Script, ScriptAmount, TransactionDetails, TxBuilderResult,
};
#[derive(Debug)]
pub(crate) struct Wallet {
pub(crate) inner_mutex: Mutex<BdkWallet<AnyDatabase>>,
}
/// A Bitcoin wallet.
/// The Wallet acts as a way of coherently interfacing with output descriptors and related transactions. Its main components are:
/// 1. Output descriptors from which it can derive addresses.
/// 2. A Database where it tracks transactions and utxos related to the descriptors.
/// 3. Signers that can contribute signatures to addresses instantiated from the descriptors.
impl Wallet {
pub(crate) fn new(
descriptor: Arc<Descriptor>,
change_descriptor: Option<Arc<Descriptor>>,
network: Network,
database_config: DatabaseConfig,
) -> Result<Self, BdkError> {
let any_database_config = match database_config {
DatabaseConfig::Memory => AnyDatabaseConfig::Memory(()),
DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config),
DatabaseConfig::Sqlite { config } => AnyDatabaseConfig::Sqlite(config),
};
let database = AnyDatabase::from_config(&any_database_config)?;
let descriptor: String = descriptor.as_string_private();
let change_descriptor: Option<String> = change_descriptor.map(|d| d.as_string_private());
let wallet_mutex = Mutex::new(BdkWallet::new(
&descriptor,
change_descriptor.as_ref(),
network.into(),
database,
)?);
Ok(Wallet {
inner_mutex: wallet_mutex,
})
}
pub(crate) fn get_wallet(&self) -> MutexGuard<BdkWallet<AnyDatabase>> {
self.inner_mutex.lock().expect("wallet")
}
/// Get the Bitcoin network the wallet is using.
pub(crate) fn network(&self) -> Network {
self.get_wallet().network().into()
}
/// Return whether or not a script is part of this wallet (either internal or external).
pub(crate) fn is_mine(&self, script: Arc<Script>) -> Result<bool, BdkError> {
self.get_wallet().is_mine(&script.0)
}
/// Sync the internal database with the blockchain.
pub(crate) fn sync(
&self,
blockchain: &Blockchain,
progress: Option<Box<dyn Progress>>,
) -> Result<(), BdkError> {
let bdk_sync_opts = BdkSyncOptions {
progress: progress.map(|p| {
Box::new(ProgressHolder { progress: p })
as Box<(dyn bdk::blockchain::Progress + 'static)>
}),
};
let blockchain = blockchain.get_blockchain();
self.get_wallet().sync(blockchain.deref(), bdk_sync_opts)
}
/// Return a derived address using the external descriptor, see AddressIndex for available address index selection
/// strategies. If none of the keys in the descriptor are derivable (i.e. the descriptor does not end with a * character)
/// then the same address will always be returned for any AddressIndex.
pub(crate) fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, BdkError> {
self.get_wallet()
.get_address(address_index.into())
.map(AddressInfo::from)
}
/// Return a derived address using the internal (change) descriptor.
///
/// If the wallet doesn't have an internal descriptor it will use the external descriptor.
///
/// see [`AddressIndex`] for available address index selection strategies. If none of the keys
/// in the descriptor are derivable (i.e. does not end with /*) then the same address will always
/// be returned for any [`AddressIndex`].
pub(crate) fn get_internal_address(
&self,
address_index: AddressIndex,
) -> Result<AddressInfo, BdkError> {
self.get_wallet()
.get_internal_address(address_index.into())
.map(AddressInfo::from)
}
/// Return the balance, meaning the sum of this wallets unspent outputs values. Note that this method only operates
/// on the internal database, which first needs to be Wallet.sync manually.
pub(crate) fn get_balance(&self) -> Result<Balance, BdkError> {
self.get_wallet().get_balance().map(|b| b.into())
}
/// Sign a transaction with all the wallet's signers, in the order specified by every signer's
/// [`SignerOrdering`]. This function returns the `Result` type with an encapsulated `bool` that
/// has the value true if the PSBT was finalized, or false otherwise.
///
/// The [`SignOptions`] can be used to tweak the behavior of the software signers, and the way
/// the transaction is finalized at the end. Note that it can't be guaranteed that *every*
/// signers will follow the options, but the "software signers" (WIF keys and `xprv`) defined
/// in this library will.
pub(crate) fn sign(
&self,
psbt: &PartiallySignedTransaction,
sign_options: Option<SignOptions>,
) -> Result<bool, BdkError> {
let mut psbt = psbt.inner.lock().unwrap();
self.get_wallet().sign(
&mut psbt,
sign_options.map(SignOptions::into).unwrap_or_default(),
)
}
/// Return the list of transactions made and received by the wallet. Note that this method only operate on the internal database, which first needs to be [Wallet.sync] manually.
pub(crate) fn list_transactions(
&self,
include_raw: bool,
) -> Result<Vec<TransactionDetails>, BdkError> {
let transaction_details = self.get_wallet().list_transactions(include_raw)?;
Ok(transaction_details
.into_iter()
.map(TransactionDetails::from)
.collect())
}
/// Return the list of unspent outputs of this wallet. Note that this method only operates on the internal database,
/// which first needs to be Wallet.sync manually.
pub(crate) fn list_unspent(&self) -> Result<Vec<LocalUtxo>, BdkError> {
let unspents: Vec<BdkLocalUtxo> = self.get_wallet().list_unspent()?;
Ok(unspents.into_iter().map(LocalUtxo::from).collect())
}
}
/// Options for a software signer
///
/// Adjust the behavior of our software signers and the way a transaction is finalized
#[derive(Debug, Clone, Default)]
pub struct SignOptions {
/// Whether the signer should trust the `witness_utxo`, if the `non_witness_utxo` hasn't been
/// provided
///
/// Defaults to `false` to mitigate the "SegWit bug" which should trick the wallet into
/// paying a fee larger than expected.
///
/// Some wallets, especially if relatively old, might not provide the `non_witness_utxo` for
/// SegWit transactions in the PSBT they generate: in those cases setting this to `true`
/// should correctly produce a signature, at the expense of an increased trust in the creator
/// of the PSBT.
///
/// For more details see: <https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd>
pub trust_witness_utxo: bool,
/// Whether the wallet should assume a specific height has been reached when trying to finalize
/// a transaction
///
/// The wallet will only "use" a timelock to satisfy the spending policy of an input if the
/// timelock height has already been reached. This option allows overriding the "current height" to let the
/// wallet use timelocks in the future to spend a coin.
pub assume_height: Option<u32>,
/// Whether the signer should use the `sighash_type` set in the PSBT when signing, no matter
/// what its value is
///
/// Defaults to `false` which will only allow signing using `SIGHASH_ALL`.
pub allow_all_sighashes: bool,
/// Whether to remove partial signatures from the PSBT inputs while finalizing PSBT.
///
/// Defaults to `true` which will remove partial signatures during finalization.
pub remove_partial_sigs: bool,
/// Whether to try finalizing the PSBT after the inputs are signed.
///
/// Defaults to `true` which will try finalizing PSBT after inputs are signed.
pub try_finalize: bool,
// Specifies which Taproot script-spend leaves we should sign for. This option is
// ignored if we're signing a non-taproot PSBT.
//
// Defaults to All, i.e., the wallet will sign all the leaves it has a key for.
// TODO pub tap_leaves_options: TapLeavesOptions,
/// Whether we should try to sign a taproot transaction with the taproot internal key
/// or not. This option is ignored if we're signing a non-taproot PSBT.
///
/// Defaults to `true`, i.e., we always try to sign with the taproot internal key.
pub sign_with_tap_internal_key: bool,
/// Whether we should grind ECDSA signature to ensure signing with low r
/// or not.
/// Defaults to `true`, i.e., we always grind ECDSA signature to sign with low r.
pub allow_grinding: bool,
}
impl From<SignOptions> for BdkSignOptions {
fn from(sign_options: SignOptions) -> Self {
BdkSignOptions {
trust_witness_utxo: sign_options.trust_witness_utxo,
assume_height: sign_options.assume_height,
allow_all_sighashes: sign_options.allow_all_sighashes,
remove_partial_sigs: sign_options.remove_partial_sigs,
try_finalize: sign_options.try_finalize,
tap_leaves_options: Default::default(),
sign_with_tap_internal_key: sign_options.sign_with_tap_internal_key,
allow_grinding: sign_options.allow_grinding,
}
}
}
/// A transaction builder.
/// After creating the TxBuilder, you set options on it until finally calling finish to consume the builder and generate the transaction.
/// Each method on the TxBuilder returns an instance of a new TxBuilder with the option set/added.
#[derive(Clone, Debug)]
pub(crate) struct TxBuilder {
pub(crate) recipients: Vec<(BdkScriptBuf, u64)>,
pub(crate) utxos: Vec<OutPoint>,
pub(crate) unspendable: HashSet<OutPoint>,
pub(crate) change_policy: ChangeSpendPolicy,
pub(crate) manually_selected_only: bool,
pub(crate) fee_rate: Option<f32>,
pub(crate) fee_absolute: Option<u64>,
pub(crate) drain_wallet: bool,
pub(crate) drain_to: Option<BdkScriptBuf>,
pub(crate) rbf: Option<RbfValue>,
pub(crate) data: Vec<u8>,
}
impl TxBuilder {
pub(crate) fn new() -> Self {
TxBuilder {
recipients: Vec::new(),
utxos: Vec::new(),
unspendable: HashSet::new(),
change_policy: ChangeSpendPolicy::ChangeAllowed,
manually_selected_only: false,
fee_rate: None,
fee_absolute: None,
drain_wallet: false,
drain_to: None,
rbf: None,
data: Vec::new(),
}
}
/// Add a recipient to the internal list.
pub(crate) fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
let mut recipients: Vec<(BdkScriptBuf, u64)> = self.recipients.clone();
recipients.append(&mut vec![(script.0.clone(), amount)]);
Arc::new(TxBuilder {
recipients,
..self.clone()
})
}
pub(crate) fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
let recipients = recipients
.iter()
.map(|script_amount| (script_amount.script.0.clone(), script_amount.amount))
.collect();
Arc::new(TxBuilder {
recipients,
..self.clone()
})
}
/// Add a utxo to the internal list of unspendable utxos. Its important to note that the "must-be-spent"
/// utxos added with [TxBuilder.addUtxo] have priority over this. See the Rust docs of the two linked methods for more details.
pub(crate) fn add_unspendable(&self, unspendable: OutPoint) -> Arc<Self> {
let mut unspendable_hash_set = self.unspendable.clone();
unspendable_hash_set.insert(unspendable);
Arc::new(TxBuilder {
unspendable: unspendable_hash_set,
..self.clone()
})
}
/// Add an outpoint to the internal list of UTXOs that must be spent. These have priority over the "unspendable"
/// utxos, meaning that if a utxo is present both in the "utxos" and the "unspendable" list, it will be spent.
pub(crate) fn add_utxo(&self, outpoint: OutPoint) -> Arc<Self> {
self.add_utxos(vec![outpoint])
}
/// Add the list of outpoints to the internal list of UTXOs that must be spent. If an error occurs while adding
/// any of the UTXOs then none of them are added and the error is returned. These have priority over the "unspendable"
/// utxos, meaning that if a utxo is present both in the "utxos" and the "unspendable" list, it will be spent.
pub(crate) fn add_utxos(&self, mut outpoints: Vec<OutPoint>) -> Arc<Self> {
let mut utxos = self.utxos.to_vec();
utxos.append(&mut outpoints);
Arc::new(TxBuilder {
utxos,
..self.clone()
})
}
/// Do not spend change outputs. This effectively adds all the change outputs to the "unspendable" list. See TxBuilder.unspendable.
pub(crate) fn do_not_spend_change(&self) -> Arc<Self> {
Arc::new(TxBuilder {
change_policy: ChangeSpendPolicy::ChangeForbidden,
..self.clone()
})
}
/// Only spend utxos added by [add_utxo]. The wallet will not add additional utxos to the transaction even if they are
/// needed to make the transaction valid.
pub(crate) fn manually_selected_only(&self) -> Arc<Self> {
Arc::new(TxBuilder {
manually_selected_only: true,
..self.clone()
})
}
/// Only spend change outputs. This effectively adds all the non-change outputs to the "unspendable" list. See TxBuilder.unspendable.
pub(crate) fn only_spend_change(&self) -> Arc<Self> {
Arc::new(TxBuilder {
change_policy: ChangeSpendPolicy::OnlyChange,
..self.clone()
})
}
/// Replace the internal list of unspendable utxos with a new list. Its important to note that the "must-be-spent" utxos added with
/// TxBuilder.addUtxo have priority over these. See the Rust docs of the two linked methods for more details.
pub(crate) fn unspendable(&self, unspendable: Vec<OutPoint>) -> Arc<Self> {
Arc::new(TxBuilder {
unspendable: unspendable.into_iter().collect(),
..self.clone()
})
}
/// Set a custom fee rate.
pub(crate) fn fee_rate(&self, sat_per_vb: f32) -> Arc<Self> {
Arc::new(TxBuilder {
fee_rate: Some(sat_per_vb),
..self.clone()
})
}
/// Set an absolute fee.
pub(crate) fn fee_absolute(&self, fee_amount: u64) -> Arc<Self> {
Arc::new(TxBuilder {
fee_absolute: Some(fee_amount),
..self.clone()
})
}
/// Spend all the available inputs. This respects filters like TxBuilder.unspendable and the change policy.
pub(crate) fn drain_wallet(&self) -> Arc<Self> {
Arc::new(TxBuilder {
drain_wallet: true,
..self.clone()
})
}
/// Sets the address to drain excess coins to. Usually, when there are excess coins they are sent to a change address
/// generated by the wallet. This option replaces the usual change address with an arbitrary ScriptPubKey of your choosing.
/// Just as with a change output, if the drain output is not needed (the excess coins are too small) it will not be included
/// in the resulting transaction. The only difference is that it is valid to use drain_to without setting any ordinary recipients
/// with add_recipient (but it is perfectly fine to add recipients as well). If you choose not to set any recipients, you should
/// either provide the utxos that the transaction should spend via add_utxos, or set drain_wallet to spend all of them.
/// When bumping the fees of a transaction made with this option, you probably want to use BumpFeeTxBuilder.allow_shrinking
/// to allow this output to be reduced to pay for the extra fees.
pub(crate) fn drain_to(&self, script: Arc<Script>) -> Arc<Self> {
Arc::new(TxBuilder {
drain_to: Some(script.0.clone()),
..self.clone()
})
}
/// Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`.
pub(crate) fn enable_rbf(&self) -> Arc<Self> {
Arc::new(TxBuilder {
rbf: Some(RbfValue::Default),
..self.clone()
})
}
/// Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors contain an
/// "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence` is higher than `0xFFFFFFFD`
/// an error will be thrown, since it would not be a valid nSequence to signal RBF.
pub(crate) fn enable_rbf_with_sequence(&self, nsequence: u32) -> Arc<Self> {
Arc::new(TxBuilder {
rbf: Some(RbfValue::Value(nsequence)),
..self.clone()
})
}
/// Add data as an output using OP_RETURN.
pub(crate) fn add_data(&self, data: Vec<u8>) -> Arc<Self> {
Arc::new(TxBuilder {
data,
..self.clone()
})
}
/// Finish building the transaction. Returns the BIP174 PSBT.
pub(crate) fn finish(&self, wallet: &Wallet) -> Result<TxBuilderResult, BdkError> {
let wallet = wallet.get_wallet();
let mut tx_builder = wallet.build_tx();
for (script, amount) in &self.recipients {
tx_builder.add_recipient(script.clone(), *amount);
}
tx_builder.change_policy(self.change_policy);
if !self.utxos.is_empty() {
let bdk_utxos: Vec<BdkOutPoint> = self.utxos.iter().map(BdkOutPoint::from).collect();
let utxos: &[BdkOutPoint] = &bdk_utxos;
tx_builder.add_utxos(utxos)?;
}
if !self.unspendable.is_empty() {
let bdk_unspendable: Vec<BdkOutPoint> =
self.unspendable.iter().map(BdkOutPoint::from).collect();
tx_builder.unspendable(bdk_unspendable);
}
if self.manually_selected_only {
tx_builder.manually_selected_only();
}
if let Some(sat_per_vb) = self.fee_rate {
tx_builder.fee_rate(FeeRate::from_sat_per_vb(sat_per_vb));
}
if let Some(fee_amount) = self.fee_absolute {
tx_builder.fee_absolute(fee_amount);
}
if self.drain_wallet {
tx_builder.drain_wallet();
}
if let Some(script) = &self.drain_to {
tx_builder.drain_to(script.clone());
}
if let Some(rbf) = &self.rbf {
match *rbf {
RbfValue::Default => {
tx_builder.enable_rbf();
}
RbfValue::Value(nsequence) => {
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
}
}
}
if !&self.data.is_empty() {
let push_bytes = PushBytesBuf::try_from(self.data.clone()).map_err(|_| {
BdkError::Generic("Failed to convert data to PushBytes".to_string())
})?;
tx_builder.add_data(&push_bytes);
}
tx_builder
.finish()
.map(|(psbt, tx_details)| TxBuilderResult {
psbt: Arc::new(PartiallySignedTransaction {
inner: Mutex::new(psbt),
}),
transaction_details: TransactionDetails::from(tx_details),
})
}
}
/// The BumpFeeTxBuilder is used to bump the fee on a transaction that has been broadcast and has its RBF flag set to true.
#[derive(Clone)]
pub(crate) struct BumpFeeTxBuilder {
pub(crate) txid: String,
pub(crate) fee_rate: f32,
pub(crate) allow_shrinking: Option<Arc<Script>>,
pub(crate) rbf: Option<RbfValue>,
}
impl BumpFeeTxBuilder {
pub(crate) fn new(txid: String, fee_rate: f32) -> Self {
Self {
txid,
fee_rate,
allow_shrinking: None,
rbf: None,
}
}
/// Explicitly tells the wallet that it is allowed to reduce the amount of the output matching this script_pubkey
/// in order to bump the transaction fee. Without specifying this the wallet will attempt to find a change output to
/// shrink instead. Note that the output may shrink to below the dust limit and therefore be removed. If it is preserved
/// then it is currently not guaranteed to be in the same position as it was originally. Returns an error if script_pubkey
/// cant be found among the recipients of the transaction we are bumping.
pub(crate) fn allow_shrinking(&self, script_pubkey: Arc<Script>) -> Arc<Self> {
Arc::new(Self {
allow_shrinking: Some(script_pubkey),
..self.clone()
})
}
/// Enable signaling RBF. This will use the default `nsequence` value of `0xFFFFFFFD`.
pub(crate) fn enable_rbf(&self) -> Arc<Self> {
Arc::new(Self {
rbf: Some(RbfValue::Default),
..self.clone()
})
}
/// Enable signaling RBF with a specific nSequence value. This can cause conflicts if the wallet's descriptors contain an
/// "older" (OP_CSV) operator and the given `nsequence` is lower than the CSV value. If the `nsequence` is higher than `0xFFFFFFFD`
/// an error will be thrown, since it would not be a valid nSequence to signal RBF.
pub(crate) fn enable_rbf_with_sequence(&self, nsequence: u32) -> Arc<Self> {
Arc::new(Self {
rbf: Some(RbfValue::Value(nsequence)),
..self.clone()
})
}
/// Finish building the transaction. Returns the BIP174 PSBT.
pub(crate) fn finish(
&self,
wallet: &Wallet,
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
let wallet = wallet.get_wallet();
let txid = Txid::from_str(self.txid.as_str())?;
let mut tx_builder = wallet.build_fee_bump(txid)?;
tx_builder.fee_rate(FeeRate::from_sat_per_vb(self.fee_rate));
if let Some(allow_shrinking) = &self.allow_shrinking {
tx_builder.allow_shrinking(allow_shrinking.0.clone())?;
}
if let Some(rbf) = &self.rbf {
match *rbf {
RbfValue::Default => {
tx_builder.enable_rbf();
}
RbfValue::Value(nsequence) => {
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
}
}
}
tx_builder
.finish()
.map(|(psbt, _)| PartiallySignedTransaction {
inner: Mutex::new(psbt),
})
.map(Arc::new)
}
}
// The goal of these tests to to ensure `bdk-ffi` intermediate code correctly calls `bdk` APIs.
// These tests should not be used to verify `bdk` behavior that is already tested in the `bdk`
// crate.
#[cfg(test)]
mod test {
use crate::database::DatabaseConfig;
use crate::descriptor::Descriptor;
use crate::keys::{DescriptorSecretKey, Mnemonic};
use crate::wallet::{AddressIndex, TxBuilder, Wallet};
use crate::Network;
use crate::Script;
use assert_matches::assert_matches;
use bdk::bitcoin::Address;
use bdk::wallet::get_funded_wallet;
use bdk::KeychainKind;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
#[test]
fn test_drain_wallet() {
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
let test_wallet = Wallet {
inner_mutex: Mutex::new(funded_wallet),
};
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
let drain_to_script = crate::Address::new(drain_to_address, Network::Testnet)
.unwrap()
.script_pubkey();
let tx_builder = TxBuilder::new()
.drain_wallet()
.drain_to(drain_to_script.clone());
assert!(tx_builder.drain_wallet);
assert_eq!(tx_builder.drain_to, Some(drain_to_script.0.clone()));
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
let psbt = tx_builder_result.psbt.inner.lock().unwrap().clone();
let tx_details = tx_builder_result.transaction_details;
// confirm one input with 50,000 sats
assert_eq!(psbt.inputs.len(), 1);
let input_value = psbt
.inputs
.get(0)
.cloned()
.unwrap()
.non_witness_utxo
.unwrap()
.output
.get(0)
.unwrap()
.value;
assert_eq!(input_value, 50_000_u64);
// confirm one output to correct address with all sats - fee
assert_eq!(psbt.outputs.len(), 1);
let output_address = Address::from_script(
&psbt
.unsigned_tx
.output
.get(0)
.cloned()
.unwrap()
.script_pubkey,
Network::Testnet.into(),
)
.unwrap();
assert_eq!(
output_address,
Address::from_str("tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt")
.unwrap()
.assume_checked()
);
let output_value = psbt.unsigned_tx.output.get(0).cloned().unwrap().value;
assert_eq!(output_value, 49_890_u64); // input - fee
assert_eq!(
tx_details.txid,
"312f1733badab22dc26b8dcbc83ba5629fb7b493af802e8abe07d865e49629c5"
);
assert_eq!(tx_details.received, 0);
assert_eq!(tx_details.sent, 50000);
assert!(tx_details.fee.is_some());
assert_eq!(tx_details.fee.unwrap(), 110);
assert!(tx_details.confirmation_time.is_none());
}
#[test]
fn test_peek_reset_address() {
let test_wpkh = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)";
let descriptor = Descriptor::new(test_wpkh.to_string(), Network::Regtest).unwrap();
let change_descriptor = Descriptor::new(
test_wpkh.to_string().replace("/0/*", "/1/*"),
Network::Regtest,
)
.unwrap();
let wallet = Wallet::new(
Arc::new(descriptor),
Some(Arc::new(change_descriptor)),
Network::Regtest,
DatabaseConfig::Memory,
)
.unwrap();
assert_eq!(
wallet
.get_address(AddressIndex::Peek { index: 2 })
.unwrap()
.address
.as_string(),
"bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj"
);
assert_eq!(
wallet
.get_address(AddressIndex::Peek { index: 1 })
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
// new index still 0
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
);
// new index now 1
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
// new index now 2
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1q5g0mq6dkmwzvxscqwgc932jhgcxuqqkjv09tkj"
);
// peek index 1
assert_eq!(
wallet
.get_address(AddressIndex::Peek { index: 1 })
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
// reset to index 0
assert_eq!(
wallet
.get_address(AddressIndex::Reset { index: 0 })
.unwrap()
.address
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
);
// new index 1 again
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
}
#[test]
fn test_get_address() {
let test_wpkh = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)";
let descriptor = Descriptor::new(test_wpkh.to_string(), Network::Regtest).unwrap();
let change_descriptor = Descriptor::new(
test_wpkh.to_string().replace("/0/*", "/1/*"),
Network::Regtest,
)
.unwrap();
let wallet = Wallet::new(
Arc::new(descriptor),
Some(Arc::new(change_descriptor)),
Network::Regtest,
DatabaseConfig::Memory,
)
.unwrap();
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1qqjn9gky9mkrm3c28e5e87t5akd3twg6xezp0tv"
);
assert_eq!(
wallet
.get_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
assert_eq!(
wallet
.get_address(AddressIndex::LastUnused)
.unwrap()
.address
.as_string(),
"bcrt1q0xs7dau8af22rspp4klya4f7lhggcnqfun2y3a"
);
assert_eq!(
wallet
.get_internal_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1qpmz73cyx00r4a5dea469j40ax6d6kqyd67nnpj"
);
assert_eq!(
wallet
.get_internal_address(AddressIndex::New)
.unwrap()
.address
.as_string(),
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
);
assert_eq!(
wallet
.get_internal_address(AddressIndex::LastUnused)
.unwrap()
.address
.as_string(),
"bcrt1qaux734vuhykww9632v8cmdnk7z2mw5lsf74v6k"
);
}
#[test]
fn test_is_mine() {
// is_mine should return true for addresses generated by the wallet
let mnemonic: Mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
let secret_key: DescriptorSecretKey =
DescriptorSecretKey::new(Network::Testnet, Arc::new(mnemonic), None);
let descriptor: Descriptor = Descriptor::new_bip84(
Arc::new(secret_key),
KeychainKind::External,
Network::Testnet,
);
let wallet: Wallet = Wallet::new(
Arc::new(descriptor),
None,
Network::Testnet,
DatabaseConfig::Memory,
)
.unwrap();
let address = wallet.get_address(AddressIndex::New).unwrap();
let script: Arc<Script> = address.address.script_pubkey();
let is_mine_1: bool = wallet.is_mine(script).unwrap();
assert!(is_mine_1);
// is_mine returns false when provided a script that is not in the wallet
let other_wpkh = "wpkh(tprv8hwWMmPE4BVNxGdVt3HhEERZhondQvodUY7Ajyseyhudr4WabJqWKWLr4Wi2r26CDaNCQhhxEftEaNzz7dPGhWuKFU4VULesmhEfZYyBXdE/0/*)";
let other_descriptor = Descriptor::new(other_wpkh.to_string(), Network::Testnet).unwrap();
let other_wallet = Wallet::new(
Arc::new(other_descriptor),
None,
Network::Testnet,
DatabaseConfig::Memory,
)
.unwrap();
let other_address = other_wallet.get_address(AddressIndex::New).unwrap();
let other_script: Arc<Script> = other_address.address.script_pubkey();
let is_mine_2: bool = wallet.is_mine(other_script).unwrap();
assert_matches!(is_mine_2, false);
}
}

21
bdk-ffi/tests/README.md Normal file
View File

@@ -0,0 +1,21 @@
# Integration tests for bdk-ffi
This contains simple tests to make sure bdk-ffi can be used as a dependency for each of the
supported bindings languages.
To skip integration tests and only run unit tests use `cargo test --lib`.
To run all tests including integration tests use `CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test`.
Before running integration tests you must install the following development tools:
1. [Java](https://openjdk.org/) and [Kotlin](https://kotlinlang.org/),
[sdkman](https://sdkman.io/) can help:
```shell
sdk install java 11.0.16.1-zulu
sdk install kotlin 1.7.20`
```
2. [Swift](https://www.swift.org/)
3. [Python](https://www.python.org/)

View File

@@ -0,0 +1,8 @@
/*
* This is a basic test kotlin program that does nothing but confirm that the kotlin bindings compile
* and that a program that depends on them will run.
*/
import org.bitcoindevkit.*
val network = Network.TESTNET

View File

@@ -0,0 +1,10 @@
import unittest
from bdk import *
class TestBdk(unittest.TestCase):
def test_some_enum(self):
network = Network.TESTNET
if __name__=='__main__':
unittest.main()

View File

@@ -0,0 +1,9 @@
/*
* This is a basic test swift program that does nothing but confirm that the swift bindings compile
* and that a program that depends on them will run.
*/
import Foundation
import bdk
let network = Network.testnet

Binary file not shown.

View File

@@ -0,0 +1,5 @@
uniffi::build_foreign_language_testcases!(
"tests/bindings/test.kts",
"tests/bindings/test.swift",
"tests/bindings/test.py",
);

View File

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

107
bdk-jvm/README.md Normal file
View File

@@ -0,0 +1,107 @@
# bdk-jvm
This project builds a .jar package for the JVM platform that provide Kotlin language bindings for the [`bdk`] library. The Kotlin language bindings are created by the `bdk-ffi` project which is included in the root of this repository.
## How to Use
To use the Kotlin language bindings for [`bdk`] in your JVM project add the following to your gradle dependencies:
```kotlin
repositories {
mavenCentral()
}
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version>")
}
```
You may then import and use the `org.bitcoindevkit` library in your Kotlin code. For example:
```kotlin
import org.bitcoindevkit.*
// ...
val externalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
val internalDescriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)", Network.TESTNET)
val databaseConfig = DatabaseConfig.Memory
val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u, true)
)
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
val newAddress = wallet.getAddress(AddressIndex.LastUnused)
```
### Snapshot releases
To use a snapshot release, specify the snapshot repository url in the `repositories` block and use the snapshot version in the `dependencies` block:
```kotlin
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
implementation("org.bitcoindevkit:bdk-jvm:<version-SNAPSHOT>")
}
```
## Example Projects
* [Tatooine Faucet](https://github.com/thunderbiscuit/tatooine)
## How to build
_Note that Kotlin version `1.6.10` or later is required to build the library._
1. Install JDK 11. It must be version 11 (not 17), otherwise it won't build. For example, with SDKMAN!:
```shell
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk install java 11.0.19-tem
```
2. Install Rust (note that we are currently building using Rust 1.67.0):
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup default 1.67.0
```
3. Clone this repository.
```shell
git clone https://github.com/bitcoindevkit/bdk-ffi
```
4. If building on macOS install required intel and m1 jvm targets
```sh
rustup target add x86_64-apple-darwin aarch64-apple-darwin
```
5. Build kotlin bindings
```sh
./gradlew buildJvmLib
```
## How to publish to your local Maven repo
```shell
cd bdk-jvm
./gradlew publishToMavenLocal --exclude-task signMavenPublication
```
Note that the commands assume you don't need the local libraries to be signed. If you do wish to sign them, simply set your `~/.gradle/gradle.properties` signing key values like so:
```properties
signing.gnupg.keyName=<YOUR_GNUPG_ID>
signing.gnupg.passphrase=<YOUR_GNUPG_PASSPHRASE>
```
and use the `publishToMavenLocal` task without excluding the signing task:
```shell
./gradlew publishToMavenLocal
```
## Known issues
## JNA dependency
Depending on the JVM version you use, you might not have the JNA dependency on your classpath. The exception thrown will be
```shell
class file for com.sun.jna.Pointer not found
```
The solution is to add JNA as a dependency like so:
```kotlin
dependencies {
// ...
implementation("net.java.dev.jna:jna:5.12.1")
}
```
[`bdk`]: https://github.com/bitcoindevkit/bdk
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi

27
bdk-jvm/build.gradle.kts Normal file
View File

@@ -0,0 +1,27 @@
plugins {
id("io.github.gradle-nexus.publish-plugin") version "1.1.0"
}
// library version is defined in gradle.properties
val libraryVersion: String by project
// These properties are required here so that the nexus publish-plugin
// finds a staging profile with the correct group (group is otherwise set as "")
// and knows whether to publish to a SNAPSHOT repository or not
// https://github.com/gradle-nexus/publish-plugin#applying-the-plugin
group = "org.bitcoindevkit"
version = libraryVersion
nexusPublishing {
repositories {
create("sonatype") {
nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/"))
snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/"))
val ossrhUsername: String? by project
val ossrhPassword: String? by project
username.set(ossrhUsername)
password.set(ossrhPassword)
}
}
}

View File

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

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

234
bdk-jvm/gradlew vendored Executable file
View File

@@ -0,0 +1,234 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# 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
#
# https://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.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

89
bdk-jvm/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,114 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.*
import org.gradle.api.tasks.testing.logging.TestLogEvent.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
// library version is defined in gradle.properties
val libraryVersion: String by project
plugins {
id("org.jetbrains.kotlin.jvm") version "1.6.10"
id("java-library")
id("maven-publish")
id("signing")
// Custom plugin to generate the native libs and bindings file
id("org.bitcoindevkit.plugins.generate-jvm-bindings")
}
repositories {
mavenCentral()
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
withSourcesJar()
withJavadocJar()
}
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
events(PASSED, SKIPPED, FAILED, STANDARD_OUT, STANDARD_ERROR)
exceptionFormat = FULL
showExceptions = true
showCauses = true
showStackTraces = true
}
}
dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7")
implementation("net.java.dev.jna:jna:5.8.0")
api("org.slf4j:slf4j-api:1.7.30")
testImplementation("junit:junit:4.13.2")
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2")
testImplementation("ch.qos.logback:logback-classic:1.2.3")
testImplementation("ch.qos.logback:logback-core:1.2.3")
}
afterEvaluate {
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "org.bitcoindevkit"
artifactId = "bdk-jvm"
version = libraryVersion
from(components["java"])
pom {
name.set("bdk-jvm")
description.set("Bitcoin Dev Kit Kotlin language bindings.")
url.set("https://bitcoindevkit.org")
licenses {
license {
name.set("APACHE 2.0")
url.set("https://github.com/bitcoindevkit/bdk/blob/master/LICENSE-APACHE")
}
license {
name.set("MIT")
url.set("https://github.com/bitcoindevkit/bdk/blob/master/LICENSE-MIT")
}
}
developers {
developer {
id.set("notmandatory")
name.set("Steve Myers")
email.set("notmandatory@noreply.github.org")
}
developer {
id.set("artfuldev")
name.set("Sudarsan Balaji")
email.set("sudarsan.balaji@artfuldev.com")
}
}
scm {
connection.set("scm:git:github.com/bitcoindevkit/bdk-ffi.git")
developerConnection.set("scm:git:ssh://github.com/bitcoindevkit/bdk-ffi.git")
url.set("https://github.com/bitcoindevkit/bdk-ffi/tree/master")
}
}
}
}
}
}
signing {
val signingKeyId: String? by project
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKeyId, signingKey, signingPassword)
sign(publishing.publications)
}
// This task dependency ensures that we build the bindings
// binaries before running the tests
tasks.withType<KotlinCompile> {
dependsOn("buildJvmLib")
kotlinOptions {
jvmTarget = "11"
}
}

View File

@@ -0,0 +1,73 @@
package org.bitcoindevkit
import org.junit.Assert.*
import org.junit.Test
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File
import java.nio.file.Files
/**
* Library test, which will execute on linux host.
*/
class JvmLibTest {
private fun getTestDataDir(): String {
return Files.createTempDirectory("bdk-test").toString()
}
private fun cleanupTestDataDir(testDataDir: String) {
File(testDataDir).deleteRecursively()
}
class LogProgress : Progress {
private val log: Logger = LoggerFactory.getLogger(JvmLibTest::class.java)
override fun update(progress: Float, message: String?) {
log.debug("Syncing...")
}
}
private val descriptor = Descriptor("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)", Network.TESTNET)
private val databaseConfig = DatabaseConfig.Memory
private val blockchainConfig = BlockchainConfig.Electrum(
ElectrumConfig(
"ssl://electrum.blockstream.info:60002",
null,
5u,
null,
100u,
true,
)
)
@Test
fun memoryWalletNewAddress() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val address = wallet.getAddress(AddressIndex.New).address.asString()
assertEquals("tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", address)
}
@Test
fun memoryWalletSyncGetBalance() {
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val blockchain = Blockchain(blockchainConfig)
wallet.sync(blockchain, LogProgress())
val balance: Balance = wallet.getBalance()
assertTrue(balance.total > 0u)
}
@Test
fun sqliteWalletSyncGetBalance() {
val testDataDir = getTestDataDir() + "/bdk-wallet.sqlite"
val databaseConfig = DatabaseConfig.Sqlite(SqliteDbConfiguration(testDataDir))
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
val blockchain = Blockchain(blockchainConfig)
wallet.sync(blockchain, LogProgress())
val balance: Balance = wallet.getBalance()
assertTrue(balance.total > 0u)
cleanupTestDataDir(testDataDir)
}
}

16
bdk-jvm/plugins/README.md Normal file
View File

@@ -0,0 +1,16 @@
# Readme
The purpose of this directory is to host the Gradle plugin that adds tasks for building the native binaries required by bdk-jvm, and building the language bindings files.
The plugin is applied to the `build.gradle.kts` file through the `plugins` block:
```kotlin
plugins {
id("org.bitcoindevkit.plugin.generate-jvm-bindings")
}
```
The plugin adds a series of tasks which are brought together into an aggregate task called `buildJvmLib` for `bdk-jvm`.
This aggregate task:
1. Builds the native library(ies) using `bdk-ffi`
2. Places it in the correct resource directory
3. Builds the bindings file

View File

@@ -0,0 +1,13 @@
plugins {
id("java-gradle-plugin")
`kotlin-dsl`
}
gradlePlugin {
plugins {
create("uniFfiJvmBindings") {
id = "org.bitcoindevkit.plugins.generate-jvm-bindings"
implementationClass = "org.bitcoindevkit.plugins.UniFfiJvmPlugin"
}
}
}

View File

@@ -0,0 +1,8 @@
dependencyResolutionManagement {
repositories {
mavenCentral()
google()
}
}
// include(":plugins")

View File

@@ -0,0 +1,16 @@
package org.bitcoindevkit.plugins
val operatingSystem: OS = when {
System.getProperty("os.name").contains("mac", ignoreCase = true) -> OS.MAC
System.getProperty("os.name").contains("linux", ignoreCase = true) -> OS.LINUX
System.getProperty("os.name").contains("windows", ignoreCase = true) -> OS.WINDOWS
else -> OS.OTHER
}
enum class OS {
MAC,
LINUX,
WINDOWS,
OTHER,
}

View File

@@ -0,0 +1,135 @@
package org.bitcoindevkit.plugins
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.tasks.Exec
import org.gradle.kotlin.dsl.getValue
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.register
internal class UniFfiJvmPlugin : Plugin<Project> {
override fun apply(target: Project): Unit = target.run {
// register a task called buildJvmBinaries which will run something like
// cargo build --release --target aarch64-apple-darwin
val buildJvmBinaries by tasks.register<DefaultTask>("buildJvmBinaries") {
if (operatingSystem == OS.MAC) {
exec {
workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-apple-darwin")
args(cargoArgs)
}
exec {
workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "aarch64-apple-darwin")
args(cargoArgs)
}
} else if (operatingSystem == OS.LINUX) {
exec {
workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-unknown-linux-gnu")
args(cargoArgs)
}
} else if (operatingSystem == OS.WINDOWS) {
exec {
workingDir("${project.projectDir}/../../bdk-ffi")
executable("cargo")
val cargoArgs: List<String> = listOf("build", "--profile", "release-smaller", "--target", "x86_64-pc-windows-msvc")
args(cargoArgs)
}
}
}
// move the native libs build by cargo from target/.../release/
// to their place in the bdk-jvm library
val moveNativeJvmLibs by tasks.register<DefaultTask>("moveNativeJvmLibs") {
// dependsOn(buildJvmBinaryX86_64MacOS, buildJvmBinaryAarch64MacOS, buildJvmBinaryLinux)
dependsOn(buildJvmBinaries)
data class CopyMetadata(val targetDir: String, val resDir: String, val ext: String)
val libsToCopy: MutableList<CopyMetadata> = mutableListOf()
if (operatingSystem == OS.MAC) {
libsToCopy.add(
CopyMetadata(
targetDir = "aarch64-apple-darwin",
resDir = "darwin-aarch64",
ext = "dylib"
)
)
libsToCopy.add(
CopyMetadata(
targetDir = "x86_64-apple-darwin",
resDir = "darwin-x86-64",
ext = "dylib"
)
)
} else if (operatingSystem == OS.LINUX) {
libsToCopy.add(
CopyMetadata(
targetDir = "x86_64-unknown-linux-gnu",
resDir = "linux-x86-64",
ext = "so"
)
)
} else if (operatingSystem == OS.WINDOWS) {
libsToCopy.add(
CopyMetadata(
targetDir = "x86_64-pc-windows-msvc",
resDir = "win32-x86-64",
ext = "dll"
)
)
}
val libName = when (operatingSystem) {
OS.WINDOWS -> "bdkffi"
else -> "libbdkffi"
}
libsToCopy.forEach {
doFirst {
copy {
with(it) {
from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/${libName}.${this.ext}")
into("${project.projectDir}/../../bdk-jvm/lib/src/main/resources/${this.resDir}/")
}
}
}
}
}
// generate the bindings using the bdk-ffi-bindgen tool created in the bdk-ffi submodule
val generateJvmBindings by tasks.register<Exec>("generateJvmBindings") {
dependsOn(moveNativeJvmLibs)
workingDir("${project.projectDir}/../../bdk-ffi")
val cargoArgs: List<String> = listOf("run", "--bin", "uniffi-bindgen", "generate", "src/bdk.udl", "--language", "kotlin", "--out-dir", "../bdk-jvm/lib/src/main/kotlin", "--no-format")
executable("cargo")
args(cargoArgs)
doLast {
println("JVM bindings file successfully created")
}
}
// we need an aggregate task which will run the 3 required tasks to build the JVM libs in order
// the task will also appear in the printout of the ./gradlew tasks task with a group and description
tasks.register("buildJvmLib") {
group = "Bitcoindevkit"
description = "Aggregate task to build JVM library"
dependsOn(
buildJvmBinaries,
moveNativeJvmLibs,
generateJvmBindings
)
}
}
}

View File

@@ -0,0 +1,4 @@
rootProject.name = "bdk-jvm"
include(":lib")
includeBuild("plugins")

16
bdk-python/.gitignore vendored Normal file
View File

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

3
bdk-python/MANIFEST.in Normal file
View File

@@ -0,0 +1,3 @@
include ./src/bdkpython/libbdkffi.dylib
include ./src/bdkpython/libbdkffi.so
include ./src/bdkpython/bdkffi.dll

36
bdk-python/README.md Normal file
View File

@@ -0,0 +1,36 @@
# 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
pip install --requirement requirements.txt
bash ./scripts/generate-linux.sh # here you should run the script appropriate for your platform
python setup.py bdist_wheel --verbose
pip install ./dist/bdkpython-<yourversion>.whl --force-reinstall
python -m unittest --verbose tests/test_bdk.py
```
## Build the package
```shell
# Install dependencies
pip install --requirement requirements.txt
# Generate the bindings (use the script appropriate for your platform)
bash ./scripts/generate-linux.sh
# Build the wheel
python setup.py --verbose bdist_wheel
```
## Install locally
```shell
pip install ./dist/bdkpython-<yourversion>.whl
```

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1,20 @@
with import <nixpkgs> {};
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 ];
}

View File

@@ -0,0 +1,7 @@
[build-system]
requires = ["setuptools", "wheel", "setuptools-rust"]
[tool.pytest.ini_options]
pythonpath = [
"."
]

View File

@@ -0,0 +1,2 @@
pytest==7.1.2
tox==3.25.1

View File

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

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
${PYBIN}/python --version
${PYBIN}/pip install -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup default 1.67.0
cargo build --profile release-smaller
echo "Copying linux libbdkffi.so..."
cp ../target/release-smaller/libbdkffi.so ../bdk-python/src/bdkpython/libbdkffi.so
echo "All done!"

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
python3 --version
pip install --user -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup default 1.67.0
rustup target add aarch64-apple-darwin
cargo build --profile release-smaller --target aarch64-apple-darwin
echo "Copying libraries libbdkffi.dylib..."
cp ../target/aarch64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
echo "All done!"

View File

@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
python3 --version
pip install --user -r requirements.txt
echo "Generating bdk.py..."
cd ../bdk-ffi/
cargo run --bin uniffi-bindgen generate src/bdk.udl --language python --out-dir ../bdk-python/src/bdkpython/ --no-format
echo "Generating native binaries..."
rustup target add x86_64-apple-darwin
cargo build --profile release-smaller --target x86_64-apple-darwin
echo "Copying libraries libbdkffi.dylib..."
cp ../target/x86_64-apple-darwin/release-smaller/libbdkffi.dylib ../bdk-python/src/bdkpython/libbdkffi.dylib
echo "All done!"

Some files were not shown because too many files have changed in this diff Show More