Remove non-kotlin related files, add bdk-ffi as submodule, update build.sh
This commit is contained in:
		
							parent
							
								
									09ce971708
								
							
						
					
					
						commit
						0f42ba7590
					
				
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -14,3 +14,5 @@ testdb | |||||||
| xcuserdata | xcuserdata | ||||||
| .lsp | .lsp | ||||||
| .clj-kondo | .clj-kondo | ||||||
|  | .idea | ||||||
|  | bdk.kt | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | [submodule "bdk-ffi"] | ||||||
|  | 	path = bdk-ffi | ||||||
|  | 	url = git@github.com:bitcoindevkit/bdk-ffi.git | ||||||
							
								
								
									
										20
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								Cargo.toml
									
									
									
									
									
								
							| @ -1,20 +0,0 @@ | |||||||
| [package] |  | ||||||
| name = "bdk-ffi" |  | ||||||
| version = "0.1.0" |  | ||||||
| authors = ["Steve Myers <steve@notmandatory.org>", "Sudarsan Balaji <sudarsan.balaji@artfuldev.com>"] |  | ||||||
| edition = "2018" |  | ||||||
| 
 |  | ||||||
| # 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.13", features = ["all-keys", "use-esplora-ureq"] } |  | ||||||
| uniffi_macros = "0.14.1" |  | ||||||
| uniffi = "0.14.1" |  | ||||||
| thiserror = "1.0" |  | ||||||
| anyhow = "=1.0.45" # remove after upgrading to next version of uniffi |  | ||||||
| 
 |  | ||||||
| [build-dependencies] |  | ||||||
| uniffi_build = "0.14.1" |  | ||||||
							
								
								
									
										1
									
								
								bdk-ffi
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										1
									
								
								bdk-ffi
									
									
									
									
									
										Submodule
									
								
							| @ -0,0 +1 @@ | |||||||
|  | Subproject commit e4d53b5e4b213e484bf4b76a4bf33884dd68f086 | ||||||
							
								
								
									
										7
									
								
								bindings/bdk-kotlin/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								bindings/bdk-kotlin/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,7 +0,0 @@ | |||||||
| .idea |  | ||||||
| .gradle |  | ||||||
| local.properties |  | ||||||
| build |  | ||||||
| *.so |  | ||||||
| *.dylib |  | ||||||
| bdk.kt |  | ||||||
							
								
								
									
										3
									
								
								build.rs
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								build.rs
									
									
									
									
									
								
							| @ -1,3 +0,0 @@ | |||||||
| fn main() { |  | ||||||
|     uniffi_build::generate_scaffolding("src/bdk.udl").unwrap(); |  | ||||||
| } |  | ||||||
							
								
								
									
										154
									
								
								build.sh
									
									
									
									
									
								
							
							
						
						
									
										154
									
								
								build.sh
									
									
									
									
									
								
							| @ -1,107 +1,65 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
| set -eo pipefail | set -eo pipefail | ||||||
| 
 | 
 | ||||||
| # functions | echo "Build and test bdk-ffi library for local platform (darwin or linux)" | ||||||
|  | pushd bdk-ffi | ||||||
| 
 | 
 | ||||||
