diff --git a/cktap-ffi/src/sats_card.rs b/cktap-ffi/src/sats_card.rs index 476726e..ded63e1 100644 --- a/cktap-ffi/src/sats_card.rs +++ b/cktap-ffi/src/sats_card.rs @@ -67,14 +67,10 @@ impl SatsCard { Ok(pubkey_desc) } - /// Wait 15 seconds or until auth delay timeout is done - pub async fn wait(&self) -> Result<(), CkTapError> { + /// Wait one second of auth delay and return the remaining delay, if any. + pub async fn wait(&self) -> Result, CkTapError> { let mut card = self.0.lock().await; - // if auth delay call wait - while card.auth_delay().is_some() { - card.wait(None).await?; - } - Ok(()) + card.wait(None).await.map_err(CkTapError::from) } /// Verify the card has authentic Coinkite root certificate diff --git a/cktap-ffi/src/sats_chip.rs b/cktap-ffi/src/sats_chip.rs index 1b73d05..7f97c8a 100644 --- a/cktap-ffi/src/sats_chip.rs +++ b/cktap-ffi/src/sats_chip.rs @@ -47,13 +47,9 @@ impl SatsChip { read(&mut *card, None).await } - pub async fn wait(&self) -> Result<(), CkTapError> { + pub async fn wait(&self) -> Result, CkTapError> { let mut card = self.0.lock().await; - // if auth delay call wait - while card.auth_delay().is_some() { - card.wait(None).await?; - } - Ok(()) + card.wait(None).await.map_err(CkTapError::from) } pub async fn check_cert(&self) -> Result<(), CertsError> { diff --git a/cktap-ffi/src/tap_signer.rs b/cktap-ffi/src/tap_signer.rs index 919da01..1b56345 100644 --- a/cktap-ffi/src/tap_signer.rs +++ b/cktap-ffi/src/tap_signer.rs @@ -50,13 +50,9 @@ impl TapSigner { read(&mut *card, Some(cvc)).await } - pub async fn wait(&self) -> Result<(), CkTapError> { + pub async fn wait(&self) -> Result, CkTapError> { let mut card = self.0.lock().await; - // if auth delay call wait - while card.auth_delay().is_some() { - card.wait(None).await?; - } - Ok(()) + card.wait(None).await.map_err(CkTapError::from) } pub async fn check_cert(&self) -> Result<(), CertsError> { diff --git a/cktap-swift/Sources/CKTap/cktap_ffi.swift b/cktap-swift/Sources/CKTap/cktap_ffi.swift index d39b580..fe52910 100644 --- a/cktap-swift/Sources/CKTap/cktap_ffi.swift +++ b/cktap-swift/Sources/CKTap/cktap_ffi.swift @@ -602,9 +602,9 @@ public protocol SatsCardProtocol: AnyObject, Sendable { func unseal(cvc: String) async throws -> SlotDetails /** - * Wait 15 seconds or until auth delay timeout is done + * Wait one second of auth delay and return the remaining delay, if any. */ - func wait() async throws + func wait() async throws -> UInt8? } open class SatsCard: SatsCardProtocol, @unchecked Sendable { @@ -649,11 +649,6 @@ open class SatsCard: SatsCardProtocol, @unchecked Sendable { // No primary constructor declared for this class. deinit { - if handle == 0 { - // Mock objects have handle=0 don't try to free them - return - } - try! rustCall { uniffi_cktap_ffi_fn_free_satscard(handle, $0) } } @@ -840,9 +835,9 @@ open func unseal(cvc: String)async throws -> SlotDetails { } /** - * Wait 15 seconds or until auth delay timeout is done + * Wait one second of auth delay and return the remaining delay, if any. */ -open func wait()async throws { +open func wait()async throws -> UInt8? { return try await uniffiRustCallAsync( rustFutureFunc: { @@ -851,16 +846,15 @@ open func wait()async throws { ) }, - pollFunc: ffi_cktap_ffi_rust_future_poll_void, - completeFunc: ffi_cktap_ffi_rust_future_complete_void, - freeFunc: ffi_cktap_ffi_rust_future_free_void, - liftFunc: { $0 }, + pollFunc: ffi_cktap_ffi_rust_future_poll_rust_buffer, + completeFunc: ffi_cktap_ffi_rust_future_complete_rust_buffer, + freeFunc: ffi_cktap_ffi_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionUInt8.lift, errorHandler: FfiConverterTypeCkTapError_lift ) } - } @@ -890,6 +884,7 @@ public struct FfiConverterTypeSatsCard: FfiConverter { } + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -927,7 +922,7 @@ public protocol SatsChipProtocol: AnyObject, Sendable { func status() async -> SatsChipStatus - func wait() async throws + func wait() async throws -> UInt8? func xpub(master: Bool, cvc: String) async throws -> String @@ -974,11 +969,6 @@ open class SatsChip: SatsChipProtocol, @unchecked Sendable { // No primary constructor declared for this class. deinit { - if handle == 0 { - // Mock objects have handle=0 don't try to free them - return - } - try! rustCall { uniffi_cktap_ffi_fn_free_satschip(handle, $0) } } @@ -1122,7 +1112,7 @@ open func status()async -> SatsChipStatus { ) } -open func wait()async throws { +open func wait()async throws -> UInt8? { return try await uniffiRustCallAsync( rustFutureFunc: { @@ -1131,10 +1121,10 @@ open func wait()async throws { ) }, - pollFunc: ffi_cktap_ffi_rust_future_poll_void, - completeFunc: ffi_cktap_ffi_rust_future_complete_void, - freeFunc: ffi_cktap_ffi_rust_future_free_void, - liftFunc: { $0 }, + pollFunc: ffi_cktap_ffi_rust_future_poll_rust_buffer, + completeFunc: ffi_cktap_ffi_rust_future_complete_rust_buffer, + freeFunc: ffi_cktap_ffi_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionUInt8.lift, errorHandler: FfiConverterTypeCkTapError_lift ) } @@ -1157,7 +1147,6 @@ open func xpub(master: Bool, cvc: String)async throws -> String { } - } @@ -1187,6 +1176,7 @@ public struct FfiConverterTypeSatsChip: FfiConverter { } + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1224,7 +1214,7 @@ public protocol TapSignerProtocol: AnyObject, Sendable { func status() async -> TapSignerStatus - func wait() async throws + func wait() async throws -> UInt8? func xpub(master: Bool, cvc: String) async throws -> String @@ -1271,11 +1261,6 @@ open class TapSigner: TapSignerProtocol, @unchecked Sendable { // No primary constructor declared for this class. deinit { - if handle == 0 { - // Mock objects have handle=0 don't try to free them - return - } - try! rustCall { uniffi_cktap_ffi_fn_free_tapsigner(handle, $0) } } @@ -1419,7 +1404,7 @@ open func status()async -> TapSignerStatus { ) } -open func wait()async throws { +open func wait()async throws -> UInt8? { return try await uniffiRustCallAsync( rustFutureFunc: { @@ -1428,10 +1413,10 @@ open func wait()async throws { ) }, - pollFunc: ffi_cktap_ffi_rust_future_poll_void, - completeFunc: ffi_cktap_ffi_rust_future_complete_void, - freeFunc: ffi_cktap_ffi_rust_future_free_void, - liftFunc: { $0 }, + pollFunc: ffi_cktap_ffi_rust_future_poll_rust_buffer, + completeFunc: ffi_cktap_ffi_rust_future_complete_rust_buffer, + freeFunc: ffi_cktap_ffi_rust_future_free_rust_buffer, + liftFunc: FfiConverterOptionUInt8.lift, errorHandler: FfiConverterTypeCkTapError_lift ) } @@ -1454,7 +1439,6 @@ open func xpub(master: Bool, cvc: String)async throws -> String { } - } @@ -1484,6 +1468,7 @@ public struct FfiConverterTypeTapSigner: FfiConverter { } + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1501,7 +1486,7 @@ public func FfiConverterTypeTapSigner_lower(_ value: TapSigner) -> UInt64 { -public struct SatsCardStatus: Equatable, Hashable { +public struct SatsCardStatus { public var proto: UInt64 public var ver: String public var birth: UInt64 @@ -1525,16 +1510,60 @@ public struct SatsCardStatus: Equatable, Hashable { self.cardIdent = cardIdent self.authDelay = authDelay } - - - - } #if compiler(>=6) extension SatsCardStatus: Sendable {} #endif + +extension SatsCardStatus: Equatable, Hashable { + public static func ==(lhs: SatsCardStatus, rhs: SatsCardStatus) -> Bool { + if lhs.proto != rhs.proto { + return false + } + if lhs.ver != rhs.ver { + return false + } + if lhs.birth != rhs.birth { + return false + } + if lhs.activeSlot != rhs.activeSlot { + return false + } + if lhs.numSlots != rhs.numSlots { + return false + } + if lhs.addr != rhs.addr { + return false + } + if lhs.pubkey != rhs.pubkey { + return false + } + if lhs.cardIdent != rhs.cardIdent { + return false + } + if lhs.authDelay != rhs.authDelay { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(proto) + hasher.combine(ver) + hasher.combine(birth) + hasher.combine(activeSlot) + hasher.combine(numSlots) + hasher.combine(addr) + hasher.combine(pubkey) + hasher.combine(cardIdent) + hasher.combine(authDelay) + } +} + + + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1583,7 +1612,7 @@ public func FfiConverterTypeSatsCardStatus_lower(_ value: SatsCardStatus) -> Rus } -public struct SatsChipStatus: Equatable, Hashable { +public struct SatsChipStatus { public var proto: UInt64 public var ver: String public var birth: UInt64 @@ -1603,16 +1632,52 @@ public struct SatsChipStatus: Equatable, Hashable { self.cardIdent = cardIdent self.authDelay = authDelay } - - - - } #if compiler(>=6) extension SatsChipStatus: Sendable {} #endif + +extension SatsChipStatus: Equatable, Hashable { + public static func ==(lhs: SatsChipStatus, rhs: SatsChipStatus) -> Bool { + if lhs.proto != rhs.proto { + return false + } + if lhs.ver != rhs.ver { + return false + } + if lhs.birth != rhs.birth { + return false + } + if lhs.path != rhs.path { + return false + } + if lhs.pubkey != rhs.pubkey { + return false + } + if lhs.cardIdent != rhs.cardIdent { + return false + } + if lhs.authDelay != rhs.authDelay { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(proto) + hasher.combine(ver) + hasher.combine(birth) + hasher.combine(path) + hasher.combine(pubkey) + hasher.combine(cardIdent) + hasher.combine(authDelay) + } +} + + + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1657,7 +1722,7 @@ public func FfiConverterTypeSatsChipStatus_lower(_ value: SatsChipStatus) -> Rus } -public struct SlotDetails: Equatable, Hashable { +public struct SlotDetails { public var privkey: String? public var pubkey: String public var pubkeyDescriptor: String @@ -1669,16 +1734,36 @@ public struct SlotDetails: Equatable, Hashable { self.pubkey = pubkey self.pubkeyDescriptor = pubkeyDescriptor } - - - - } #if compiler(>=6) extension SlotDetails: Sendable {} #endif + +extension SlotDetails: Equatable, Hashable { + public static func ==(lhs: SlotDetails, rhs: SlotDetails) -> Bool { + if lhs.privkey != rhs.privkey { + return false + } + if lhs.pubkey != rhs.pubkey { + return false + } + if lhs.pubkeyDescriptor != rhs.pubkeyDescriptor { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(privkey) + hasher.combine(pubkey) + hasher.combine(pubkeyDescriptor) + } +} + + + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1715,7 +1800,7 @@ public func FfiConverterTypeSlotDetails_lower(_ value: SlotDetails) -> RustBuffe } -public struct TapSignerStatus: Equatable, Hashable { +public struct TapSignerStatus { public var proto: UInt64 public var ver: String public var birth: UInt64 @@ -1737,16 +1822,56 @@ public struct TapSignerStatus: Equatable, Hashable { self.cardIdent = cardIdent self.authDelay = authDelay } - - - - } #if compiler(>=6) extension TapSignerStatus: Sendable {} #endif + +extension TapSignerStatus: Equatable, Hashable { + public static func ==(lhs: TapSignerStatus, rhs: TapSignerStatus) -> Bool { + if lhs.proto != rhs.proto { + return false + } + if lhs.ver != rhs.ver { + return false + } + if lhs.birth != rhs.birth { + return false + } + if lhs.path != rhs.path { + return false + } + if lhs.numBackups != rhs.numBackups { + return false + } + if lhs.pubkey != rhs.pubkey { + return false + } + if lhs.cardIdent != rhs.cardIdent { + return false + } + if lhs.authDelay != rhs.authDelay { + return false + } + return true + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(proto) + hasher.combine(ver) + hasher.combine(birth) + hasher.combine(path) + hasher.combine(numBackups) + hasher.combine(pubkey) + hasher.combine(cardIdent) + hasher.combine(authDelay) + } +} + + + #if swift(>=5.8) @_documentation(visibility: private) #endif @@ -1796,7 +1921,7 @@ public func FfiConverterTypeTapSignerStatus_lower(_ value: TapSignerStatus) -> R /** * Errors returned by the CkTap card. */ -public enum CardError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum CardError: Swift.Error { @@ -1811,21 +1936,8 @@ public enum CardError: Swift.Error, Equatable, Hashable, Foundation.LocalizedErr case BadCbor case BackupFirst case RateLimited - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension CardError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -1926,10 +2038,25 @@ public func FfiConverterTypeCardError_lower(_ value: CardError) -> RustBuffer { } +extension CardError: Equatable, Hashable {} + + + + +extension CardError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `certs` command. */ -public enum CertsError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum CertsError: Swift.Error { @@ -1939,21 +2066,8 @@ public enum CertsError: Swift.Error, Equatable, Hashable, Foundation.LocalizedEr ) case InvalidRootCert(msg: String ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension CertsError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2023,10 +2137,25 @@ public func FfiConverterTypeCertsError_lower(_ value: CertsError) -> RustBuffer } +extension CertsError: Equatable, Hashable {} + + + + +extension CertsError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `change` command. */ -public enum ChangeError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum ChangeError: Swift.Error { @@ -2037,21 +2166,8 @@ public enum ChangeError: Swift.Error, Equatable, Hashable, Foundation.LocalizedE case TooLong(len: UInt64 ) case SameAsOld - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension ChangeError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2125,6 +2241,21 @@ public func FfiConverterTypeChangeError_lower(_ value: ChangeError) -> RustBuffe return FfiConverterTypeChangeError.lower(value) } + +extension ChangeError: Equatable, Hashable {} + + + + +extension ChangeError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + // Note that we don't yet support `indirect` for enums. // See https://github.com/mozilla/uniffi-rs/issues/396 for further discussion. @@ -2136,13 +2267,9 @@ public enum CkTapCard { ) case satsChip(SatsChip ) - - - - - } + #if compiler(>=6) extension CkTapCard: Sendable {} #endif @@ -2209,10 +2336,14 @@ public func FfiConverterTypeCkTapCard_lower(_ value: CkTapCard) -> RustBuffer { + + + + /** * Errors returned by the card, CBOR deserialization or value encoding, or the APDU transport. */ -public enum CkTapError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum CkTapError: Swift.Error { @@ -2225,21 +2356,8 @@ public enum CkTapError: Swift.Error, Equatable, Hashable, Foundation.LocalizedEr case Transport(msg: String ) case UnknownCardType - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension CkTapError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2322,10 +2440,25 @@ public func FfiConverterTypeCkTapError_lower(_ value: CkTapError) -> RustBuffer } +extension CkTapError: Equatable, Hashable {} + + + + +extension CkTapError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `derive` command. */ -public enum DeriveError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum DeriveError: Swift.Error { @@ -2335,21 +2468,8 @@ public enum DeriveError: Swift.Error, Equatable, Hashable, Foundation.LocalizedE ) case InvalidChainCode(msg: String ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension DeriveError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2419,10 +2539,25 @@ public func FfiConverterTypeDeriveError_lower(_ value: DeriveError) -> RustBuffe } +extension DeriveError: Equatable, Hashable {} + + + + +extension DeriveError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `dump` command. */ -public enum DumpError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum DumpError: Swift.Error { @@ -2441,21 +2576,8 @@ public enum DumpError: Swift.Error, Equatable, Hashable, Foundation.LocalizedErr */ case SlotTampered(slot: UInt8 ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension DumpError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2541,29 +2663,31 @@ public func FfiConverterTypeDumpError_lower(_ value: DumpError) -> RustBuffer { } -public enum KeyError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +extension DumpError: Equatable, Hashable {} - - - case Secp256k1(msg: String - ) - case KeyFromSlice(msg: String - ) - - - +extension DumpError: Foundation.LocalizedError { public var errorDescription: String? { String(reflecting: self) } +} + + + + + +public enum KeyError: Swift.Error { + + + case Secp256k1(msg: String + ) + case KeyFromSlice(msg: String + ) } -#if compiler(>=6) -extension KeyError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2625,10 +2749,25 @@ public func FfiConverterTypeKeyError_lower(_ value: KeyError) -> RustBuffer { } +extension KeyError: Equatable, Hashable {} + + + + +extension KeyError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `read` command. */ -public enum ReadError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum ReadError: Swift.Error { @@ -2636,21 +2775,8 @@ public enum ReadError: Swift.Error, Equatable, Hashable, Foundation.LocalizedErr ) case Key(err: KeyError ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension ReadError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2712,7 +2838,22 @@ public func FfiConverterTypeReadError_lower(_ value: ReadError) -> RustBuffer { } -public enum SignPsbtError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +extension ReadError: Equatable, Hashable {} + + + + +extension ReadError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + +public enum SignPsbtError: Swift.Error { @@ -2740,21 +2881,8 @@ public enum SignPsbtError: Swift.Error, Equatable, Hashable, Foundation.Localize ) case Base64Encoding(msg: String ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension SignPsbtError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2896,10 +3024,25 @@ public func FfiConverterTypeSignPsbtError_lower(_ value: SignPsbtError) -> RustB } +extension SignPsbtError: Equatable, Hashable {} + + + + +extension SignPsbtError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `status` command. */ -public enum StatusError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum StatusError: Swift.Error { @@ -2907,21 +3050,8 @@ public enum StatusError: Swift.Error, Equatable, Hashable, Foundation.LocalizedE ) case Key(err: KeyError ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension StatusError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -2983,10 +3113,25 @@ public func FfiConverterTypeStatusError_lower(_ value: StatusError) -> RustBuffe } +extension StatusError: Equatable, Hashable {} + + + + +extension StatusError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `unseal` command. */ -public enum UnsealError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum UnsealError: Swift.Error { @@ -2994,21 +3139,8 @@ public enum UnsealError: Swift.Error, Equatable, Hashable, Foundation.LocalizedE ) case Key(err: KeyError ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension UnsealError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -3070,10 +3202,25 @@ public func FfiConverterTypeUnsealError_lower(_ value: UnsealError) -> RustBuffe } +extension UnsealError: Equatable, Hashable {} + + + + +extension UnsealError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + /** * Errors returned by the `xpub` command. */ -public enum XpubError: Swift.Error, Equatable, Hashable, Foundation.LocalizedError { +public enum XpubError: Swift.Error { @@ -3081,21 +3228,8 @@ public enum XpubError: Swift.Error, Equatable, Hashable, Foundation.LocalizedErr ) case Bip32(msg: String ) - - - - - - - public var errorDescription: String? { - String(reflecting: self) - } - } -#if compiler(>=6) -extension XpubError: Sendable {} -#endif #if swift(>=5.8) @_documentation(visibility: private) @@ -3157,6 +3291,21 @@ public func FfiConverterTypeXpubError_lower(_ value: XpubError) -> RustBuffer { } +extension XpubError: Equatable, Hashable {} + + + + +extension XpubError: Foundation.LocalizedError { + public var errorDescription: String? { + String(reflecting: self) + } +} + + + + + public protocol CkTransport: AnyObject, Sendable { @@ -3172,8 +3321,9 @@ fileprivate struct UniffiCallbackInterfaceCkTransport { // Create the VTable using a series of closures. // Swift automatically converts these into C callback functions. // - // Store the vtable directly. - static let vtable: UniffiVTableCallbackInterfaceCkTransport = UniffiVTableCallbackInterfaceCkTransport( + // This creates 1-element array, since this seems to be the only way to construct a const + // pointer that we can pass to the Rust code. + static let vtable: [UniffiVTableCallbackInterfaceCkTransport] = [UniffiVTableCallbackInterfaceCkTransport( uniffiFree: { (uniffiHandle: UInt64) -> () in do { try FfiConverterCallbackInterfaceCkTransport.handleMap.remove(handle: uniffiHandle) @@ -3231,19 +3381,11 @@ fileprivate struct UniffiCallbackInterfaceCkTransport { droppedCallback: uniffiOutDroppedCallback ) } - ) - - // Rust stores this pointer for future callback invocations, so it must live - // for the process lifetime (not just for the init function call). - static let vtablePtr: UnsafePointer = { - let ptr = UnsafeMutablePointer.allocate(capacity: 1) - ptr.initialize(to: vtable) - return UnsafePointer(ptr) - }() + )] } private func uniffiCallbackInitCkTransport() { - uniffi_cktap_ffi_fn_init_callback_vtable_cktransport(UniffiCallbackInterfaceCkTransport.vtablePtr) + uniffi_cktap_ffi_fn_init_callback_vtable_cktransport(UniffiCallbackInterfaceCkTransport.vtable) } // FfiConverter protocol for callback interfaces @@ -3452,9 +3594,7 @@ fileprivate func uniffiRustCallAsync( pollResult = await withUnsafeContinuation { pollFunc( rustFuture, - { handle, pollResult in - uniffiFutureContinuationCallback(handle: handle, pollResult: pollResult) - }, + uniffiFutureContinuationCallback, uniffiContinuationHandleMap.insert(obj: $0) ) } @@ -3482,22 +3622,11 @@ private func uniffiTraitInterfaceCallAsync( droppedCallback: UnsafeMutablePointer ) { let task = Task { - // Note: it's important we call either `handleSuccess` or `handleError` exactly once. Each - // call consumes an Arc reference, which means there should be no possibility of a double - // call. The following code is structured so that will will never call both `handleSuccess` - // and `handleError`, even in the face of weird errors. - // - // On platforms that need extra machinery to make C-ABI calls, like JNA or ctypes, it's - // possible that we fail to make either call. However, it doesn't seem like this is - // possible on Swift since swift can just make the C call directly. - var callResult: T do { - callResult = try await makeCall() + handleSuccess(try await makeCall()) } catch { handleError(CALL_UNEXPECTED_ERROR, FfiConverterString.lower(String(describing: error))) - return } - handleSuccess(callResult) } let handle = UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert(obj: task) droppedCallback.pointee = UniffiForeignFutureDroppedCallbackStruct( @@ -3514,19 +3643,13 @@ private func uniffiTraitInterfaceCallAsyncWithError( droppedCallback: UnsafeMutablePointer ) { let task = Task { - // See the note in uniffiTraitInterfaceCallAsync for details on `handleSuccess` and - // `handleError`. - var callResult: T do { - callResult = try await makeCall() + handleSuccess(try await makeCall()) } catch let error as E { handleError(CALL_ERROR, lowerError(error)) - return } catch { handleError(CALL_UNEXPECTED_ERROR, FfiConverterString.lower(String(describing: error))) - return } - handleSuccess(callResult) } let handle = UNIFFI_FOREIGN_FUTURE_HANDLE_MAP.insert(obj: task) droppedCallback.pointee = UniffiForeignFutureDroppedCallbackStruct( @@ -3595,100 +3718,100 @@ private let initializationResult: InitializationResult = { if bindings_contract_version != scaffolding_contract_version { return InitializationResult.contractVersionMismatch } - if (uniffi_cktap_ffi_checksum_func_to_cktap() != 32899) { + if (uniffi_cktap_ffi_checksum_func_to_cktap() != 56485) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_address() != 37827) { + if (uniffi_cktap_ffi_checksum_method_satscard_address() != 9818) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_check_cert() != 25375) { + if (uniffi_cktap_ffi_checksum_method_satscard_check_cert() != 6533) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_dump() != 20225) { + if (uniffi_cktap_ffi_checksum_method_satscard_dump() != 37004) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_new_slot() != 360) { + if (uniffi_cktap_ffi_checksum_method_satscard_new_slot() != 45340) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_nfc() != 5150) { + if (uniffi_cktap_ffi_checksum_method_satscard_nfc() != 40391) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_read() != 18530) { + if (uniffi_cktap_ffi_checksum_method_satscard_read() != 43229) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_sign_psbt() != 16908) { + if (uniffi_cktap_ffi_checksum_method_satscard_sign_psbt() != 883) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_status() != 2484) { + if (uniffi_cktap_ffi_checksum_method_satscard_status() != 20150) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_unseal() != 18864) { + if (uniffi_cktap_ffi_checksum_method_satscard_unseal() != 57458) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satscard_wait() != 29851) { + if (uniffi_cktap_ffi_checksum_method_satscard_wait() != 25633) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_change() != 64965) { + if (uniffi_cktap_ffi_checksum_method_satschip_change() != 49089) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_check_cert() != 22418) { + if (uniffi_cktap_ffi_checksum_method_satschip_check_cert() != 60748) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_derive() != 35847) { + if (uniffi_cktap_ffi_checksum_method_satschip_derive() != 63960) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_init() != 43462) { + if (uniffi_cktap_ffi_checksum_method_satschip_init() != 64376) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_nfc() != 32869) { + if (uniffi_cktap_ffi_checksum_method_satschip_nfc() != 6460) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_read() != 49709) { + if (uniffi_cktap_ffi_checksum_method_satschip_read() != 36900) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_sign_psbt() != 141) { + if (uniffi_cktap_ffi_checksum_method_satschip_sign_psbt() != 39519) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_status() != 7960) { + if (uniffi_cktap_ffi_checksum_method_satschip_status() != 14916) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_wait() != 13706) { + if (uniffi_cktap_ffi_checksum_method_satschip_wait() != 900) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_satschip_xpub() != 63340) { + if (uniffi_cktap_ffi_checksum_method_satschip_xpub() != 24217) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_change() != 63099) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_change() != 45) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_check_cert() != 18657) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_check_cert() != 64898) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_derive() != 36393) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_derive() != 1802) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_init() != 19476) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_init() != 56161) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_nfc() != 36157) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_nfc() != 1711) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_read() != 700) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_read() != 26591) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_sign_psbt() != 3541) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_sign_psbt() != 19540) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_status() != 53193) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_status() != 24164) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_wait() != 44324) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_wait() != 51284) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_tapsigner_xpub() != 48830) { + if (uniffi_cktap_ffi_checksum_method_tapsigner_xpub() != 22073) { return InitializationResult.apiChecksumMismatch } - if (uniffi_cktap_ffi_checksum_method_cktransport_transmit_apdu() != 56609) { + if (uniffi_cktap_ffi_checksum_method_cktransport_transmit_apdu() != 15044) { return InitializationResult.apiChecksumMismatch } diff --git a/cktap-swift/Tests/CKTapTests/CKTapTests.swift b/cktap-swift/Tests/CKTapTests/CKTapTests.swift index da80d75..378793b 100644 --- a/cktap-swift/Tests/CKTapTests/CKTapTests.swift +++ b/cktap-swift/Tests/CKTapTests/CKTapTests.swift @@ -74,4 +74,19 @@ final class CKTapTests: XCTestCase { print("SatsChip xpub: \(xpub)") } } + + func testWaitReturnsNilWhenNoDelayIsActive() async throws { + let cardEmulator = CardEmulator() + let card = try await toCktap(transport: cardEmulator) + + switch card { + case .satsCard(let satsCard): + let remainingDelay = try await satsCard.wait() + XCTAssertNil(remainingDelay) + case .tapSigner: + throw XCTSkip("stepwise wait is only exposed on SatsCard in this release") + case .satsChip: + throw XCTSkip("stepwise wait is only exposed on SatsCard in this release") + } + } }