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 | ||||
| .lsp | ||||
| .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 | ||||
| set -eo pipefail | ||||
| 
 | ||||
| # functions | ||||
| echo "Build and test bdk-ffi library for local platform (darwin or linux)" | ||||
| pushd bdk-ffi | ||||
| 
 | ||||
| ## help | ||||
| help() | ||||
| { | ||||
|    # 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) | ||||
| } | ||||
| cargo fmt | ||||
| cargo build --release | ||||
| cargo test | ||||
| 
 | ||||
| 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" ] | ||||
| then | ||||
|   help | ||||
| else | ||||
|   build_rust | ||||
| echo "Generate kotlin bindings from bdk.udl to jvm subproject" | ||||
| uniffi-bindgen generate src/bdk.udl --no-format --out-dir ../jvm/src/main/kotlin --language kotlin | ||||
| 
 | ||||
|   while [ -n "$1" ]; do # while loop starts | ||||
|     case "$1" in | ||||
|       -a) build_android ;; | ||||
|       -k) build_kotlin ;; | ||||
|       -h) help ;; | ||||
|       *) echo "Option $1 not recognized" ;; | ||||
|     esac | ||||
|     shift | ||||
|   done | ||||
| ## android | ||||
| 
 | ||||
| # 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 ../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 | ||||
| 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
									
									
								
							
							
								
								
									
										178
									
								
								bindings/bdk-kotlin/gradlew.bat → gradlew.bat
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										178
									
								
								bindings/bdk-kotlin/gradlew.bat → gradlew.bat
									
									
									
									
										vendored
									
									
								
							| @ -1,89 +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 | ||||
| @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 | ||||
							
								
								
									
										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