| ## help | cargo fmt | ||||||
| help() | cargo build --release | ||||||
| { | cargo test | ||||||
|    # Display Help |  | ||||||
|    echo "Build bdk-ffi and related libraries." |  | ||||||
|    echo |  | ||||||
|    echo "Syntax: build [-a|h|k|s]" |  | ||||||
|    echo "options:" |  | ||||||
|    echo "-a     Android." |  | ||||||
|    echo "-h     Print this Help." |  | ||||||
|    echo "-k     Kotlin." |  | ||||||
|    echo |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ## rust |  | ||||||
| build_rust() { |  | ||||||
|   echo "Build Rust library" |  | ||||||
|   cargo fmt |  | ||||||
|   cargo build --release |  | ||||||
|   cargo test |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ## copy to bdk-bdk-kotlin |  | ||||||
| copy_lib_kotlin() { |  | ||||||
|   echo -n "Copy " |  | ||||||
|   case $OS in |  | ||||||
|     "Darwin") |  | ||||||
|       echo -n "darwin " |  | ||||||
|       mkdir -p bindings/bdk-kotlin/jvm/src/main/resources/darwin-x86-64 |  | ||||||
|       cp target/release/libbdkffi.dylib bindings/bdk-kotlin/jvm/src/main/resources/darwin-x86-64 |  | ||||||
|       ;; |  | ||||||
|     "Linux") |  | ||||||
|       echo -n "linux " |  | ||||||
|       mkdir -p bindings/bdk-kotlin/jvm/src/main/resources/linux-x86-64 |  | ||||||
|       cp target/release/libbdkffi.so bindings/bdk-kotlin/jvm/src/main/resources/linux-x86-64 |  | ||||||
|       ;; |  | ||||||
|   esac |  | ||||||
|   echo "libs to kotlin sub-project" |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ## bdk-bdk-kotlin jar |  | ||||||
| build_kotlin() { |  | ||||||
|   copy_lib_kotlin |  | ||||||
|   uniffi-bindgen generate src/bdk.udl --no-format --out-dir bindings/bdk-kotlin/jvm/src/main/kotlin --language kotlin |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ## rust android |  | ||||||
| build_android() { |  | ||||||
|   build_kotlin |  | ||||||
| 
 |  | ||||||
|   # If ANDROID_NDK_HOME is not set then set it to github actions default |  | ||||||
|   [ -z "$ANDROID_NDK_HOME" ] && export ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle |  | ||||||
| 
 |  | ||||||
|   # Update this line accordingly if you are not building *from* darwin-x86_64 or linux-x86_64 |  | ||||||
|   export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/`uname | tr '[:upper:]' '[:lower:]'`-x86_64/bin |  | ||||||
| 
 |  | ||||||
|   # Required for 'ring' dependency to cross-compile to Android platform, must be at least 21 |  | ||||||
|   export CFLAGS="-D__ANDROID_API__=21" |  | ||||||
| 
 |  | ||||||
|   # IMPORTANT: make sure every target is not a substring of a different one. We check for them with grep later on |  | ||||||
|   BUILD_TARGETS="${BUILD_TARGETS:-aarch64,x86_64,i686}" |  | ||||||
| 
 |  | ||||||
|   mkdir -p bindings/bdk-kotlin/android/src/main/jniLibs/ bindings/bdk-kotlin/android/src/main/jniLibs/arm64-v8a bindings/bdk-kotlin/android/src/main/jniLibs/x86_64 bindings/bdk-kotlin/android/src/main/jniLibs/x86 |  | ||||||
| 
 |  | ||||||
|   if echo $BUILD_TARGETS | grep "aarch64"; then |  | ||||||
|       CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="aarch64-linux-android21-clang" CC="aarch64-linux-android21-clang" cargo build --release --target=aarch64-linux-android |  | ||||||
|       cp target/aarch64-linux-android/release/libbdkffi.so bindings/bdk-kotlin/android/src/main/jniLibs/arm64-v8a |  | ||||||
|   fi |  | ||||||
|   if echo $BUILD_TARGETS | grep "x86_64"; then |  | ||||||
|       CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="x86_64-linux-android21-clang" CC="x86_64-linux-android21-clang" cargo build --release --target=x86_64-linux-android |  | ||||||
|       cp target/x86_64-linux-android/release/libbdkffi.so bindings/bdk-kotlin/android/src/main/jniLibs/x86_64 |  | ||||||
|   fi |  | ||||||
|   if echo $BUILD_TARGETS | grep "i686"; then |  | ||||||
|       CARGO_TARGET_I686_LINUX_ANDROID_LINKER="i686-linux-android21-clang" CC="i686-linux-android21-clang" cargo build --release --target=i686-linux-android |  | ||||||
|       cp target/i686-linux-android/release/libbdkffi.so bindings/bdk-kotlin/android/src/main/jniLibs/x86 |  | ||||||
|   fi |  | ||||||
| 
 |  | ||||||
|   # copy sources |  | ||||||
|   cp -R bindings/bdk-kotlin/jvm/src/main/kotlin bindings/bdk-kotlin/android/src/main |  | ||||||
| 
 |  | ||||||
|   # bdk-kotlin aar |  | ||||||
|   (cd bindings/bdk-kotlin && ./gradlew :android:build) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| OS=$(uname) | OS=$(uname) | ||||||
|  | echo -n "Copy " | ||||||
|  | case $OS in | ||||||
|  |   "Darwin") | ||||||
|  |     echo -n "darwin " | ||||||
|  |     mkdir -p ../jvm/src/main/resources/darwin-x86-64 | ||||||
|  |     cp target/release/libbdkffi.dylib ../jvm/src/main/resources/darwin-x86-64 | ||||||
|  |     ;; | ||||||
|  |   "Linux") | ||||||
|  |     echo -n "linux " | ||||||
|  |     mkdir -p ../jvm/src/main/resources/linux-x86-64 | ||||||
|  |     cp target/release/libbdkffi.so ../jvm/src/main/resources/linux-x86-64 | ||||||
|  |     ;; | ||||||
|  | esac | ||||||
|  | echo "libs to jvm subproject" | ||||||
| 
 | 
 | ||||||
| if [ "$1" == "-h" ] | echo "Generate kotlin bindings from bdk.udl to jvm subproject" | ||||||
| then | uniffi-bindgen generate src/bdk.udl --no-format --out-dir ../jvm/src/main/kotlin --language kotlin | ||||||
|   help |  | ||||||
| else |  | ||||||
|   build_rust |  | ||||||
| 
 | 
 | ||||||
|   while [ -n "$1" ]; do # while loop starts | ## android | ||||||
|     case "$1" in | 
 | ||||||
|       -a) build_android ;; | # If ANDROID_NDK_HOME is not set then set it to github actions default | ||||||
|       -k) build_kotlin ;; | [ -z "$ANDROID_NDK_HOME" ] && export ANDROID_NDK_HOME=$ANDROID_HOME/ndk-bundle | ||||||
|       -h) help ;; | 
 | ||||||
