diff --git a/Cargo.lock b/Cargo.lock index dad0f2a..4ebbe0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -475,7 +475,7 @@ dependencies = [ [[package]] name = "bitkitcore" -version = "0.1.51" +version = "0.1.54" dependencies = [ "android_logger", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index 1d6642f..5db0d3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bitkitcore" -version = "0.1.51" +version = "0.1.54" edition = "2021" [lib] diff --git a/Package.swift b/Package.swift index ead8f28..dd5c863 100644 --- a/Package.swift +++ b/Package.swift @@ -3,8 +3,8 @@ import PackageDescription -let tag = "v0.1.51" -let checksum = "fc2a9b3884dcd1b08d7112458621c589413339e84e52955e0ece4ff1c7596dda" +let tag = "v0.1.54" +let checksum = "8ca81d51d6d9f66ef3c33f81969d07221c21744d131f907be2006d87a807ed05" let url = "https://github.com/synonymdev/bitkit-core/releases/download/\(tag)/BitkitCore.xcframework.zip" let package = Package( diff --git a/bindings/android/gradle.properties b/bindings/android/gradle.properties index 9d9cf09..00086f6 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.51 +version=0.1.54 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 a923a58..6c32490 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/armeabi-v7a/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/armeabi-v7a/libbitkitcore.so index bc600dc..eca7c64 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/x86/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/x86/libbitkitcore.so index 64414c0..3f065c9 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_64/libbitkitcore.so b/bindings/android/lib/src/main/jniLibs/x86_64/libbitkitcore.so index f30f0e8..92dcc64 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/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt b/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.android.kt index eb99f1d..a08952b 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 @@ -1420,6 +1420,10 @@ internal typealias UniffiVTableCallbackInterfaceTrezorUiCallbackUniffiByValue = + + + + @@ -1476,6 +1480,9 @@ internal object IntegrityCheckingUniffiLib : Library { if (uniffi_bitkitcore_checksum_func_add_tags() != 63739.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (uniffi_bitkitcore_checksum_func_approve_pubky_auth() != 22222.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries() != 40127.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -1680,6 +1687,9 @@ internal object IntegrityCheckingUniffiLib : Library { if (uniffi_bitkitcore_checksum_func_open_channel() != 21402.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (uniffi_bitkitcore_checksum_func_parse_pubky_auth_url() != 56972.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (uniffi_bitkitcore_checksum_func_prepare_sweep_transaction() != 18273.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -1924,6 +1934,9 @@ internal object IntegrityCheckingUniffiLib : Library { external fun uniffi_bitkitcore_checksum_func_add_tags( ): Short @JvmStatic + external fun uniffi_bitkitcore_checksum_func_approve_pubky_auth( + ): Short + @JvmStatic external fun uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries( ): Short @JvmStatic @@ -2128,6 +2141,9 @@ internal object IntegrityCheckingUniffiLib : Library { external fun uniffi_bitkitcore_checksum_func_open_channel( ): Short @JvmStatic + external fun uniffi_bitkitcore_checksum_func_parse_pubky_auth_url( + ): Short + @JvmStatic external fun uniffi_bitkitcore_checksum_func_prepare_sweep_transaction( ): Short @JvmStatic @@ -2506,6 +2522,11 @@ internal object UniffiLib : Library { uniffiCallStatus: UniffiRustCallStatus, ): Unit @JvmStatic + external fun uniffi_bitkitcore_fn_func_approve_pubky_auth( + `authUrl`: RustBufferByValue, + `secretKeyHex`: RustBufferByValue, + ): Long + @JvmStatic external fun uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries( ): Long @JvmStatic @@ -2878,6 +2899,11 @@ internal object UniffiLib : Library { `connectionString`: RustBufferByValue, ): Long @JvmStatic + external fun uniffi_bitkitcore_fn_func_parse_pubky_auth_url( + `authUrl`: RustBufferByValue, + uniffiCallStatus: UniffiRustCallStatus, + ): RustBufferByValue + @JvmStatic external fun uniffi_bitkitcore_fn_func_prepare_sweep_transaction( `mnemonicPhrase`: RustBufferByValue, `network`: RustBufferByValue, @@ -6635,6 +6661,37 @@ public object FfiConverterTypePubkyAuth: FfiConverterRustBuffer { +public object FfiConverterTypePubkyAuthDetails: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PubkyAuthDetails { + return PubkyAuthDetails( + FfiConverterTypePubkyAuthKind.read(buf), + FfiConverterString.read(buf), + FfiConverterString.read(buf), + FfiConverterOptionalString.read(buf), + FfiConverterOptionalString.read(buf), + ) + } + + override fun allocationSize(value: PubkyAuthDetails): ULong = ( + FfiConverterTypePubkyAuthKind.allocationSize(value.`kind`) + + FfiConverterString.allocationSize(value.`capabilities`) + + FfiConverterString.allocationSize(value.`relay`) + + FfiConverterOptionalString.allocationSize(value.`homeserver`) + + FfiConverterOptionalString.allocationSize(value.`signupToken`) + ) + + override fun write(value: PubkyAuthDetails, buf: ByteBuffer) { + FfiConverterTypePubkyAuthKind.write(value.`kind`, buf) + FfiConverterString.write(value.`capabilities`, buf) + FfiConverterString.write(value.`relay`, buf) + FfiConverterOptionalString.write(value.`homeserver`, buf) + FfiConverterOptionalString.write(value.`signupToken`, buf) + } +} + + + + public object FfiConverterTypePubkyProfile: FfiConverterRustBuffer { override fun read(buf: ByteBuffer): PubkyProfile { return PubkyProfile( @@ -9166,6 +9223,24 @@ public object FfiConverterTypePaymentType: FfiConverterRustBuffer { + +public object FfiConverterTypePubkyAuthKind: FfiConverterRustBuffer { + override fun read(buf: ByteBuffer): PubkyAuthKind = try { + PubkyAuthKind.entries[buf.getInt() - 1] + } catch (e: IndexOutOfBoundsException) { + throw RuntimeException("invalid enum value, something is very wrong!!", e) + } + + override fun allocationSize(value: PubkyAuthKind): ULong = 4UL + + override fun write(value: PubkyAuthKind, buf: ByteBuffer) { + buf.putInt(value.ordinal + 1) + } +} + + + + public object PubkyExceptionErrorHandler : UniffiRustCallStatusErrorHandler { override fun lift(errorBuf: RustBufferByValue): PubkyException = FfiConverterTypePubkyError.lift(errorBuf) } @@ -12115,6 +12190,25 @@ public fun `addTags`(`activityId`: kotlin.String, `tags`: List) { } } +@Throws(PubkyException::class, kotlin.coroutines.cancellation.CancellationException::class) +public suspend fun `approvePubkyAuth`(`authUrl`: kotlin.String, `secretKeyHex`: kotlin.String) { + return uniffiRustCallAsync( + UniffiLib.uniffi_bitkitcore_fn_func_approve_pubky_auth( + FfiConverterString.lower(`authUrl`), + FfiConverterString.lower(`secretKeyHex`), + ), + { future, callback, continuation -> UniffiLib.ffi_bitkitcore_rust_future_poll_void(future, callback, continuation) }, + { future, continuation -> UniffiLib.ffi_bitkitcore_rust_future_complete_void(future, continuation) }, + { future -> UniffiLib.ffi_bitkitcore_rust_future_free_void(future) }, + { future -> UniffiLib.ffi_bitkitcore_rust_future_cancel_void(future) }, + // lift function + { Unit }, + + // Error FFI converter + PubkyExceptionErrorHandler, + ) +} + @Throws(BlocktankException::class, kotlin.coroutines.cancellation.CancellationException::class) public suspend fun `blocktankRemoveAllCjitEntries`() { return uniffiRustCallAsync( @@ -13115,6 +13209,16 @@ public suspend fun `openChannel`(`orderId`: kotlin.String, `connectionString`: k ) } +@Throws(PubkyException::class) +public fun `parsePubkyAuthUrl`(`authUrl`: kotlin.String): PubkyAuthDetails { + return FfiConverterTypePubkyAuthDetails.lift(uniffiRustCallWithError(PubkyExceptionErrorHandler) { uniffiRustCallStatus -> + UniffiLib.uniffi_bitkitcore_fn_func_parse_pubky_auth_url( + FfiConverterString.lower(`authUrl`), + uniffiRustCallStatus, + ) + }) +} + @Throws(SweepException::class, kotlin.coroutines.cancellation.CancellationException::class) public suspend fun `prepareSweepTransaction`(`mnemonicPhrase`: kotlin.String, `network`: Network?, `bip39Passphrase`: kotlin.String?, `electrumUrl`: kotlin.String, `destinationAddress`: kotlin.String, `feeRateSatsPerVbyte`: kotlin.UInt?): SweepTransactionPreview { return uniffiRustCallAsync( diff --git a/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.common.kt b/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.common.kt index b292599..2115755 100644 --- a/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.common.kt +++ b/bindings/android/lib/src/main/kotlin/com/synonym/bitkitcore/bitkitcore.common.kt @@ -1338,6 +1338,37 @@ public data class PubkyAuth ( +/** + * Details extracted from a `pubkyauth://` deep-link URL. + */ +@kotlinx.serialization.Serializable +public data class PubkyAuthDetails ( + /** + * Whether this is a signin or signup flow. + */ + val `kind`: PubkyAuthKind, + /** + * Requested capabilities (e.g. `"/pub/pubky.app/:rw"`). + */ + val `capabilities`: kotlin.String, + /** + * Relay URL used for the auth exchange. + */ + val `relay`: kotlin.String, + /** + * Homeserver public key (z32-encoded). Present only for signup flows. + */ + val `homeserver`: kotlin.String?, + /** + * Signup token. Present only for signup flows. + */ + val `signupToken`: kotlin.String? +) { + public companion object +} + + + @kotlinx.serialization.Serializable public data class PubkyProfile ( val `name`: kotlin.String, @@ -3376,6 +3407,23 @@ public enum class PaymentType { +/** + * The type of a `pubkyauth://` deep-link flow. + */ + +@kotlinx.serialization.Serializable +public enum class PubkyAuthKind { + + SIGNIN, + SIGNUP; + public companion object +} + + + + + + public sealed class PubkyException: kotlin.Exception() { diff --git a/bindings/ios/BitkitCore.xcframework.zip b/bindings/ios/BitkitCore.xcframework.zip index 3859e36..195965c 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 a6c1fba..52ccb89 100644 --- a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h +++ b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/Headers/bitkitcoreFFI.h @@ -485,6 +485,11 @@ void uniffi_bitkitcore_fn_func_add_pre_activity_metadata_tags(RustBuffer payment void uniffi_bitkitcore_fn_func_add_tags(RustBuffer activity_id, RustBuffer tags, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +uint64_t uniffi_bitkitcore_fn_func_approve_pubky_auth(RustBuffer auth_url, RustBuffer secret_key_hex +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES uint64_t uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries(void @@ -835,6 +840,11 @@ uint64_t uniffi_bitkitcore_fn_func_onchain_get_transaction_history(RustBuffer ex uint64_t uniffi_bitkitcore_fn_func_open_channel(RustBuffer order_id, RustBuffer connection_string ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +RustBuffer uniffi_bitkitcore_fn_func_parse_pubky_auth_url(RustBuffer auth_url, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION uint64_t uniffi_bitkitcore_fn_func_prepare_sweep_transaction(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer electrum_url, RustBuffer destination_address, RustBuffer fee_rate_sats_per_vbyte @@ -1466,6 +1476,12 @@ uint16_t uniffi_bitkitcore_checksum_func_add_pre_activity_metadata_tags(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_ADD_TAGS uint16_t uniffi_bitkitcore_checksum_func_add_tags(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +uint16_t uniffi_bitkitcore_checksum_func_approve_pubky_auth(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES @@ -1874,6 +1890,12 @@ uint16_t uniffi_bitkitcore_checksum_func_onchain_get_transaction_history(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_OPEN_CHANNEL uint16_t uniffi_bitkitcore_checksum_func_open_channel(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +uint16_t uniffi_bitkitcore_checksum_func_parse_pubky_auth_url(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PREPARE_SWEEP_TRANSACTION diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a b/bindings/ios/BitkitCore.xcframework/ios-arm64-simulator/libbitkitcore.a index c8deaca..fad9bab 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 a6c1fba..52ccb89 100644 --- a/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h +++ b/bindings/ios/BitkitCore.xcframework/ios-arm64/Headers/bitkitcoreFFI.h @@ -485,6 +485,11 @@ void uniffi_bitkitcore_fn_func_add_pre_activity_metadata_tags(RustBuffer payment void uniffi_bitkitcore_fn_func_add_tags(RustBuffer activity_id, RustBuffer tags, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +uint64_t uniffi_bitkitcore_fn_func_approve_pubky_auth(RustBuffer auth_url, RustBuffer secret_key_hex +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES uint64_t uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries(void @@ -835,6 +840,11 @@ uint64_t uniffi_bitkitcore_fn_func_onchain_get_transaction_history(RustBuffer ex uint64_t uniffi_bitkitcore_fn_func_open_channel(RustBuffer order_id, RustBuffer connection_string ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +RustBuffer uniffi_bitkitcore_fn_func_parse_pubky_auth_url(RustBuffer auth_url, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION uint64_t uniffi_bitkitcore_fn_func_prepare_sweep_transaction(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer electrum_url, RustBuffer destination_address, RustBuffer fee_rate_sats_per_vbyte @@ -1466,6 +1476,12 @@ uint16_t uniffi_bitkitcore_checksum_func_add_pre_activity_metadata_tags(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_ADD_TAGS uint16_t uniffi_bitkitcore_checksum_func_add_tags(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +uint16_t uniffi_bitkitcore_checksum_func_approve_pubky_auth(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES @@ -1874,6 +1890,12 @@ uint16_t uniffi_bitkitcore_checksum_func_onchain_get_transaction_history(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_OPEN_CHANNEL uint16_t uniffi_bitkitcore_checksum_func_open_channel(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +uint16_t uniffi_bitkitcore_checksum_func_parse_pubky_auth_url(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PREPARE_SWEEP_TRANSACTION diff --git a/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a b/bindings/ios/BitkitCore.xcframework/ios-arm64/libbitkitcore.a index 63ceb76..6d1222e 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 c1d8459..3c30aac 100644 --- a/bindings/ios/bitkitcore.swift +++ b/bindings/ios/bitkitcore.swift @@ -8036,6 +8036,135 @@ public func FfiConverterTypePubkyAuth_lower(_ value: PubkyAuth) -> RustBuffer { } +/** + * Details extracted from a `pubkyauth://` deep-link URL. + */ +public struct PubkyAuthDetails { + /** + * Whether this is a signin or signup flow. + */ + public var kind: PubkyAuthKind + /** + * Requested capabilities (e.g. `"/pub/pubky.app/:rw"`). + */ + public var capabilities: String + /** + * Relay URL used for the auth exchange. + */ + public var relay: String + /** + * Homeserver public key (z32-encoded). Present only for signup flows. + */ + public var homeserver: String? + /** + * Signup token. Present only for signup flows. + */ + public var signupToken: String? + + // Default memberwise initializers are never public by default, so we + // declare one manually. + public init( + /** + * Whether this is a signin or signup flow. + */kind: PubkyAuthKind, + /** + * Requested capabilities (e.g. `"/pub/pubky.app/:rw"`). + */capabilities: String, + /** + * Relay URL used for the auth exchange. + */relay: String, + /** + * Homeserver public key (z32-encoded). Present only for signup flows. + */homeserver: String?, + /** + * Signup token. Present only for signup flows. + */signupToken: String?) { + self.kind = kind + self.capabilities = capabilities + self.relay = relay + self.homeserver = homeserver + self.signupToken = signupToken + } +} + +#if compiler(>=6) +extension PubkyAuthDetails: Sendable {} +#endif + + +extension PubkyAuthDetails: Equatable, Hashable { + public static func ==(lhs: PubkyAuthDetails, rhs: PubkyAuthDetails) -> Bool { + if lhs.kind != rhs.kind { + return false + } + if lhs.capabilities != rhs.capabilities { + return false + } + if lhs.relay != rhs.relay { + return false + } + if lhs.homeserver != rhs.homeserver { + return false + } + if lhs.signupToken != rhs.signupToken { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(kind) + hasher.combine(capabilities) + hasher.combine(relay) + hasher.combine(homeserver) + hasher.combine(signupToken) + } +} + +extension PubkyAuthDetails: Codable {} + + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypePubkyAuthDetails: FfiConverterRustBuffer { + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> PubkyAuthDetails { + return + try PubkyAuthDetails( + kind: FfiConverterTypePubkyAuthKind.read(from: &buf), + capabilities: FfiConverterString.read(from: &buf), + relay: FfiConverterString.read(from: &buf), + homeserver: FfiConverterOptionString.read(from: &buf), + signupToken: FfiConverterOptionString.read(from: &buf) + ) + } + + public static func write(_ value: PubkyAuthDetails, into buf: inout [UInt8]) { + FfiConverterTypePubkyAuthKind.write(value.kind, into: &buf) + FfiConverterString.write(value.capabilities, into: &buf) + FfiConverterString.write(value.relay, into: &buf) + FfiConverterOptionString.write(value.homeserver, into: &buf) + FfiConverterOptionString.write(value.signupToken, into: &buf) + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypePubkyAuthDetails_lift(_ buf: RustBuffer) throws -> PubkyAuthDetails { + return try FfiConverterTypePubkyAuthDetails.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypePubkyAuthDetails_lower(_ value: PubkyAuthDetails) -> RustBuffer { + return FfiConverterTypePubkyAuthDetails.lower(value) +} + + public struct PubkyProfile { public var name: String public var bio: String? @@ -15553,6 +15682,81 @@ extension PaymentType: Codable {} +// Note that we don't yet support `indirect` for enums. +// See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. +/** + * The type of a `pubkyauth://` deep-link flow. + */ + +public enum PubkyAuthKind { + + case signin + case signup +} + + +#if compiler(>=6) +extension PubkyAuthKind: Sendable {} +#endif + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public struct FfiConverterTypePubkyAuthKind: FfiConverterRustBuffer { + typealias SwiftType = PubkyAuthKind + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> PubkyAuthKind { + let variant: Int32 = try readInt(&buf) + switch variant { + + case 1: return .signin + + case 2: return .signup + + default: throw UniffiInternalError.unexpectedEnumCase + } + } + + public static func write(_ value: PubkyAuthKind, into buf: inout [UInt8]) { + switch value { + + + case .signin: + writeInt(&buf, Int32(1)) + + + case .signup: + writeInt(&buf, Int32(2)) + + } + } +} + + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypePubkyAuthKind_lift(_ buf: RustBuffer) throws -> PubkyAuthKind { + return try FfiConverterTypePubkyAuthKind.lift(buf) +} + +#if swift(>=5.8) +@_documentation(visibility: private) +#endif +public func FfiConverterTypePubkyAuthKind_lower(_ value: PubkyAuthKind) -> RustBuffer { + return FfiConverterTypePubkyAuthKind.lower(value) +} + + +extension PubkyAuthKind: Equatable, Hashable {} + +extension PubkyAuthKind: Codable {} + + + + + + public enum PubkyError: Swift.Error { @@ -18825,6 +19029,20 @@ public func addTags(activityId: String, tags: [String])throws {try rustCallWit ) } } +public func approvePubkyAuth(authUrl: String, secretKeyHex: String)async throws { + return + try await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_bitkitcore_fn_func_approve_pubky_auth(FfiConverterString.lower(authUrl),FfiConverterString.lower(secretKeyHex) + ) + }, + pollFunc: ffi_bitkitcore_rust_future_poll_void, + completeFunc: ffi_bitkitcore_rust_future_complete_void, + freeFunc: ffi_bitkitcore_rust_future_free_void, + liftFunc: { $0 }, + errorHandler: FfiConverterTypePubkyError_lift + ) +} public func blocktankRemoveAllCjitEntries()async throws { return try await uniffiRustCallAsync( @@ -19582,6 +19800,13 @@ public func openChannel(orderId: String, connectionString: String)async throws errorHandler: FfiConverterTypeBlocktankError_lift ) } +public func parsePubkyAuthUrl(authUrl: String)throws -> PubkyAuthDetails { + return try FfiConverterTypePubkyAuthDetails_lift(try rustCallWithError(FfiConverterTypePubkyError_lift) { + uniffi_bitkitcore_fn_func_parse_pubky_auth_url( + FfiConverterString.lower(authUrl),$0 + ) +}) +} public func prepareSweepTransaction(mnemonicPhrase: String, network: Network?, bip39Passphrase: String?, electrumUrl: String, destinationAddress: String, feeRateSatsPerVbyte: UInt32?)async throws -> SweepTransactionPreview { return try await uniffiRustCallAsync( @@ -20416,6 +20641,9 @@ private let initializationResult: InitializationResult = { if (uniffi_bitkitcore_checksum_func_add_tags() != 63739) { return InitializationResult.apiChecksumMismatch } + if (uniffi_bitkitcore_checksum_func_approve_pubky_auth() != 22222) { + return InitializationResult.apiChecksumMismatch + } if (uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries() != 40127) { return InitializationResult.apiChecksumMismatch } @@ -20620,6 +20848,9 @@ private let initializationResult: InitializationResult = { if (uniffi_bitkitcore_checksum_func_open_channel() != 21402) { return InitializationResult.apiChecksumMismatch } + if (uniffi_bitkitcore_checksum_func_parse_pubky_auth_url() != 56972) { + return InitializationResult.apiChecksumMismatch + } if (uniffi_bitkitcore_checksum_func_prepare_sweep_transaction() != 18273) { return InitializationResult.apiChecksumMismatch } diff --git a/bindings/ios/bitkitcoreFFI.h b/bindings/ios/bitkitcoreFFI.h index a6c1fba..52ccb89 100644 --- a/bindings/ios/bitkitcoreFFI.h +++ b/bindings/ios/bitkitcoreFFI.h @@ -485,6 +485,11 @@ void uniffi_bitkitcore_fn_func_add_pre_activity_metadata_tags(RustBuffer payment void uniffi_bitkitcore_fn_func_add_tags(RustBuffer activity_id, RustBuffer tags, RustCallStatus *_Nonnull out_status ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_APPROVE_PUBKY_AUTH +uint64_t uniffi_bitkitcore_fn_func_approve_pubky_auth(RustBuffer auth_url, RustBuffer secret_key_hex +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES uint64_t uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries(void @@ -835,6 +840,11 @@ uint64_t uniffi_bitkitcore_fn_func_onchain_get_transaction_history(RustBuffer ex uint64_t uniffi_bitkitcore_fn_func_open_channel(RustBuffer order_id, RustBuffer connection_string ); #endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PARSE_PUBKY_AUTH_URL +RustBuffer uniffi_bitkitcore_fn_func_parse_pubky_auth_url(RustBuffer auth_url, RustCallStatus *_Nonnull out_status +); +#endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_FN_FUNC_PREPARE_SWEEP_TRANSACTION uint64_t uniffi_bitkitcore_fn_func_prepare_sweep_transaction(RustBuffer mnemonic_phrase, RustBuffer network, RustBuffer bip39_passphrase, RustBuffer electrum_url, RustBuffer destination_address, RustBuffer fee_rate_sats_per_vbyte @@ -1466,6 +1476,12 @@ uint16_t uniffi_bitkitcore_checksum_func_add_pre_activity_metadata_tags(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_ADD_TAGS uint16_t uniffi_bitkitcore_checksum_func_add_tags(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_APPROVE_PUBKY_AUTH +uint16_t uniffi_bitkitcore_checksum_func_approve_pubky_auth(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_BLOCKTANK_REMOVE_ALL_CJIT_ENTRIES @@ -1874,6 +1890,12 @@ uint16_t uniffi_bitkitcore_checksum_func_onchain_get_transaction_history(void #define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_OPEN_CHANNEL uint16_t uniffi_bitkitcore_checksum_func_open_channel(void +); +#endif +#ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +#define UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PARSE_PUBKY_AUTH_URL +uint16_t uniffi_bitkitcore_checksum_func_parse_pubky_auth_url(void + ); #endif #ifndef UNIFFI_FFIDEF_UNIFFI_BITKITCORE_CHECKSUM_FUNC_PREPARE_SWEEP_TRANSACTION diff --git a/bindings/python/bitkitcore/bitkitcore.py b/bindings/python/bitkitcore/bitkitcore.py index f776ff8..2ad1664 100644 --- a/bindings/python/bitkitcore/bitkitcore.py +++ b/bindings/python/bitkitcore/bitkitcore.py @@ -469,6 +469,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_add_tags() != 63739: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_bitkitcore_checksum_func_approve_pubky_auth() != 22222: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries() != 40127: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_blocktank_remove_all_orders() != 38913: @@ -605,6 +607,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_open_channel() != 21402: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + if lib.uniffi_bitkitcore_checksum_func_parse_pubky_auth_url() != 56972: + raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_prepare_sweep_transaction() != 18273: raise InternalError("UniFFI API checksum mismatch: try cleaning and rebuilding your project") if lib.uniffi_bitkitcore_checksum_func_pubky_public_key_from_secret() != 47481: @@ -1052,6 +1056,11 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): ctypes.POINTER(_UniffiRustCallStatus), ) _UniffiLib.uniffi_bitkitcore_fn_func_add_tags.restype = None +_UniffiLib.uniffi_bitkitcore_fn_func_approve_pubky_auth.argtypes = ( + _UniffiRustBuffer, + _UniffiRustBuffer, +) +_UniffiLib.uniffi_bitkitcore_fn_func_approve_pubky_auth.restype = ctypes.c_uint64 _UniffiLib.uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_fn_func_blocktank_remove_all_cjit_entries.restype = ctypes.c_uint64 @@ -1424,6 +1433,11 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): _UniffiRustBuffer, ) _UniffiLib.uniffi_bitkitcore_fn_func_open_channel.restype = ctypes.c_uint64 +_UniffiLib.uniffi_bitkitcore_fn_func_parse_pubky_auth_url.argtypes = ( + _UniffiRustBuffer, + ctypes.POINTER(_UniffiRustCallStatus), +) +_UniffiLib.uniffi_bitkitcore_fn_func_parse_pubky_auth_url.restype = _UniffiRustBuffer _UniffiLib.uniffi_bitkitcore_fn_func_prepare_sweep_transaction.argtypes = ( _UniffiRustBuffer, _UniffiRustBuffer, @@ -1997,6 +2011,9 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): _UniffiLib.uniffi_bitkitcore_checksum_func_add_tags.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_add_tags.restype = ctypes.c_uint16 +_UniffiLib.uniffi_bitkitcore_checksum_func_approve_pubky_auth.argtypes = ( +) +_UniffiLib.uniffi_bitkitcore_checksum_func_approve_pubky_auth.restype = ctypes.c_uint16 _UniffiLib.uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_blocktank_remove_all_cjit_entries.restype = ctypes.c_uint16 @@ -2201,6 +2218,9 @@ class _UniffiVTableCallbackInterfaceTrezorUiCallback(ctypes.Structure): _UniffiLib.uniffi_bitkitcore_checksum_func_open_channel.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_open_channel.restype = ctypes.c_uint16 +_UniffiLib.uniffi_bitkitcore_checksum_func_parse_pubky_auth_url.argtypes = ( +) +_UniffiLib.uniffi_bitkitcore_checksum_func_parse_pubky_auth_url.restype = ctypes.c_uint16 _UniffiLib.uniffi_bitkitcore_checksum_func_prepare_sweep_transaction.argtypes = ( ) _UniffiLib.uniffi_bitkitcore_checksum_func_prepare_sweep_transaction.restype = ctypes.c_uint16 @@ -6719,6 +6739,87 @@ def write(value, buf): _UniffiConverterString.write(value.data, buf) +class PubkyAuthDetails: + """ + Details extracted from a `pubkyauth://` deep-link URL. + """ + + kind: "PubkyAuthKind" + """ + Whether this is a signin or signup flow. + """ + + capabilities: "str" + """ + Requested capabilities (e.g. `"/pub/pubky.app/:rw"`). + """ + + relay: "str" + """ + Relay URL used for the auth exchange. + """ + + homeserver: "typing.Optional[str]" + """ + Homeserver public key (z32-encoded). Present only for signup flows. + """ + + signup_token: "typing.Optional[str]" + """ + Signup token. Present only for signup flows. + """ + + def __init__(self, *, kind: "PubkyAuthKind", capabilities: "str", relay: "str", homeserver: "typing.Optional[str]", signup_token: "typing.Optional[str]"): + self.kind = kind + self.capabilities = capabilities + self.relay = relay + self.homeserver = homeserver + self.signup_token = signup_token + + def __str__(self): + return "PubkyAuthDetails(kind={}, capabilities={}, relay={}, homeserver={}, signup_token={})".format(self.kind, self.capabilities, self.relay, self.homeserver, self.signup_token) + + def __eq__(self, other): + if self.kind != other.kind: + return False + if self.capabilities != other.capabilities: + return False + if self.relay != other.relay: + return False + if self.homeserver != other.homeserver: + return False + if self.signup_token != other.signup_token: + return False + return True + +class _UniffiConverterTypePubkyAuthDetails(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + return PubkyAuthDetails( + kind=_UniffiConverterTypePubkyAuthKind.read(buf), + capabilities=_UniffiConverterString.read(buf), + relay=_UniffiConverterString.read(buf), + homeserver=_UniffiConverterOptionalString.read(buf), + signup_token=_UniffiConverterOptionalString.read(buf), + ) + + @staticmethod + def check_lower(value): + _UniffiConverterTypePubkyAuthKind.check_lower(value.kind) + _UniffiConverterString.check_lower(value.capabilities) + _UniffiConverterString.check_lower(value.relay) + _UniffiConverterOptionalString.check_lower(value.homeserver) + _UniffiConverterOptionalString.check_lower(value.signup_token) + + @staticmethod + def write(value, buf): + _UniffiConverterTypePubkyAuthKind.write(value.kind, buf) + _UniffiConverterString.write(value.capabilities, buf) + _UniffiConverterString.write(value.relay, buf) + _UniffiConverterOptionalString.write(value.homeserver, buf) + _UniffiConverterOptionalString.write(value.signup_token, buf) + + class PubkyProfile: name: "str" bio: "typing.Optional[str]" @@ -12379,6 +12480,48 @@ def write(value, buf): + + + +class PubkyAuthKind(enum.Enum): + """ + The type of a `pubkyauth://` deep-link flow. + """ + + SIGNIN = 0 + + SIGNUP = 1 + + + +class _UniffiConverterTypePubkyAuthKind(_UniffiConverterRustBuffer): + @staticmethod + def read(buf): + variant = buf.read_i32() + if variant == 1: + return PubkyAuthKind.SIGNIN + if variant == 2: + return PubkyAuthKind.SIGNUP + raise InternalError("Raw enum value doesn't match any cases") + + @staticmethod + def check_lower(value): + if value == PubkyAuthKind.SIGNIN: + return + if value == PubkyAuthKind.SIGNUP: + return + raise ValueError(value) + + @staticmethod + def write(value, buf): + if value == PubkyAuthKind.SIGNIN: + buf.write_i32(1) + if value == PubkyAuthKind.SIGNUP: + buf.write_i32(2) + + + + # PubkyError # We want to define each variant as a nested class that's also a subclass, # which is tricky in Python. To accomplish this we're going to create each @@ -17141,6 +17284,27 @@ def add_tags(activity_id: "str",tags: "typing.List[str]") -> None: _UniffiConverterString.lower(activity_id), _UniffiConverterSequenceString.lower(tags)) +async def approve_pubky_auth(auth_url: "str",secret_key_hex: "str") -> None: + + _UniffiConverterString.check_lower(auth_url) + + _UniffiConverterString.check_lower(secret_key_hex) + + return await _uniffi_rust_call_async( + _UniffiLib.uniffi_bitkitcore_fn_func_approve_pubky_auth( + _UniffiConverterString.lower(auth_url), + _UniffiConverterString.lower(secret_key_hex)), + _UniffiLib.ffi_bitkitcore_rust_future_poll_void, + _UniffiLib.ffi_bitkitcore_rust_future_complete_void, + _UniffiLib.ffi_bitkitcore_rust_future_free_void, + # lift function + lambda val: None, + + + # Error FFI converter +_UniffiConverterTypePubkyError, + + ) async def blocktank_remove_all_cjit_entries() -> None: return await _uniffi_rust_call_async( @@ -18179,6 +18343,13 @@ async def open_channel(order_id: "str",connection_string: "str") -> "IBtOrder": _UniffiConverterTypeBlocktankError, ) + +def parse_pubky_auth_url(auth_url: "str") -> "PubkyAuthDetails": + _UniffiConverterString.check_lower(auth_url) + + return _UniffiConverterTypePubkyAuthDetails.lift(_uniffi_rust_call_with_error(_UniffiConverterTypePubkyError,_UniffiLib.uniffi_bitkitcore_fn_func_parse_pubky_auth_url, + _UniffiConverterString.lower(auth_url))) + async def prepare_sweep_transaction(mnemonic_phrase: "str",network: "typing.Optional[Network]",bip39_passphrase: "typing.Optional[str]",electrum_url: "str",destination_address: "str",fee_rate_sats_per_vbyte: "typing.Optional[int]") -> "SweepTransactionPreview": _UniffiConverterString.check_lower(mnemonic_phrase) @@ -19238,6 +19409,7 @@ def wipe_all_transaction_details() -> None: "NetworkType", "PaymentState", "PaymentType", + "PubkyAuthKind", "PubkyError", "Scanner", "SortDirection", @@ -19304,6 +19476,7 @@ def wipe_all_transaction_details() -> None: "OnchainActivity", "PreActivityMetadata", "PubkyAuth", + "PubkyAuthDetails", "PubkyProfile", "PubkyProfileLink", "SingleAddressInfoResult", @@ -19343,6 +19516,7 @@ def wipe_all_transaction_details() -> None: "add_pre_activity_metadata", "add_pre_activity_metadata_tags", "add_tags", + "approve_pubky_auth", "blocktank_remove_all_cjit_entries", "blocktank_remove_all_orders", "blocktank_wipe_all", @@ -19411,6 +19585,7 @@ def wipe_all_transaction_details() -> None: "onchain_get_transaction_detail", "onchain_get_transaction_history", "open_channel", + "parse_pubky_auth_url", "prepare_sweep_transaction", "pubky_public_key_from_secret", "pubky_put_with_secret_key", diff --git a/bindings/python/bitkitcore/libbitkitcore.dylib b/bindings/python/bitkitcore/libbitkitcore.dylib index 5e2381d..2d02ac5 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 37efff5..f566be5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,7 +31,7 @@ use crate::modules::blocktank::{ IBt0ConfMinTxFeeWindow, IBtBolt11Invoice, IBtEstimateFeeResponse, IBtEstimateFeeResponse2, IBtInfo, IBtOrder, ICJitEntry, IGift, }; -use crate::modules::pubky::{PubkyError, PubkyProfile}; +use crate::modules::pubky::{PubkyAuthDetails, PubkyAuthKind, PubkyError, PubkyProfile}; use crate::modules::trezor::account_type_to_script_type; pub use crate::modules::trezor::{ get_transport_callback, trezor_is_ble_available, trezor_set_transport_callback, @@ -1902,6 +1902,28 @@ pub async fn complete_pubky_auth() -> Result { }) } +#[uniffi::export] +pub fn parse_pubky_auth_url(auth_url: String) -> Result { + crate::modules::pubky::parse_pubky_auth_url(auth_url) +} + +#[uniffi::export] +pub async fn approve_pubky_auth( + auth_url: String, + secret_key_hex: String, +) -> Result<(), PubkyError> { + let rt = ensure_runtime(); + rt.spawn( + async move { crate::modules::pubky::approve_pubky_auth(auth_url, secret_key_hex).await }, + ) + .await + .unwrap_or_else(|e| { + Err(PubkyError::AuthFailed { + reason: format!("Runtime error: {}", e), + }) + }) +} + #[uniffi::export] pub async fn fetch_pubky_profile(public_key: String) -> Result { let rt = ensure_runtime(); diff --git a/src/modules/pubky/auth.rs b/src/modules/pubky/auth.rs index ad4d2b6..92c9f8f 100644 --- a/src/modules/pubky/auth.rs +++ b/src/modules/pubky/auth.rs @@ -1,8 +1,11 @@ use once_cell::sync::OnceCell; +use pubky::deep_links::DeepLink; use pubky::{AuthFlowKind, Capabilities, PubkyAuthFlow}; use tokio::sync::Mutex as TokioMutex; use super::errors::PubkyError; +use super::keys::keypair_from_hex; +use super::resolve::get_pubky; static AUTH_FLOW: OnceCell>> = OnceCell::new(); @@ -60,3 +63,74 @@ pub async fn complete_pubky_auth() -> Result { Ok(session.export_secret()) } + +/// The type of a `pubkyauth://` deep-link flow. +#[derive(uniffi::Enum, Debug, Clone, PartialEq)] +pub enum PubkyAuthKind { + Signin, + Signup, +} + +/// Details extracted from a `pubkyauth://` deep-link URL. +#[derive(uniffi::Record, Debug, Clone)] +pub struct PubkyAuthDetails { + /// Whether this is a signin or signup flow. + pub kind: PubkyAuthKind, + /// Requested capabilities (e.g. `"/pub/pubky.app/:rw"`). + pub capabilities: String, + /// Relay URL used for the auth exchange. + pub relay: String, + /// Homeserver public key (z32-encoded). Present only for signup flows. + pub homeserver: Option, + /// Signup token. Present only for signup flows. + pub signup_token: Option, +} + +/// Parse a `pubkyauth://` URL and return its details for UI display. +pub fn parse_pubky_auth_url(auth_url: String) -> Result { + let deep_link: DeepLink = + auth_url + .parse() + .map_err( + |e: pubky::deep_links::DeepLinkParseError| PubkyError::AuthFailed { + reason: e.to_string(), + }, + )?; + + match deep_link { + DeepLink::Signin(signin) => Ok(PubkyAuthDetails { + kind: PubkyAuthKind::Signin, + capabilities: signin.capabilities().to_string(), + relay: signin.relay().to_string(), + homeserver: None, + signup_token: None, + }), + DeepLink::Signup(signup) => Ok(PubkyAuthDetails { + kind: PubkyAuthKind::Signup, + capabilities: signup.capabilities().to_string(), + relay: signup.relay().to_string(), + homeserver: Some(signup.homeserver().z32()), + signup_token: signup.signup_token(), + }), + DeepLink::SeedExport(_) => Err(PubkyError::AuthFailed { + reason: "seed_export deep links are not auth URLs".to_string(), + }), + } +} + +/// Approve a Pubky auth request by signing an AuthToken and posting it to the relay. +pub async fn approve_pubky_auth( + auth_url: String, + secret_key_hex: String, +) -> Result<(), PubkyError> { + let kp = keypair_from_hex(&secret_key_hex)?; + let pubky = get_pubky()?; + let signer = pubky.signer(kp); + + signer + .approve_auth(&auth_url) + .await + .map_err(|e| PubkyError::AuthFailed { + reason: e.to_string(), + }) +} diff --git a/src/modules/pubky/tests.rs b/src/modules/pubky/tests.rs index 9b488b5..4c8daa1 100644 --- a/src/modules/pubky/tests.rs +++ b/src/modules/pubky/tests.rs @@ -409,6 +409,109 @@ async fn session_list_invalid_session_returns_error() { } } +// ============================================================================ +// Approver auth tests +// ============================================================================ + +#[test] +fn parse_signin_auth_url() { + let url = "pubkyauth://signin?caps=/pub/pubky.app/:rw&secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8&relay=https://httprelay.pubky.app/link"; + let details = parse_pubky_auth_url(url.into()).unwrap(); + assert_eq!(details.kind, PubkyAuthKind::Signin); + assert_eq!(details.capabilities, "/pub/pubky.app/:rw"); + assert_eq!(details.relay, "https://httprelay.pubky.app/link"); + assert!(details.homeserver.is_none()); + assert!(details.signup_token.is_none()); +} + +#[test] +fn parse_signup_auth_url_with_token() { + let url = "pubkyauth://signup?caps=/pub/pubky.app/:rw&secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8&relay=https://httprelay.pubky.app/link&hs=5jsjx1o6fzu6aeeo697r3i5rx15zq41kikcye8wtwdqm4nb4tryo&st=1234567890"; + let details = parse_pubky_auth_url(url.into()).unwrap(); + assert_eq!(details.kind, PubkyAuthKind::Signup); + assert_eq!(details.capabilities, "/pub/pubky.app/:rw"); + assert_eq!(details.relay, "https://httprelay.pubky.app/link"); + assert_eq!( + details.homeserver.as_deref(), + Some("5jsjx1o6fzu6aeeo697r3i5rx15zq41kikcye8wtwdqm4nb4tryo") + ); + assert_eq!(details.signup_token.as_deref(), Some("1234567890")); +} + +#[test] +fn parse_signup_auth_url_without_token() { + let url = "pubkyauth://signup?caps=/pub/pubky.app/:rw&secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8&relay=https://httprelay.pubky.app/link&hs=5jsjx1o6fzu6aeeo697r3i5rx15zq41kikcye8wtwdqm4nb4tryo"; + let details = parse_pubky_auth_url(url.into()).unwrap(); + assert_eq!(details.kind, PubkyAuthKind::Signup); + assert_eq!( + details.homeserver.as_deref(), + Some("5jsjx1o6fzu6aeeo697r3i5rx15zq41kikcye8wtwdqm4nb4tryo") + ); + assert!(details.signup_token.is_none()); +} + +#[test] +fn parse_old_format_auth_url() { + let url = "pubkyauth:///?caps=/pub/pubky.app/:rw&secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8&relay=https://httprelay.pubky.app/link"; + let details = parse_pubky_auth_url(url.into()).unwrap(); + assert_eq!(details.kind, PubkyAuthKind::Signin); +} + +#[test] +fn parse_invalid_auth_url_returns_error() { + let result = parse_pubky_auth_url("not-a-valid-url".into()); + assert!(result.is_err()); + match result.unwrap_err() { + PubkyError::AuthFailed { .. } => {} + other => panic!("expected AuthFailed, got: {other:?}"), + } +} + +#[test] +fn parse_auth_url_missing_params_returns_error() { + // Missing secret and relay + let result = parse_pubky_auth_url("pubkyauth://signin?caps=/pub/pubky.app/:rw".into()); + assert!(result.is_err()); + match result.unwrap_err() { + PubkyError::AuthFailed { .. } => {} + other => panic!("expected AuthFailed, got: {other:?}"), + } +} + +#[test] +fn parse_seed_export_url_returns_error() { + let url = "pubkyauth://secret_export?secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8"; + let result = parse_pubky_auth_url(url.into()); + assert!(result.is_err()); + match result.unwrap_err() { + PubkyError::AuthFailed { .. } => {} + other => panic!("expected AuthFailed, got: {other:?}"), + } +} + +#[tokio::test] +async fn approve_auth_invalid_key_returns_error() { + let url = "pubkyauth://signin?caps=/pub/pubky.app/:rw&secret=kqnceEMgrNQM_xi06oQXjA3cJHX_RQmw1BY6JE1bse8&relay=https://httprelay.pubky.app/link"; + let result = approve_pubky_auth(url.into(), "bad-hex".into()).await; + assert!(result.is_err()); + match result.unwrap_err() { + PubkyError::KeyError { .. } => {} + other => panic!("expected KeyError, got: {other:?}"), + } +} + +#[tokio::test] +async fn approve_auth_invalid_url_returns_error() { + let seed = vec![0xABu8; 64]; + let secret = derive_pubky_secret_key(seed).unwrap(); + let result = approve_pubky_auth("not-a-url".into(), secret).await; + assert!(result.is_err()); + match result.unwrap_err() { + PubkyError::AuthFailed { .. } => {} + other => panic!("expected AuthFailed, got: {other:?}"), + } +} + // ============================================================================ // String fetch tests // ============================================================================