diff --git a/Cargo.lock b/Cargo.lock index 575214f..a6a0b6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -475,7 +475,7 @@ dependencies = [ [[package]] name = "bitkitcore" -version = "0.1.58" +version = "0.1.60" dependencies = [ "android_logger", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 21ec542..936214a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitkitcore" -version = "0.1.58" +version = "0.1.60" edition = "2021" [lib] diff --git a/Package.swift b/Package.swift index 4a1cf8b..d4d94e2 100644 --- a/Package.swift +++ b/Package.swift @@ -3,8 +3,8 @@ import PackageDescription -let tag = "v0.1.58" -let checksum = "89821971ec3f1ce8c16ac46ed5b35ddaf127e087113829b1a6b6cb023a449c88" +let tag = "v0.1.60" +let checksum = "2491068759664686c279f33f7c9612c568b559cacb5174d20262f8b65fb731ec" let url = "https://github.com/synonymdev/bitkit-core/releases/download/\(tag)/BitkitCore.xcframework.zip" let package = Package( @@ -32,4 +32,4 @@ let package = Package( checksum: checksum ) ] -) \ No newline at end of file +) diff --git a/bindings/android/gradle.properties b/bindings/android/gradle.properties index 14e2677..1507630 100644 --- a/bindings/android/gradle.properties +++ b/bindings/android/gradle.properties @@ -3,4 +3,4 @@ android.useAndroidX=true android.enableJetifier=true kotlin.code.style=official group=com.synonym -version=0.1.58 +version=0.1.60 diff --git a/bindings/android/lib/src/main/jniLibs/arm64-v8a/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/arm64-v8a/libbitkitcore.so index a8f2001..6eb7bd8 100755 Binary files a/bindings/android/lib/src/main/jniLibs/arm64-v8a/libbitkitcore.so and b/bindings/android/lib/src/main/jniLibs/arm64-v8a/libbitkitcore.so differ diff --git a/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-90a3a8b6be1a7a22.so b/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-90a3a8b6be1a7a22.so deleted file mode 100755 index 2856ba2..0000000 Binary files a/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-90a3a8b6be1a7a22.so and /dev/null differ diff --git a/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-fc4495b5409b2d39.so b/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-fc4495b5409b2d39.so new file mode 100755 index 0000000..a14e63e Binary files /dev/null and b/bindings/android/lib/src/main/jniLibs/arm64-v8a/libpubky_app_specs-fc4495b5409b2d39.so differ diff --git a/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libbitkitcore.so index 116d9d9..b956088 100755 Binary files a/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libbitkitcore.so and b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libbitkitcore.so differ diff --git a/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-a5b33175be180155.so b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-a5b33175be180155.so deleted file mode 100755 index 9df27c8..0000000 Binary files a/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-a5b33175be180155.so and /dev/null differ diff --git a/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-c99f298ca8acda0f.so b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-c99f298ca8acda0f.so new file mode 100755 index 0000000..034e56d Binary files /dev/null and b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libpubky_app_specs-c99f298ca8acda0f.so differ diff --git a/bindings/android/lib/src/main/jniLibs/x86/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/x86/libbitkitcore.so index f5f78d6..38723ce 100755 Binary files a/bindings/android/lib/src/main/jniLibs/x86/libbitkitcore.so and b/bindings/android/lib/src/main/jniLibs/x86/libbitkitcore.so differ diff --git a/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-43984173235c5d3b.so b/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-43984173235c5d3b.so new file mode 100755 index 0000000..12fdb3c Binary files /dev/null and b/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-43984173235c5d3b.so differ diff --git a/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-6691cf4f97b9d92f.so b/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-6691cf4f97b9d92f.so deleted file mode 100755 index d08e98c..0000000 Binary files a/bindings/android/lib/src/main/jniLibs/x86/libpubky_app_specs-6691cf4f97b9d92f.so and /dev/null differ diff --git a/bindings/android/lib/src/main/jniLibs/x86_64/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/x86_64/libbitkitcore.so index 93d425e..1c8056f 100755 Binary files a/bindings/android/lib/src/main/jniLibs/x86_64/libbitkitcore.so and b/bindings/android/lib/src/main/jniLibs/x86_64/libbitkitcore.so differ diff --git a/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-4ad86c877f377f40.so b/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-4ad86c877f377f40.so deleted file mode 100755 index 8f8f793..0000000 Binary files a/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-4ad86c877f377f40.so and /dev/null differ diff --git a/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-de79160b8ee95e02.so b/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-de79160b8ee95e02.so new file mode 100755 index 0000000..4b4cfad Binary files /dev/null and b/bindings/android/lib/src/main/jniLibs/x86_64/libpubky_app_specs-de79160b8ee95e02.so differ diff --git a/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt b/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt index cb8bd74..096a300 100644 --- a/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt +++ b/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt @@ -1426,6 +1426,8 @@ internal typealias UniffiVTableCallbackInterfaceTrezorUiCallbackUniffiByValue = + + @@ -1537,6 +1539,9 @@ internal object IntegrityCheckingUniffiLib : Library { if (uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses() != 34371.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (uniffi_bitkitcore_checksum_func_derive_onchain_descriptor() != 49652.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (uniffi_bitkitcore_checksum_func_derive_private_key() != 25155.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -1991,6 +1996,9 @@ internal object IntegrityCheckingUniffiLib : Library { external fun uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses( ): Short @JvmStatic + external fun uniffi_bitkitcore_checksum_func_derive_onchain_descriptor( + ): Short + @JvmStatic external fun uniffi_bitkitcore_checksum_func_derive_private_key( ): Short @JvmStatic @@ -2631,6 +2639,15 @@ internal object UniffiLib : Library { uniffiCallStatus: UniffiRustCallStatus, ): RustBufferByValue @JvmStatic + external fun uniffi_bitkitcore_fn_func_derive_onchain_descriptor( + `mnemonicPhrase`: RustBufferByValue, + `network`: RustBufferByValue, + `bip39Passphrase`: RustBufferByValue, + `accountType`: RustBufferByValue, + `accountIndex`: Int, + uniffiCallStatus: UniffiRustCallStatus, + ): RustBufferByValue + @JvmStatic external fun uniffi_bitkitcore_fn_func_derive_private_key( `mnemonicPhrase`: RustBufferByValue, `derivationPathStr`: RustBufferByValue, @@ -12492,6 +12509,20 @@ public fun `deriveBitcoinAddresses`(`mnemonicPhrase`: kotlin.String, `derivation }) } +@Throws(AddressException::class) +public fun `deriveOnchainDescriptor`(`mnemonicPhrase`: kotlin.String, `network`: Network, `bip39Passphrase`: kotlin.String?, `accountType`: AccountType, `accountIndex`: kotlin.UInt): kotlin.String { + return FfiConverterString.lift(uniffiRustCallWithError(AddressExceptionErrorHandler) { uniffiRustCallStatus -> + UniffiLib.uniffi_bitkitcore_fn_func_derive_onchain_descriptor( + FfiConverterString.lower(`mnemonicPhrase`), + FfiConverterTypeNetwork.lower(`network`), + FfiConverterOptionalString.lower(`bip39Passphrase`), + FfiConverterTypeAccountType.lower(`accountType`), + FfiConverterUInt.lower(`accountIndex`), + uniffiRustCallStatus, + ) + }) +} + @Throws(AddressException::class) public fun `derivePrivateKey`(`mnemonicPhrase`: kotlin.String, `derivationPathStr`: kotlin.String?, `network`: Network?, `bip39Passphrase`: kotlin.String?): kotlin.String { return FfiConverterString.lift(uniffiRustCallWithError(AddressExceptionErrorHandler) { uniffiRustCallStatus -> diff --git a/bindings/ios/BitkitCore.xcframework.zip b/bindings/ios/BitkitCore.xcframework.zip index aeaee95..1fd45b7 100644 Binary files a/bindings/ios/BitkitCore.xcframework.zip and b/bindings/ios/BitkitCore.xcframework.zip differ diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h index 52ccb89..1d40072 100644 --- a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h +++ b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h @@ -585,6 +585,11 @@ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_address(RustBuffer mnemonic_ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_addresses(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer is_change, RustBuffer start_index, RustBuffer count, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +RustBuffer uniffi_bitkitcore_fn_func_derive_onchain_descriptor(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer account_type, uint32_t account_index, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY RustBuffer uniffi_bitkitcore_fn_func_derive_private_key(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustCallStatus *_Nonnull out_status @@ -1590,6 +1595,12 @@ uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_address(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_BITCOIN_ADDRESSES uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +uint16_t uniffi_bitkitcore_checksum_func_derive_onchain_descriptor(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_PRIVATE_KEY diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a index ed4f18d..3bd1161 100644 Binary files a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a and b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a differ diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h b/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h index 52ccb89..1d40072 100644 --- a/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h +++ b/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h @@ -585,6 +585,11 @@ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_address(RustBuffer mnemonic_ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_addresses(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer is_change, RustBuffer start_index, RustBuffer count, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +RustBuffer uniffi_bitkitcore_fn_func_derive_onchain_descriptor(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer account_type, uint32_t account_index, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY RustBuffer uniffi_bitkitcore_fn_func_derive_private_key(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustCallStatus *_Nonnull out_status @@ -1590,6 +1595,12 @@ uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_address(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_BITCOIN_ADDRESSES uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +uint16_t uniffi_bitkitcore_checksum_func_derive_onchain_descriptor(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_PRIVATE_KEY diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a b/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a index 0134942..105442e 100644 Binary files a/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a and b/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a differ diff --git a/bindings/ios/bitkitcore.swift b/bindings/ios/bitkitcore.swift index 000a65e..d2c9d09 100644 --- a/bindings/ios/bitkitcore.swift +++ b/bindings/ios/bitkitcore.swift @@ -19269,6 +19269,17 @@ public func deriveBitcoinAddresses(mnemonicPhrase: String, derivationPathStr: St ) }) } +public func deriveOnchainDescriptor(mnemonicPhrase: String, network: Network, bip39Passphrase: String?, accountType: AccountType, accountIndex: UInt32)throws -> String { + return try FfiConverterString.lift(try rustCallWithError(FfiConverterTypeAddressError_lift) { + uniffi_bitkitcore_fn_func_derive_onchain_descriptor( + FfiConverterString.lower(mnemonicPhrase), + FfiConverterTypeNetwork_lower(network), + FfiConverterOptionString.lower(bip39Passphrase), + FfiConverterTypeAccountType_lower(accountType), + FfiConverterUInt32.lower(accountIndex),$0 + ) +}) +} public func derivePrivateKey(mnemonicPhrase: String, derivationPathStr: String?, network: Network?, bip39Passphrase: String?)throws -> String { return try FfiConverterString.lift(try rustCallWithError(FfiConverterTypeAddressError_lift) { uniffi_bitkitcore_fn_func_derive_private_key( @@ -20714,6 +20725,9 @@ private let initializationResult: InitializationResult = { if (uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses() != 34371) { return InitializationResult.apiChecksumMismatch } + if (uniffi_bitkitcore_checksum_func_derive_onchain_descriptor() != 49652) { + return InitializationResult.apiChecksumMismatch + } if (uniffi_bitkitcore_checksum_func_derive_private_key() != 25155) { return InitializationResult.apiChecksumMismatch } diff --git a/bindings/ios/bitkitcoreFFI.h b/bindings/ios/bitkitcoreFFI.h index 52ccb89..1d40072 100644 --- a/bindings/ios/bitkitcoreFFI.h +++ b/bindings/ios/bitkitcoreFFI.h @@ -585,6 +585,11 @@ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_address(RustBuffer mnemonic_ RustBuffer uniffi_bitkitcore_fn_func_derive_bitcoin_addresses(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer is_change, RustBuffer start_index, RustBuffer count, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +RustBuffer uniffi_bitkitcore_fn_func_derive_onchain_descriptor(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer account_type, uint32_t account_index, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_DERIVE_PRIVATE_KEY RustBuffer uniffi_bitkitcore_fn_func_derive_private_key(RustBuffer mnemonic_phrase, RustBuffer derivation_path_str, RustBuffer network, RustBuffer bip39_passphrase, RustCallStatus *_Nonnull out_status @@ -1590,6 +1595,12 @@ uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_address(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_BITCOIN_ADDRESSES uint16_t uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_ONCHAIN_DESCRIPTOR +uint16_t uniffi_bitkitcore_checksum_func_derive_onchain_descriptor(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_DERIVE_PRIVATE_KEY diff --git a/bindings/python/bitkitcore/bitkitcore.py b/bindings/python/bitkitcore/bitkitcore.py index a1d05f6..50e10fe 100644 --- a/bindings/python/bitkitcore/bitkitcore.py +++ b/bindings/python/bitkitcore/bitkitcore.py @@ -507,6 +507,8 @@ def _uniffi_check_api_checksums(lib): raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses() != 34371: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_bitkitcore_checksum_func_derive_onchain_descriptor() != 49652: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_derive_private_key() != 25155: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_derive_pubky_secret_key() != 36989: @@ -1165,6 +1167,15 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_bitkitcore_fn_func_derive_bitcoin_addresses.restype = _UniffiRustBuffer +_UniffiLib.uniffi_bitkitcore_fn_func_derive_onchain_descriptor.argtypes = ( + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, + _UniffiRustBuffer, + ctypes.c_uint32, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_bitkitcore_fn_func_derive_onchain_descriptor.restype = _UniffiRustBuffer _UniffiLib.uniffi_bitkitcore_fn_func_derive_private_key.argtypes = ( _UniffiRustBuffer, _UniffiRustBuffer, @@ -2068,6 +2079,9 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): _UniffiLib.uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_derive_bitcoin_addresses.restype = ctypes.c_uint16 +_UniffiLib.uniffi_bitkitcore_checksum_func_derive_onchain_descriptor.argtypes = ( +) +_UniffiLib.uniffi_bitkitcore_checksum_func_derive_onchain_descriptor.restype = ctypes.c_uint16 _UniffiLib.uniffi_bitkitcore_checksum_func_derive_private_key.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_derive_private_key.restype = ctypes.c_uint16 @@ -17622,6 +17636,25 @@ def derive_bitcoin_addresses(mnemonic_phrase: "str",derivation_path_str: "typing _UniffiConverterOptionalUInt32.lower(count))) +def derive_onchain_descriptor(mnemonic_phrase: "str",network: "Network",bip39_passphrase: "typing.Optional[str]",account_type: "AccountType",account_index: "int") -> "str": + _UniffiConverterString.check_lower(mnemonic_phrase) + + _UniffiConverterTypeNetwork.check_lower(network) + + _UniffiConverterOptionalString.check_lower(bip39_passphrase) + + _UniffiConverterTypeAccountType.check_lower(account_type) + + _UniffiConverterUInt32.check_lower(account_index) + + return _UniffiConverterString.lift(_uniffi_rust_call_with_error(_UniffiConverterTypeAddressError,_UniffiLib.uniffi_bitkitcore_fn_func_derive_onchain_descriptor, + _UniffiConverterString.lower(mnemonic_phrase), + _UniffiConverterTypeNetwork.lower(network), + _UniffiConverterOptionalString.lower(bip39_passphrase), + _UniffiConverterTypeAccountType.lower(account_type), + _UniffiConverterUInt32.lower(account_index))) + + def derive_private_key(mnemonic_phrase: "str",derivation_path_str: "typing.Optional[str]",network: "typing.Optional[Network]",bip39_passphrase: "typing.Optional[str]") -> "str": _UniffiConverterString.check_lower(mnemonic_phrase) @@ -19549,6 +19582,7 @@ def wipe_all_transaction_details() -> None: "delete_transaction_details", "derive_bitcoin_address", "derive_bitcoin_addresses", + "derive_onchain_descriptor", "derive_private_key", "derive_pubky_secret_key", "entropy_to_mnemonic", diff --git a/bindings/python/bitkitcore/libbitkitcore.dylib b/bindings/python/bitkitcore/libbitkitcore.dylib index d7a5bfd..e62b2cd 100755 Binary files a/bindings/python/bitkitcore/libbitkitcore.dylib and b/bindings/python/bitkitcore/libbitkitcore.dylib differ diff --git a/src/lib.rs b/src/lib.rs index f566be5..18a6998 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -252,6 +252,23 @@ pub fn derive_private_key( ) } +#[uniffi::export] +pub fn derive_onchain_descriptor( + mnemonic_phrase: String, + network: Network, + bip39_passphrase: Option, + account_type: AccountType, + account_index: u32, +) -> Result { + onchain::BitcoinAddressValidator::derive_onchain_descriptor( + &mnemonic_phrase, + network.into(), + bip39_passphrase.as_deref(), + account_type, + account_index, + ) +} + #[uniffi::export] pub fn validate_mnemonic(mnemonic_phrase: String) -> Result<(), AddressError> { onchain::BitcoinAddressValidator::validate_mnemonic(&mnemonic_phrase) diff --git a/src/modules/onchain/implementation.rs b/src/modules/onchain/implementation.rs index 366b7f3..0b6c2f6 100644 --- a/src/modules/onchain/implementation.rs +++ b/src/modules/onchain/implementation.rs @@ -13,13 +13,15 @@ use bdk::bitcoin::{ use bdk::blockchain::ElectrumBlockchain; use bdk::database::MemoryDatabase; use bdk::electrum_client::ElectrumApi; -use bdk::keys::bip39::Mnemonic; +use bdk::keys::bip39::Mnemonic as BdkMnemonic; use bdk::template::{Bip44, Bip49, Bip86}; use bdk::wallet::signer::SignOptions; use bdk::wallet::{AddressIndex as BdkAddressIndex, SyncOptions, Wallet}; use bdk::KeychainKind; +use bip39::Mnemonic as Bip39Mnemonic; use bitcoin::address::{Address, NetworkUnchecked}; -use bitcoin::Network; +use bitcoin::bip32::{DerivationPath, Xpriv, Xpub}; +use bitcoin::{Network, NetworkKind}; use bitcoin_address_generator; use super::errors::AccountInfoError; @@ -187,6 +189,47 @@ impl BitcoinAddressValidator { Ok(private_key) } + pub fn derive_onchain_descriptor( + mnemonic_phrase: &str, + network: Network, + bip39_passphrase: Option<&str>, + account_type: AccountType, + account_index: u32, + ) -> Result { + let bdk_network = onchain_to_bdk_network(network.into()); + let derivation_path = derive_base_path(account_type, bdk_network, account_index); + + let mnemonic = + Bip39Mnemonic::parse(mnemonic_phrase).map_err(|_| AddressError::InvalidMnemonic)?; + let seed = mnemonic.to_seed(bip39_passphrase.unwrap_or("")); + let path = DerivationPath::from_str(&derivation_path) + .map_err(|_| AddressError::AddressDerivationFailed)?; + + let secp = bitcoin::secp256k1::Secp256k1::new(); + let root = + Xpriv::new_master(network, &seed).map_err(|_| AddressError::AddressDerivationFailed)?; + let account = root + .derive_priv(&secp, &path) + .map_err(|_| AddressError::AddressDerivationFailed)?; + + let master_fingerprint = root.fingerprint(&secp).to_string(); + let mut account_xpub = Xpub::from_priv(&secp, &account); + // Export standard xpub descriptors; the key origin path still carries + // the selected network's coin type. + account_xpub.network = NetworkKind::Main; + let account_xpub = account_xpub.to_string(); + let key_origin_path = derivation_path + .strip_prefix("m/") + .unwrap_or(&derivation_path); + let (external_descriptor, _) = build_descriptors( + &account_xpub, + account_type, + Some((&master_fingerprint, key_origin_path)), + ); + + Ok(external_descriptor) + } + fn create_sweep_wallets( mnemonic_phrase: &str, network: Network, @@ -194,7 +237,7 @@ impl BitcoinAddressValidator { ) -> Result { let bdk_network = onchain_to_bdk_network(network.into()); let mnemonic = - Mnemonic::from_str(mnemonic_phrase).map_err(|_| SweepError::InvalidMnemonic)?; + BdkMnemonic::from_str(mnemonic_phrase).map_err(|_| SweepError::InvalidMnemonic)?; let key = (mnemonic.clone(), bip39_passphrase.map(String::from)); let legacy_wallet = Wallet::new( diff --git a/src/modules/onchain/tests.rs b/src/modules/onchain/tests.rs index a02136b..6338979 100644 --- a/src/modules/onchain/tests.rs +++ b/src/modules/onchain/tests.rs @@ -1,9 +1,13 @@ #[cfg(test)] mod tests { - use crate::modules::onchain::{AddressType, BitcoinAddressValidator}; + use crate::modules::onchain::{AccountType, AddressType, BitcoinAddressValidator}; use crate::modules::scanner::NetworkType; use crate::onchain::types::WordCount; - use bitcoin::Network; + use bdk::database::MemoryDatabase; + use bdk::wallet::{AddressIndex as BdkAddressIndex, Wallet}; + use bitcoin::bip32::Xpub; + use bitcoin::{Network, NetworkKind}; + use std::str::FromStr; #[test] fn test_address_types() { @@ -202,6 +206,75 @@ mod tests { assert_eq!(result.addresses[1].path, "m/84'/0'/0'/0/6"); } + #[test] + fn test_derive_onchain_descriptor() { + let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + let result = BitcoinAddressValidator::derive_onchain_descriptor( + mnemonic, + Network::Bitcoin, + None, + AccountType::NativeSegwit, + 0, + ) + .unwrap(); + + assert!(result.starts_with("wpkh([73c5da0a/84'/0'/0']xpub")); + assert!(result.ends_with("/0/*)")); + + let wallet = Wallet::new( + result.as_str(), + None, + bdk::bitcoin::Network::Bitcoin, + MemoryDatabase::new(), + ) + .unwrap(); + let address = wallet.get_address(BdkAddressIndex::Peek(0)).unwrap(); + assert_eq!( + address.address.to_string(), + "bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu" + ); + } + + #[test] + fn test_derive_onchain_descriptor_uses_test_coin_type_and_xpub_for_regtest() { + let mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; + let result = BitcoinAddressValidator::derive_onchain_descriptor( + mnemonic, + Network::Regtest, + None, + AccountType::NativeSegwit, + 0, + ) + .unwrap(); + + assert!(result.contains("/84'/1'/0']xpub")); + + // BDK validates regtest descriptors with tpub; the exported descriptor + // keeps xpub while retaining the test coin type in the origin path. + let xpub = result + .split("]xpub") + .nth(1) + .and_then(|suffix| suffix.split('/').next()) + .map(|suffix| format!("xpub{}", suffix)) + .unwrap(); + let mut testnet_xpub = Xpub::from_str(&xpub).unwrap(); + testnet_xpub.network = NetworkKind::Test; + let regtest_descriptor = result.replace(&xpub, &testnet_xpub.to_string()); + + let wallet = Wallet::new( + regtest_descriptor.as_str(), + None, + bdk::bitcoin::Network::Regtest, + MemoryDatabase::new(), + ) + .unwrap(); + let address = wallet.get_address(BdkAddressIndex::Peek(0)).unwrap(); + assert_eq!( + address.address.to_string(), + "bcrt1q6rz28mcfaxtmd6v789l9rrlrusdprr9pz3cppk" + ); + } + #[test] fn test_derive_private_key() { // Use the standard test mnemonic