|       *) echo "Option $1 not recognized" ;; | # Update this line accordingly if you are not building *from* darwin-x86_64 or linux-x86_64 | ||||||
|     esac | export PATH=$PATH:$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/`uname | tr '[:upper:]' '[:lower:]'`-x86_64/bin | ||||||
|     shift | 
 | ||||||
|   done | # Required for 'ring' dependency to cross-compile to Android platform, must be at least 21 | ||||||
|  | export CFLAGS="-D__ANDROID_API__=21" | ||||||
|  | 
 | ||||||
|  | # IMPORTANT: make sure every target is not a substring of a different one. We check for them with grep later on | ||||||
|  | BUILD_TARGETS="${BUILD_TARGETS:-aarch64,x86_64,i686}" | ||||||
|  | 
 | ||||||
|  | mkdir -p ../android/src/main/jniLibs/arm64-v8a ../android/src/main/jniLibs/x86_64 ../android/src/main/jniLibs/x86 | ||||||
|  | 
 | ||||||
|  | if echo $BUILD_TARGETS | grep "aarch64"; then | ||||||
|  |     CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="aarch64-linux-android21-clang" CC="aarch64-linux-android21-clang" cargo build --release --target=aarch64-linux-android | ||||||
|  |     cp target/aarch64-linux-android/release/libbdkffi.so ../android/src/main/jniLibs/arm64-v8a | ||||||
| fi | fi | ||||||
|  | if echo $BUILD_TARGETS | grep "x86_64"; then | ||||||
|  |     CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="x86_64-linux-android21-clang" CC="x86_64-linux-android21-clang" cargo build --release --target=x86_64-linux-android | ||||||
|  |     cp target/x86_64-linux-android/release/libbdkffi.so ../android/src/main/jniLibs/x86_64 | ||||||
|  | fi | ||||||
|  | if echo $BUILD_TARGETS | grep "i686"; then | ||||||
|  |     CARGO_TARGET_I686_LINUX_ANDROID_LINKER="i686-linux-android21-clang" CC="i686-linux-android21-clang" cargo build --release --target=i686-linux-android | ||||||
|  |     cp target/i686-linux-android/release/libbdkffi.so ../android/src/main/jniLibs/x86 | ||||||
|  | fi | ||||||
|  | 
 | ||||||
|  | popd | ||||||
|  | 
 | ||||||
|  | # copy bdk-ffi kotlin binding sources from jvm to android | ||||||
|  | cp -R jvm/src/main/kotlin android/src/main | ||||||
|  | 
 | ||||||
|  | # bdk-kotlin build jar and aar subprojects | ||||||
|  | ./gradlew build | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								bindings/bdk-kotlin/gradlew → gradlew
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								bindings/bdk-kotlin/gradlew → gradlew
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										167
									
								
								src/bdk.udl
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								src/bdk.udl
									
									
									
									
									
								
							| @ -1,167 +0,0 @@ | |||||||
