Compare commits
472 Commits
release/0.
...
v0.25.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9741943b56 | ||
|
|
8c62905d39 | ||
|
|
3cd17bb908 | ||
|
|
17b3712000 | ||
|
|
a925ddfc47 | ||
|
|
5dd5828e88 | ||
|
|
2645f69853 | ||
|
|
f834da11c5 | ||
|
|
8c934e9bfc | ||
|
|
9c0606e036 | ||
|
|
832387d32d | ||
|
|
84f5677abb | ||
|
|
e790764915 | ||
|
|
b9bb5962ae | ||
|
|
13cbe89167 | ||
|
|
07f5b5f8ba | ||
|
|
a12b1f8d7a | ||
|
|
97d011acc0 | ||
|
|
b7efb37632 | ||
|
|
3edda27ef2 | ||
|
|
e017d76351 | ||
|
|
427816fd9a | ||
|
|
29614b5b78 | ||
|
|
063f69222a | ||
|
|
95a36bc9e2 | ||
|
|
8857c851f6 | ||
|
|
632f48e75a | ||
|
|
6a9c2eb80e | ||
|
|
be058e11d9 | ||
|
|
ce9ca63bc7 | ||
|
|
16ab09d7df | ||
|
|
738ed656fc | ||
|
|
e6708d4c5b | ||
|
|
af77b9b9b1 | ||
|
|
0c1a9d7f1d | ||
|
|
4f544e465b | ||
|
|
64c496f815 | ||
|
|
8bb8c00a6b | ||
|
|
26ef0d4a34 | ||
|
|
8240d8dc99 | ||
|
|
da4c792046 | ||
|
|
b06528d10c | ||
|
|
662270364b | ||
|
|
413ca8bdeb | ||
|
|
2a97218991 | ||
|
|
ec7b3769b5 | ||
|
|
f07473e1ca | ||
|
|
3be23ad7f9 | ||
|
|
ffd85e6bd1 | ||
|
|
073c89db4b | ||
|
|
04aae0486a | ||
|
|
929147f182 | ||
|
|
eb9241d315 | ||
|
|
0648075555 | ||
|
|
3f81346e6b | ||
|
|
a25fb1348d | ||
|
|
ae1ea99ed3 | ||
|
|
9a381f6d32 | ||
|
|
3a07b4838a | ||
|
|
29de6f2d06 | ||
|
|
73ba73fd03 | ||
|
|
82126ece78 | ||
|
|
9866649fdc | ||
|
|
4ff3f71cb8 | ||
|
|
4abda332de | ||
|
|
c2aecb0597 | ||
|
|
ba71a7a27c | ||
|
|
c8436f519c | ||
|
|
beca56ba3c | ||
|
|
036e790a75 | ||
|
|
5991b07385 | ||
|
|
7ba5f3757d | ||
|
|
ee6ee8139a | ||
|
|
f820b4fd6f | ||
|
|
3bec5d2cab | ||
|
|
b9aa0a2cf1 | ||
|
|
65f2c0fcf1 | ||
|
|
c7d0803000 | ||
|
|
1a4b9b440d | ||
|
|
1f914c2b4d | ||
|
|
fadb316451 | ||
|
|
3fefd3c1fb | ||
|
|
2cbb314d0b | ||
|
|
535fc70433 | ||
|
|
10fa276bec | ||
|
|
e5e38d7f77 | ||
|
|
20134bb96a | ||
|
|
1cc9afaeb3 | ||
|
|
6f5e621561 | ||
|
|
1dd6f2d9f8 | ||
|
|
f92b45db6a | ||
|
|
3a0fe79dd8 | ||
|
|
6598df9ed9 | ||
|
|
c971d54aea | ||
|
|
2abccafb8f | ||
|
|
75d0415bec | ||
|
|
4ff428a9a6 | ||
|
|
d539d8eaf8 | ||
|
|
96889b43a8 | ||
|
|
02a572cbc6 | ||
|
|
3f35a18d41 | ||
|
|
b9c283c89b | ||
|
|
3e96aad10e | ||
|
|
a671c4f86b | ||
|
|
157b1875c5 | ||
|
|
af89ebaeea | ||
|
|
4259f260a9 | ||
|
|
4d973e7ab6 | ||
|
|
d603932e23 | ||
|
|
db64f372f2 | ||
|
|
810e22dc9c | ||
|
|
a3cbc4477f | ||
|
|
6b993b22db | ||
|
|
b8f9d199a8 | ||
|
|
b5ff0a7914 | ||
|
|
4e14e8d22a | ||
|
|
222d1594ca | ||
|
|
3cd252f877 | ||
|
|
b259d376b0 | ||
|
|
fc288bc92b | ||
|
|
7e25684399 | ||
|
|
a0adc8fc74 | ||
|
|
8b042ef470 | ||
|
|
db4ad1a78d | ||
|
|
9c485a952f | ||
|
|
3750a7ebd6 | ||
|
|
989b7339a0 | ||
|
|
d00813e1d6 | ||
|
|
fbf9792b38 | ||
|
|
184dcba882 | ||
|
|
d916fbd7be | ||
|
|
66376f05ec | ||
|
|
d633d6d2a9 | ||
|
|
7a9a6f5169 | ||
|
|
b19f776e68 | ||
|
|
4396ebaa72 | ||
|
|
697b58d33e | ||
|
|
b8129ccd15 | ||
|
|
d50e2a6832 | ||
|
|
8df13adac7 | ||
|
|
d978993d06 | ||
|
|
5862b13dac | ||
|
|
5db9b1bc7b | ||
|
|
fe59f29cbc | ||
|
|
0dfaf3fd35 | ||
|
|
c4b1985076 | ||
|
|
d213266c52 | ||
|
|
29f09e7cd8 | ||
|
|
860130f08c | ||
|
|
d8c3ddca16 | ||
|
|
df67ded9f1 | ||
|
|
5f2297ed7c | ||
|
|
de9fde0d9c | ||
|
|
fe045c13f4 | ||
|
|
b76bdfcb22 | ||
|
|
9b8cc006ba | ||
|
|
c9c85875a5 | ||
|
|
a9e868cb7e | ||
|
|
5622b07047 | ||
|
|
e6223be905 | ||
|
|
cecf973777 | ||
|
|
108fcd46ec | ||
|
|
44b724ea9f | ||
|
|
03b2097173 | ||
|
|
29821069d8 | ||
|
|
3ae2f48846 | ||
|
|
cc730b00b2 | ||
|
|
d23dfb831b | ||
|
|
711747efc0 | ||
|
|
45216c7563 | ||
|
|
a9f42dd945 | ||
|
|
d8cfa1110d | ||
|
|
e41bc9a84f | ||
|
|
0ab14264c0 | ||
|
|
14622ef75b | ||
|
|
4dc4182236 | ||
|
|
12e04a634b | ||
|
|
51f978e78e | ||
|
|
b8e1282eba | ||
|
|
758608419b | ||
|
|
e566c4017c | ||
|
|
35f097542b | ||
|
|
06d3f96706 | ||
|
|
a8d0bf52d2 | ||
|
|
1bcacece65 | ||
|
|
25863c527f | ||
|
|
1905d8804d | ||
|
|
65b9a3f9b6 | ||
|
|
43865b0ad0 | ||
|
|
907f67eb83 | ||
|
|
f205269d97 | ||
|
|
0aa9db450d | ||
|
|
4f121f8289 | ||
|
|
42b8db8609 | ||
|
|
61295bf7ac | ||
|
|
f99ba7f992 | ||
|
|
fa1b94da10 | ||
|
|
16e6a4b170 | ||
|
|
aea8d703e1 | ||
|
|
bb9d0869ac | ||
|
|
aa13e113fa | ||
|
|
6332e78375 | ||
|
|
f1f69c6fdf | ||
|
|
e139e3d999 | ||
|
|
fadaef5105 | ||
|
|
bb1e69e73f | ||
|
|
dc9ad20d99 | ||
|
|
e9111f74c5 | ||
|
|
322b5b4343 | ||
|
|
4e4d2c64b4 | ||
|
|
a1b4d66f47 | ||
|
|
a495bd9605 | ||
|
|
b0b44550a1 | ||
|
|
5b760717bf | ||
|
|
e48a0d9b54 | ||
|
|
1ff345ab1d | ||
|
|
7c9a624eab | ||
|
|
8b50e8d3ad | ||
|
|
6f848254bc | ||
|
|
680d3ccc86 | ||
|
|
e42e2c15e2 | ||
|
|
d41f787efd | ||
|
|
e851f42aee | ||
|
|
2ebd4979b0 | ||
|
|
91b290e474 | ||
|
|
61c75b24bd | ||
|
|
2cd5fa6934 | ||
|
|
453dc6e7ea | ||
|
|
1ec6d2538e | ||
|
|
54a28d65b8 | ||
|
|
9123cbbaef | ||
|
|
9e35866a47 | ||
|
|
a21b69a217 | ||
|
|
933af8c706 | ||
|
|
5514dc577e | ||
|
|
6195ba0896 | ||
|
|
9a3f930148 | ||
|
|
e7e4b0f48b | ||
|
|
74f6d2bb9e | ||
|
|
6df9a98fb6 | ||
|
|
19e88e3e67 | ||
|
|
95ef8eb3de | ||
|
|
25f5bd26b4 | ||
|
|
4e66758048 | ||
|
|
bd13eca0f3 | ||
|
|
4656cf50b5 | ||
|
|
77a5353469 | ||
|
|
4de866de20 | ||
|
|
472edb6e8c | ||
|
|
7982a73aa7 | ||
|
|
a6943af686 | ||
|
|
be87629aba | ||
|
|
c364b20dd9 | ||
|
|
acb8380b61 | ||
|
|
d2bbecc5f5 | ||
|
|
9ef075c67e | ||
|
|
c917a77639 | ||
|
|
e26d7b9c9c | ||
|
|
ba51cbf64e | ||
|
|
62db844911 | ||
|
|
530031e088 | ||
|
|
f601a17daa | ||
|
|
438f05a39a | ||
|
|
7b060f2e7e | ||
|
|
68dea8b258 | ||
|
|
9bb629d0a8 | ||
|
|
2a658d2ff6 | ||
|
|
6c1de427ff | ||
|
|
6967ee0ace | ||
|
|
7ab48613c3 | ||
|
|
67ecd89d5f | ||
|
|
cd55d01f72 | ||
|
|
e4a7e4efa1 | ||
|
|
e409856d62 | ||
|
|
d0be3bd6da | ||
|
|
0f42ba7590 | ||
|
|
964b7ae5f0 | ||
|
|
d946e53c60 | ||
|
|
3aef401092 | ||
|
|
662c425743 | ||
|
|
65bd7ea428 | ||
|
|
9f3194d315 | ||
|
|
5e82625b76 | ||
|
|
c750af1b9a | ||
|
|
5e376db385 | ||
|
|
45cdd6911a | ||
|
|
f898bc0351 | ||
|
|
5fd491a4e7 | ||
|
|
145c526fc1 | ||
|
|
247340632b | ||
|
|
58f189f987 | ||
|
|
f2b857a609 | ||
|
|
e450668b9d | ||
|
|
a33e856b48 | ||
|
|
250df250ff | ||
|
|
dcefae806d | ||
|
|
05a6a21e9e | ||
|
|
ee56748348 | ||
|
|
09ce971708 | ||
|
|
aa84f5583e | ||
|
|
18a2efa8da | ||
|
|
14c10b6631 | ||
|
|
a74f5caaff | ||
|
|
71496cd56a | ||
|
|
2ccd89ed2e | ||
|
|
38403e00b4 | ||
|
|
743ba939ca | ||
|
|
af101d0b41 | ||
|
|
581787a775 | ||
|
|
9fa6fd5133 | ||
|
|
3f28be0854 | ||
|
|
02dd2af0d3 | ||
|
|
0d68d2341b | ||
|
|
9131c37d8e | ||
|
|
597d0685ae | ||
|
|
df5bb9b722 | ||
|
|
62d7d6fbd5 | ||
|
|
5512cee539 | ||
|
|
613f25a79e | ||
|
|
52529b7d05 | ||
|
|
5ecfab3c0e | ||
|
|
39554e11be | ||
|
|
152e2147e6 | ||
|
|
a4e32e7833 | ||
|
|
fb3bfbde70 | ||
|
|
cfde899b2c | ||
|
|
dc7339a174 | ||
|
|
931461e10d | ||
|
|
1edc4ec878 | ||
|
|
4e5741f55d | ||
|
|
b2bdb5c818 | ||
|
|
bfe38d9890 | ||
|
|
87a8af9457 | ||
|
|
e738126bed | ||
|
|
de47771c12 | ||
|
|
578771ffe1 | ||
|
|
683a817c55 | ||
|
|
d190008f2c | ||
|
|
f4e9af18b5 | ||
|
|
620d65e217 | ||
|
|
202f6c71e6 | ||
|
|
ba12b632b4 | ||
|
|
850ef7208d | ||
|
|
1888c2e2a1 | ||
|
|
076de31dcc | ||
|
|
498fabf97d | ||
|
|
862029a0ba | ||
|
|
12628a62d8 | ||
|
|
b6835364b3 | ||
|
|
ae2294c83b | ||
|
|
a8f69fbd2b | ||
|
|
fa1c6ffa33 | ||
|
|
99affffd32 | ||
|
|
fea6a3d1ee | ||
|
|
cafc15197c | ||
|
|
2fc37eef61 | ||
|
|
fec67b7622 | ||
|
|
b7703e30f9 | ||
|
|
28d13b57d6 | ||
|
|
95074b4834 | ||
|
|
f5be0fae3d | ||
|
|
a946a0cb44 | ||
|
|
8406ff04b7 | ||
|
|
f04c1f7fa8 | ||
|
|
925d92c4b8 | ||
|
|
6fc53fdfe7 | ||
|
|
9757b9900e | ||
|
|
33f37ae593 | ||
|
|
6a25dbfb05 | ||
|
|
d833ebadfc | ||
|
|
091f5df97d | ||
|
|
cda099a2f2 | ||
|
|
3b9df0d110 | ||
|
|
852f7a6468 | ||
|
|
79e691e4f3 | ||
|
|
be24f18d84 | ||
|
|
e20a41a186 | ||
|
|
360d2c9005 | ||
|
|
fd03eb95eb | ||
|
|
db4f2db748 | ||
|
|
e9f00dcb75 | ||
|
|
5ece17d67a | ||
|
|
e64b1f67c1 | ||
|
|
c9e8368694 | ||
|
|
f556f611b0 | ||
|
|
0b500d8e05 | ||
|
|
b91d96278b | ||
|
|
6122051431 | ||
|
|
9b4419088c | ||
|
|
b47c3c482d | ||
|
|
50dc701ec4 | ||
|
|
87437fbddc | ||
|
|
25977408df | ||
|
|
9d3b31b56e | ||
|
|
d343bce815 | ||
|
|
69efddafec | ||
|
|
ca0a2cba15 | ||
|
|
58d774a3f3 | ||
|
|
320771d7f8 | ||
|
|
9d6229df58 | ||
|
|
33a291f760 | ||
|
|
d4c832b8de | ||
|
|
0b3fda9da8 | ||
|
|
3f620ecf19 | ||
|
|
85d803afcf | ||
|
|
2dab31209e | ||
|
|
95980c5e14 | ||
|
|
31db42ae0e | ||
|
|
830cbd852e | ||
|
|
c15c69fb08 | ||
|
|
5ab47ef815 | ||
|
|
9ba0625824 | ||
|
|
2907eb074d | ||
|
|
40a4b58757 | ||
|
|
0fc04fc34e | ||
|
|
038c9ef23c | ||
|
|
fffb2e2cbc | ||
|
|
58ef298a42 | ||
|
|
6f01c38a71 | ||
|
|
23c17ca841 | ||
|
|
a66e8eb8ed | ||
|
|
42582158bf | ||
|
|
1864a3e6ba | ||
|
|
07b35bb20f | ||
|
|
a8a2de9d24 | ||
|
|
da24bb2bfc | ||
|
|
9ea2494940 | ||
|
|
5459ad3e7e | ||
|
|
b94620819c | ||
|
|
290db0105f | ||
|
|
a7f7ab0ef9 | ||
|
|
87a4e09862 | ||
|
|
121e2b34b5 | ||
|
|
3ccf780ed3 | ||
|
|
a92aa66358 | ||
|
|
84d28a0476 | ||
|
|
cdb90aa35c | ||
|
|
aa63457d9c | ||
|
|
6f46e2deb6 | ||
|
|
c11e17b5e2 | ||
|
|
e5a74344f3 | ||
|
|
24e71b5a39 | ||
|
|
b437b78668 | ||
|
|
cd813a14b1 | ||
|
|
adadcbc982 | ||
|
|
8443265142 | ||
|
|
d00cc73261 | ||
|
|
62f18bdc2c | ||
|
|
f8365cc939 | ||
|
|
273cad8318 | ||
|
|
f5dd87b02a | ||
|
|
1249a4c491 | ||
|
|
757113c002 | ||
|
|
110dfbd13c | ||
|
|
9fd29871ca | ||
|
|
c921120216 | ||
|
|
d248bca299 | ||
|
|
90c4fd3328 | ||
|
|
e6fabc81b3 | ||
|
|
adb54e3b87 | ||
|
|
f1c1524e61 | ||
|
|
a830d9b082 | ||
|
|
9e5aac759d | ||
|
|
87c823d497 | ||
|
|
610d393923 | ||
|
|
bec53bd836 | ||
|
|
4682fb3ec8 | ||
|
|
e266634560 | ||
|
|
a37bae5b9d | ||
|
|
a5ad4cd0a5 | ||
|
|
8deb39ac76 | ||
|
|
8aa18fbf20 |
@@ -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
|
||||
101
.github/ISSUE_TEMPLATE/minor_release.md
vendored
Normal file
101
.github/ISSUE_TEMPLATE/minor_release.md
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
name: Minor Release
|
||||
about: Create a new minor release [for release managers only]
|
||||
title: 'Release MAJOR.MINOR+1.0'
|
||||
labels: 'release'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Create a new minor release
|
||||
|
||||
### Summary
|
||||
|
||||
<--release summary to be used in announcements-->
|
||||
|
||||
### Commit
|
||||
|
||||
<--latest commit ID to include in this release-->
|
||||
|
||||
### Changelog
|
||||
|
||||
<--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
|
||||
|
||||
### Checklist
|
||||
|
||||
Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
|
||||
branch **development** version is *MAJOR.MINOR.0*.
|
||||
|
||||
#### On the day of the feature freeze
|
||||
|
||||
Change the `master` branch to the next MINOR+1 version:
|
||||
|
||||
- [ ] Switch to the `master` branch.
|
||||
- [ ] Create a new PR branch called `bump_dev_MAJOR_MINOR+1`, eg. `bump_dev_0_22`.
|
||||
- [ ] Bump the `bump_dev_MAJOR_MINOR+1` branch to the next development MINOR+1 version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR+1.0".
|
||||
- [ ] Create PR and merge the `bump_dev_MAJOR_MINOR+1` branch to `master`.
|
||||
- Title PR "Bump version to MAJOR.MINOR+1.0".
|
||||
|
||||
Create a new release branch:
|
||||
|
||||
- [ ] Double check that your local `master` is up-to-date with the upstream repo.
|
||||
- [ ] Create a new branch called `release/MAJOR.MINOR+1` from `master`.
|
||||
|
||||
Add a release candidate tag, this is optional and only needed for major `bdk-ffi` changes that
|
||||
require a longer testing cycle:
|
||||
|
||||
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0-rc.1` version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0-rc.1`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR+1.0-rc.1".
|
||||
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
|
||||
- The tag name should be `vMAJOR.MINOR+1.0-rc.1`
|
||||
- Use message "Release MAJOR.MINOR+1.0 rc.1".
|
||||
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
|
||||
- [ ] Push the `release/MAJOR.MINOR` branch and new tag to the `bitcoindevkit/bdk` repo.
|
||||
- Use `git push --tags` option to push the new `vMAJOR.MINOR+1.0-rc.1` tag.
|
||||
|
||||
If any issues need to be fixed before the *MAJOR.MINOR+1.0* version is released:
|
||||
|
||||
- [ ] Merge fix PRs to the `master` branch.
|
||||
- [ ] Git cherry-pick fix commits to the `release/MAJOR.MINOR+1` branch.
|
||||
- [ ] Verify fixes in `release/MAJOR.MINOR+1` branch.
|
||||
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0-rc.x+1` version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0-rc.x+1`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR+1.0-rc.x+1".
|
||||
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
|
||||
- The tag name should be `vMAJOR.MINOR+1.0-rc.x+1`, where x is the current release candidate number.
|
||||
- Use tag message "Release MAJOR.MINOR+1.0 rc.x+1".
|
||||
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
|
||||
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
|
||||
- Use `git push --tags` option to push the new `vMAJOR.MINOR+1.0-rc.x+1` tag.
|
||||
|
||||
#### On the day of the release
|
||||
|
||||
Tag and publish new release:
|
||||
|
||||
- [ ] Bump the `release/MAJOR.MINOR+1` branch to `MAJOR.MINOR+1.0` version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR+1.0`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR+1.0".
|
||||
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR+1` branch.
|
||||
- The tag name should be `vMAJOR.MINOR+1.0`
|
||||
- The first line of the tag message should be "Release MAJOR.MINOR+1.0".
|
||||
- In the body of the tag message put a copy of the **Summary** and **Changelog** for the release.
|
||||
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
|
||||
- [ ] Wait for the CI to finish one last time.
|
||||
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
|
||||
- [ ] Create the release on GitHub.
|
||||
- Go to "tags", click on the dots on the right and select "Create Release".
|
||||
- Set the title to `Release MAJOR.MINOR+1.0`.
|
||||
- In the release notes body put the **Summary** and **Changelog**.
|
||||
- Use the "+ Auto-generate release notes" button to add details from included PRs.
|
||||
- Until we reach a `1.0.0` release check the "Pre-release" box.
|
||||
- [ ] After downstream language repos are also updated announce the release, using the **Summary**,
|
||||
on Discord, Twitter and Mastodon.
|
||||
- [ ] Celebrate 🎉
|
||||
|
||||
[Semantic Versioning]: https://semver.org/
|
||||
[crates.io]: https://crates.io/crates/bdk
|
||||
[docs.rs]: https://docs.rs/bdk/latest/bdk
|
||||
["keep a changelog"]: https://keepachangelog.com/en/1.0.0/
|
||||
69
.github/ISSUE_TEMPLATE/patch_release.md
vendored
Normal file
69
.github/ISSUE_TEMPLATE/patch_release.md
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
---
|
||||
name: Patch Release
|
||||
about: Create a new patch release [for release managers only]
|
||||
title: 'Release MAJOR.MINOR.PATCH+1'
|
||||
labels: 'release'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Create a new patch release
|
||||
|
||||
### Summary
|
||||
|
||||
<--release summary to be used in announcements-->
|
||||
|
||||
### Commit
|
||||
|
||||
<--latest commit ID to include in this release-->
|
||||
|
||||
### Changelog
|
||||
|
||||
<--add notices from PRs merged since the prior release, see ["keep a changelog"]-->
|
||||
|
||||
### Checklist
|
||||
|
||||
Release numbering must follow [Semantic Versioning]. These steps assume the current `master`
|
||||
branch **development** version is *MAJOR.MINOR.PATCH*.
|
||||
|
||||
### On the day of the patch release
|
||||
|
||||
Change the `master` branch to the new PATCH+1 version:
|
||||
|
||||
- [ ] Switch to the `master` branch.
|
||||
- [ ] Create a new PR branch called `bump_dev_MAJOR_MINOR_PATCH+1`, eg. `bump_dev_0_22_1`.
|
||||
- [ ] Bump the `bump_dev_MAJOR_MINOR` branch to the next development PATCH+1 version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR.PATCH+1`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR.PATCH+1".
|
||||
- [ ] Create PR and merge the `bump_dev_MAJOR_MINOR_PATCH+1` branch to `master`.
|
||||
- Title PR "Bump version to MAJOR.MINOR.PATCH+1".
|
||||
|
||||
Cherry-pick, tag and publish new PATCH+1 release:
|
||||
|
||||
- [ ] Merge fix PRs to the `master` branch.
|
||||
- [ ] Git cherry-pick fix commits to the `release/MAJOR.MINOR` branch to be patched.
|
||||
- [ ] Verify fixes in `release/MAJOR.MINOR` branch.
|
||||
- [ ] Bump the `release/MAJOR.MINOR.PATCH+1` branch to `MAJOR.MINOR.PATCH+1` version.
|
||||
- Change the `Cargo.toml` version value to `MAJOR.MINOR.MINOR.PATCH+1`.
|
||||
- The commit message should be "Bump version to MAJOR.MINOR.PATCH+1".
|
||||
- [ ] Add a tag to the `HEAD` commit in the `release/MAJOR.MINOR` branch.
|
||||
- The tag name should be `vMAJOR.MINOR.PATCH+1`
|
||||
- The first line of the tag message should be "Release MAJOR.MINOR.PATCH+1".
|
||||
- In the body of the tag message put a copy of the **Summary** and **Changelog** for the release.
|
||||
- Make sure the tag is signed, for extra safety use the explicit `--sign` flag.
|
||||
- [ ] Wait for the CI to finish one last time.
|
||||
- [ ] Push the new tag to the `bitcoindevkit/bdk` repo.
|
||||
- [ ] Create the release on GitHub.
|
||||
- Go to "tags", click on the dots on the right and select "Create Release".
|
||||
- Set the title to `Release MAJOR.MINOR.PATCH+1`.
|
||||
- In the release notes body put the **Summary** and **Changelog**.
|
||||
- Use the "+ Auto-generate release notes" button to add details from included PRs.
|
||||
- Until we reach a `1.0.0` release check the "Pre-release" box.
|
||||
- [ ] After downstream language repos are also updated announce the release, using the **Summary**,
|
||||
on Discord, Twitter and Mastodon.
|
||||
- [ ] Celebrate 🎉
|
||||
|
||||
[Semantic Versioning]: https://semver.org/
|
||||
[crates.io]: https://crates.io/crates/bdk
|
||||
[docs.rs]: https://docs.rs/bdk/latest/bdk
|
||||
["keep a changelog"]: https://keepachangelog.com/en/1.0.0/
|
||||
8
.github/pull_request_template.md
vendored
8
.github/pull_request_template.md
vendored
@@ -1,4 +1,4 @@
|
||||
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
||||
<!-- Erase any parts of this template not applicable to your Pull Request. -->
|
||||
|
||||
### Description
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
<!-- 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:
|
||||
@@ -21,7 +26,6 @@ of the PR were done in a specific way -->
|
||||
|
||||
* [ ] I've added tests for the new feature
|
||||
* [ ] I've added docs for the new feature
|
||||
* [ ] I've updated `CHANGELOG.md`
|
||||
|
||||
#### Bugfixes:
|
||||
|
||||
|
||||
4
.github/workflows/audit.yml
vendored
4
.github/workflows/audit.yml
vendored
@@ -9,11 +9,11 @@ on:
|
||||
- cron: '0 0 * * 0' # Once per week
|
||||
|
||||
jobs:
|
||||
|
||||
security_audit:
|
||||
name: Security Audit
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions-rs/audit-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
126
.github/workflows/build-python-wheels.yaml
vendored
Normal file
126
.github/workflows/build-python-wheels.yaml
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
name: Build Python wheels
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-python/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-python/**"
|
||||
|
||||
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
|
||||
# makes it very hard to use GitHub's javascript actions (checkout, upload-artifact, etc).
|
||||
# They mount their own nodejs interpreter inside your container, but since that's not statically linked it
|
||||
# tries to load glibc and fails because it requires a more recent version.
|
||||
|
||||
jobs:
|
||||
build-manylinux2014-x86_64-wheel:
|
||||
name: 'Build Manylinux 2014 x86_64 wheel'
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
container:
|
||||
image: quay.io/pypa/manylinux2014_x86_64
|
||||
env:
|
||||
PLAT: manylinux2014_x86_64
|
||||
PYBIN: '/opt/python/${{ matrix.python }}/bin'
|
||||
strategy:
|
||||
matrix:
|
||||
python: # Update this list whenever the docker image is updated (check /opt/python/)
|
||||
# - cp36-cp36m
|
||||
# - cp37-cp37m
|
||||
# - cp38-cp38
|
||||
# - cp39-cp39
|
||||
- cp310-cp310
|
||||
# - pp37-pypy37_pp73
|
||||
# - pp38-pypy38_pp73
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: install requirements
|
||||
run: ${PYBIN}/pip install -r requirements.txt
|
||||
- name: generate bindings
|
||||
run: bash generate.sh
|
||||
- name: build wheel
|
||||
run: ${PYBIN}/pip wheel . --no-deps -w /tmp/wheelhouse
|
||||
- name: repair wheel
|
||||
run: auditwheel repair /tmp/wheelhouse/* --plat "$PLAT" -w /tmp/wheelhouse-repaired
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
||||
path: /tmp/wheelhouse-repaired/*.whl
|
||||
|
||||
build-macos-universal-wheel:
|
||||
name: 'Build macOS universal wheel'
|
||||
runs-on: macos-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
# - '3.7'
|
||||
# - '3.8'
|
||||
# - '3.9'
|
||||
- '3.10'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- run: python3 --version
|
||||
- run: rustup target add aarch64-apple-darwin
|
||||
- run: pip3 install --user -r requirements.txt
|
||||
- run: pip3 install --user wheel
|
||||
- run: bash generate.sh
|
||||
- name: build wheel
|
||||
env:
|
||||
ARCHFLAGS: "-arch x86_64 -arch arm64"
|
||||
run: python3 setup.py -v bdist_wheel
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-macos-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
|
||||
build-windows-wheel:
|
||||
name: 'Build windows wheel'
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
# - '3.7'
|
||||
# - '3.8'
|
||||
# - '3.9'
|
||||
- '3.10'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- run: python --version
|
||||
- run: pip install --user -r requirements.txt
|
||||
- run: bash generate.sh
|
||||
shell: bash
|
||||
- run: pip install --user wheel
|
||||
- name: build wheel
|
||||
run: python setup.py -v bdist_wheel
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-win-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
13
.github/workflows/cont_integration.yml
vendored
13
.github/workflows/cont_integration.yml
vendored
@@ -1,6 +1,11 @@
|
||||
on: [push, pull_request]
|
||||
|
||||
name: CI
|
||||
name: bdk-ffi CI
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -41,7 +46,7 @@ jobs:
|
||||
if: ${{ matrix.rust.clippy }}
|
||||
run: cargo clippy --all-targets -- -D warnings
|
||||
- name: Test
|
||||
run: cargo test
|
||||
run: CLASSPATH=./tests/jna/jna-5.8.0.jar cargo test
|
||||
|
||||
fmt:
|
||||
name: Rust fmt
|
||||
|
||||
55
.github/workflows/publish-android.yaml
vendored
Normal file
55
.github/workflows/publish-android.yaml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Publish bdk-android to Maven Central
|
||||
on: [workflow_dispatch]
|
||||
|
||||
env:
|
||||
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
|
||||
# By default, the new ubuntu-20.04 images use the following ANDROID_NDK_ROOT
|
||||
# ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.0.8775105
|
||||
|
||||
jobs:
|
||||
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@v2
|
||||
|
||||
- name: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./target
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- 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
|
||||
93
.github/workflows/publish-jvm.yaml
vendored
Normal file
93
.github/workflows/publish-jvm.yaml
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
name: Publish bdk-jvm to Maven Central
|
||||
on: [workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build-jvm-macOS-M1-native-lib:
|
||||
name: Create M1 and x86_64 JVM native binaries
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- name: Checkout publishing branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Install aarch64 Rust target
|
||||
run: rustup target add aarch64-apple-darwin
|
||||
|
||||
- name: Build bdk-jvm library
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
./gradlew buildJvmLib
|
||||
|
||||
# build aarch64 + x86_64 native libraries and upload
|
||||
- name: Upload macOS native libraries for reuse in publishing job
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
# name: no name is required because we upload the entire directory
|
||||
# the default name "artifact" will be used
|
||||
path: /Users/runner/work/bdk-ffi/bdk-ffi/bdk-jvm/lib/src/main/resources/
|
||||
|
||||
build-jvm-full-library:
|
||||
name: Create full bdk-jvm library
|
||||
needs: [build-jvm-macOS-M1-native-lib]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout publishing branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Update bdk-ffi git submodule
|
||||
run: |
|
||||
git submodule set-url bdk-ffi https://github.com/bitcoindevkit/bdk-ffi.git
|
||||
git submodule update --init bdk-ffi
|
||||
|
||||
- name: Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./target
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Build bdk-jvm library
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
./gradlew buildJvmLib
|
||||
|
||||
- name: Download macOS native libraries from previous job
|
||||
uses: actions/download-artifact@v3
|
||||
id: download
|
||||
with:
|
||||
# download the artifact created in the prior job (named "artifact")
|
||||
name: artifact
|
||||
path: ./bdk-jvm/lib/src/main/resources/
|
||||
|
||||
- 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
|
||||
153
.github/workflows/publish-python.yaml
vendored
Normal file
153
.github/workflows/publish-python.yaml
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
name: Build and publish Python wheels
|
||||
on: [workflow_dispatch]
|
||||
|
||||
# We use manylinux2014 because older CentOS versions used by 2010 and 1 have a very old glibc version, which
|
||||
# makes it very hard to use GitHub's javascript actions (checkout, upload-artifact, etc).
|
||||
# They mount their own nodejs interpreter inside your container, but since that's not statically linked it
|
||||
# tries to load glibc and fails because it requires a more recent version.
|
||||
|
||||
jobs:
|
||||
build-manylinux2014-x86_64-wheel:
|
||||
name: 'Build Manylinux 2014 x86_64 wheel'
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
container:
|
||||
image: quay.io/pypa/manylinux2014_x86_64
|
||||
env:
|
||||
PLAT: manylinux2014_x86_64
|
||||
PYBIN: '/opt/python/${{ matrix.python }}/bin'
|
||||
strategy:
|
||||
matrix:
|
||||
python: # Update this list whenever the docker image is updated (check /opt/python/)
|
||||
- cp36-cp36m
|
||||
- cp37-cp37m
|
||||
- cp38-cp38
|
||||
- cp39-cp39
|
||||
- cp310-cp310
|
||||
- pp37-pypy37_pp73
|
||||
- pp38-pypy38_pp73
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
- name: install requirements
|
||||
run: ${PYBIN}/pip install -r requirements.txt
|
||||
- name: generate bindings
|
||||
run: bash generate.sh
|
||||
- name: build wheel
|
||||
run: ${PYBIN}/pip wheel . --no-deps -w /tmp/wheelhouse
|
||||
- name: repair wheel
|
||||
run: auditwheel repair /tmp/wheelhouse/* --plat "$PLAT" -w /tmp/wheelhouse-repaired
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-manylinux2014-x86_64-${{ matrix.python }}
|
||||
path: /tmp/wheelhouse-repaired/*.whl
|
||||
|
||||
build-macos-universal-wheel:
|
||||
name: 'Build macOS universal wheel'
|
||||
runs-on: macos-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- run: python3 --version
|
||||
- run: rustup target add aarch64-apple-darwin
|
||||
- run: pip3 install --user -r requirements.txt
|
||||
- run: pip3 install --user wheel
|
||||
- run: bash generate.sh
|
||||
- name: build wheel
|
||||
env:
|
||||
ARCHFLAGS: "-arch x86_64 -arch arm64"
|
||||
run: python3 setup.py -v bdist_wheel
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-macos-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
|
||||
build-windows-wheel:
|
||||
name: 'Build windows wheel'
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
strategy:
|
||||
matrix:
|
||||
python:
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
- run: python --version
|
||||
- run: pip install --user -r requirements.txt
|
||||
- run: bash generate.sh
|
||||
shell: bash
|
||||
- run: pip install --user wheel
|
||||
- name: build wheel
|
||||
run: python setup.py -v bdist_wheel
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: bdkpython-win-${{ matrix.python }}
|
||||
path: dist/*.whl
|
||||
|
||||
publish-pypi:
|
||||
name: 'Publish on PyPI'
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: bdk-python
|
||||
needs: [build-manylinux2014-x86_64-wheel, build-macos-universal-wheel, build-windows-wheel]
|
||||
# needs: [build-macos-universal-wheel]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: 'Download artifacts in dist/ directory'
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
path: dist/
|
||||
|
||||
# - name: Display structure of downloaded files
|
||||
# run: ls -R
|
||||
|
||||
# - name: 'Publish on test PyPI'
|
||||
# uses: pypa/gh-action-pypi-publish@release/v1
|
||||
# with:
|
||||
# user: __token__
|
||||
# password: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
||||
# repository_url: https://test.pypi.org/legacy/
|
||||
# packages_dir: dist/*/
|
||||
|
||||
- name: 'Publish on PyPI'
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||||
packages_dir: dist/*/
|
||||
57
.github/workflows/test-android.yaml
vendored
Normal file
57
.github/workflows/test-android.yaml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: Test Android
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-android/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-android/**"
|
||||
|
||||
env:
|
||||
ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/21.4.7075529
|
||||
# By default, the new ubuntu-20.04 images use the following ANDROID_NDK_ROOT
|
||||
# ANDROID_NDK_ROOT: /usr/local/lib/android/sdk/ndk/25.0.8775105
|
||||
|
||||
jobs:
|
||||
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@v2
|
||||
|
||||
- name: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./target
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- 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: Run Android tests
|
||||
run: |
|
||||
cd bdk-android
|
||||
./gradlew test --console=rich
|
||||
42
.github/workflows/test-jvm.yaml
vendored
Normal file
42
.github/workflows/test-jvm.yaml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Test JVM
|
||||
on:
|
||||
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@v2
|
||||
|
||||
- name: cache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
./target
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/Cargo.toml','**/Cargo.lock') }}
|
||||
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 11
|
||||
|
||||
- name: Build bdk-jvm library
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
./gradlew buildJvmLib
|
||||
|
||||
- name: Run JVM tests
|
||||
run: |
|
||||
cd bdk-jvm
|
||||
./gradlew test --console=rich
|
||||
51
.github/workflows/test-swift.yaml
vendored
Normal file
51
.github/workflows/test-swift.yaml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Test Swift
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-swift/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- "bdk-ffi/**"
|
||||
- "bdk-swift/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- name: Checkout branch
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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 --package bdk-ffi-bindgen -- --language swift --out-dir ../bdk-swift/Sources/BitcoinDevKit
|
||||
|
||||
- name: Build bdk-ffi for x86_64-apple-darwin
|
||||
run: cargo build --profile release-smaller --target x86_64-apple-darwin
|
||||
|
||||
- name: Build bdk-ffi for aarch64-apple-darwin
|
||||
run: cargo build --profile release-smaller --target aarch64-apple-darwin
|
||||
|
||||
- name: Create lipo-ios-sim and 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
|
||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,7 +1,5 @@
|
||||
target
|
||||
build
|
||||
Cargo.lock
|
||||
/bindings/bdk-kotlin/local.properties
|
||||
.gradle
|
||||
wallet_db
|
||||
bdk_ffi_test
|
||||
@@ -15,3 +13,21 @@ 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
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
All notable changes to this project prior to release **0.9.0** are documented in this file. Future
|
||||
changelog information can be found in each release's git tag and can be viewed with `git tag -ln100 "v*"`.
|
||||
Changelog info is also documented on the [GitHub releases](https://github.com/bitcoindevkit/bdk-ffi/releases)
|
||||
page. See [DEVELOPMENT_CYCLE.md](DEVELOPMENT_CYCLE.md) for more details.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
1545
Cargo.lock
generated
Normal file
1545
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
31
Cargo.toml
31
Cargo.toml
@@ -1,23 +1,12 @@
|
||||
[package]
|
||||
name = "bdk-ffi"
|
||||
version = "0.9.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", "bdk-ffi-bindgen"]
|
||||
default-members = ["bdk-ffi", "bdk-ffi-bindgen"]
|
||||
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.22", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
|
||||
|
||||
uniffi_macros = { version = "0.19.3", features = ["builtin-bindgen"] }
|
||||
uniffi = { version = "0.19.3", features = ["builtin-bindgen"] }
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = { version = "0.19.3", 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
35
DEVELOPMENT_CYCLE.md
Normal 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
14
PGP-BDK-BINDINGS.asc
Normal 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-----
|
||||
157
README.md
157
README.md
@@ -5,71 +5,152 @@
|
||||
<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>
|
||||
</p>
|
||||
|
||||
The workspace in this repository creates the `libbdkffi` multi-language library for the rust based
|
||||
The workspace in this repository creates the `libbdkffi` multi-language library for the Rust-based
|
||||
[bdk] library from the [Bitcoin Dev Kit] project. The `bdk-ffi-bindgen` package builds a tool for
|
||||
generating the actual language binding code used to access the `libbdkffi` library.
|
||||
|
||||
Each supported language has its own repository that includes this project as a [git submodule].
|
||||
The rust code in this project is a wrapper around the [bdk] library to expose it's APIs in a
|
||||
uniform way using the [mozilla/uniffi-rs] bindings generator for each supported target language.
|
||||
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 | Repository |
|
||||
| -------- | ------------ | ------------ |
|
||||
| Kotlin | jvm | [bdk-kotlin] |
|
||||
| Kotlin | android | [bdk-kotlin] |
|
||||
| Swift | iOS, macOS | [bdk-swift] |
|
||||
| Python | linux, macOS | [bdk-python] |
|
||||
| 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 bindings generator tool
|
||||
|
||||
Use the `bdk-ffi-bindgen` tool to generate language binding code for the above supported languages.
|
||||
To run `bdk-ffi-bindgen` and see the available options use the command:
|
||||
```shell
|
||||
cargo run -p bdk-ffi-bindgen -- --help
|
||||
```
|
||||
|
||||
[bdk]: https://github.com/bitcoindevkit/bdk
|
||||
[Bitcoin Dev Kit]: https://github.com/bitcoindevkit
|
||||
[git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules
|
||||
[uniffi-rs]: https://github.com/mozilla/uniffi-rs
|
||||
|
||||
[bdk-kotlin]: https://github.com/bitcoindevkit/bdk-kotlin
|
||||
[bdk-swift]: https://github.com/bitcoindevkit/bdk-swift
|
||||
[bdk-python]: https://github.com/bitcoindevkit/bdk-python
|
||||
|
||||
## Contributing
|
||||
|
||||
### Adding new structs and functions
|
||||
|
||||
See the [UniFFI User Guide](https://mozilla.github.io/uniffi-rs/)
|
||||
|
||||
#### For pass by value objects
|
||||
1. Create new rust struct with only fields that are supported UniFFI types
|
||||
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/
|
||||
|
||||
4
api-docs/kotlin/Module1.md
Normal file
4
api-docs/kotlin/Module1.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# Module bdk-android
|
||||
The [bitcoindevkit](https://bitcoindevkit.org/) language bindings library for Android.
|
||||
|
||||
# Package org.bitcoindevkit
|
||||
4
api-docs/kotlin/Module2.md
Normal file
4
api-docs/kotlin/Module2.md
Normal 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
|
||||
46
api-docs/kotlin/build.gradle.kts
Normal file
46
api-docs/kotlin/build.gradle.kts
Normal 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")
|
||||
}
|
||||
}
|
||||
}
|
||||
8
api-docs/kotlin/deploy.sh
Normal file
8
api-docs/kotlin/deploy.sh
Normal 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
|
||||
1
api-docs/kotlin/gradle.properties
Normal file
1
api-docs/kotlin/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
kotlin.code.style=official
|
||||
BIN
api-docs/kotlin/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
api-docs/kotlin/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
api-docs/kotlin/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
api-docs/kotlin/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
234
api-docs/kotlin/gradlew
vendored
Executable 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
89
api-docs/kotlin/gradlew.bat
vendored
Normal 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
|
||||
1
api-docs/kotlin/settings.gradle.kts
Normal file
1
api-docs/kotlin/settings.gradle.kts
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = "BDK Android and BDK JVM API Docs"
|
||||
595
api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt
Normal file
595
api-docs/kotlin/src/main/kotlin/org/bitcoindevkit/bdk.kt
Normal file
@@ -0,0 +1,595 @@
|
||||
package org.bitcoindevkit
|
||||
|
||||
/**
|
||||
* The cryptocurrency to act on.
|
||||
*
|
||||
* @sample org.bitcoindevkit.networkSample
|
||||
*/
|
||||
enum class Network {
|
||||
/** Bitcoin's mainnet. */
|
||||
BITCOIN,
|
||||
|
||||
/** Bitcoin’s testnet. */
|
||||
TESTNET,
|
||||
|
||||
/** Bitcoin’s signet. */
|
||||
SIGNET,
|
||||
|
||||
/** Bitcoin’s regtest. */
|
||||
REGTEST,
|
||||
}
|
||||
|
||||
/**
|
||||
* A derived address and the index it was found at.
|
||||
*
|
||||
* @property index Child index of this address.
|
||||
* @property address Address.
|
||||
*
|
||||
* @sample org.bitcoindevkit.addressInfoSample
|
||||
*/
|
||||
data class AddressInfo (
|
||||
var index: UInt,
|
||||
var address: String
|
||||
)
|
||||
|
||||
/**
|
||||
* The address index selection strategy to use to derive an address from the wallet’s external descriptor.
|
||||
*
|
||||
* If you’re unsure which one to use, use `AddressIndex.NEW`.
|
||||
*
|
||||
* @sample org.bitcoindevkit.addressIndexSample
|
||||
*/
|
||||
enum class 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.
|
||||
*/
|
||||
LAST_UNUSED,
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @sample org.bitcoindevkit.electrumBlockchainConfigSample
|
||||
*/
|
||||
data class ElectrumConfig (
|
||||
var url: String,
|
||||
var socks5: String?,
|
||||
var retry: UByte,
|
||||
var timeout: UByte?,
|
||||
var stopGap: ULong
|
||||
)
|
||||
|
||||
/**
|
||||
* 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?
|
||||
)
|
||||
|
||||
/**
|
||||
* 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()
|
||||
}
|
||||
|
||||
/**
|
||||
* A wallet transaction.
|
||||
*
|
||||
* @property fee Fee value (sats) if available. 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.
|
||||
* @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 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(psbt: PartiallySignedBitcoinTransaction): String {}
|
||||
|
||||
/** Get the current height of the blockchain. */
|
||||
fun getHeight(): UInt {}
|
||||
|
||||
/** Get the block hash of a given block. */
|
||||
fun getBlockHash(height: UInt): String {}
|
||||
}
|
||||
|
||||
/**
|
||||
* A partially signed bitcoin transaction.
|
||||
*
|
||||
* @constructor Build a new Partially Signed Bitcoin Transaction.
|
||||
*
|
||||
* @param psbtBase64 The PSBT in base64 format.
|
||||
*/
|
||||
class PartiallySignedBitcoinTransaction(psbtBase64: String) {
|
||||
/** Return the PSBT in string format, using a base64 encoding. */
|
||||
fun serialize(): String {}
|
||||
|
||||
/** Get the txid of the PSBT. */
|
||||
fun txid(): String {}
|
||||
|
||||
/** Return the transaction as bytes. */
|
||||
fun extractTx(): List<UByte>
|
||||
|
||||
/**
|
||||
* 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: PartiallySignedBitcoinTransaction): PartiallySignedBitcoinTransaction
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to a transaction output.
|
||||
*
|
||||
* @property txid The referenced transaction’s txid.
|
||||
* @property vout The index of the referenced output in its transaction’s 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 address The address of the output.
|
||||
*/
|
||||
data class TxOut (
|
||||
var value: ULong,
|
||||
var address: String
|
||||
)
|
||||
|
||||
/**
|
||||
* 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: String,
|
||||
changeDescriptor: String,
|
||||
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 the balance, meaning the sum of this wallet’s unspent outputs’ values. Note that this method only operates on the internal database, which first needs to be [Wallet.sync] manually. */
|
||||
fun getBalance(): ULong {}
|
||||
|
||||
/** Sign a transaction with all the wallet’s signers. */
|
||||
fun sign(psbt: PartiallySignedBitcoinTransaction): 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(): 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. It’s 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. It’s 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(address: String): 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 {}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 can’t 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
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: PartiallySignedBitcoinTransaction,
|
||||
var transactionDetails: TransactionDetails
|
||||
)
|
||||
|
||||
/**
|
||||
* A bitcoin script.
|
||||
*/
|
||||
class Script(rawOutputScript: List<UByte>)
|
||||
|
||||
/**
|
||||
* A bitcoin address.
|
||||
*
|
||||
* @param address The address in string format.
|
||||
*/
|
||||
class Address(address: String) {
|
||||
/* Return the ScriptPubKey. */
|
||||
fun scriptPubkey(): Script
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
245
api-docs/kotlin/src/test/kotlin/org/bitcoindevkit/Samples.kt
Normal file
245
api-docs/kotlin/src/test/kotlin/org/bitcoindevkit/Samples.kt
Normal file
@@ -0,0 +1,245 @@
|
||||
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 getLastUnusedAddress(): AddressInfo {
|
||||
return wallet.getAddress(AddressIndex.LAST_UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
fun addressInfoSample() {
|
||||
val wallet: Wallet = Wallet(
|
||||
descriptor = descriptor,
|
||||
changeDescriptor = changeDescriptor,
|
||||
network = Network.TESTNET,
|
||||
databaseConfig = DatabaseConfig.Memory
|
||||
)
|
||||
|
||||
fun getLastUnusedAddress(): AddressInfo {
|
||||
return wallet.getAddress(AddressIndex.NEW)
|
||||
}
|
||||
|
||||
val newAddress: AddressInfo = getLastUnusedAddress()
|
||||
|
||||
println("New address at index ${newAddress.index} is ${newAddress.address}")
|
||||
}
|
||||
|
||||
fun blockchainSample() {
|
||||
val blockchainConfig: BlockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig(
|
||||
electrumURL,
|
||||
null,
|
||||
5u,
|
||||
null,
|
||||
10u
|
||||
)
|
||||
)
|
||||
|
||||
val blockchain: Blockchain = Blockchain(blockchainConfig)
|
||||
|
||||
blockchain.broadcast(signedPsbt)
|
||||
}
|
||||
|
||||
|
||||
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())
|
||||
}
|
||||
99
bdk-android/README.md
Normal file
99
bdk-android/README.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# 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 = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
|
||||
|
||||
val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u)
|
||||
)
|
||||
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
|
||||
val newAddress = wallet.getAddress(AddressIndex.LAST_UNUSED)
|
||||
```
|
||||
|
||||
### 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. If building on macOS install required intel and m1 jvm targets
|
||||
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 (NDK major version 21 is required):
|
||||
```shell
|
||||
export ANDROID_SDK_ROOT=~/Android/Sdk
|
||||
export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/21.<NDK_VERSION>
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
[`bdk`]: https://github.com/bitcoindevkit/bdk
|
||||
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
|
||||
36
bdk-android/build.gradle.kts
Normal file
36
bdk-android/build.gradle.kts
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
5
bdk-android/gradle.properties
Normal file
5
bdk-android/gradle.properties
Normal file
@@ -0,0 +1,5 @@
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
kotlin.code.style=official
|
||||
libraryVersion=0.25.0
|
||||
BIN
bdk-android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
bdk-android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
bdk-android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
bdk-android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
234
bdk-android/gradlew
vendored
Executable 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
89
bdk-android/gradlew.bat
vendored
Normal 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
|
||||
109
bdk-android/lib/build.gradle.kts
Normal file
109
bdk-android/lib/build.gradle.kts
Normal file
@@ -0,0 +1,109 @@
|
||||
// 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)
|
||||
}
|
||||
28
bdk-android/lib/proguard-rules.pro
vendored
Normal file
28
bdk-android/lib/proguard-rules.pro
vendored
Normal 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 *; }
|
||||
14
bdk-android/lib/src/androidTest/assets/logback.xml
Normal file
14
bdk-android/lib/src/androidTest/assets/logback.xml
Normal 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>
|
||||
@@ -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 =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
|
||||
private val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
private val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig(
|
||||
"ssl://electrum.blockstream.info:60002",
|
||||
null,
|
||||
5u,
|
||||
null,
|
||||
100u
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun memoryWalletNewAddress() {
|
||||
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
|
||||
val address = wallet.getAddress(AddressIndex.NEW).address
|
||||
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)
|
||||
}
|
||||
}
|
||||
6
bdk-android/lib/src/main/AndroidManifest.xml
Normal file
6
bdk-android/lib/src/main/AndroidManifest.xml
Normal 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>
|
||||
17
bdk-android/plugins/README.md
Normal file
17
bdk-android/plugins/README.md
Normal 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
|
||||
13
bdk-android/plugins/build.gradle.kts
Normal file
13
bdk-android/plugins/build.gradle.kts
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
bdk-android/plugins/settings.gradle.kts
Normal file
8
bdk-android/plugins/settings.gradle.kts
Normal file
@@ -0,0 +1,8 @@
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
// include(":plugins")
|
||||
@@ -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,
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
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: MutableList<String> =
|
||||
mutableListOf("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_API__=21"),
|
||||
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: MutableList<String> =
|
||||
mutableListOf("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_API__=21"),
|
||||
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: MutableList<String> =
|
||||
mutableListOf("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_API__=21"),
|
||||
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")
|
||||
executable("cargo")
|
||||
args(
|
||||
"run",
|
||||
"--package",
|
||||
"bdk-ffi-bindgen",
|
||||
"--",
|
||||
"--language",
|
||||
"kotlin",
|
||||
"--out-dir",
|
||||
"../bdk-android/lib/src/main/kotlin"
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
4
bdk-android/settings.gradle.kts
Normal file
4
bdk-android/settings.gradle.kts
Normal file
@@ -0,0 +1,4 @@
|
||||
rootProject.name = "bdk-android"
|
||||
|
||||
include(":lib")
|
||||
includeBuild("plugins")
|
||||
@@ -4,7 +4,7 @@ version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "=1.0.45" # remove after upgrading to next version of uniffi
|
||||
anyhow = "1.0.45" # remove after upgrading to next version of uniffi
|
||||
structopt = "0.3"
|
||||
uniffi_bindgen = "0.19.5"
|
||||
uniffi_bindgen = "0.21.0"
|
||||
camino = "1.0.9"
|
||||
|
||||
19
bdk-ffi/Cargo.toml
Normal file
19
bdk-ffi/Cargo.toml
Normal file
@@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "bdk-ffi"
|
||||
version = "0.25.0"
|
||||
authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib", "cdylib"]
|
||||
name = "bdkffi"
|
||||
|
||||
[dependencies]
|
||||
bdk = { version = "0.25", features = ["all-keys", "use-esplora-ureq", "sqlite-bundled"] }
|
||||
|
||||
uniffi_macros = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
uniffi = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
|
||||
[build-dependencies]
|
||||
uniffi_build = { version = "0.21.0", features = ["builtin-bindgen"] }
|
||||
@@ -1,6 +1,5 @@
|
||||
namespace bdk {
|
||||
[Throws=BdkError]
|
||||
string generate_mnemonic(WordCount word_count);
|
||||
|
||||
};
|
||||
|
||||
[Error]
|
||||
@@ -33,9 +32,9 @@ enum BdkError {
|
||||
"ProgressUpdateError",
|
||||
"InvalidOutpoint",
|
||||
"Descriptor",
|
||||
"AddressValidator",
|
||||
"Encode",
|
||||
"Miniscript",
|
||||
"MiniscriptPsbt",
|
||||
"Bip32",
|
||||
"Secp256k1",
|
||||
"Json",
|
||||
@@ -138,7 +137,7 @@ interface Blockchain {
|
||||
constructor(BlockchainConfig config);
|
||||
|
||||
[Throws=BdkError]
|
||||
void broadcast([ByRef] PartiallySignedBitcoinTransaction psbt);
|
||||
void broadcast([ByRef] PartiallySignedTransaction psbt);
|
||||
|
||||
[Throws=BdkError]
|
||||
u32 get_height();
|
||||
@@ -173,8 +172,8 @@ dictionary LocalUtxo {
|
||||
boolean is_spent;
|
||||
};
|
||||
|
||||
dictionary AddressAmount {
|
||||
string address;
|
||||
dictionary ScriptAmount {
|
||||
Script script;
|
||||
u64 amount;
|
||||
};
|
||||
|
||||
@@ -189,7 +188,7 @@ interface Wallet {
|
||||
Balance get_balance();
|
||||
|
||||
[Throws=BdkError]
|
||||
boolean sign([ByRef] PartiallySignedBitcoinTransaction psbt);
|
||||
boolean sign([ByRef] PartiallySignedTransaction psbt);
|
||||
|
||||
[Throws=BdkError]
|
||||
sequence<TransactionDetails> list_transactions();
|
||||
@@ -203,19 +202,40 @@ interface Wallet {
|
||||
sequence<LocalUtxo> list_unspent();
|
||||
};
|
||||
|
||||
interface PartiallySignedBitcoinTransaction {
|
||||
interface FeeRate {
|
||||
[Name=from_sat_per_vb]
|
||||
constructor(float sat_per_vb);
|
||||
|
||||
float as_sat_per_vb();
|
||||
};
|
||||
|
||||
interface PartiallySignedTransaction {
|
||||
[Throws=BdkError]
|
||||
constructor(string psbt_base64);
|
||||
|
||||
string serialize();
|
||||
|
||||
string txid();
|
||||
|
||||
sequence<u8> extract_tx();
|
||||
|
||||
[Throws=BdkError]
|
||||
PartiallySignedTransaction combine(PartiallySignedTransaction other);
|
||||
|
||||
u64? fee_amount();
|
||||
|
||||
FeeRate? fee_rate();
|
||||
};
|
||||
|
||||
dictionary TxBuilderResult {
|
||||
PartiallySignedTransaction psbt;
|
||||
TransactionDetails transaction_details;
|
||||
};
|
||||
|
||||
interface TxBuilder {
|
||||
constructor();
|
||||
|
||||
TxBuilder add_recipient(string address, u64 amount);
|
||||
TxBuilder add_recipient(Script script, u64 amount);
|
||||
|
||||
TxBuilder add_unspendable(OutPoint unspendable);
|
||||
|
||||
@@ -245,10 +265,10 @@ interface TxBuilder {
|
||||
|
||||
TxBuilder add_data(sequence<u8> data);
|
||||
|
||||
TxBuilder set_recipients(sequence<AddressAmount> recipients);
|
||||
TxBuilder set_recipients(sequence<ScriptAmount> recipients);
|
||||
|
||||
[Throws=BdkError]
|
||||
PartiallySignedBitcoinTransaction finish([ByRef] Wallet wallet);
|
||||
TxBuilderResult finish([ByRef] Wallet wallet);
|
||||
};
|
||||
|
||||
interface BumpFeeTxBuilder {
|
||||
@@ -261,7 +281,19 @@ interface BumpFeeTxBuilder {
|
||||
BumpFeeTxBuilder enable_rbf_with_sequence(u32 nsequence);
|
||||
|
||||
[Throws=BdkError]
|
||||
PartiallySignedBitcoinTransaction finish([ByRef] Wallet wallet);
|
||||
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 {
|
||||
@@ -270,24 +302,44 @@ interface DerivationPath {
|
||||
};
|
||||
|
||||
interface DescriptorSecretKey {
|
||||
[Throws=BdkError]
|
||||
constructor(Network network, string mnemonic, string? password);
|
||||
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 Address {
|
||||
[Throws=BdkError]
|
||||
constructor(string address);
|
||||
|
||||
Script script_pubkey();
|
||||
};
|
||||
|
||||
interface Script {
|
||||
constructor(sequence<u8> raw_output_script);
|
||||
};
|
||||
@@ -1,8 +1,11 @@
|
||||
use bdk::bitcoin::blockdata::script::Script as BdkScript;
|
||||
use bdk::bitcoin::hashes::hex::ToHex;
|
||||
use bdk::bitcoin::secp256k1::Secp256k1;
|
||||
use bdk::bitcoin::util::bip32::DerivationPath as BdkDerivationPath;
|
||||
use bdk::bitcoin::util::psbt::PartiallySignedTransaction;
|
||||
use bdk::bitcoin::{Address, Network, OutPoint as BdkOutPoint, Script, Txid};
|
||||
use bdk::bitcoin::util::psbt::serialize::Serialize;
|
||||
use bdk::bitcoin::util::psbt::PartiallySignedTransaction as BdkPartiallySignedTransaction;
|
||||
use bdk::bitcoin::Sequence;
|
||||
use bdk::bitcoin::{Address as BdkAddress, Network, OutPoint as BdkOutPoint, Txid};
|
||||
use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig};
|
||||
use bdk::blockchain::GetBlockHash;
|
||||
use bdk::blockchain::GetHeight;
|
||||
@@ -13,17 +16,18 @@ use bdk::blockchain::{Blockchain as BdkBlockchain, Progress as BdkProgress};
|
||||
use bdk::database::any::{AnyDatabase, SledDbConfiguration, SqliteDbConfiguration};
|
||||
use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase};
|
||||
use bdk::descriptor::DescriptorXKey;
|
||||
use bdk::keys::bip39::{Language, Mnemonic, WordCount};
|
||||
use bdk::keys::bip39::{Language, Mnemonic as BdkMnemonic, WordCount};
|
||||
use bdk::keys::{
|
||||
DerivableKey, DescriptorPublicKey as BdkDescriptorPublicKey,
|
||||
DescriptorSecretKey as BdkDescriptorSecretKey, ExtendedKey, GeneratableKey, GeneratedKey,
|
||||
};
|
||||
use bdk::miniscript::BareCtx;
|
||||
use bdk::psbt::PsbtUtils;
|
||||
use bdk::wallet::tx_builder::ChangeSpendPolicy;
|
||||
use bdk::wallet::AddressIndex as BdkAddressIndex;
|
||||
use bdk::wallet::AddressInfo as BdkAddressInfo;
|
||||
use bdk::{
|
||||
Balance as BdkBalance, BlockTime, Error, FeeRate, KeychainKind, SignOptions,
|
||||
Balance as BdkBalance, BlockTime, Error as BdkError, FeeRate, KeychainKind, SignOptions,
|
||||
SyncOptions as BdkSyncOptions, Wallet as BdkWallet,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
@@ -35,10 +39,9 @@ use std::sync::{Arc, Mutex, MutexGuard};
|
||||
|
||||
uniffi_macros::include_scaffolding!("bdk");
|
||||
|
||||
type BdkError = Error;
|
||||
|
||||
pub struct AddressAmount {
|
||||
pub address: String,
|
||||
/// A output script and an amount of satoshis.
|
||||
pub struct ScriptAmount {
|
||||
pub script: Arc<Script>,
|
||||
pub amount: u64,
|
||||
}
|
||||
|
||||
@@ -208,16 +211,16 @@ impl Blockchain {
|
||||
self.blockchain_mutex.lock().expect("blockchain")
|
||||
}
|
||||
|
||||
fn broadcast(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<(), Error> {
|
||||
fn broadcast(&self, psbt: &PartiallySignedTransaction) -> Result<(), BdkError> {
|
||||
let tx = psbt.internal.lock().unwrap().clone().extract_tx();
|
||||
self.get_blockchain().broadcast(&tx)
|
||||
}
|
||||
|
||||
fn get_height(&self) -> Result<u32, Error> {
|
||||
fn get_height(&self) -> Result<u32, BdkError> {
|
||||
self.get_blockchain().get_height()
|
||||
}
|
||||
|
||||
fn get_block_hash(&self, height: u32) -> Result<String, Error> {
|
||||
fn get_block_hash(&self, height: u32) -> Result<String, BdkError> {
|
||||
self.get_blockchain()
|
||||
.get_block_hash(u64::from(height))
|
||||
.map(|hash| hash.to_string())
|
||||
@@ -304,12 +307,9 @@ impl NetworkLocalUtxo for LocalUtxo {
|
||||
},
|
||||
txout: TxOut {
|
||||
value: x.txout.value,
|
||||
address: bdk::bitcoin::util::address::Address::from_script(
|
||||
&x.txout.script_pubkey,
|
||||
network,
|
||||
)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
address: BdkAddress::from_script(&x.txout.script_pubkey, network)
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
},
|
||||
keychain: x.keychain,
|
||||
is_spent: x.is_spent,
|
||||
@@ -329,7 +329,7 @@ struct ProgressHolder {
|
||||
}
|
||||
|
||||
impl BdkProgress for ProgressHolder {
|
||||
fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
|
||||
fn update(&self, progress: f32, message: Option<String>) -> Result<(), BdkError> {
|
||||
self.progress.update(progress, message);
|
||||
Ok(())
|
||||
}
|
||||
@@ -342,14 +342,15 @@ impl fmt::Debug for ProgressHolder {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PartiallySignedBitcoinTransaction {
|
||||
internal: Mutex<PartiallySignedTransaction>,
|
||||
pub struct PartiallySignedTransaction {
|
||||
internal: Mutex<BdkPartiallySignedTransaction>,
|
||||
}
|
||||
|
||||
impl PartiallySignedBitcoinTransaction {
|
||||
fn new(psbt_base64: String) -> Result<Self, Error> {
|
||||
let psbt: PartiallySignedTransaction = PartiallySignedTransaction::from_str(&psbt_base64)?;
|
||||
Ok(PartiallySignedBitcoinTransaction {
|
||||
impl PartiallySignedTransaction {
|
||||
fn new(psbt_base64: String) -> Result<Self, BdkError> {
|
||||
let psbt: BdkPartiallySignedTransaction =
|
||||
BdkPartiallySignedTransaction::from_str(&psbt_base64)?;
|
||||
Ok(PartiallySignedTransaction {
|
||||
internal: Mutex::new(psbt),
|
||||
})
|
||||
}
|
||||
@@ -364,6 +365,46 @@ impl PartiallySignedBitcoinTransaction {
|
||||
let txid = tx.txid();
|
||||
txid.to_hex()
|
||||
}
|
||||
|
||||
/// Return the transaction as bytes.
|
||||
fn extract_tx(&self) -> Vec<u8> {
|
||||
self.internal
|
||||
.lock()
|
||||
.unwrap()
|
||||
.clone()
|
||||
.extract_tx()
|
||||
.serialize()
|
||||
}
|
||||
|
||||
/// 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)`
|
||||
fn combine(
|
||||
&self,
|
||||
other: Arc<PartiallySignedTransaction>,
|
||||
) -> Result<Arc<PartiallySignedTransaction>, BdkError> {
|
||||
let other_psbt = other.internal.lock().unwrap().clone();
|
||||
let mut original_psbt = self.internal.lock().unwrap().clone();
|
||||
|
||||
original_psbt.combine(other_psbt)?;
|
||||
Ok(Arc::new(PartiallySignedTransaction {
|
||||
internal: 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.
|
||||
fn fee_amount(&self) -> Option<u64> {
|
||||
self.internal.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.
|
||||
fn fee_rate(&self) -> Option<Arc<FeeRate>> {
|
||||
self.internal.lock().unwrap().fee_rate().map(Arc::new)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Bitcoin wallet.
|
||||
@@ -430,18 +471,18 @@ impl Wallet {
|
||||
|
||||
/// Return the balance, meaning the sum of this wallet’s unspent outputs’ values. Note that this method only operates
|
||||
/// on the internal database, which first needs to be Wallet.sync manually.
|
||||
fn get_balance(&self) -> Result<Balance, Error> {
|
||||
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.
|
||||
fn sign(&self, psbt: &PartiallySignedBitcoinTransaction) -> Result<bool, Error> {
|
||||
fn sign(&self, psbt: &PartiallySignedTransaction) -> Result<bool, BdkError> {
|
||||
let mut psbt = psbt.internal.lock().unwrap();
|
||||
self.get_wallet().sign(&mut psbt, SignOptions::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.
|
||||
fn list_transactions(&self) -> Result<Vec<TransactionDetails>, Error> {
|
||||
fn list_transactions(&self) -> Result<Vec<TransactionDetails>, BdkError> {
|
||||
let transaction_details = self.get_wallet().list_transactions(true)?;
|
||||
Ok(transaction_details
|
||||
.iter()
|
||||
@@ -451,7 +492,7 @@ impl Wallet {
|
||||
|
||||
/// 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.
|
||||
fn list_unspent(&self) -> Result<Vec<LocalUtxo>, Error> {
|
||||
fn list_unspent(&self) -> Result<Vec<LocalUtxo>, BdkError> {
|
||||
let unspents = self.get_wallet().list_unspent()?;
|
||||
Ok(unspents
|
||||
.iter()
|
||||
@@ -460,24 +501,63 @@ impl Wallet {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_script_pubkey(address: &str) -> Result<Script, BdkError> {
|
||||
Address::from_str(address)
|
||||
fn to_script_pubkey(address: &str) -> Result<BdkScript, BdkError> {
|
||||
BdkAddress::from_str(address)
|
||||
.map(|x| x.script_pubkey())
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||
}
|
||||
|
||||
/// A Bitcoin address.
|
||||
struct Address {
|
||||
address: BdkAddress,
|
||||
}
|
||||
|
||||
impl Address {
|
||||
fn new(address: String) -> Result<Self, BdkError> {
|
||||
BdkAddress::from_str(address.as_str())
|
||||
.map(|a| Address { address: a })
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||
}
|
||||
|
||||
fn script_pubkey(&self) -> Arc<Script> {
|
||||
Arc::new(Script {
|
||||
script: self.address.script_pubkey(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// A Bitcoin script.
|
||||
#[derive(Clone)]
|
||||
pub struct Script {
|
||||
script: BdkScript,
|
||||
}
|
||||
|
||||
impl Script {
|
||||
fn new(raw_output_script: Vec<u8>) -> Self {
|
||||
let script: BdkScript = BdkScript::from(raw_output_script);
|
||||
Script { script }
|
||||
}
|
||||
}
|
||||
|
||||
#[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 psbt: Arc<PartiallySignedTransaction>,
|
||||
pub transaction_details: TransactionDetails,
|
||||
}
|
||||
|
||||
/// 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)]
|
||||
struct TxBuilder {
|
||||
recipients: Vec<(String, u64)>,
|
||||
recipients: Vec<(BdkScript, u64)>,
|
||||
utxos: Vec<OutPoint>,
|
||||
unspendable: HashSet<OutPoint>,
|
||||
change_policy: ChangeSpendPolicy,
|
||||
@@ -508,19 +588,19 @@ impl TxBuilder {
|
||||
}
|
||||
|
||||
/// Add a recipient to the internal list.
|
||||
fn add_recipient(&self, recipient: String, amount: u64) -> Arc<Self> {
|
||||
let mut recipients = self.recipients.to_vec();
|
||||
recipients.append(&mut vec![(recipient, amount)]);
|
||||
fn add_recipient(&self, script: Arc<Script>, amount: u64) -> Arc<Self> {
|
||||
let mut recipients: Vec<(BdkScript, u64)> = self.recipients.clone();
|
||||
recipients.append(&mut vec![(script.script.clone(), amount)]);
|
||||
Arc::new(TxBuilder {
|
||||
recipients,
|
||||
..self.clone()
|
||||
})
|
||||
}
|
||||
|
||||
fn set_recipients(&self, recipients: Vec<AddressAmount>) -> Arc<Self> {
|
||||
fn set_recipients(&self, recipients: Vec<ScriptAmount>) -> Arc<Self> {
|
||||
let recipients = recipients
|
||||
.iter()
|
||||
.map(|address_amount| (address_amount.address.clone(), address_amount.amount))
|
||||
.map(|script_amount| (script_amount.script.script.clone(), script_amount.amount))
|
||||
.collect();
|
||||
Arc::new(TxBuilder {
|
||||
recipients,
|
||||
@@ -657,11 +737,11 @@ impl TxBuilder {
|
||||
}
|
||||
|
||||
/// Finish building the transaction. Returns the BIP174 PSBT.
|
||||
fn finish(&self, wallet: &Wallet) -> Result<Arc<PartiallySignedBitcoinTransaction>, Error> {
|
||||
fn finish(&self, wallet: &Wallet) -> Result<TxBuilderResult, BdkError> {
|
||||
let wallet = wallet.get_wallet();
|
||||
let mut tx_builder = wallet.build_tx();
|
||||
for (address, amount) in &self.recipients {
|
||||
tx_builder.add_recipient(to_script_pubkey(address)?, *amount);
|
||||
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() {
|
||||
@@ -695,7 +775,7 @@ impl TxBuilder {
|
||||
tx_builder.enable_rbf();
|
||||
}
|
||||
RbfValue::Value(nsequence) => {
|
||||
tx_builder.enable_rbf_with_sequence(nsequence);
|
||||
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -705,10 +785,12 @@ impl TxBuilder {
|
||||
|
||||
tx_builder
|
||||
.finish()
|
||||
.map(|(psbt, _)| PartiallySignedBitcoinTransaction {
|
||||
internal: Mutex::new(psbt),
|
||||
.map(|(psbt, tx_details)| TxBuilderResult {
|
||||
psbt: Arc::new(PartiallySignedTransaction {
|
||||
internal: Mutex::new(psbt),
|
||||
}),
|
||||
transaction_details: TransactionDetails::from(&tx_details),
|
||||
})
|
||||
.map(Arc::new)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,14 +844,14 @@ impl BumpFeeTxBuilder {
|
||||
}
|
||||
|
||||
/// Finish building the transaction. Returns the BIP174 PSBT.
|
||||
fn finish(&self, wallet: &Wallet) -> Result<Arc<PartiallySignedBitcoinTransaction>, Error> {
|
||||
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 {
|
||||
let address =
|
||||
Address::from_str(allow_shrinking).map_err(|e| Error::Generic(e.to_string()))?;
|
||||
let address = BdkAddress::from_str(allow_shrinking)
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||
let script = address.script_pubkey();
|
||||
tx_builder.allow_shrinking(script)?;
|
||||
}
|
||||
@@ -779,23 +861,53 @@ impl BumpFeeTxBuilder {
|
||||
tx_builder.enable_rbf();
|
||||
}
|
||||
RbfValue::Value(nsequence) => {
|
||||
tx_builder.enable_rbf_with_sequence(nsequence);
|
||||
tx_builder.enable_rbf_with_sequence(Sequence(nsequence));
|
||||
}
|
||||
}
|
||||
}
|
||||
tx_builder
|
||||
.finish()
|
||||
.map(|(psbt, _)| PartiallySignedBitcoinTransaction {
|
||||
.map(|(psbt, _)| PartiallySignedTransaction {
|
||||
internal: Mutex::new(psbt),
|
||||
})
|
||||
.map(Arc::new)
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_mnemonic(word_count: WordCount) -> Result<String, BdkError> {
|
||||
let mnemonic: GeneratedKey<_, BareCtx> =
|
||||
Mnemonic::generate((word_count, Language::English)).unwrap();
|
||||
Ok(mnemonic.to_string())
|
||||
/// Mnemonic phrases are a human-readable version of the private keys.
|
||||
/// Supported number of words are 12, 15, 18, 21 and 24.
|
||||
struct Mnemonic {
|
||||
internal: BdkMnemonic,
|
||||
}
|
||||
|
||||
impl Mnemonic {
|
||||
/// Generates Mnemonic with a random entropy
|
||||
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 { internal: mnemonic }
|
||||
}
|
||||
|
||||
/// Parse a Mnemonic with given string
|
||||
fn from_string(mnemonic: String) -> Result<Self, BdkError> {
|
||||
BdkMnemonic::from_str(&mnemonic)
|
||||
.map(|m| Mnemonic { internal: 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.
|
||||
fn from_entropy(entropy: Vec<u8>) -> Result<Self, BdkError> {
|
||||
BdkMnemonic::from_entropy(entropy.as_slice())
|
||||
.map(|m| Mnemonic { internal: m })
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))
|
||||
}
|
||||
|
||||
/// Returns Mnemonic as string
|
||||
fn as_string(&self) -> String {
|
||||
self.internal.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
struct DerivationPath {
|
||||
@@ -812,21 +924,29 @@ impl DerivationPath {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DescriptorSecretKey {
|
||||
descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
|
||||
}
|
||||
|
||||
impl DescriptorSecretKey {
|
||||
fn new(network: Network, mnemonic: String, password: Option<String>) -> Result<Self, BdkError> {
|
||||
let mnemonic = Mnemonic::parse_in(Language::English, mnemonic)
|
||||
.map_err(|e| BdkError::Generic(e.to_string()))?;
|
||||
let xkey: ExtendedKey = (mnemonic, password).into_extended_key()?;
|
||||
fn new(network: Network, mnemonic: Arc<Mnemonic>, password: Option<String>) -> Self {
|
||||
let mnemonic = mnemonic.internal.clone();
|
||||
let xkey: ExtendedKey = (mnemonic, password).into_extended_key().unwrap();
|
||||
let descriptor_secret_key = BdkDescriptorSecretKey::XPrv(DescriptorXKey {
|
||||
origin: None,
|
||||
xkey: xkey.into_xprv(network).unwrap(),
|
||||
derivation_path: BdkDerivationPath::master(),
|
||||
wildcard: bdk::descriptor::Wildcard::Unhardened,
|
||||
});
|
||||
Self {
|
||||
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
|
||||
})
|
||||
@@ -853,13 +973,13 @@ impl DescriptorSecretKey {
|
||||
descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
|
||||
}))
|
||||
}
|
||||
BdkDescriptorSecretKey::SinglePriv(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||
"Cannot derive from a single key".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
|
||||
fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
||||
match descriptor_secret_key.deref() {
|
||||
@@ -871,13 +991,13 @@ impl DescriptorSecretKey {
|
||||
derivation_path: extended_path,
|
||||
wildcard: descriptor_x_key.wildcard,
|
||||
});
|
||||
Arc::new(Self {
|
||||
Ok(Arc::new(Self {
|
||||
descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
|
||||
})
|
||||
}
|
||||
BdkDescriptorSecretKey::SinglePriv(_) => {
|
||||
unreachable!()
|
||||
}))
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
|
||||
"Cannot extend from a single key".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,23 +1007,47 @@ impl DescriptorSecretKey {
|
||||
.descriptor_secret_key_mutex
|
||||
.lock()
|
||||
.unwrap()
|
||||
.as_public(&secp)
|
||||
.to_public(&secp)
|
||||
.unwrap();
|
||||
Arc::new(DescriptorPublicKey {
|
||||
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the private key as bytes.
|
||||
fn secret_bytes(&self) -> Vec<u8> {
|
||||
let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
|
||||
let secret_bytes: Vec<u8> = match descriptor_secret_key.deref() {
|
||||
BdkDescriptorSecretKey::XPrv(descriptor_x_key) => {
|
||||
descriptor_x_key.xkey.private_key.secret_bytes().to_vec()
|
||||
}
|
||||
BdkDescriptorSecretKey::Single(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
secret_bytes
|
||||
}
|
||||
|
||||
fn as_string(&self) -> String {
|
||||
self.descriptor_secret_key_mutex.lock().unwrap().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct DescriptorPublicKey {
|
||||
descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
|
||||
}
|
||||
|
||||
impl DescriptorPublicKey {
|
||||
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 {
|
||||
descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
|
||||
})
|
||||
}
|
||||
|
||||
fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||
let secp = Secp256k1::new();
|
||||
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
||||
@@ -926,13 +1070,13 @@ impl DescriptorPublicKey {
|
||||
descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
|
||||
}))
|
||||
}
|
||||
BdkDescriptorPublicKey::SinglePub(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||
"Cannot derive from a single key".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
|
||||
fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
|
||||
let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
|
||||
let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
|
||||
match descriptor_public_key.deref() {
|
||||
@@ -944,13 +1088,13 @@ impl DescriptorPublicKey {
|
||||
derivation_path: extended_path,
|
||||
wildcard: descriptor_x_key.wildcard,
|
||||
});
|
||||
Arc::new(Self {
|
||||
Ok(Arc::new(Self {
|
||||
descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
|
||||
})
|
||||
}
|
||||
BdkDescriptorPublicKey::SinglePub(_) => {
|
||||
unreachable!()
|
||||
}))
|
||||
}
|
||||
BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
|
||||
"Cannot extend from a single key".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -984,12 +1128,12 @@ mod test {
|
||||
let tx_builder = TxBuilder::new()
|
||||
.drain_wallet()
|
||||
.drain_to(drain_to_address.clone());
|
||||
//dbg!(&tx_builder);
|
||||
assert!(tx_builder.drain_wallet);
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_address));
|
||||
|
||||
let psbt = tx_builder.finish(&test_wallet).unwrap();
|
||||
let psbt = psbt.internal.lock().unwrap().clone();
|
||||
let tx_builder_result = tx_builder.finish(&test_wallet).unwrap();
|
||||
let psbt = tx_builder_result.psbt.internal.lock().unwrap().clone();
|
||||
let tx_details = tx_builder_result.transaction_details;
|
||||
|
||||
// confirm one input with 50,000 sats
|
||||
assert_eq!(psbt.inputs.len(), 1);
|
||||
@@ -1025,12 +1169,21 @@ mod test {
|
||||
);
|
||||
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());
|
||||
}
|
||||
|
||||
fn get_descriptor_secret_key() -> DescriptorSecretKey {
|
||||
let mnemonic =
|
||||
"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();
|
||||
DescriptorSecretKey::new(Network::Testnet, mnemonic, None).unwrap()
|
||||
let mnemonic = Mnemonic::from_string("chaos fabric time speed sponsor all flat solution wisdom trophy crack object robot pave observe combine where aware bench orient secret primary cable detect".to_string()).unwrap();
|
||||
DescriptorSecretKey::new(Testnet, Arc::new(mnemonic), None)
|
||||
}
|
||||
|
||||
fn derive_dsk(
|
||||
@@ -1041,7 +1194,10 @@ mod test {
|
||||
key.derive(path)
|
||||
}
|
||||
|
||||
fn extend_dsk(key: &DescriptorSecretKey, path: &str) -> Arc<DescriptorSecretKey> {
|
||||
fn extend_dsk(
|
||||
key: &DescriptorSecretKey,
|
||||
path: &str,
|
||||
) -> Result<Arc<DescriptorSecretKey>, BdkError> {
|
||||
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
|
||||
key.extend(path)
|
||||
}
|
||||
@@ -1054,7 +1210,10 @@ mod test {
|
||||
key.derive(path)
|
||||
}
|
||||
|
||||
fn extend_dpk(key: &DescriptorPublicKey, path: &str) -> Arc<DescriptorPublicKey> {
|
||||
fn extend_dpk(
|
||||
key: &DescriptorPublicKey,
|
||||
path: &str,
|
||||
) -> Result<Arc<DescriptorPublicKey>, BdkError> {
|
||||
let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
|
||||
key.extend(path)
|
||||
}
|
||||
@@ -1091,24 +1250,45 @@ mod test {
|
||||
#[test]
|
||||
fn test_extend_descriptor_keys() {
|
||||
let master_dsk = get_descriptor_secret_key();
|
||||
let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0");
|
||||
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");
|
||||
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_descriptor_secret_key() {
|
||||
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_descriptor_secret_key() {
|
||||
let master_dsk = get_descriptor_secret_key();
|
||||
|
||||
// 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");
|
||||
let extended_dsk: &DescriptorSecretKey = &extend_dsk(derived_dsk, "m/0").unwrap();
|
||||
assert_eq!(extended_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
|
||||
}
|
||||
|
||||
@@ -1118,4 +1298,42 @@ mod test {
|
||||
let derived_dpk = &derive_dpk(&master_dpk, "m/84h/1h/0h");
|
||||
assert!(derived_dpk.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_retrieve_master_secret_key() {
|
||||
let master_dpk = get_descriptor_secret_key();
|
||||
let master_private_key = master_dpk.secret_bytes().to_hex();
|
||||
assert_eq!(
|
||||
master_private_key,
|
||||
"e93315d6ce401eb4db803a56232f0ed3e69b053774e6047df54f1bd00e5ea936"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_psbt_fee() {
|
||||
let test_wpkh = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
|
||||
let (funded_wallet, _, _) = get_funded_wallet(test_wpkh);
|
||||
let test_wallet = Wallet {
|
||||
wallet_mutex: Mutex::new(funded_wallet),
|
||||
};
|
||||
let drain_to_address = "tb1ql7w62elx9ucw4pj5lgw4l028hmuw80sndtntxt".to_string();
|
||||
let tx_builder = TxBuilder::new()
|
||||
.fee_rate(2.0)
|
||||
.drain_wallet()
|
||||
.drain_to(drain_to_address.clone());
|
||||
//dbg!(&tx_builder);
|
||||
assert!(tx_builder.drain_wallet);
|
||||
assert_eq!(tx_builder.drain_to, Some(drain_to_address));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
21
bdk-ffi/tests/README.md
Normal file
21
bdk-ffi/tests/README.md
Normal 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/)
|
||||
8
bdk-ffi/tests/bindings/test.kts
Normal file
8
bdk-ffi/tests/bindings/test.kts
Normal 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
|
||||
15
bdk-ffi/tests/bindings/test.py
Normal file
15
bdk-ffi/tests/bindings/test.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import unittest
|
||||
from bdk import *
|
||||
|
||||
class TestBdk(unittest.TestCase):
|
||||
|
||||
def test_some_enum(self):
|
||||
network = Network.TESTNET
|
||||
|
||||
def test_some_dict(self):
|
||||
a = AddressInfo(index=42, address="testaddress")
|
||||
self.assertEqual(42, a.index)
|
||||
self.assertEqual("testaddress", a.address)
|
||||
|
||||
if __name__=='__main__':
|
||||
unittest.main()
|
||||
9
bdk-ffi/tests/bindings/test.swift
Normal file
9
bdk-ffi/tests/bindings/test.swift
Normal 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
|
||||
BIN
bdk-ffi/tests/jna/jna-5.8.0.jar
Normal file
BIN
bdk-ffi/tests/jna/jna-5.8.0.jar
Normal file
Binary file not shown.
8
bdk-ffi/tests/test_generated_bindings.rs
Normal file
8
bdk-ffi/tests/test_generated_bindings.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
uniffi_macros::build_foreign_language_testcases!(
|
||||
["src/bdk.udl",],
|
||||
[
|
||||
"tests/bindings/test.kts",
|
||||
"tests/bindings/test.swift",
|
||||
"tests/bindings/test.py"
|
||||
]
|
||||
);
|
||||
86
bdk-jvm/README.md
Normal file
86
bdk-jvm/README.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# bdk-android
|
||||
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 = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
val internalDescriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"
|
||||
|
||||
val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig("ssl://electrum.blockstream.info:60002", null, 5u, null, 10u)
|
||||
)
|
||||
val wallet = Wallet(externalDescriptor, internalDescriptor, Network.TESTNET, databaseConfig, blockchainConfig)
|
||||
val newAddress = wallet.getAddress(AddressIndex.LAST_UNUSED)
|
||||
```
|
||||
|
||||
### 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. Clone this repository.
|
||||
```shell
|
||||
git clone https://github.com/bitcoindevkit/bdk-ffi
|
||||
```
|
||||
2. Follow the "General" bdk-ffi ["Getting Started (Developer)"] instructions.
|
||||
3. If building on macOS install required intel and m1 jvm targets
|
||||
```sh
|
||||
rustup target add x86_64-apple-darwin aarch64-apple-darwin
|
||||
```
|
||||
4. Build kotlin bindings
|
||||
```sh
|
||||
# build JVM library
|
||||
./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
|
||||
```
|
||||
|
||||
[`bdk`]: https://github.com/bitcoindevkit/bdk
|
||||
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
|
||||
27
bdk-jvm/build.gradle.kts
Normal file
27
bdk-jvm/build.gradle.kts
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
4
bdk-jvm/gradle.properties
Normal file
4
bdk-jvm/gradle.properties
Normal file
@@ -0,0 +1,4 @@
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
android.enableJetifier=true
|
||||
kotlin.code.style=official
|
||||
libraryVersion=0.25.0
|
||||
BIN
bdk-jvm/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
bdk-jvm/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
bdk-jvm/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
bdk-jvm/gradle/wrapper/gradle-wrapper.properties
vendored
Normal 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
234
bdk-jvm/gradlew
vendored
Executable 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
89
bdk-jvm/gradlew.bat
vendored
Normal 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
|
||||
103
bdk-jvm/lib/build.gradle.kts
Normal file
103
bdk-jvm/lib/build.gradle.kts
Normal file
@@ -0,0 +1,103 @@
|
||||
import org.gradle.api.tasks.testing.logging.TestExceptionFormat.*
|
||||
import org.gradle.api.tasks.testing.logging.TestLogEvent.*
|
||||
|
||||
// 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_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
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)
|
||||
}
|
||||
73
bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/JvmLibTest.kt
Normal file
73
bdk-jvm/lib/src/test/kotlin/org/bitcoindevkit/JvmLibTest.kt
Normal 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 =
|
||||
"wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
|
||||
private val databaseConfig = DatabaseConfig.Memory
|
||||
|
||||
private val blockchainConfig = BlockchainConfig.Electrum(
|
||||
ElectrumConfig(
|
||||
"ssl://electrum.blockstream.info:60002",
|
||||
null,
|
||||
5u,
|
||||
null,
|
||||
100u
|
||||
)
|
||||
)
|
||||
|
||||
@Test
|
||||
fun memoryWalletNewAddress() {
|
||||
val wallet = Wallet(descriptor, null, Network.TESTNET, databaseConfig)
|
||||
val address = wallet.getAddress(AddressIndex.NEW).address
|
||||
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
16
bdk-jvm/plugins/README.md
Normal 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
|
||||
13
bdk-jvm/plugins/build.gradle.kts
Normal file
13
bdk-jvm/plugins/build.gradle.kts
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
bdk-jvm/plugins/settings.gradle.kts
Normal file
8
bdk-jvm/plugins/settings.gradle.kts
Normal file
@@ -0,0 +1,8 @@
|
||||
dependencyResolutionManagement {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
}
|
||||
|
||||
// include(":plugins")
|
||||
@@ -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,
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
libsToCopy.forEach {
|
||||
doFirst {
|
||||
copy {
|
||||
with(it) {
|
||||
from("${project.projectDir}/../../target/${this.targetDir}/release-smaller/libbdkffi.${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")
|
||||
executable("cargo")
|
||||
args(
|
||||
"run",
|
||||
"--package",
|
||||
"bdk-ffi-bindgen",
|
||||
"--",
|
||||
"--language",
|
||||
"kotlin",
|
||||
"--out-dir",
|
||||
"../bdk-jvm/lib/src/main/kotlin"
|
||||
)
|
||||
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
4
bdk-jvm/settings.gradle.kts
Normal file
4
bdk-jvm/settings.gradle.kts
Normal file
@@ -0,0 +1,4 @@
|
||||
rootProject.name = "bdk-jvm"
|
||||
|
||||
include(":lib")
|
||||
includeBuild("plugins")
|
||||
16
bdk-python/.gitignore
vendored
Normal file
16
bdk-python/.gitignore
vendored
Normal 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
|
||||
14
bdk-python/LICENSE
Normal file
14
bdk-python/LICENSE
Normal file
@@ -0,0 +1,14 @@
|
||||
This software is licensed under [Apache 2.0](LICENSE-APACHE) or
|
||||
[MIT](LICENSE-MIT), at your option.
|
||||
|
||||
Some files retain their own copyright notice, however, for full authorship
|
||||
information, see version control history.
|
||||
|
||||
Except as otherwise noted in individual files, all files in this repository are
|
||||
licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
http://opensource.org/licenses/MIT>, at your option.
|
||||
|
||||
You may not use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of this software or any files in this repository except in
|
||||
accordance with one or both of these licenses.
|
||||
201
bdk-python/LICENSE-APACHE
Normal file
201
bdk-python/LICENSE-APACHE
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
17
bdk-python/LICENSE-MIT
Normal file
17
bdk-python/LICENSE-MIT
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
48
bdk-python/README.md
Normal file
48
bdk-python/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# bdk-python
|
||||
The Python language bindings for the [bitcoindevkit](https://github.com/bitcoindevkit).
|
||||
|
||||
See the [package on PyPI](https://pypi.org/project/bdkpython/).
|
||||
|
||||
## Install from PyPI
|
||||
Install the latest release using
|
||||
```shell
|
||||
pip install bdkpython
|
||||
```
|
||||
|
||||
## Run the tests
|
||||
```shell
|
||||
pip3 install --requirement requirements.txt
|
||||
bash ./generate.sh
|
||||
python3 setup.py --verbose bdist_wheel
|
||||
pip3 install ./dist/bdkpython-<yourversion>-py3-none-any.whl
|
||||
python -m unittest --verbose tests/test_bdk.py
|
||||
```
|
||||
|
||||
## Build the package
|
||||
```shell
|
||||
# Install dependencies
|
||||
pip install --requirement requirements.txt
|
||||
|
||||
# Generate the bindings first
|
||||
bash generate.sh
|
||||
|
||||
# Build the wheel
|
||||
python3 setup.py --verbose bdist_wheel
|
||||
```
|
||||
|
||||
## Run tox to build and test locally
|
||||
```shell
|
||||
# install dev requirements
|
||||
pip install --requirement requirements-dev.txt
|
||||
|
||||
# build bindings glue code (located at .bdk-python/src/bdkpython/bdk.py)
|
||||
source ./generate.sh
|
||||
|
||||
# build and test
|
||||
tox -vv
|
||||
```
|
||||
|
||||
## Install locally
|
||||
```shell
|
||||
pip install ./dist/bdkpython-<yourversion>-py3-none-any.whl
|
||||
```
|
||||
11
bdk-python/generate.sh
Normal file
11
bdk-python/generate.sh
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR=$(dirname "$(realpath $0)")
|
||||
PY_SRC="${SCRIPT_DIR}/src/bdkpython/"
|
||||
|
||||
echo "Generating bdk.py..."
|
||||
# GENERATE_PYTHON_BINDINGS_OUT="$PY_SRC" GENERATE_PYTHON_BINDINGS_FIXUP_LIB_PATH=bdkffi cargo run --manifest-path ./bdk-ffi/Cargo.toml --release --bin generate --features generate-python
|
||||
# BDKFFI_BINDGEN_PYTHON_FIXUP_PATH=bdkffi cargo run --manifest-path ./bdk-ffi/Cargo.toml --package bdk-ffi-bindgen -- --language python --udl-file ./bdk-ffi/src/bdk.udl --out-dir ./src/bdkpython/
|
||||
BDKFFI_BINDGEN_OUTPUT_DIR="$PY_SRC" BDKFFI_BINDGEN_PYTHON_FIXUP_PATH=bdkffi cargo run --manifest-path ../bdk-ffi/Cargo.toml --package bdk-ffi-bindgen -- --language python --udl-file ../bdk-ffi/src/bdk.udl
|
||||
387
bdk-python/nix/uniffi_0.14.1_cargo_lock.patch
Normal file
387
bdk-python/nix/uniffi_0.14.1_cargo_lock.patch
Normal 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"
|
||||
387
bdk-python/nix/uniffi_0.15.2_cargo_lock.patch
Normal file
387
bdk-python/nix/uniffi_0.15.2_cargo_lock.patch
Normal 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"
|
||||
20
bdk-python/nix/uniffi_bindgen.nix
Normal file
20
bdk-python/nix/uniffi_bindgen.nix
Normal 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 ];
|
||||
}
|
||||
7
bdk-python/pyproject.toml
Normal file
7
bdk-python/pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel", "setuptools-rust"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
pythonpath = [
|
||||
"."
|
||||
]
|
||||
2
bdk-python/requirements-dev.txt
Normal file
2
bdk-python/requirements-dev.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pytest==7.1.2
|
||||
tox==3.25.1
|
||||
3
bdk-python/requirements.txt
Normal file
3
bdk-python/requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
semantic-version==2.9.0
|
||||
setuptools-rust==1.1.2
|
||||
typing_extensions==4.0.1
|
||||
73
bdk-python/setup.py
Normal file
73
bdk-python/setup.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
from setuptools import setup
|
||||
from setuptools_rust import Binding, RustExtension
|
||||
|
||||
LONG_DESCRIPTION = """# bdkpython
|
||||
The Python language bindings for the [Bitcoin Dev Kit](https://github.com/bitcoindevkit).
|
||||
|
||||
## Install the package
|
||||
```shell
|
||||
pip install bdkpython
|
||||
```
|
||||
|
||||
## Simple example
|
||||
```python
|
||||
import bdkpython as bdk
|
||||
|
||||
|
||||
descriptor = "wpkh(tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy/84h/0h/0h/0/*)"
|
||||
db_config = bdk.DatabaseConfig.MEMORY()
|
||||
blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
bdk.ElectrumConfig(
|
||||
"ssl://electrum.blockstream.info:60002",
|
||||
None,
|
||||
5,
|
||||
None,
|
||||
100
|
||||
)
|
||||
)
|
||||
blockchain = bdk.Blockchain(blockchain_config)
|
||||
|
||||
wallet = bdk.Wallet(
|
||||
descriptor=descriptor,
|
||||
change_descriptor=None,
|
||||
network=bdk.Network.TESTNET,
|
||||
database_config=db_config,
|
||||
)
|
||||
|
||||
# print new receive address
|
||||
address_info = wallet.get_address(bdk.AddressIndex.LAST_UNUSED)
|
||||
address = address_info.address
|
||||
index = address_info.index
|
||||
print(f"New BIP84 testnet address: {address} at index {index}")
|
||||
|
||||
|
||||
# print wallet balance
|
||||
wallet.sync(blockchain, None)
|
||||
balance = wallet.get_balance()
|
||||
print(f"Wallet balance is: {balance.total}")
|
||||
"""
|
||||
|
||||
rust_ext = RustExtension(
|
||||
target="bdkpython.bdkffi",
|
||||
path="../bdk-ffi/Cargo.toml",
|
||||
binding=Binding.NoBinding,
|
||||
)
|
||||
|
||||
setup(
|
||||
name='bdkpython',
|
||||
version='0.25.0',
|
||||
description="The Python language bindings for the Bitcoin Development Kit",
|
||||
long_description=LONG_DESCRIPTION,
|
||||
long_description_content_type='text/markdown',
|
||||
rust_extensions=[rust_ext],
|
||||
zip_safe=False,
|
||||
packages=['bdkpython'],
|
||||
package_dir={'bdkpython': './src/bdkpython'},
|
||||
url="https://github.com/bitcoindevkit/bdk-python",
|
||||
author="Alekos Filini <alekos.filini@gmail.com>, Steve Myers <steve@notmandatory.org>",
|
||||
license="MIT or Apache 2.0",
|
||||
)
|
||||
17
bdk-python/shell.nix
Normal file
17
bdk-python/shell.nix
Normal file
@@ -0,0 +1,17 @@
|
||||
with import <nixpkgs> {};
|
||||
|
||||
mkShell {
|
||||
name = "bdk-python-shell";
|
||||
packages = [ ( import ./nix/uniffi_bindgen.nix ) ];
|
||||
buildInputs = with python37.pkgs; [
|
||||
pip
|
||||
setuptools
|
||||
];
|
||||
shellHook = ''
|
||||
export LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH
|
||||
alias pip="PIP_PREFIX='$(pwd)/_build/pip_packages' \pip"
|
||||
export PYTHONPATH="$(pwd)/_build/pip_packages/lib/python3.7/site-packages:$(pwd):$PYTHONPATH"
|
||||
export PATH="$(pwd)/_build/pip_packages/bin:$PATH"
|
||||
unset SOURCE_DATE_EPOCH
|
||||
'';
|
||||
}
|
||||
1
bdk-python/src/bdkpython/__init__.py
Normal file
1
bdk-python/src/bdkpython/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from bdkpython.bdk import *
|
||||
46
bdk-python/tests/test_bdk.py
Normal file
46
bdk-python/tests/test_bdk.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import bdkpython as bdk
|
||||
import unittest
|
||||
|
||||
descriptor = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
db_config = bdk.DatabaseConfig.MEMORY()
|
||||
blockchain_config = bdk.BlockchainConfig.ELECTRUM(
|
||||
bdk.ElectrumConfig(
|
||||
"ssl://electrum.blockstream.info:60002",
|
||||
None,
|
||||
5,
|
||||
None,
|
||||
100
|
||||
)
|
||||
)
|
||||
blockchain = bdk.Blockchain(blockchain_config)
|
||||
|
||||
|
||||
class TestSimpleBip84Wallet(unittest.TestCase):
|
||||
|
||||
def test_address_bip84_testnet(self):
|
||||
wallet = bdk.Wallet(
|
||||
descriptor=descriptor,
|
||||
change_descriptor=None,
|
||||
network=bdk.Network.TESTNET,
|
||||
database_config=db_config
|
||||
)
|
||||
address_info = wallet.get_address(bdk.AddressIndex.LAST_UNUSED)
|
||||
address = address_info.address
|
||||
# print(f"New address is {address}")
|
||||
assert address == "tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e", f"Wrong address {address}, should be tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e"
|
||||
|
||||
def test_wallet_balance(self):
|
||||
wallet = bdk.Wallet(
|
||||
descriptor=descriptor,
|
||||
change_descriptor=None,
|
||||
network=bdk.Network.TESTNET,
|
||||
database_config=db_config,
|
||||
)
|
||||
wallet.sync(blockchain, None)
|
||||
balance = wallet.get_balance()
|
||||
# print(f"Balance is {balance.total} sat")
|
||||
assert balance.total > 0, "Balance is 0, send testnet coins to tb1qzg4mckdh50nwdm9hkzq06528rsu73hjxxzem3e"
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
16
bdk-python/tox.ini
Normal file
16
bdk-python/tox.ini
Normal file
@@ -0,0 +1,16 @@
|
||||
[tox]
|
||||
envlist =
|
||||
py38
|
||||
py39
|
||||
|
||||
|
||||
[testenv]
|
||||
usedevelop=true
|
||||
deps =
|
||||
-rrequirements.txt
|
||||
-rrequirements-dev.txt
|
||||
commands =
|
||||
python3 setup.py -v build
|
||||
python3 setup.py -v install
|
||||
pytest --verbose --override-ini console_output_style=count
|
||||
python3 setup.py --verbose bdist_wheel
|
||||
37
bdk-swift/Package.swift
Normal file
37
bdk-swift/Package.swift
Normal file
@@ -0,0 +1,37 @@
|
||||
// swift-tools-version:5.5
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "bdk-swift",
|
||||
platforms: [
|
||||
.macOS(.v12),
|
||||
.iOS(.v15)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "BitcoinDevKit",
|
||||
targets: ["bdkFFI", "BitcoinDevKit"]),
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
// .package(url: /* package url */, from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
// .binaryTarget(
|
||||
// name: "bdkFFI",
|
||||
// url: "https://github.com/bitcoindevkit/bdk-swift/releases/download/0.3.0/bdkFFI.xcframework.zip",
|
||||
// checksum: "7d4a2fdeb03fb3eff107e45ee3148dd9b67966406c82d6e3c19f653c27180cfd"),
|
||||
.binaryTarget(name: "bdkFFI", path: "./bdkFFI.xcframework"),
|
||||
.target(
|
||||
name: "BitcoinDevKit",
|
||||
dependencies: ["bdkFFI"]),
|
||||
.testTarget(
|
||||
name: "BitcoinDevKitTests",
|
||||
dependencies: ["BitcoinDevKit"]),
|
||||
]
|
||||
)
|
||||
36
bdk-swift/Package.swift.txt
Normal file
36
bdk-swift/Package.swift.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
// swift-tools-version:5.5
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "bdk-swift",
|
||||
platforms: [
|
||||
.macOS(.v12),
|
||||
.iOS(.v15)
|
||||
],
|
||||
products: [
|
||||
// Products define the executables and libraries a package produces, and make them visible to other packages.
|
||||
.library(
|
||||
name: "BitcoinDevKit",
|
||||
targets: ["bdkFFI", "BitcoinDevKit"]),
|
||||
],
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
// .package(url: /* package url */, from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages this package depends on.
|
||||
.binaryTarget(
|
||||
name: "bdkFFI",
|
||||
url: "BDKFFIURL",
|
||||
checksum: "BDKFFICHECKSUM"),
|
||||
.target(
|
||||
name: "BitcoinDevKit",
|
||||
dependencies: ["bdkFFI"]),
|
||||
.testTarget(
|
||||
name: "BitcoinDevKitTests",
|
||||
dependencies: ["BitcoinDevKit"]),
|
||||
]
|
||||
)
|
||||
52
bdk-swift/README.md
Normal file
52
bdk-swift/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# bdk-swift
|
||||
|
||||
This project builds a Swift package that provides [Swift] language bindings for the
|
||||
[`bdk`] library. The Swift language bindings are created by the [`bdk-ffi`] project which is included as a module of this repository.
|
||||
|
||||
Supported target platforms are:
|
||||
|
||||
- MacOS, X86_64 and M1 (aarch64)
|
||||
- iOS, iPhones (aarch64)
|
||||
- iOS simulator, X86_64 and M1 (aarch64)
|
||||
|
||||
## How to Use
|
||||
|
||||
To use the Swift language bindings for [`bdk`] in your [Xcode] iOS or MacOS project add
|
||||
the github repository https://github.com/bitcoindevkit/bdk-swift and select one of the
|
||||
release versions. You may then import and use the `BitcoinDevKit` library in your Swift
|
||||
code. For example:
|
||||
|
||||
```swift
|
||||
import BitcoinDevKit
|
||||
|
||||
...
|
||||
|
||||
```
|
||||
|
||||
Swift Package Manager releases for `bdk-swift` are published to a separate repository (https://github.com/bitcoindevkit/bdk-swift), and that is where the releases are created for it.
|
||||
|
||||
The `bdk-swift/build-local-swift.sh` script can be used instead to create a version of the project for local testing.
|
||||
|
||||
### How to test
|
||||
|
||||
```shell
|
||||
swift test
|
||||
```
|
||||
|
||||
### Example Projects
|
||||
|
||||
* [BdkSwiftSample](https://github.com/futurepaul/BdkSwiftSample), iOS
|
||||
|
||||
## How to Build and Publish
|
||||
|
||||
If you are a maintainer of this project or want to build and publish this project to your
|
||||
own Github repository use the following steps:
|
||||
|
||||
1. If it doesn't already exist, create a new `release/0.MINOR` branch from the `master` branch.
|
||||
2. Add a tag `v0.MINOR.PATCH`.
|
||||
3. Run the `publish-spm` workflow on Github from the `bdk-swift` repo for version `0.MINOR.PATCH`.
|
||||
|
||||
[Swift]: https://developer.apple.com/swift/
|
||||
[Xcode]: https://developer.apple.com/documentation/Xcode
|
||||
[`bdk`]: https://github.com/bitcoindevkit/bdk
|
||||
[`bdk-ffi`]: https://github.com/bitcoindevkit/bdk-ffi
|
||||
12
bdk-swift/Tests/BitcoinDevKitTests/BitcoinDevKitTests.swift
Normal file
12
bdk-swift/Tests/BitcoinDevKitTests/BitcoinDevKitTests.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
import XCTest
|
||||
@testable import BitcoinDevKit
|
||||
|
||||
final class BitcoinDevKitTests: XCTestCase {
|
||||
func testMemoryWalletNewAddress() throws {
|
||||
let desc = "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)"
|
||||
let databaseConfig = DatabaseConfig.memory
|
||||
let wallet = try Wallet.init(descriptor: desc, changeDescriptor: nil, network: Network.regtest, databaseConfig: databaseConfig)
|
||||
let addressInfo = try wallet.getAddress(addressIndex: AddressIndex.new)
|
||||
XCTAssertEqual(addressInfo.address, "bcrt1qzg4mckdh50nwdm9hkzq06528rsu73hjxytqkxs")
|
||||
}
|
||||
}
|
||||
53
bdk-swift/bdkFFI.xcframework/Info.plist
Normal file
53
bdk-swift/bdkFFI.xcframework/Info.plist
Normal file
@@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>macos-arm64_x86_64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>bdkFFI.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>macos</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64_x86_64-simulator</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>bdkFFI.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
<key>SupportedPlatformVariant</key>
|
||||
<string>simulator</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>bdkFFI.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,4 @@
|
||||
// This is the "umbrella header" for our combined Rust code library.
|
||||
// It needs to import all of the individual headers.
|
||||
|
||||
#import "bdkFFI.h"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user