From f0a019d1ea2c07c455f55f411d3d4285101da4d0 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 20 Nov 2024 15:50:27 -0800 Subject: [PATCH] bump the pod spec --- LibXMTP.podspec | 4 +- Package.swift | 4 +- Sources/LibXMTP/libxmtp-version.txt | 4 +- Sources/LibXMTP/xmtpv3.swift | 265 +++++++++++++++++++++++++++- 4 files changed, 263 insertions(+), 14 deletions(-) diff --git a/LibXMTP.podspec b/LibXMTP.podspec index 0a1479d..b254e1f 100644 --- a/LibXMTP.podspec +++ b/LibXMTP.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'LibXMTP' - s.version = '3.0.3' + s.version = '3.0.4' s.summary = 'XMTP shared Rust code that powers cross-platform SDKs' s.homepage = 'https://github.com/xmtp/libxmtp-swift' @@ -10,7 +10,7 @@ Pod::Spec.new do |s| s.platform = :ios, '14.0', :macos, '11.0' s.swift_version = '5.3' - s.source = { :http => "https://github.com/xmtp/libxmtp/releases/download/swift-bindings-46e3bc7/LibXMTPSwiftFFI.zip", :type => :zip } + s.source = { :http => "https://github.com/xmtp/libxmtp/releases/download/swift-bindings-9d7aa5d/LibXMTPSwiftFFI.zip", :type => :zip } s.vendored_frameworks = 'LibXMTPSwiftFFI.xcframework' s.source_files = 'Sources/LibXMTP/**/*' end diff --git a/Package.swift b/Package.swift index f7b930a..3bec6da 100644 --- a/Package.swift +++ b/Package.swift @@ -27,8 +27,8 @@ let package = Package( ), .binaryTarget( name: "LibXMTPSwiftFFI", - url: "https://github.com/xmtp/libxmtp/releases/download/swift-bindings-46e3bc7/LibXMTPSwiftFFI.zip", - checksum: "40a4f9352f0ee6af9cd194625f3a7c85b56c89e0955ee824c0cbcb81adce5242" + url: "https://github.com/xmtp/libxmtp/releases/download/swift-bindings-9d7aa5d/LibXMTPSwiftFFI.zip", + checksum: "94933db15aac507d7b750a36d86311680de2095479f340a07f83b4f6024fb1b4" ), .testTarget(name: "LibXMTPTests", dependencies: ["LibXMTP"]), ] diff --git a/Sources/LibXMTP/libxmtp-version.txt b/Sources/LibXMTP/libxmtp-version.txt index 4929643..0029a27 100644 --- a/Sources/LibXMTP/libxmtp-version.txt +++ b/Sources/LibXMTP/libxmtp-version.txt @@ -1,3 +1,3 @@ -Version: 8e8ff6a6 +Version: 960ed509 Branch: main -Date: 2024-11-19 01:30:43 +0000 +Date: 2024-11-20 23:31:05 +0000 diff --git a/Sources/LibXMTP/xmtpv3.swift b/Sources/LibXMTP/xmtpv3.swift index 051fbbf..7320e57 100644 --- a/Sources/LibXMTP/xmtpv3.swift +++ b/Sources/LibXMTP/xmtpv3.swift @@ -542,6 +542,198 @@ private struct FfiConverterData: FfiConverterRustBuffer { } } +public protocol FfiConsentCallback: AnyObject { + func onConsentUpdate(consent: [FfiConsent]) + + func onError(error: FfiSubscribeError) +} + +open class FfiConsentCallbackImpl: + FfiConsentCallback +{ + fileprivate let pointer: UnsafeMutableRawPointer! + + /// Used to instantiate a [FFIObject] without an actual pointer, for fakes in tests, mostly. + #if swift(>=5.8) + @_documentation(visibility: private) + #endif + public struct NoPointer { + public init() {} + } + + // TODO: We'd like this to be `private` but for Swifty reasons, + // we can't implement `FfiConverter` without making this `required` and we can't + // make it `required` without making it `public`. + public required init(unsafeFromRawPointer pointer: UnsafeMutableRawPointer) { + self.pointer = pointer + } + + // This constructor can be used to instantiate a fake object. + // - Parameter noPointer: Placeholder value so we can have a constructor separate from the default empty one that may be implemented for classes extending [FFIObject]. + // + // - Warning: + // Any object instantiated with this constructor cannot be passed to an actual Rust-backed object. Since there isn't a backing [Pointer] the FFI lower functions will crash. + #if swift(>=5.8) + @_documentation(visibility: private) + #endif + public init(noPointer _: NoPointer) { + pointer = nil + } + + #if swift(>=5.8) + @_documentation(visibility: private) + #endif + public func uniffiClonePointer() -> UnsafeMutableRawPointer { + return try! rustCall { uniffi_xmtpv3_fn_clone_fficonsentcallback(self.pointer, $0) } + } + + // No primary constructor declared for this class. + + deinit { + guard let pointer = pointer else { + return + } + + try! rustCall { uniffi_xmtpv3_fn_free_fficonsentcallback(pointer, $0) } + } + + open func onConsentUpdate(consent: [FfiConsent]) { try! rustCall { + uniffi_xmtpv3_fn_method_fficonsentcallback_on_consent_update(self.uniffiClonePointer(), + FfiConverterSequenceTypeFfiConsent.lower(consent), $0) + } + } + + open func onError(error: FfiSubscribeError) { try! rustCall { + uniffi_xmtpv3_fn_method_fficonsentcallback_on_error(self.uniffiClonePointer(), + FfiConverterTypeFfiSubscribeError.lower(error), $0) + } + } +} + +// Magic number for the Rust proxy to call using the same mechanism as every other method, +// to free the callback once it's dropped by Rust. +private let IDX_CALLBACK_FREE: Int32 = 0 +// Callback return codes +private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0 +private let UNIFFI_CALLBACK_ERROR: Int32 = 1 +private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2 + +// Put the implementation in a struct so we don't pollute the top-level namespace +private enum UniffiCallbackInterfaceFfiConsentCallback { + // Create the VTable using a series of closures. + // Swift automatically converts these into C callback functions. + static var vtable: UniffiVTableCallbackInterfaceFfiConsentCallback = .init( + onConsentUpdate: { ( + uniffiHandle: UInt64, + consent: RustBuffer, + _: UnsafeMutableRawPointer, + uniffiCallStatus: UnsafeMutablePointer + ) in + let makeCall = { + () throws in + guard let uniffiObj = try? FfiConverterTypeFfiConsentCallback.handleMap.get(handle: uniffiHandle) else { + throw UniffiInternalError.unexpectedStaleHandle + } + return try uniffiObj.onConsentUpdate( + consent: FfiConverterSequenceTypeFfiConsent.lift(consent) + ) + } + + let writeReturn = { () } + uniffiTraitInterfaceCall( + callStatus: uniffiCallStatus, + makeCall: makeCall, + writeReturn: writeReturn + ) + }, + onError: { ( + uniffiHandle: UInt64, + error: RustBuffer, + _: UnsafeMutableRawPointer, + uniffiCallStatus: UnsafeMutablePointer + ) in + let makeCall = { + () throws in + guard let uniffiObj = try? FfiConverterTypeFfiConsentCallback.handleMap.get(handle: uniffiHandle) else { + throw UniffiInternalError.unexpectedStaleHandle + } + return try uniffiObj.onError( + error: FfiConverterTypeFfiSubscribeError.lift(error) + ) + } + + let writeReturn = { () } + uniffiTraitInterfaceCall( + callStatus: uniffiCallStatus, + makeCall: makeCall, + writeReturn: writeReturn + ) + }, + uniffiFree: { (uniffiHandle: UInt64) in + let result = try? FfiConverterTypeFfiConsentCallback.handleMap.remove(handle: uniffiHandle) + if result == nil { + print("Uniffi callback interface FfiConsentCallback: handle missing in uniffiFree") + } + } + ) +} + +private func uniffiCallbackInitFfiConsentCallback() { + uniffi_xmtpv3_fn_init_callback_vtable_fficonsentcallback(&UniffiCallbackInterfaceFfiConsentCallback.vtable) +} + +#if swift(>=5.8) + @_documentation(visibility: private) +#endif +public struct FfiConverterTypeFfiConsentCallback: FfiConverter { + fileprivate static var handleMap = UniffiHandleMap() + + typealias FfiType = UnsafeMutableRawPointer + typealias SwiftType = FfiConsentCallback + + public static func lift(_ pointer: UnsafeMutableRawPointer) throws -> FfiConsentCallback { + return FfiConsentCallbackImpl(unsafeFromRawPointer: pointer) + } + + public static func lower(_ value: FfiConsentCallback) -> UnsafeMutableRawPointer { + guard let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: handleMap.insert(obj: value))) else { + fatalError("Cast to UnsafeMutableRawPointer failed") + } + return ptr + } + + public static func read(from buf: inout (data: Data, offset: Data.Index)) throws -> FfiConsentCallback { + let v: UInt64 = try readInt(&buf) + // The Rust code won't compile if a pointer won't fit in a UInt64. + // We have to go via `UInt` because that's the thing that's the size of a pointer. + let ptr = UnsafeMutableRawPointer(bitPattern: UInt(truncatingIfNeeded: v)) + if ptr == nil { + throw UniffiInternalError.unexpectedNullPointer + } + return try lift(ptr!) + } + + public static func write(_ value: FfiConsentCallback, into buf: inout [UInt8]) { + // This fiddling is because `Int` is the thing that's the same size as a pointer. + // The Rust code won't compile if a pointer won't fit in a `UInt64`. + writeInt(&buf, UInt64(bitPattern: Int64(Int(bitPattern: lower(value))))) + } +} + +#if swift(>=5.8) + @_documentation(visibility: private) +#endif +public func FfiConverterTypeFfiConsentCallback_lift(_ pointer: UnsafeMutableRawPointer) throws -> FfiConsentCallback { + return try FfiConverterTypeFfiConsentCallback.lift(pointer) +} + +#if swift(>=5.8) + @_documentation(visibility: private) +#endif +public func FfiConverterTypeFfiConsentCallback_lower(_ value: FfiConsentCallback) -> UnsafeMutableRawPointer { + return FfiConverterTypeFfiConsentCallback.lower(value) +} + public protocol FfiConversationProtocol: AnyObject { func addAdmin(inboxId: String) async throws @@ -1243,14 +1435,6 @@ open class FfiConversationCallbackImpl: } } -// Magic number for the Rust proxy to call using the same mechanism as every other method, -// to free the callback once it's dropped by Rust. -private let IDX_CALLBACK_FREE: Int32 = 0 -// Callback return codes -private let UNIFFI_CALLBACK_SUCCESS: Int32 = 0 -private let UNIFFI_CALLBACK_ERROR: Int32 = 1 -private let UNIFFI_CALLBACK_UNEXPECTED_ERROR: Int32 = 2 - // Put the implementation in a struct so we don't pollute the top-level namespace private enum UniffiCallbackInterfaceFfiConversationCallback { // Create the VTable using a series of closures. @@ -1487,6 +1671,8 @@ public protocol FfiConversationsProtocol: AnyObject { func createGroup(accountAddresses: [String], opts: FfiCreateGroupOptions) async throws -> FfiConversation + func getSyncGroup() throws -> FfiConversation + func list(opts: FfiListConversationsOptions) async throws -> [FfiConversation] func listDms(opts: FfiListConversationsOptions) async throws -> [FfiConversation] @@ -1503,6 +1689,8 @@ public protocol FfiConversationsProtocol: AnyObject { func streamAllMessages(messageCallback: FfiMessageCallback) async -> FfiStreamCloser + func streamConsent(callback: FfiConsentCallback) async -> FfiStreamCloser + func streamDms(callback: FfiConversationCallback) async -> FfiStreamCloser func streamGroups(callback: FfiConversationCallback) async -> FfiStreamCloser @@ -1595,6 +1783,12 @@ open class FfiConversations: ) } + open func getSyncGroup() throws -> FfiConversation { + return try FfiConverterTypeFfiConversation.lift(rustCallWithError(FfiConverterTypeGenericError.lift) { + uniffi_xmtpv3_fn_method_fficonversations_get_sync_group(self.uniffiClonePointer(), $0) + }) + } + open func list(opts: FfiListConversationsOptions) async throws -> [FfiConversation] { return try await uniffiRustCallAsync( @@ -1731,6 +1925,23 @@ open class FfiConversations: ) } + open func streamConsent(callback: FfiConsentCallback) async -> FfiStreamCloser { + return + try! await uniffiRustCallAsync( + rustFutureFunc: { + uniffi_xmtpv3_fn_method_fficonversations_stream_consent( + self.uniffiClonePointer(), + FfiConverterTypeFfiConsentCallback.lower(callback) + ) + }, + pollFunc: ffi_xmtpv3_rust_future_poll_pointer, + completeFunc: ffi_xmtpv3_rust_future_complete_pointer, + freeFunc: ffi_xmtpv3_rust_future_free_pointer, + liftFunc: FfiConverterTypeFfiStreamCloser.lift, + errorHandler: nil + ) + } + open func streamDms(callback: FfiConversationCallback) async -> FfiStreamCloser { return try! await uniffiRustCallAsync( @@ -3116,6 +3327,10 @@ public protocol FfiXmtpClientProtocol: AnyObject { func signWithInstallationKey(text: String) throws -> Data func signatureRequest() -> FfiSignatureRequest? + + func verifySignedWithInstallationKey(signatureText: String, signatureBytes: Data) throws + + func verifySignedWithPublicKey(signatureText: String, signatureBytes: Data, publicKey: Data) throws } open class FfiXmtpClient: @@ -3499,6 +3714,21 @@ open class FfiXmtpClient: uniffi_xmtpv3_fn_method_ffixmtpclient_signature_request(self.uniffiClonePointer(), $0) }) } + + open func verifySignedWithInstallationKey(signatureText: String, signatureBytes: Data) throws { try rustCallWithError(FfiConverterTypeGenericError.lift) { + uniffi_xmtpv3_fn_method_ffixmtpclient_verify_signed_with_installation_key(self.uniffiClonePointer(), + FfiConverterString.lower(signatureText), + FfiConverterData.lower(signatureBytes), $0) + } + } + + open func verifySignedWithPublicKey(signatureText: String, signatureBytes: Data, publicKey: Data) throws { try rustCallWithError(FfiConverterTypeGenericError.lift) { + uniffi_xmtpv3_fn_method_ffixmtpclient_verify_signed_with_public_key(self.uniffiClonePointer(), + FfiConverterString.lower(signatureText), + FfiConverterData.lower(signatureBytes), + FfiConverterData.lower(publicKey), $0) + } + } } #if swift(>=5.8) @@ -6967,6 +7197,12 @@ private var initializationResult: InitializationResult = { if uniffi_xmtpv3_checksum_func_verify_k256_sha256() != 25521 { return InitializationResult.apiChecksumMismatch } + if uniffi_xmtpv3_checksum_method_fficonsentcallback_on_consent_update() != 12532 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_xmtpv3_checksum_method_fficonsentcallback_on_error() != 5882 { + return InitializationResult.apiChecksumMismatch + } if uniffi_xmtpv3_checksum_method_fficonversation_add_admin() != 52417 { return InitializationResult.apiChecksumMismatch } @@ -7102,6 +7338,9 @@ private var initializationResult: InitializationResult = { if uniffi_xmtpv3_checksum_method_fficonversations_create_group() != 7282 { return InitializationResult.apiChecksumMismatch } + if uniffi_xmtpv3_checksum_method_fficonversations_get_sync_group() != 42973 { + return InitializationResult.apiChecksumMismatch + } if uniffi_xmtpv3_checksum_method_fficonversations_list() != 42790 { return InitializationResult.apiChecksumMismatch } @@ -7126,6 +7365,9 @@ private var initializationResult: InitializationResult = { if uniffi_xmtpv3_checksum_method_fficonversations_stream_all_messages() != 63519 { return InitializationResult.apiChecksumMismatch } + if uniffi_xmtpv3_checksum_method_fficonversations_stream_consent() != 12642 { + return InitializationResult.apiChecksumMismatch + } if uniffi_xmtpv3_checksum_method_fficonversations_stream_dms() != 52710 { return InitializationResult.apiChecksumMismatch } @@ -7279,6 +7521,12 @@ private var initializationResult: InitializationResult = { if uniffi_xmtpv3_checksum_method_ffixmtpclient_signature_request() != 18270 { return InitializationResult.apiChecksumMismatch } + if uniffi_xmtpv3_checksum_method_ffixmtpclient_verify_signed_with_installation_key() != 4340 { + return InitializationResult.apiChecksumMismatch + } + if uniffi_xmtpv3_checksum_method_ffixmtpclient_verify_signed_with_public_key() != 21532 { + return InitializationResult.apiChecksumMismatch + } if uniffi_xmtpv3_checksum_method_ffiinboxowner_get_address() != 2205 { return InitializationResult.apiChecksumMismatch } @@ -7289,6 +7537,7 @@ private var initializationResult: InitializationResult = { return InitializationResult.apiChecksumMismatch } + uniffiCallbackInitFfiConsentCallback() uniffiCallbackInitFfiConversationCallback() uniffiCallbackInitFfiMessageCallback() uniffiCallbackInitFfiV2SubscriptionCallback()