| namespace bdk { |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   ExtendedKeyInfo generate_extended_key(Network network, MnemonicType mnemonic_type, string? password); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   ExtendedKeyInfo restore_extended_key(Network network, string mnemonic, string? password); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| [Error] |  | ||||||
| enum BdkError { |  | ||||||
|   "InvalidU32Bytes", |  | ||||||
|   "Generic", |  | ||||||
|   "ScriptDoesntHaveAddressForm", |  | ||||||
|   "NoRecipients", |  | ||||||
|   "NoUtxosSelected", |  | ||||||
|   "OutputBelowDustLimit", |  | ||||||
|   "InsufficientFunds", |  | ||||||
|   "BnBTotalTriesExceeded", |  | ||||||
|   "BnBNoExactMatch", |  | ||||||
|   "UnknownUtxo", |  | ||||||
|   "TransactionNotFound", |  | ||||||
|   "TransactionConfirmed", |  | ||||||
|   "IrreplaceableTransaction", |  | ||||||
|   "FeeRateTooLow", |  | ||||||
|   "FeeTooLow", |  | ||||||
|   "FeeRateUnavailable", |  | ||||||
|   "MissingKeyOrigin", |  | ||||||
|   "Key", |  | ||||||
|   "ChecksumMismatch", |  | ||||||
|   "SpendingPolicyRequired", |  | ||||||
|   "InvalidPolicyPathError", |  | ||||||
|   "Signer", |  | ||||||
|   "InvalidNetwork", |  | ||||||
|   "InvalidProgressValue", |  | ||||||
|   "ProgressUpdateError", |  | ||||||
|   "InvalidOutpoint", |  | ||||||
|   "Descriptor", |  | ||||||
|   "AddressValidator", |  | ||||||
|   "Encode", |  | ||||||
|   "Miniscript", |  | ||||||
|   "Bip32", |  | ||||||
|   "Secp256k1", |  | ||||||
|   "Json", |  | ||||||
|   "Hex", |  | ||||||
|   "Psbt", |  | ||||||
|   "PsbtParse", |  | ||||||
|   "Electrum", |  | ||||||
|   "Esplora", |  | ||||||
|   "Sled", |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum Network { |  | ||||||
|   "Bitcoin", |  | ||||||
|   "Testnet", |  | ||||||
|   "Signet", |  | ||||||
|   "Regtest", |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary SledDbConfiguration { |  | ||||||
|   string path; |  | ||||||
|   string tree_name; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| [Enum] |  | ||||||
| interface DatabaseConfig { |  | ||||||
|   Memory(string junk); |  | ||||||
|   Sled(SledDbConfiguration config); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary TransactionDetails { |  | ||||||
|     u64? fees; |  | ||||||
|     u64 received; |  | ||||||
|     u64 sent; |  | ||||||
|     string txid; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary Confirmation { |  | ||||||
|     u32 height; |  | ||||||
|     u64 timestamp; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| [Enum] |  | ||||||
| interface Transaction { |  | ||||||
|   Unconfirmed(TransactionDetails details); |  | ||||||
|   Confirmed(TransactionDetails details, Confirmation confirmation); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| interface OfflineWallet { |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   constructor(string descriptor, Network network, DatabaseConfig database_config); |  | ||||||
| 
 |  | ||||||
|   // OfflineWalletOperations |  | ||||||
|   string get_new_address(); |  | ||||||
|   string get_last_unused_address(); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   u64 get_balance(); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   void sign([ByRef] PartiallySignedBitcoinTransaction psbt); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   sequence<Transaction> get_transactions(); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary ElectrumConfig { |  | ||||||
|   string url; |  | ||||||
|   string? socks5; |  | ||||||
|   u8 retry; |  | ||||||
|   u8? timeout; |  | ||||||
|   u64 stop_gap; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary EsploraConfig { |  | ||||||
|   string base_url; |  | ||||||
|   string? proxy; |  | ||||||
|   u64 timeout_read; |  | ||||||
|   u64 timeout_write; |  | ||||||
|   u64 stop_gap; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| [Enum] |  | ||||||
| interface BlockchainConfig { |  | ||||||
|   Electrum(ElectrumConfig config); |  | ||||||
|   Esplora(EsploraConfig config); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| callback interface BdkProgress { |  | ||||||
|   void update(f32 progress, string? message); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| interface OnlineWallet { |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   constructor(string descriptor, string? change_descriptor, Network network, DatabaseConfig database_config, BlockchainConfig blockchain_config); |  | ||||||
| 
 |  | ||||||
|   // OfflineWalletOperations |  | ||||||
|   string get_new_address(); |  | ||||||
|   string get_last_unused_address(); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   u64 get_balance(); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   void sign([ByRef] PartiallySignedBitcoinTransaction psbt); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   sequence<Transaction> get_transactions(); |  | ||||||
| 
 |  | ||||||
|   // OnlineWalletInterface |  | ||||||
|   Network get_network(); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   void sync(BdkProgress progress_update, u32? max_address_param); |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   Transaction broadcast([ByRef] PartiallySignedBitcoinTransaction psbt); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| interface PartiallySignedBitcoinTransaction { |  | ||||||
|   [Throws=BdkError] |  | ||||||
|   constructor([ByRef] OnlineWallet wallet, string recipient, u64 amount, float? fee_rate); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| dictionary ExtendedKeyInfo { |  | ||||||
|   string mnemonic; |  | ||||||
|   string xprv; |  | ||||||
|   string fingerprint; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum MnemonicType { |  | ||||||
|   "Words12", |  | ||||||
|   "Words15", |  | ||||||
|   "Words18", |  | ||||||
|   "Words21", |  | ||||||
|   "Words24", |  | ||||||
| }; |  | ||||||
							
								
								
									
										340
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										340
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -1,340 +0,0 @@ | |||||||
| use bdk::bitcoin::secp256k1::Secp256k1; |  | ||||||
| use bdk::bitcoin::util::psbt::PartiallySignedTransaction; |  | ||||||
| use bdk::bitcoin::{Address, Network}; |  | ||||||
| use bdk::blockchain::any::{AnyBlockchain, AnyBlockchainConfig}; |  | ||||||
| use bdk::blockchain::Progress; |  | ||||||
| use bdk::blockchain::{ |  | ||||||
|     electrum::ElectrumBlockchainConfig, esplora::EsploraBlockchainConfig, ConfigurableBlockchain, |  | ||||||
| }; |  | ||||||
| use bdk::database::any::{AnyDatabase, SledDbConfiguration}; |  | ||||||
| use bdk::database::{AnyDatabaseConfig, ConfigurableDatabase}; |  | ||||||
| use bdk::keys::bip39::{Language, Mnemonic, MnemonicType}; |  | ||||||
| use bdk::keys::{DerivableKey, ExtendedKey, GeneratableKey, GeneratedKey}; |  | ||||||
| use bdk::miniscript::BareCtx; |  | ||||||
| use bdk::wallet::AddressIndex; |  | ||||||
| use bdk::{ConfirmationTime, Error, FeeRate, SignOptions, Wallet}; |  | ||||||
| use std::convert::TryFrom; |  | ||||||
| use std::str::FromStr; |  | ||||||
| use std::sync::{Mutex, MutexGuard}; |  | ||||||
| 
 |  | ||||||
| uniffi_macros::include_scaffolding!("bdk"); |  | ||||||
| 
 |  | ||||||
| type BdkError = Error; |  | ||||||
| 
 |  | ||||||
| pub enum DatabaseConfig { |  | ||||||
|     Memory { junk: String }, |  | ||||||
|     Sled { config: SledDbConfiguration }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct ElectrumConfig { |  | ||||||
|     pub url: String, |  | ||||||
|     pub socks5: Option<String>, |  | ||||||
|     pub retry: u8, |  | ||||||
|     pub timeout: Option<u8>, |  | ||||||
|     pub stop_gap: u64, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct EsploraConfig { |  | ||||||
|     pub base_url: String, |  | ||||||
|     pub proxy: Option<String>, |  | ||||||
|     pub timeout_read: u64, |  | ||||||
|     pub timeout_write: u64, |  | ||||||
|     pub stop_gap: u64, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub enum BlockchainConfig { |  | ||||||
|     Electrum { config: ElectrumConfig }, |  | ||||||
|     Esplora { config: EsploraConfig }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| trait WalletHolder<B> { |  | ||||||
|     fn get_wallet(&self) -> MutexGuard<Wallet<B, AnyDatabase>>; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct OfflineWallet { |  | ||||||
|     wallet: Mutex<Wallet<(), AnyDatabase>>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl WalletHolder<()> for OfflineWallet { |  | ||||||
|     fn get_wallet(&self) -> MutexGuard<Wallet<(), AnyDatabase>> { |  | ||||||
|         self.wallet.lock().unwrap() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone, PartialEq, Eq, Default)] |  | ||||||
| pub struct TransactionDetails { |  | ||||||
|     pub fees: Option<u64>, |  | ||||||
|     pub received: u64, |  | ||||||
|     pub sent: u64, |  | ||||||
|     pub txid: String, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| type Confirmation = ConfirmationTime; |  | ||||||
| 
 |  | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] |  | ||||||
| pub enum Transaction { |  | ||||||
|     Unconfirmed { |  | ||||||
|         details: TransactionDetails, |  | ||||||
|     }, |  | ||||||
|     Confirmed { |  | ||||||
|         details: TransactionDetails, |  | ||||||
|         confirmation: Confirmation, |  | ||||||
|     }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<&bdk::TransactionDetails> for TransactionDetails { |  | ||||||
|     fn from(x: &bdk::TransactionDetails) -> TransactionDetails { |  | ||||||
|         TransactionDetails { |  | ||||||
|             fees: x.fee, |  | ||||||
|             txid: x.txid.to_string(), |  | ||||||
|             received: x.received, |  | ||||||
|             sent: x.sent, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<&bdk::TransactionDetails> for Transaction { |  | ||||||
|     fn from(x: &bdk::TransactionDetails) -> Transaction { |  | ||||||
|         match x.confirmation_time.clone() { |  | ||||||
|             Some(confirmation) => Transaction::Confirmed { |  | ||||||
|                 details: TransactionDetails::from(x), |  | ||||||
|                 confirmation, |  | ||||||
|             }, |  | ||||||
|             None => Transaction::Unconfirmed { |  | ||||||
|                 details: TransactionDetails::from(x), |  | ||||||
|             }, |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| trait OfflineWalletOperations<B>: WalletHolder<B> { |  | ||||||
|     fn get_new_address(&self) -> String { |  | ||||||
|         self.get_wallet() |  | ||||||
|             .get_address(AddressIndex::New) |  | ||||||
|             .unwrap() |  | ||||||
|             .address |  | ||||||
|             .to_string() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn get_last_unused_address(&self) -> String { |  | ||||||
|         self.get_wallet() |  | ||||||
|             .get_address(AddressIndex::LastUnused) |  | ||||||
|             .unwrap() |  | ||||||
|             .address |  | ||||||
|             .to_string() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn get_balance(&self) -> Result<u64, Error> { |  | ||||||
|         self.get_wallet().get_balance() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn sign<'a>(&self, psbt: &'a PartiallySignedBitcoinTransaction) -> Result<(), Error> { |  | ||||||
|         let mut psbt = psbt.internal.lock().unwrap(); |  | ||||||
|         let finalized = self.get_wallet().sign(&mut psbt, SignOptions::default())?; |  | ||||||
|         match finalized { |  | ||||||
|             true => Ok(()), |  | ||||||
|             false => Err(BdkError::Generic(format!( |  | ||||||
|                 "transaction signing not finalized {:?}", |  | ||||||
|                 psbt |  | ||||||
|             ))), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn get_transactions(&self) -> Result<Vec<Transaction>, Error> { |  | ||||||
|         let transactions = self.get_wallet().list_transactions(true)?; |  | ||||||
|         Ok(transactions.iter().map(Transaction::from).collect()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl OfflineWallet { |  | ||||||
|     fn new( |  | ||||||
|         descriptor: String, |  | ||||||
|         network: Network, |  | ||||||
|         database_config: DatabaseConfig, |  | ||||||
|     ) -> Result<Self, BdkError> { |  | ||||||
|         let any_database_config = match database_config { |  | ||||||
|             DatabaseConfig::Memory { .. } => AnyDatabaseConfig::Memory(()), |  | ||||||
|             DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), |  | ||||||
|         }; |  | ||||||
|         let database = AnyDatabase::from_config(&any_database_config)?; |  | ||||||
|         let wallet = Mutex::new(Wallet::new_offline(&descriptor, None, network, database)?); |  | ||||||
|         Ok(OfflineWallet { wallet }) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl OfflineWalletOperations<()> for OfflineWallet {} |  | ||||||
| 
 |  | ||||||
| struct OnlineWallet { |  | ||||||
|     wallet: Mutex<Wallet<AnyBlockchain, AnyDatabase>>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub trait BdkProgress: Send + Sync { |  | ||||||
|     fn update(&self, progress: f32, message: Option<String>); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct BdkProgressHolder { |  | ||||||
|     progress_update: Box<dyn BdkProgress>, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl Progress for BdkProgressHolder { |  | ||||||
|     fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> { |  | ||||||
|         self.progress_update.update(progress, message); |  | ||||||
|         Ok(()) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct PartiallySignedBitcoinTransaction { |  | ||||||
|     internal: Mutex<PartiallySignedTransaction>, |  | ||||||
|     details: bdk::TransactionDetails, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl PartiallySignedBitcoinTransaction { |  | ||||||
|     fn new( |  | ||||||
|         online_wallet: &OnlineWallet, |  | ||||||
|         recipient: String, |  | ||||||
|         amount: u64, |  | ||||||
|         fee_rate: Option<f32>, // satoshis per vbyte
 |  | ||||||
|     ) -> Result<Self, Error> { |  | ||||||
|         let wallet = online_wallet.get_wallet(); |  | ||||||
|         match Address::from_str(&recipient) { |  | ||||||
|             Ok(address) => { |  | ||||||
|                 let (psbt, details) = { |  | ||||||
|                     let mut builder = wallet.build_tx(); |  | ||||||
|                     builder.add_recipient(address.script_pubkey(), amount); |  | ||||||
|                     if let Some(sat_per_vb) = fee_rate { |  | ||||||
|                         builder.fee_rate(FeeRate::from_sat_per_vb(sat_per_vb)); |  | ||||||
|                     } |  | ||||||
|                     builder.finish()? |  | ||||||
|                 }; |  | ||||||
|                 Ok(PartiallySignedBitcoinTransaction { |  | ||||||
|                     internal: Mutex::new(psbt), |  | ||||||
|                     details, |  | ||||||
|                 }) |  | ||||||
|             } |  | ||||||
|             Err(..) => Err(BdkError::Generic( |  | ||||||
|                 "failed to read wallet address".to_string(), |  | ||||||
|             )), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl OnlineWallet { |  | ||||||
|     fn new( |  | ||||||
|         descriptor: String, |  | ||||||
|         change_descriptor: Option<String>, |  | ||||||
|         network: Network, |  | ||||||
|         database_config: DatabaseConfig, |  | ||||||
|         blockchain_config: BlockchainConfig, |  | ||||||
|     ) -> Result<Self, BdkError> { |  | ||||||
|         let any_database_config = match database_config { |  | ||||||
|             DatabaseConfig::Memory { .. } => AnyDatabaseConfig::Memory(()), |  | ||||||
|             DatabaseConfig::Sled { config } => AnyDatabaseConfig::Sled(config), |  | ||||||
|         }; |  | ||||||
|         let any_blockchain_config = match blockchain_config { |  | ||||||
|             BlockchainConfig::Electrum { config } => { |  | ||||||
|                 AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig { |  | ||||||
|                     retry: config.retry, |  | ||||||
|                     socks5: config.socks5, |  | ||||||
|                     timeout: config.timeout, |  | ||||||
|                     url: config.url, |  | ||||||
|                     stop_gap: usize::try_from(config.stop_gap).unwrap(), |  | ||||||
|                 }) |  | ||||||
|             } |  | ||||||
|             BlockchainConfig::Esplora { config } => { |  | ||||||
|                 AnyBlockchainConfig::Esplora(EsploraBlockchainConfig { |  | ||||||
|                     base_url: config.base_url, |  | ||||||
|                     proxy: config.proxy, |  | ||||||
|                     timeout_read: config.timeout_read, |  | ||||||
|                     timeout_write: config.timeout_write, |  | ||||||
|                     stop_gap: usize::try_from(config.stop_gap).unwrap(), |  | ||||||
|                 }) |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
|         let database = AnyDatabase::from_config(&any_database_config)?; |  | ||||||
|         let blockchain = AnyBlockchain::from_config(&any_blockchain_config)?; |  | ||||||
|         let wallet = Mutex::new(Wallet::new( |  | ||||||
|             &descriptor, |  | ||||||
|             change_descriptor.to_owned().as_ref(), |  | ||||||
|             network, |  | ||||||
|             database, |  | ||||||
|             blockchain, |  | ||||||
|         )?); |  | ||||||
|         Ok(OnlineWallet { wallet }) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn get_network(&self) -> Network { |  | ||||||
|         self.wallet.lock().unwrap().network() |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn sync( |  | ||||||
|         &self, |  | ||||||
|         progress_update: Box<dyn BdkProgress>, |  | ||||||
|         max_address_param: Option<u32>, |  | ||||||
|     ) -> Result<(), BdkError> { |  | ||||||
|         progress_update.update(21.0, Some("message".to_string())); |  | ||||||
|         self.wallet |  | ||||||
|             .lock() |  | ||||||
|             .unwrap() |  | ||||||
|             .sync(BdkProgressHolder { progress_update }, max_address_param) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     fn broadcast<'a>( |  | ||||||
|         &self, |  | ||||||
|         psbt: &'a PartiallySignedBitcoinTransaction, |  | ||||||
|     ) -> Result<Transaction, Error> { |  | ||||||
|         let tx = psbt.internal.lock().unwrap().clone().extract_tx(); |  | ||||||
|         self.get_wallet().broadcast(tx)?; |  | ||||||
|         Ok(Transaction::from(&psbt.details)) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl WalletHolder<AnyBlockchain> for OnlineWallet { |  | ||||||
|     fn get_wallet(&self) -> MutexGuard<Wallet<AnyBlockchain, AnyDatabase>> { |  | ||||||
|         self.wallet.lock().unwrap() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl OfflineWalletOperations<AnyBlockchain> for OnlineWallet {} |  | ||||||
| 
 |  | ||||||
| pub struct ExtendedKeyInfo { |  | ||||||
|     mnemonic: String, |  | ||||||
|     xprv: String, |  | ||||||
|     fingerprint: String, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn generate_extended_key( |  | ||||||
|     network: Network, |  | ||||||
|     mnemonic_type: MnemonicType, |  | ||||||
|     password: Option<String>, |  | ||||||
| ) -> Result<ExtendedKeyInfo, Error> { |  | ||||||
|     let mnemonic: GeneratedKey<_, BareCtx> = |  | ||||||
|         Mnemonic::generate((mnemonic_type, Language::English)).unwrap(); |  | ||||||
|     let mnemonic = mnemonic.into_key(); |  | ||||||
|     let xkey: ExtendedKey = (mnemonic.clone(), password).into_extended_key()?; |  | ||||||
|     let xprv = xkey.into_xprv(network).unwrap(); |  | ||||||
|     let fingerprint = xprv.fingerprint(&Secp256k1::new()); |  | ||||||
|     Ok(ExtendedKeyInfo { |  | ||||||
|         mnemonic: mnemonic.to_string(), |  | ||||||
|         xprv: xprv.to_string(), |  | ||||||
|         fingerprint: fingerprint.to_string(), |  | ||||||
|     }) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| fn restore_extended_key( |  | ||||||
|     network: Network, |  | ||||||
|     mnemonic: String, |  | ||||||
|     password: Option<String>, |  | ||||||
| ) -> Result<ExtendedKeyInfo, Error> { |  | ||||||
|     let mnemonic = Mnemonic::from_phrase(mnemonic.as_ref(), Language::English).unwrap(); |  | ||||||
|     let xkey: ExtendedKey = (mnemonic.clone(), password).into_extended_key()?; |  | ||||||
|     let xprv = xkey.into_xprv(network).unwrap(); |  | ||||||
|     let fingerprint = xprv.fingerprint(&Secp256k1::new()); |  | ||||||
|     Ok(ExtendedKeyInfo { |  | ||||||
|         mnemonic: mnemonic.to_string(), |  | ||||||
|         xprv: xprv.to_string(), |  | ||||||
|         fingerprint: fingerprint.to_string(), |  | ||||||
|     }) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uniffi::deps::static_assertions::assert_impl_all!(OfflineWallet: Sync, Send); |  | ||||||
| uniffi::deps::static_assertions::assert_impl_all!(OnlineWallet: Sync, Send); |  | ||||||
							
								
								
									
										44
									
								
								test.sh
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								test.sh
									
									
									
									
									
								
							| @ -1,44 +0,0 @@ | |||||||
| #!/usr/bin/env bash |  | ||||||
| set -eo pipefail |  | ||||||
| 
 |  | ||||||
| # functions |  | ||||||
| 
 |  | ||||||
| ## help |  | ||||||
| help() |  | ||||||
| { |  | ||||||
|    # Display Help |  | ||||||
|    echo "Test bdk-uniffi and related libraries." |  | ||||||
|    echo |  | ||||||
|    echo "Syntax: build [-a|h|k]" |  | ||||||
|    echo "options:" |  | ||||||
|    echo "-a     Android connected device tests." |  | ||||||
|    echo "-h     Print this Help." |  | ||||||
|    echo "-k     Kotlin tests." |  | ||||||
|    echo |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| test_kotlin() { |  | ||||||
|   (cd bindings/bdk-kotlin && ./gradlew :jvm:test -Djna.debug_load=true) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| test_android() { |  | ||||||
|   (cd bindings/bdk-kotlin && ./gradlew :android:connectedDebugAndroidTest) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| if [ $1 = "-h" ] |  | ||||||
| then |  | ||||||
|   help |  | ||||||
| else |  | ||||||
|   cargo test |  | ||||||
| 
 |  | ||||||
|   # optional tests |  | ||||||
|   while [ -n "$1" ]; do # while loop starts |  | ||||||
|     case "$1" in |  | ||||||
|       -a) test_android ;; |  | ||||||
|       -h) help ;; |  | ||||||
|       -k) test_kotlin ;; |  | ||||||
|       *) echo "Option $1 not recognized" ;; |  | ||||||
|     esac |  | ||||||
|     shift |  | ||||||
|   done |  | ||||||
| fi |  | ||||||
							
								
								
									
										12
									
								
								uniffi.toml
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								uniffi.toml
									
									
									
									
									
								
							| @ -1,12 +0,0 @@ | |||||||
| [bindings.kotlin] |  | ||||||
| package_name = "org.bitcoindevkit" |  | ||||||
| cdylib_name = "bdkffi" |  | ||||||
| 
 |  | ||||||
| [bindings.python] |  | ||||||
| cdylib_name = "bdkffi" |  | ||||||
| 
 |  | ||||||
| [bindings.ruby] |  | ||||||
| cdylib_name = "bdkffi" |  | ||||||
| 
 |  | ||||||
| [bindings.swift] |  | ||||||
| cdylib_name = "bdkffi" |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user