From 4d9d0183b02e3a280ca1060406670269b6a471ea Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 2 Oct 2024 13:19:07 -0600 Subject: [PATCH 01/28] bump the pod --- ios/XMTPReactNative.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 5d012342e..c660965ee 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.14.14" + s.dependency "XMTP", "= 0.15.0-alpha1" end From 8c6a186d0b00eeb4e7c25f74702458a7df37cf2b Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 24 Sep 2024 13:31:47 -0600 Subject: [PATCH 02/28] add chainId and isSmartContractWallet fields --- example/ios/Podfile.lock | 18 ++++++++++++------ ios/ReactNativeSigner.swift | 8 +++++++- ios/XMTPReactNative.podspec | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 72451fbe8..7adf0a2bf 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,7 +56,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (0.5.9-beta0) + - LibXMTP (0.5.8-beta5) - Logging (1.0.0) - MessagePacker (0.4.7) - MMKV (1.3.9): @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.15.0): + - XMTP (0.15.0-alpha0): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 0.5.9-beta0) + - LibXMTP (= 0.5.8-beta5) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 0.15.0) + - XMTP (= 0.15.0-alpha0) - Yoga (1.14.0) DEPENDENCIES: @@ -711,7 +711,13 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 +<<<<<<< HEAD LibXMTP: 5a38722a68a9469be2e711857a5e7d9dd3aa8a61 +||||||| parent of ef6c705a (add chainId and isSmartContractWallet fields) + LibXMTP: c7338cace222bed90f950579300725325a2c0bfd +======= + LibXMTP: ee1591fdb51bc6cc690c1a9ba10792ccc2104328 +>>>>>>> ef6c705a (add chainId and isSmartContractWallet fields) Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: 817ba1eea17421547e01e087285606eb270a8dcb @@ -763,8 +769,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 09faa347569b092005997364f7fe787ccc33f3d5 - XMTPReactNative: 6404c11e6dd11820742d4af899daeea389fc442f + XMTP: 934d57cbfa3c13450587e63490efb9426e1353b4 + XMTPReactNative: c95ed3393330dec9d6adede024f4fb3b2bd1a659 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index 018238867..dc1f6f5e7 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -14,11 +14,17 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { var module: XMTPModule var address: String + var isSmartContractWallet: Bool + var chainId: UInt64 + var blockNumber: UInt64 var continuations: [String: CheckedContinuation] = [:] - init(module: XMTPModule, address: String) { + init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64 = 1, blockNumber: UInt64 = 1) { self.module = module self.address = address + self.isSmartContractWallet = isSmartContractWallet + self.chainId = chainId + self.blockNumber = blockNumber } func handle(id: String, signature: String) throws { diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index c660965ee..773d0ed35 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.15.0-alpha1" + s.dependency "XMTP", "= 0.15.0-alpha0" end From 37b92718b488c8814b1b97d9bcf9dc423fbdd985 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 24 Sep 2024 13:52:18 -0600 Subject: [PATCH 03/28] add interface for signer --- src/lib/Signer.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lib/Signer.ts b/src/lib/Signer.ts index 3ef6a7c3f..437d435b7 100644 --- a/src/lib/Signer.ts +++ b/src/lib/Signer.ts @@ -2,6 +2,8 @@ import type { WalletClient } from 'viem' export interface Signer { getAddress: () => Promise + getChainId: () => bigint + isSmartContractWallet: () => boolean signMessage: (message: string) => Promise } @@ -37,5 +39,8 @@ export function convertWalletClientToSigner( message: typeof message === 'string' ? message : { raw: message }, account, }), + // Not supported by viem wallet client yet + getChainId: () => 1n, + isSmartContractWallet: () => false, } } From 268e461a6e71eb75b1f6d47eae0e4f6e422de691 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 24 Sep 2024 14:19:45 -0600 Subject: [PATCH 04/28] pass the fields to the signer --- ios/Wrappers/AuthParamsWrapper.swift | 21 +++++++++++++++++---- ios/XMTPModule.swift | 4 ++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index 763071ee8..2fa9d324f 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -14,19 +14,25 @@ struct AuthParamsWrapper { let enableV3: Bool let dbDirectory: String? let historySyncUrl: String? - - init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?) { + let isSmartContractWallet: Bool + let chainId: UInt64 + let blockNumber: UInt64 + + init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, isSmartContractWallet: Bool, chainId: UInt64, blockNumber: UInt64) { self.environment = environment self.appVersion = appVersion self.enableV3 = enableV3 self.dbDirectory = dbDirectory self.historySyncUrl = historySyncUrl + self.isSmartContractWallet = isSmartContractWallet + self.chainId = chainId + self.blockNumber = blockNumber } static func authParamsFromJson(_ authParams: String) -> AuthParamsWrapper { guard let data = authParams.data(using: .utf8), let jsonOptions = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { - return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil) + return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil, isSmartContractWallet: false, chainId: 1, blockNumber: 1) } let environment = jsonOptions["environment"] as? String ?? "dev" @@ -34,13 +40,20 @@ struct AuthParamsWrapper { let enableV3 = jsonOptions["enableV3"] as? Bool ?? false let dbDirectory = jsonOptions["dbDirectory"] as? String let historySyncUrl = jsonOptions["historySyncUrl"] as? String + let isSmartContractWallet = jsonOptions["isSmartContractWallet"] as? Bool ?? false + let chainId = jsonOptions["chainId"] as? UInt64 ?? 1 + let blockNumber = jsonOptions["blockNumber"] as? UInt64 ?? 1 + return AuthParamsWrapper( environment: environment, appVersion: appVersion, enableV3: enableV3, dbDirectory: dbDirectory, - historySyncUrl: historySyncUrl + historySyncUrl: historySyncUrl, + isSmartContractWallet: isSmartContractWallet, + chainId: chainId, + blockNumber: blockNumber ) } } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 08edd2df5..efa037cef 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -318,7 +318,8 @@ public class XMTPModule: Module { } AsyncFunction("createOrBuild") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in - let signer = ReactNativeSigner(module: self, address: address) + let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) + let signer = ReactNativeSigner(module: self, address: address, isSmartContractWallet: authOptions.isSmartContractWallet, chainId: authOptions.chainId, blockNumber: authOptions.blockNumber) self.signer = signer if(hasCreateIdentityCallback ?? false) { self.preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0) @@ -333,7 +334,6 @@ public class XMTPModule: Module { let preEnableIdentityCallback: PreEventCallback? = hasEnableIdentityCallback ?? false ? self.preEnableIdentityCallback : nil let preAuthenticateToInboxCallback: PreEventCallback? = hasAuthenticateToInboxCallback ?? false ? self.preAuthenticateToInboxCallback : nil let encryptionKeyData = dbEncryptionKey == nil ? nil : Data(dbEncryptionKey!) - let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) let options = self.createClientConfig( env: authOptions.environment, From 2c72d557ec1d8c352130e6f66f2471433d4d2505 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Tue, 24 Sep 2024 14:27:52 -0600 Subject: [PATCH 05/28] get the create the build --- src/index.ts | 11 ++++++++++- src/lib/Client.ts | 5 ++++- src/lib/Signer.ts | 2 ++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index b1cbfc675..bd4e80537 100644 --- a/src/index.ts +++ b/src/index.ts @@ -219,7 +219,10 @@ export async function createOrBuild( enableV3?: boolean | undefined, dbEncryptionKey?: Uint8Array | undefined, dbDirectory?: string | undefined, - historySyncUrl?: string | undefined + historySyncUrl?: string | undefined, + isSmartContractWallet?: boolean | undefined, + chainId?: bigint | undefined, + blockNumber?: bigint | undefined ) { const encryptionKey = dbEncryptionKey ? Array.from(dbEncryptionKey) @@ -231,6 +234,9 @@ export async function createOrBuild( enableV3, dbDirectory, historySyncUrl, + isSmartContractWallet, + chainId, + blockNumber, } return await XMTPModule.createOrBuild( address, @@ -1272,6 +1278,9 @@ interface AuthParams { enableV3?: boolean dbDirectory?: string historySyncUrl?: string + isSmartContractWallet?: boolean + chainId?: bigint + blockNumber?: bigint } interface CreateGroupParams { diff --git a/src/lib/Client.ts b/src/lib/Client.ts index c9b9a95df..8e2a2f68c 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -389,7 +389,10 @@ export class Client< Boolean(options.enableV3), options.dbEncryptionKey, options.dbDirectory, - options.historySyncUrl + options.historySyncUrl, + signer.isSmartContractWallet(), + signer.getChainId(), + signer.getBlockNumber() ) })().catch((error) => { this.removeAllSubscriptions( diff --git a/src/lib/Signer.ts b/src/lib/Signer.ts index 437d435b7..2766699e3 100644 --- a/src/lib/Signer.ts +++ b/src/lib/Signer.ts @@ -3,6 +3,7 @@ import type { WalletClient } from 'viem' export interface Signer { getAddress: () => Promise getChainId: () => bigint + getBlockNumber: () => bigint isSmartContractWallet: () => boolean signMessage: (message: string) => Promise } @@ -41,6 +42,7 @@ export function convertWalletClientToSigner( }), // Not supported by viem wallet client yet getChainId: () => 1n, + getBlockNumber: () => 1n, isSmartContractWallet: () => false, } } From 6bb9427b9cd8d0612a96b83d1ee90dfb08b1e1c5 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Thu, 26 Sep 2024 12:22:46 -0500 Subject: [PATCH 06/28] Update signer --- src/lib/Signer.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib/Signer.ts b/src/lib/Signer.ts index 2766699e3..ae1118f98 100644 --- a/src/lib/Signer.ts +++ b/src/lib/Signer.ts @@ -2,8 +2,8 @@ import type { WalletClient } from 'viem' export interface Signer { getAddress: () => Promise - getChainId: () => bigint - getBlockNumber: () => bigint + getChainId: () => number + getBlockNumber: () => number | undefined isSmartContractWallet: () => boolean signMessage: (message: string) => Promise } @@ -40,9 +40,8 @@ export function convertWalletClientToSigner( message: typeof message === 'string' ? message : { raw: message }, account, }), - // Not supported by viem wallet client yet - getChainId: () => 1n, - getBlockNumber: () => 1n, + getChainId: () => 0, + getBlockNumber: () => undefined, isSmartContractWallet: () => false, } } From 1fa7b37dd5de66d4b1b1295b5f1d7b52b15fb080 Mon Sep 17 00:00:00 2001 From: Ry Racherbaumer Date: Thu, 26 Sep 2024 12:23:03 -0500 Subject: [PATCH 07/28] Update swift --- ios/ReactNativeSigner.swift | 4 ++-- ios/Wrappers/AuthParamsWrapper.swift | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index dc1f6f5e7..d8964ccbe 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -16,10 +16,10 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { var address: String var isSmartContractWallet: Bool var chainId: UInt64 - var blockNumber: UInt64 + var blockNumber: UInt64? var continuations: [String: CheckedContinuation] = [:] - init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64 = 1, blockNumber: UInt64 = 1) { + init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64 = 1, blockNumber: UInt64? = nil) { self.module = module self.address = address self.isSmartContractWallet = isSmartContractWallet diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index 2fa9d324f..508cd291b 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -16,7 +16,7 @@ struct AuthParamsWrapper { let historySyncUrl: String? let isSmartContractWallet: Bool let chainId: UInt64 - let blockNumber: UInt64 + let blockNumber: UInt64? init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, isSmartContractWallet: Bool, chainId: UInt64, blockNumber: UInt64) { self.environment = environment @@ -41,8 +41,8 @@ struct AuthParamsWrapper { let dbDirectory = jsonOptions["dbDirectory"] as? String let historySyncUrl = jsonOptions["historySyncUrl"] as? String let isSmartContractWallet = jsonOptions["isSmartContractWallet"] as? Bool ?? false - let chainId = jsonOptions["chainId"] as? UInt64 ?? 1 - let blockNumber = jsonOptions["blockNumber"] as? UInt64 ?? 1 + let chainId = jsonOptions["chainId"] as? Int ?? 1 + let blockNumber = jsonOptions["blockNumber"] as? Int return AuthParamsWrapper( @@ -52,8 +52,8 @@ struct AuthParamsWrapper { dbDirectory: dbDirectory, historySyncUrl: historySyncUrl, isSmartContractWallet: isSmartContractWallet, - chainId: chainId, - blockNumber: blockNumber + chainId: UInt64(chainId), + blockNumber: blockNumber != nil ? UInt64(blockNumber!) : nil ) } } From a10db5293d407e9a07dbaabec294a0a1c98e3fce Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 2 Oct 2024 16:08:55 -0600 Subject: [PATCH 08/28] cherry pick all the commits from the other PR --- src/index.ts | 8 ++++---- src/lib/Client.ts | 26 +++++++++++++++----------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index bd4e80537..25edd337e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -221,8 +221,8 @@ export async function createOrBuild( dbDirectory?: string | undefined, historySyncUrl?: string | undefined, isSmartContractWallet?: boolean | undefined, - chainId?: bigint | undefined, - blockNumber?: bigint | undefined + chainId?: number | undefined, + blockNumber?: number | undefined ) { const encryptionKey = dbEncryptionKey ? Array.from(dbEncryptionKey) @@ -1279,8 +1279,8 @@ interface AuthParams { dbDirectory?: string historySyncUrl?: string isSmartContractWallet?: boolean - chainId?: bigint - blockNumber?: bigint + chainId?: number + blockNumber?: number } interface CreateGroupParams { diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 8e2a2f68c..58822d572 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -331,17 +331,21 @@ export class Client< const request: { id: string; message: string } = message try { const signatureString = await signer.signMessage(request.message) - const eSig = splitSignature(signatureString) - const r = hexToBytes(eSig.r) - const s = hexToBytes(eSig.s) - const sigBytes = new Uint8Array(65) - sigBytes.set(r) - sigBytes.set(s, r.length) - sigBytes[64] = eSig.recoveryParam - - const signature = Buffer.from(sigBytes).toString('base64') - - await XMTPModule.receiveSignature(request.id, signature) + if (signer.isSmartContractWallet()) { + + } else { + const eSig = splitSignature(signatureString) + const r = hexToBytes(eSig.r) + const s = hexToBytes(eSig.s) + const sigBytes = new Uint8Array(65) + sigBytes.set(r) + sigBytes.set(s, r.length) + sigBytes[64] = eSig.recoveryParam + + const signature = Buffer.from(sigBytes).toString('base64') + + await XMTPModule.receiveSignature(request.id, signature) + } } catch (e) { const errorMessage = 'ERROR in create. User rejected signature' console.info(errorMessage, e) From f47bcc785a46ea757619737be41e7daa36dd15c8 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 2 Oct 2024 16:18:19 -0600 Subject: [PATCH 09/28] make this cleaner --- example/ios/Podfile.lock | 6 ------ ios/ReactNativeSigner.swift | 12 ++++++++++++ ios/XMTPModule.swift | 4 ++++ ios/XMTPReactNative.podspec | 2 +- src/index.ts | 4 ++++ src/lib/Client.ts | 5 ++++- 6 files changed, 25 insertions(+), 8 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 7adf0a2bf..b938e3a36 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -711,13 +711,7 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 -<<<<<<< HEAD - LibXMTP: 5a38722a68a9469be2e711857a5e7d9dd3aa8a61 -||||||| parent of ef6c705a (add chainId and isSmartContractWallet fields) - LibXMTP: c7338cace222bed90f950579300725325a2c0bfd -======= LibXMTP: ee1591fdb51bc6cc690c1a9ba10792ccc2104328 ->>>>>>> ef6c705a (add chainId and isSmartContractWallet fields) Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: 817ba1eea17421547e01e087285606eb270a8dcb diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index d8964ccbe..476f24ff1 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -46,6 +46,18 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { continuation.resume(returning: signature) continuations.removeValue(forKey: id) } + + func handleSCW(id: String, signature: String) throws { + guard let continuation = continuations[id] else { + return + } + + let signature = XMTP.Signature.with { + $0.ecdsaCompact.bytes = signature.hexToData + } + continuation.resume(returning: signature) + continuations.removeValue(forKey: id) + } func sign(_ data: Data) async throws -> XMTP.Signature { let request = SignatureRequest(message: String(data: data, encoding: .utf8)!) diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index efa037cef..cf5eceb90 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -223,6 +223,10 @@ public class XMTPModule: Module { Function("receiveSignature") { (requestID: String, signature: String) in try signer?.handle(id: requestID, signature: signature) } + + Function("receiveSCWSignature") { (requestID: String, signature: String) in + try signer?.handleSCW(id: requestID, signature: signature) + } // Generate a random wallet and set the client to that AsyncFunction("createRandom") { (hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) -> [String: String] in diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 773d0ed35..a1a7dd265 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.15.0-alpha0" + s.dependency "XMTP", "= 0.15.0-alpha3" end diff --git a/src/index.ts b/src/index.ts index 25edd337e..1844126e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -120,6 +120,10 @@ export async function receiveSignature(requestID: string, signature: string) { return await XMTPModule.receiveSignature(requestID, signature) } +export async function receiveSCWSignature(requestID: string, signature: string) { + return await XMTPModule.receiveSCWSignature(requestID, signature) +} + export async function createRandom( environment: 'local' | 'dev' | 'production', appVersion?: string | undefined, diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 58822d572..a3d0bf5d5 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -332,7 +332,10 @@ export class Client< try { const signatureString = await signer.signMessage(request.message) if (signer.isSmartContractWallet()) { - + await XMTPModule.receiveSCWSignature( + request.id, + Buffer.from(signatureString).toString('base64') + ) } else { const eSig = splitSignature(signatureString) const r = hexToBytes(eSig.r) From 3dd9161ba3887c2c08b26cb0abd30d7cbc793885 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 2 Oct 2024 16:25:17 -0600 Subject: [PATCH 10/28] get on the latest version of the backend --- example/ios/Podfile.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b938e3a36..b8d79dd09 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,7 +56,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (0.5.8-beta5) + - LibXMTP (0.5.9-alpha2) - Logging (1.0.0) - MessagePacker (0.4.7) - MMKV (1.3.9): @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.15.0-alpha0): + - XMTP (0.15.0-alpha3): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 0.5.8-beta5) + - LibXMTP (= 0.5.9-alpha2) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 0.15.0-alpha0) + - XMTP (= 0.15.0-alpha3) - Yoga (1.14.0) DEPENDENCIES: @@ -711,7 +711,7 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: ee1591fdb51bc6cc690c1a9ba10792ccc2104328 + LibXMTP: a09c696172bb5b1082068720ef1bc230cff3c014 Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: 817ba1eea17421547e01e087285606eb270a8dcb @@ -763,8 +763,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 934d57cbfa3c13450587e63490efb9426e1353b4 - XMTPReactNative: c95ed3393330dec9d6adede024f4fb3b2bd1a659 + XMTP: b28c37f4394bf346bb3d16aa497152f2c348a340 + XMTPReactNative: 01ef6888fb00abc9c3db635045b914872ccf7231 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd From 5100167969fee02c1a20b93863c1438147552e32 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 3 Oct 2024 12:22:18 -0600 Subject: [PATCH 11/28] Android side --- android/build.gradle | 24 ++++++------- .../modules/xmtpreactnativesdk/XMTPModule.kt | 36 +++++++++++++++++-- .../wrappers/AuthParamsWrapper.kt | 13 +++++-- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index d91a38c8c..9ff82888a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -98,19 +98,19 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.15.12" +// implementation "org.xmtp:android:0.15.12" implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1" - // xmtp-android local testing setup below (comment org.xmtp:android above) - // implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') - // implementation 'com.google.crypto.tink:tink-android:1.8.0' - // implementation 'io.grpc:grpc-kotlin-stub:1.4.1' - // implementation 'io.grpc:grpc-okhttp:1.62.2' - // implementation 'io.grpc:grpc-protobuf-lite:1.62.2' - // implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' - // implementation 'org.web3j:crypto:5.0.0' - // implementation "net.java.dev.jna:jna:5.14.0@aar" - // api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' - // api 'org.xmtp:proto-kotlin:3.62.1' +// xmtp-android local testing setup below (comment org.xmtp:android above) + implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') + implementation 'com.google.crypto.tink:tink-android:1.8.0' + implementation 'io.grpc:grpc-kotlin-stub:1.4.1' + implementation 'io.grpc:grpc-okhttp:1.62.2' + implementation 'io.grpc:grpc-protobuf-lite:1.62.2' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' + implementation 'org.web3j:crypto:5.0.0' + implementation "net.java.dev.jna:jna:5.14.0@aar" + api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' + api 'org.xmtp:proto-kotlin:3.62.1' } diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index bffa998a1..5767729fc 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -36,6 +36,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext import org.json.JSONObject +import org.web3j.utils.Numeric import org.xmtp.android.library.Client import org.xmtp.android.library.ClientOptions import org.xmtp.android.library.ConsentState @@ -78,7 +79,14 @@ import kotlin.coroutines.Continuation import kotlin.coroutines.resume import kotlin.coroutines.resumeWithException -class ReactNativeSigner(var module: XMTPModule, override var address: String) : SigningKey { + +class ReactNativeSigner( + var module: XMTPModule, + override var address: String, + override var isSmartContractWallet: Boolean = false, + override var chainId: Long = 1, + override var blockNumber: Long = 1, +) : SigningKey { private val continuations: MutableMap> = mutableMapOf() fun handle(id: String, signature: String) { @@ -99,6 +107,18 @@ class ReactNativeSigner(var module: XMTPModule, override var address: String) : continuations.remove(id) } + fun handleSCW(id: String, signature: String) { + val continuation = continuations[id] ?: return + + val sig = Signature.newBuilder().also { + it.ecdsaCompact = it.ecdsaCompact.toBuilder().also { builder -> + builder.bytes = Numeric.hexStringToByteArray(signature).toByteString() + }.build() + }.build() + continuation.resume(sig) + continuations.remove(id) + } + override suspend fun sign(data: ByteArray): Signature { val request = SignatureRequest(message = String(data, Charsets.UTF_8)) module.sendEvent("sign", mapOf("id" to request.id, "message" to request.message)) @@ -328,6 +348,11 @@ class XMTPModule : Module() { signer?.handle(id = requestID, signature = signature) } + Function("receiveSCWSignature") { requestID: String, signature: String -> + logV("receiveSCWSignature") + signer?.handleSCW(id = requestID, signature = signature) + } + // Generate a random wallet and set the client to that AsyncFunction("createRandom") Coroutine { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasPreAuthenticateToInboxCallback: Boolean?, dbEncryptionKey: List?, authParams: String -> withContext(Dispatchers.IO) { @@ -376,7 +401,14 @@ class XMTPModule : Module() { AsyncFunction("createOrBuild") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List?, authParams: String -> withContext(Dispatchers.IO) { logV("createOrBuild") - val reactSigner = ReactNativeSigner(module = this@XMTPModule, address = address) + val authOptions = AuthParamsWrapper.authParamsFromJson(authParams) + val reactSigner = ReactNativeSigner( + module = this@XMTPModule, + address = address, + isSmartContractWallet = authOptions.isSmartContractWallet, + chainId = authOptions.chainId, + blockNumber = authOptions.blockNumber ?: 1 + ) signer = reactSigner val options = clientOptions( dbEncryptionKey, diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt index 99146a715..998b44102 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt @@ -8,7 +8,10 @@ class AuthParamsWrapper( val enableV3: Boolean = false, val dbDirectory: String?, val historySyncUrl: String?, -) { + val isSmartContractWallet: Boolean = false, + val chainId: Long = 1, + val blockNumber: Long?, + ) { companion object { fun authParamsFromJson(authParams: String): AuthParamsWrapper { val jsonOptions = JsonParser.parseString(authParams).asJsonObject @@ -17,8 +20,12 @@ class AuthParamsWrapper( if (jsonOptions.has("appVersion")) jsonOptions.get("appVersion").asString else null, if (jsonOptions.has("enableV3")) jsonOptions.get("enableV3").asBoolean else false, if (jsonOptions.has("dbDirectory")) jsonOptions.get("dbDirectory").asString else null, - if (jsonOptions.has("historySyncUrl")) jsonOptions.get("historySyncUrl").asString else null - ) + if (jsonOptions.has("historySyncUrl")) jsonOptions.get("historySyncUrl").asString else null, + if (jsonOptions.has("isSmartContractWallet")) jsonOptions.get("isSmartContractWallet").asBoolean else false, + if (jsonOptions.has("chainId")) jsonOptions.get("chainId").asLong else 1, + if (jsonOptions.has("blockNumber")) jsonOptions.get("blockNumber").asLong else null, + + ) } } } From 9249818c7c26fb42c637ad659db0bd5f7fed7902 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 3 Oct 2024 17:32:34 -0600 Subject: [PATCH 12/28] allow block number to be null --- android/build.gradle | 6 +++--- .../main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 9ff82888a..5dad8a29c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -102,10 +102,10 @@ dependencies { implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1" -// xmtp-android local testing setup below (comment org.xmtp:android above) - implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') + // xmtp-android local testing setup below (comment org.xmtp:android above) + implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') implementation 'com.google.crypto.tink:tink-android:1.8.0' - implementation 'io.grpc:grpc-kotlin-stub:1.4.1' + implementation 'io.grpc:grpc-kotlin-stub:1.4.1' implementation 'io.grpc:grpc-okhttp:1.62.2' implementation 'io.grpc:grpc-protobuf-lite:1.62.2' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 5767729fc..38b4132bc 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -85,7 +85,7 @@ class ReactNativeSigner( override var address: String, override var isSmartContractWallet: Boolean = false, override var chainId: Long = 1, - override var blockNumber: Long = 1, + override var blockNumber: Long? = null, ) : SigningKey { private val continuations: MutableMap> = mutableMapOf() @@ -407,7 +407,7 @@ class XMTPModule : Module() { address = address, isSmartContractWallet = authOptions.isSmartContractWallet, chainId = authOptions.chainId, - blockNumber = authOptions.blockNumber ?: 1 + blockNumber = authOptions.blockNumber ) signer = reactSigner val options = clientOptions( From e00a62e605fd6702f2043b2f06d9e055273244e5 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Fri, 11 Oct 2024 08:06:19 -0700 Subject: [PATCH 13/28] latest libxmtp --- ios/XMTPReactNative.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index a1a7dd265..3bf6f14c3 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.15.0-alpha3" + s.dependency "XMTP", "= 0.15.1-alpha1" end From c1ebdf2950bde45bba6c84b1e71ed7bd08cb322f Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Sun, 20 Oct 2024 10:59:10 -0700 Subject: [PATCH 14/28] update android and the methods --- android/build.gradle | 2 +- .../modules/xmtpreactnativesdk/XMTPModule.kt | 45 ++++++++++++----- .../wrappers/AuthParamsWrapper.kt | 4 +- example/ios/Podfile.lock | 14 +++--- ios/XMTPReactNative.podspec | 2 +- src/index.ts | 33 +++++++++++- src/lib/Client.ts | 50 +++++++++++++++++-- src/lib/Signer.ts | 4 +- 8 files changed, 123 insertions(+), 31 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 5dad8a29c..3973d278b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -103,7 +103,7 @@ dependencies { implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1" // xmtp-android local testing setup below (comment org.xmtp:android above) - implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') + implementation files('/Users/naomiplasterer/xmtp/xmtp-android/library/build/outputs/aar/library-debug.aar') implementation 'com.google.crypto.tink:tink-android:1.8.0' implementation 'io.grpc:grpc-kotlin-stub:1.4.1' implementation 'io.grpc:grpc-okhttp:1.62.2' diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 38b4132bc..620cebe60 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -54,6 +54,7 @@ import org.xmtp.android.library.codecs.EncodedContent import org.xmtp.android.library.codecs.EncryptedEncodedContent import org.xmtp.android.library.codecs.RemoteAttachment import org.xmtp.android.library.codecs.decoded +import org.xmtp.android.library.hexToByteArray import org.xmtp.android.library.messages.EnvelopeBuilder import org.xmtp.android.library.messages.InvitationV1ContextBuilder import org.xmtp.android.library.messages.MessageDeliveryStatus @@ -84,10 +85,11 @@ class ReactNativeSigner( var module: XMTPModule, override var address: String, override var isSmartContractWallet: Boolean = false, - override var chainId: Long = 1, + override var chainId: Long? = null, override var blockNumber: Long? = null, ) : SigningKey { private val continuations: MutableMap> = mutableMapOf() + private val scwContinuations: MutableMap> = mutableMapOf() fun handle(id: String, signature: String) { val continuation = continuations[id] ?: return @@ -108,15 +110,17 @@ class ReactNativeSigner( } fun handleSCW(id: String, signature: String) { - val continuation = continuations[id] ?: return + val continuation = scwContinuations[id] ?: return + continuation.resume(signature.hexToByteArray()) + scwContinuations.remove(id) + } - val sig = Signature.newBuilder().also { - it.ecdsaCompact = it.ecdsaCompact.toBuilder().also { builder -> - builder.bytes = Numeric.hexStringToByteArray(signature).toByteString() - }.build() - }.build() - continuation.resume(sig) - continuations.remove(id) + override suspend fun signSCW(message: String): ByteArray { + val request = SignatureRequest(message = message) + module.sendEvent("sign", mapOf("id" to request.id, "message" to request.message)) + return suspendCancellableCoroutine { continuation -> + scwContinuations[request.id] = continuation + } } override suspend fun sign(data: ByteArray): Signature { @@ -398,9 +402,9 @@ class XMTPModule : Module() { } } - AsyncFunction("createOrBuild") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List?, authParams: String -> + AsyncFunction("createV3") Coroutine { address: String, hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasAuthInboxCallback: Boolean?, dbEncryptionKey: List?, authParams: String -> withContext(Dispatchers.IO) { - logV("createOrBuild") + logV("createV3") val authOptions = AuthParamsWrapper.authParamsFromJson(authParams) val reactSigner = ReactNativeSigner( module = this@XMTPModule, @@ -417,7 +421,7 @@ class XMTPModule : Module() { hasEnableIdentityCallback, hasAuthInboxCallback, ) - val client = Client().createOrBuild(account = reactSigner, options = options) + val client = Client().createV3(account = reactSigner, options = options) clients[client.inboxId] = client ContentJson.Companion signer = null @@ -425,6 +429,21 @@ class XMTPModule : Module() { } } + AsyncFunction("buildV3") Coroutine { address: String, dbEncryptionKey: List?, authParams: String -> + withContext(Dispatchers.IO) { + logV("buildV3") + val authOptions = AuthParamsWrapper.authParamsFromJson(authParams) + val options = clientOptions( + dbEncryptionKey, + authParams, + ) + val client = Client().buildV3(address = address, chainId = authOptions.chainId, options = options) + ContentJson.Companion + clients[client.inboxId] = client + ClientWrapper.encodeToObj(client) + } + } + AsyncFunction("createRandomV3") Coroutine { hasCreateIdentityCallback: Boolean?, hasEnableIdentityCallback: Boolean?, hasPreAuthenticateToInboxCallback: Boolean?, dbEncryptionKey: List?, authParams: String -> withContext(Dispatchers.IO) { logV("createRandomV3") @@ -436,7 +455,7 @@ class XMTPModule : Module() { hasEnableIdentityCallback, hasPreAuthenticateToInboxCallback, ) - val randomClient = Client().createOrBuild(account = privateKey, options = options) + val randomClient = Client().createV3(account = privateKey, options = options) ContentJson.Companion clients[randomClient.inboxId] = randomClient diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt index 998b44102..6fffcf345 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt @@ -9,7 +9,7 @@ class AuthParamsWrapper( val dbDirectory: String?, val historySyncUrl: String?, val isSmartContractWallet: Boolean = false, - val chainId: Long = 1, + val chainId: Long?, val blockNumber: Long?, ) { companion object { @@ -22,7 +22,7 @@ class AuthParamsWrapper( if (jsonOptions.has("dbDirectory")) jsonOptions.get("dbDirectory").asString else null, if (jsonOptions.has("historySyncUrl")) jsonOptions.get("historySyncUrl").asString else null, if (jsonOptions.has("isSmartContractWallet")) jsonOptions.get("isSmartContractWallet").asBoolean else false, - if (jsonOptions.has("chainId")) jsonOptions.get("chainId").asLong else 1, + if (jsonOptions.has("chainId")) jsonOptions.get("chainId").asLong else null, if (jsonOptions.has("blockNumber")) jsonOptions.get("blockNumber").asLong else null, ) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index b8d79dd09..d7fcd2753 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,7 +56,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (0.5.9-alpha2) + - LibXMTP (0.5.9-beta4) - Logging (1.0.0) - MessagePacker (0.4.7) - MMKV (1.3.9): @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.15.0-alpha3): + - XMTP (0.15.2-alpha0): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 0.5.9-alpha2) + - LibXMTP (= 0.5.9-beta4) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 0.15.0-alpha3) + - XMTP (= 0.15.2-alpha0) - Yoga (1.14.0) DEPENDENCIES: @@ -711,7 +711,7 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: a09c696172bb5b1082068720ef1bc230cff3c014 + LibXMTP: f74da41ab513ff52c5529dc21531509440a7c3b5 Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: 817ba1eea17421547e01e087285606eb270a8dcb @@ -763,8 +763,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: b28c37f4394bf346bb3d16aa497152f2c348a340 - XMTPReactNative: 01ef6888fb00abc9c3db635045b914872ccf7231 + XMTP: 6c2eeb87f247ed652c10e68bea4ef6a3c35d4657 + XMTPReactNative: df42709a1f7ecb8dbe65a00d18d295a82df80bba Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 3bf6f14c3..5611ce7b7 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.15.1-alpha1" + s.dependency "XMTP", "= 0.15.2-alpha0" end diff --git a/src/index.ts b/src/index.ts index 1844126e3..6d85a2416 100644 --- a/src/index.ts +++ b/src/index.ts @@ -213,7 +213,7 @@ export async function createRandomV3( ) } -export async function createOrBuild( +export async function createV3( address: string, environment: 'local' | 'dev' | 'production', appVersion?: string | undefined, @@ -242,7 +242,7 @@ export async function createOrBuild( chainId, blockNumber, } - return await XMTPModule.createOrBuild( + return await XMTPModule.createV3( address, hasCreateIdentityCallback, hasEnableIdentityCallback, @@ -252,6 +252,35 @@ export async function createOrBuild( ) } +export async function buildV3( + address: string, + chainId?: number | undefined, + environment: 'local' | 'dev' | 'production', + appVersion?: string | undefined, + enableV3?: boolean | undefined, + dbEncryptionKey?: Uint8Array | undefined, + dbDirectory?: string | undefined, + historySyncUrl?: string | undefined +) { + const encryptionKey = dbEncryptionKey + ? Array.from(dbEncryptionKey) + : undefined + + const authParams: AuthParams = { + environment, + appVersion, + enableV3, + dbDirectory, + historySyncUrl, + chainId, + } + return await XMTPModule.buildV3( + address, + encryptionKey, + JSON.stringify(authParams) + ) +} + export async function dropClient(inboxId: string) { return await XMTPModule.dropClient(inboxId) } diff --git a/src/lib/Client.ts b/src/lib/Client.ts index a3d0bf5d5..ca4dd7c33 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -304,7 +304,7 @@ export class Client< * * See {@link https://xmtp.org/docs/build/authentication#create-a-client | XMTP Docs} for more information. */ - static async createOrBuild< + static async createV3< ContentCodecs extends DefaultContentTypes = DefaultContentTypes, >( wallet: Signer | WalletClient | null, @@ -334,7 +334,7 @@ export class Client< if (signer.isSmartContractWallet()) { await XMTPModule.receiveSCWSignature( request.id, - Buffer.from(signatureString).toString('base64') + Buffer.from(signatureString) ) } else { const eSig = splitSignature(signatureString) @@ -386,7 +386,7 @@ export class Client< ) } ) - await XMTPModule.createOrBuild( + await XMTPModule.createV3( await signer.getAddress(), options.env, options.appVersion, @@ -412,6 +412,50 @@ export class Client< }) } + /** + * Builds a V3 ONLY instance of the Client class using the provided address and chainId if SCW. + * + * @param {string} address - The address of the account to build + * @param {Optional} chainId - The chainId of the smart contract wallet. Otherwise should be left undefined. + * @param {Partial} opts - Configuration options for the Client. Must include an encryption key. + * @returns {Promise} A Promise that resolves to a new V3 ONLY Client instance. + * + * See {@link https://xmtp.org/docs/build/authentication#create-a-client | XMTP Docs} for more information. + */ + static async buildV3< + ContentCodecs extends DefaultContentTypes = DefaultContentTypes, + >( + address: string, + chainId: number | undefined, + options: ClientOptions & { codecs?: ContentCodecs } + ): Promise> { + options.enableV3 = true + if ( + options.dbEncryptionKey === undefined || + options.dbEncryptionKey.length !== 32 + ) { + throw new Error('Must pass an encryption key that is exactly 32 bytes.') + } + const client = await XMTPModule.buildV3( + address, + chainId, + options.env, + options.appVersion, + Boolean(options.enableV3), + options.dbEncryptionKey, + options.dbDirectory, + options.historySyncUrl + ) + + return new Client( + client['address'], + client['inboxId'], + client['installationId'], + client['dbPath'], + options.codecs || [] + ) + } + /** * Drop the client from memory. Use when you want to remove the client from memory and are done with it. */ diff --git a/src/lib/Signer.ts b/src/lib/Signer.ts index ae1118f98..d6fe752a5 100644 --- a/src/lib/Signer.ts +++ b/src/lib/Signer.ts @@ -2,7 +2,7 @@ import type { WalletClient } from 'viem' export interface Signer { getAddress: () => Promise - getChainId: () => number + getChainId: () => number | undefined getBlockNumber: () => number | undefined isSmartContractWallet: () => boolean signMessage: (message: string) => Promise @@ -40,7 +40,7 @@ export function convertWalletClientToSigner( message: typeof message === 'string' ? message : { raw: message }, account, }), - getChainId: () => 0, + getChainId: () => undefined, getBlockNumber: () => undefined, isSmartContractWallet: () => false, } From f8a820c7ccccc81af1579dd3c956e0187a2cdbd3 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Sun, 20 Oct 2024 11:06:19 -0700 Subject: [PATCH 15/28] try and get the iOS side matching --- ios/ReactNativeSigner.swift | 25 ++++++++++++++++++------- ios/Wrappers/AuthParamsWrapper.swift | 10 +++++----- ios/XMTPModule.swift | 26 +++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index 476f24ff1..753279b0b 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -15,11 +15,12 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { var module: XMTPModule var address: String var isSmartContractWallet: Bool - var chainId: UInt64 + var chainId: UInt64? var blockNumber: UInt64? var continuations: [String: CheckedContinuation] = [:] + var scwContinuations: [String: CheckedContinuation] = [:] - init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64 = 1, blockNumber: UInt64? = nil) { + init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64? = nil, blockNumber: UInt64? = nil) { self.module = module self.address = address self.isSmartContractWallet = isSmartContractWallet @@ -48,15 +49,25 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { } func handleSCW(id: String, signature: String) throws { - guard let continuation = continuations[id] else { + guard let continuation = scwContinuations[id] else { return } - let signature = XMTP.Signature.with { - $0.ecdsaCompact.bytes = signature.hexToData + continuation.resume(returning: signature.hexToData) + scwContinuations.removeValue(forKey: id) + } + + func signSCW(message: String) async throws -> Data { + let request = SignatureRequest(message: message) + + module.sendEvent("sign", [ + "id": request.id, + "message": request.message, + ]) + + return try await withCheckedThrowingContinuation { continuation in + scwContinuations[request.id] = continuation } - continuation.resume(returning: signature) - continuations.removeValue(forKey: id) } func sign(_ data: Data) async throws -> XMTP.Signature { diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index 508cd291b..0c4fbe471 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -15,10 +15,10 @@ struct AuthParamsWrapper { let dbDirectory: String? let historySyncUrl: String? let isSmartContractWallet: Bool - let chainId: UInt64 + let chainId: UInt64? let blockNumber: UInt64? - init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, isSmartContractWallet: Bool, chainId: UInt64, blockNumber: UInt64) { + init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, isSmartContractWallet: Bool, chainId: UInt64?, blockNumber: UInt64?) { self.environment = environment self.appVersion = appVersion self.enableV3 = enableV3 @@ -32,7 +32,7 @@ struct AuthParamsWrapper { static func authParamsFromJson(_ authParams: String) -> AuthParamsWrapper { guard let data = authParams.data(using: .utf8), let jsonOptions = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { - return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil, isSmartContractWallet: false, chainId: 1, blockNumber: 1) + return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil, isSmartContractWallet: false, chainId: nil, blockNumber: nil) } let environment = jsonOptions["environment"] as? String ?? "dev" @@ -41,7 +41,7 @@ struct AuthParamsWrapper { let dbDirectory = jsonOptions["dbDirectory"] as? String let historySyncUrl = jsonOptions["historySyncUrl"] as? String let isSmartContractWallet = jsonOptions["isSmartContractWallet"] as? Bool ?? false - let chainId = jsonOptions["chainId"] as? Int ?? 1 + let chainId = jsonOptions["chainId"] as? Int let blockNumber = jsonOptions["blockNumber"] as? Int @@ -52,7 +52,7 @@ struct AuthParamsWrapper { dbDirectory: dbDirectory, historySyncUrl: historySyncUrl, isSmartContractWallet: isSmartContractWallet, - chainId: UInt64(chainId), + chainId: blockNumber != nil ? UInt64(chainId!) : nil, blockNumber: blockNumber != nil ? UInt64(blockNumber!) : nil ) } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index cf5eceb90..de9288496 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -315,13 +315,13 @@ public class XMTPModule: Module { dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl ) - let client = try await Client.createOrBuild(account: privateKey, options: options) + let client = try await Client.createV3(account: privateKey, options: options) await clientsManager.updateClient(key: client.inboxID, client: client) return try ClientWrapper.encodeToObj(client) } - AsyncFunction("createOrBuild") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in + AsyncFunction("createV3") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) let signer = ReactNativeSigner(module: self, address: address, isSmartContractWallet: authOptions.isSmartContractWallet, chainId: authOptions.chainId, blockNumber: authOptions.blockNumber) self.signer = signer @@ -350,11 +350,31 @@ public class XMTPModule: Module { dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl ) - let client = try await XMTP.Client.createOrBuild(account: signer, options: options) + let client = try await XMTP.Client.createV3(account: signer, options: options) await self.clientsManager.updateClient(key: client.inboxID, client: client) self.signer = nil self.sendEvent("authedV3", try ClientWrapper.encodeToObj(client)) } + + AsyncFunction("buildV3") { (address: String, dbEncryptionKey: [UInt8]?, authParams: String) -> [String: String] in + let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) + let encryptionKeyData = dbEncryptionKey == nil ? nil : Data(dbEncryptionKey!) + + let options = self.createClientConfig( + env: authOptions.environment, + appVersion: authOptions.appVersion, + preEnableIdentityCallback: preEnableIdentityCallback, + preCreateIdentityCallback: preCreateIdentityCallback, + preAuthenticateToInboxCallback: preAuthenticateToInboxCallback, + enableV3: authOptions.enableV3, + dbEncryptionKey: encryptionKeyData, + dbDirectory: authOptions.dbDirectory, + historySyncUrl: authOptions.historySyncUrl + ) + let client = try await XMTP.Client.buildV3(address: address, chainId: authOptions.chainId, options: options) + await clientsManager.updateClient(key: client.inboxID, client: client) + return try ClientWrapper.encodeToObj(client) + } // Remove a client from memory for a given inboxId AsyncFunction("dropClient") { (inboxId: String) in From 3d8063db46abb7665e8317b68bfdd6a3e330dcd7 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Sun, 20 Oct 2024 11:08:07 -0700 Subject: [PATCH 16/28] point to the potential future gradle --- android/build.gradle | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 3973d278b..87789ba68 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -98,19 +98,19 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" -// implementation "org.xmtp:android:0.15.12" + implementation "org.xmtp:android:0.16.0" implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1" // xmtp-android local testing setup below (comment org.xmtp:android above) - implementation files('/Users/naomiplasterer/xmtp/xmtp-android/library/build/outputs/aar/library-debug.aar') - implementation 'com.google.crypto.tink:tink-android:1.8.0' - implementation 'io.grpc:grpc-kotlin-stub:1.4.1' - implementation 'io.grpc:grpc-okhttp:1.62.2' - implementation 'io.grpc:grpc-protobuf-lite:1.62.2' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' - implementation 'org.web3j:crypto:5.0.0' - implementation "net.java.dev.jna:jna:5.14.0@aar" - api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' - api 'org.xmtp:proto-kotlin:3.62.1' +// implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') +// implementation 'com.google.crypto.tink:tink-android:1.8.0' +// implementation 'io.grpc:grpc-kotlin-stub:1.4.1' +// implementation 'io.grpc:grpc-okhttp:1.62.2' +// implementation 'io.grpc:grpc-protobuf-lite:1.62.2' +// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' +// implementation 'org.web3j:crypto:5.0.0' +// implementation "net.java.dev.jna:jna:5.14.0@aar" +// api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' +// api 'org.xmtp:proto-kotlin:3.62.1' } From ed81adf578ca6de51d146ab09db5ed2e317097aa Mon Sep 17 00:00:00 2001 From: Peter Ferguson Date: Mon, 21 Oct 2024 08:51:54 +0100 Subject: [PATCH 17/28] fix: optional field follows non-optional --- src/index.ts | 2 +- src/lib/Client.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9715410b1..167f85230 100644 --- a/src/index.ts +++ b/src/index.ts @@ -255,8 +255,8 @@ export async function createV3( export async function buildV3( address: string, - chainId?: number | undefined, environment: 'local' | 'dev' | 'production', + chainId?: number | undefined, appVersion?: string | undefined, enableV3?: boolean | undefined, dbEncryptionKey?: Uint8Array | undefined, diff --git a/src/lib/Client.ts b/src/lib/Client.ts index ca4dd7c33..82d92b096 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -438,8 +438,8 @@ export class Client< } const client = await XMTPModule.buildV3( address, - chainId, options.env, + chainId, options.appVersion, Boolean(options.enableV3), options.dbEncryptionKey, From 70461f476b724fe7bca544817ca0b8eb3b3e3a5e Mon Sep 17 00:00:00 2001 From: Peter Ferguson Date: Mon, 21 Oct 2024 10:36:49 +0100 Subject: [PATCH 18/28] fix chainId ternary --- ios/Wrappers/AuthParamsWrapper.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index 0c4fbe471..8ea33ea77 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -52,7 +52,7 @@ struct AuthParamsWrapper { dbDirectory: dbDirectory, historySyncUrl: historySyncUrl, isSmartContractWallet: isSmartContractWallet, - chainId: blockNumber != nil ? UInt64(chainId!) : nil, + chainId: chainId != nil ? UInt64(chainId!) : nil, blockNumber: blockNumber != nil ? UInt64(blockNumber!) : nil ) } From 1febd296e2ba9ed95a877cd9e6d4a9c716c7e961 Mon Sep 17 00:00:00 2001 From: Peter Ferguson Date: Mon, 21 Oct 2024 11:09:24 +0100 Subject: [PATCH 19/28] sig should be a string --- src/lib/Client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 82d92b096..f009d346d 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -334,7 +334,7 @@ export class Client< if (signer.isSmartContractWallet()) { await XMTPModule.receiveSCWSignature( request.id, - Buffer.from(signatureString) + signatureString ) } else { const eSig = splitSignature(signatureString) From 4fc885c971a67c2a80888b9fcf598466112b6efb Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 19:08:32 -0700 Subject: [PATCH 20/28] change to wallet type and import latest libxmtp --- .../expo/modules/xmtpreactnativesdk/XMTPModule.kt | 9 ++++----- .../wrappers/AuthParamsWrapper.kt | 15 +++++++++++---- ios/XMTPReactNative.podspec | 2 +- src/index.ts | 9 ++++----- src/lib/Client.ts | 7 ++----- src/lib/Signer.ts | 6 ++++-- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index d2e2cc7ea..1b0104bd9 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -38,7 +38,6 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withContext import org.json.JSONObject -import org.web3j.utils.Numeric import org.xmtp.android.library.Client import org.xmtp.android.library.ClientOptions import org.xmtp.android.library.ConsentState @@ -48,6 +47,7 @@ import org.xmtp.android.library.PreEventCallback import org.xmtp.android.library.PreparedMessage import org.xmtp.android.library.SendOptions import org.xmtp.android.library.SigningKey +import org.xmtp.android.library.WalletType import org.xmtp.android.library.XMTPEnvironment import org.xmtp.android.library.XMTPException import org.xmtp.android.library.codecs.Attachment @@ -71,7 +71,6 @@ import org.xmtp.proto.message.api.v1.MessageApiOuterClass import org.xmtp.proto.message.contents.Invitation.ConsentProofPayload import org.xmtp.proto.message.contents.PrivateKeyOuterClass import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration -import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.InboxState import uniffi.xmtpv3.org.xmtp.android.library.libxmtp.PermissionOption import java.io.BufferedReader import java.io.File @@ -86,7 +85,7 @@ import kotlin.coroutines.resumeWithException class ReactNativeSigner( var module: XMTPModule, override var address: String, - override var isSmartContractWallet: Boolean = false, + override var type: WalletType = WalletType.EOA, override var chainId: Long? = null, override var blockNumber: Long? = null, ) : SigningKey { @@ -411,7 +410,7 @@ class XMTPModule : Module() { val reactSigner = ReactNativeSigner( module = this@XMTPModule, address = address, - isSmartContractWallet = authOptions.isSmartContractWallet, + type = authOptions.walletType, chainId = authOptions.chainId, blockNumber = authOptions.blockNumber ) @@ -439,7 +438,7 @@ class XMTPModule : Module() { dbEncryptionKey, authParams, ) - val client = Client().buildV3(address = address, chainId = authOptions.chainId, options = options) + val client = Client().buildV3(address = address, options = options) ContentJson.Companion clients[client.inboxId] = client ClientWrapper.encodeToObj(client) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt index 6fffcf345..a1a461cea 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/AuthParamsWrapper.kt @@ -1,6 +1,7 @@ package expo.modules.xmtpreactnativesdk.wrappers import com.google.gson.JsonParser +import org.xmtp.android.library.WalletType class AuthParamsWrapper( val environment: String, @@ -8,10 +9,10 @@ class AuthParamsWrapper( val enableV3: Boolean = false, val dbDirectory: String?, val historySyncUrl: String?, - val isSmartContractWallet: Boolean = false, + val walletType: WalletType = WalletType.EOA, val chainId: Long?, val blockNumber: Long?, - ) { +) { companion object { fun authParamsFromJson(authParams: String): AuthParamsWrapper { val jsonOptions = JsonParser.parseString(authParams).asJsonObject @@ -21,10 +22,16 @@ class AuthParamsWrapper( if (jsonOptions.has("enableV3")) jsonOptions.get("enableV3").asBoolean else false, if (jsonOptions.has("dbDirectory")) jsonOptions.get("dbDirectory").asString else null, if (jsonOptions.has("historySyncUrl")) jsonOptions.get("historySyncUrl").asString else null, - if (jsonOptions.has("isSmartContractWallet")) jsonOptions.get("isSmartContractWallet").asBoolean else false, + if (jsonOptions.has("walletType")) { + when (jsonOptions.get("walletType").asString) { + "SCW" -> WalletType.SCW + else -> WalletType.EOA + } + } else { + WalletType.EOA + }, if (jsonOptions.has("chainId")) jsonOptions.get("chainId").asLong else null, if (jsonOptions.has("blockNumber")) jsonOptions.get("blockNumber").asLong else null, - ) } } diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 5611ce7b7..fd780cac2 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.15.2-alpha0" + s.dependency "XMTP", "= 0.15.2" end diff --git a/src/index.ts b/src/index.ts index 9715410b1..730a26d45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { Client } from '.' import { ConversationContext } from './XMTP.types' import XMTPModule from './XMTPModule' import { InboxId } from './lib/Client' +import { WalletType } from './lib/Signer' import { ConsentListEntry, ConsentState } from './lib/ConsentListEntry' import { ContentCodec, @@ -225,7 +226,7 @@ export async function createV3( dbEncryptionKey?: Uint8Array | undefined, dbDirectory?: string | undefined, historySyncUrl?: string | undefined, - isSmartContractWallet?: boolean | undefined, + walletType?: WalletType | undefined, chainId?: number | undefined, blockNumber?: number | undefined ) { @@ -239,7 +240,7 @@ export async function createV3( enableV3, dbDirectory, historySyncUrl, - isSmartContractWallet, + walletType, chainId, blockNumber, } @@ -255,7 +256,6 @@ export async function createV3( export async function buildV3( address: string, - chainId?: number | undefined, environment: 'local' | 'dev' | 'production', appVersion?: string | undefined, enableV3?: boolean | undefined, @@ -273,7 +273,6 @@ export async function buildV3( enableV3, dbDirectory, historySyncUrl, - chainId, } return await XMTPModule.buildV3( address, @@ -1324,7 +1323,7 @@ interface AuthParams { enableV3?: boolean dbDirectory?: string historySyncUrl?: string - isSmartContractWallet?: boolean + walletType?: string chainId?: number blockNumber?: number } diff --git a/src/lib/Client.ts b/src/lib/Client.ts index ca4dd7c33..6c880416d 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -331,7 +331,7 @@ export class Client< const request: { id: string; message: string } = message try { const signatureString = await signer.signMessage(request.message) - if (signer.isSmartContractWallet()) { + if (signer.walletType() === 'SCW') { await XMTPModule.receiveSCWSignature( request.id, Buffer.from(signatureString) @@ -397,7 +397,7 @@ export class Client< options.dbEncryptionKey, options.dbDirectory, options.historySyncUrl, - signer.isSmartContractWallet(), + signer.walletType(), signer.getChainId(), signer.getBlockNumber() ) @@ -416,7 +416,6 @@ export class Client< * Builds a V3 ONLY instance of the Client class using the provided address and chainId if SCW. * * @param {string} address - The address of the account to build - * @param {Optional} chainId - The chainId of the smart contract wallet. Otherwise should be left undefined. * @param {Partial} opts - Configuration options for the Client. Must include an encryption key. * @returns {Promise} A Promise that resolves to a new V3 ONLY Client instance. * @@ -426,7 +425,6 @@ export class Client< ContentCodecs extends DefaultContentTypes = DefaultContentTypes, >( address: string, - chainId: number | undefined, options: ClientOptions & { codecs?: ContentCodecs } ): Promise> { options.enableV3 = true @@ -438,7 +436,6 @@ export class Client< } const client = await XMTPModule.buildV3( address, - chainId, options.env, options.appVersion, Boolean(options.enableV3), diff --git a/src/lib/Signer.ts b/src/lib/Signer.ts index d6fe752a5..efc994d27 100644 --- a/src/lib/Signer.ts +++ b/src/lib/Signer.ts @@ -1,10 +1,12 @@ import type { WalletClient } from 'viem' +export type WalletType = 'EOA' | 'SCW' + export interface Signer { getAddress: () => Promise getChainId: () => number | undefined getBlockNumber: () => number | undefined - isSmartContractWallet: () => boolean + walletType: () => WalletType | undefined signMessage: (message: string) => Promise } @@ -42,6 +44,6 @@ export function convertWalletClientToSigner( }), getChainId: () => undefined, getBlockNumber: () => undefined, - isSmartContractWallet: () => false, + walletType: () => undefined, } } From 1ccaec4dbcc3e46b6f90448e1179ad19546ca8a2 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 19:10:12 -0700 Subject: [PATCH 21/28] bad merge --- src/index.ts | 1 - src/lib/Client.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 287a84003..730a26d45 100644 --- a/src/index.ts +++ b/src/index.ts @@ -257,7 +257,6 @@ export async function createV3( export async function buildV3( address: string, environment: 'local' | 'dev' | 'production', - chainId?: number | undefined, appVersion?: string | undefined, enableV3?: boolean | undefined, dbEncryptionKey?: Uint8Array | undefined, diff --git a/src/lib/Client.ts b/src/lib/Client.ts index 2020f4205..4df46aac7 100644 --- a/src/lib/Client.ts +++ b/src/lib/Client.ts @@ -437,7 +437,6 @@ export class Client< const client = await XMTPModule.buildV3( address, options.env, - chainId, options.appVersion, Boolean(options.enableV3), options.dbEncryptionKey, From 8ac19bb6c565791948af00f82997135218321de8 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 19:17:04 -0700 Subject: [PATCH 22/28] do the ios side --- ios/Wrappers/AuthParamsWrapper.swift | 17 +++++++++++------ ios/XMTPModule.swift | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index 8ea33ea77..f3995a1fd 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -14,17 +14,17 @@ struct AuthParamsWrapper { let enableV3: Bool let dbDirectory: String? let historySyncUrl: String? - let isSmartContractWallet: Bool + let walletType: WalletType let chainId: UInt64? let blockNumber: UInt64? - init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, isSmartContractWallet: Bool, chainId: UInt64?, blockNumber: UInt64?) { + init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, walletType: WalletType, chainId: UInt64?, blockNumber: UInt64?) { self.environment = environment self.appVersion = appVersion self.enableV3 = enableV3 self.dbDirectory = dbDirectory self.historySyncUrl = historySyncUrl - self.isSmartContractWallet = isSmartContractWallet + self.walletType = walletType self.chainId = chainId self.blockNumber = blockNumber } @@ -32,7 +32,7 @@ struct AuthParamsWrapper { static func authParamsFromJson(_ authParams: String) -> AuthParamsWrapper { guard let data = authParams.data(using: .utf8), let jsonOptions = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { - return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil, isSmartContractWallet: false, chainId: nil, blockNumber: nil) + return AuthParamsWrapper(environment: "dev", appVersion: nil, enableV3: false, dbDirectory: nil, historySyncUrl: nil, walletType: WalletType.EOA, chainId: nil, blockNumber: nil) } let environment = jsonOptions["environment"] as? String ?? "dev" @@ -40,9 +40,14 @@ struct AuthParamsWrapper { let enableV3 = jsonOptions["enableV3"] as? Bool ?? false let dbDirectory = jsonOptions["dbDirectory"] as? String let historySyncUrl = jsonOptions["historySyncUrl"] as? String - let isSmartContractWallet = jsonOptions["isSmartContractWallet"] as? Bool ?? false + let walletTypeString = jsonOptions["walletType"] as? String ?? "EOA" let chainId = jsonOptions["chainId"] as? Int let blockNumber = jsonOptions["blockNumber"] as? Int + + let walletType = switch walletTypeString { + case "SCW" -> return WalletType.SCW + default: return WalletType.EOA + } return AuthParamsWrapper( @@ -51,7 +56,7 @@ struct AuthParamsWrapper { enableV3: enableV3, dbDirectory: dbDirectory, historySyncUrl: historySyncUrl, - isSmartContractWallet: isSmartContractWallet, + walletType: walletType, chainId: chainId != nil ? UInt64(chainId!) : nil, blockNumber: blockNumber != nil ? UInt64(blockNumber!) : nil ) diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index d3103e7f0..8807d42f6 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -371,7 +371,7 @@ public class XMTPModule: Module { dbDirectory: authOptions.dbDirectory, historySyncUrl: authOptions.historySyncUrl ) - let client = try await XMTP.Client.buildV3(address: address, chainId: authOptions.chainId, options: options) + let client = try await XMTP.Client.buildV3(address: address, options: options) await clientsManager.updateClient(key: client.inboxID, client: client) return try ClientWrapper.encodeToObj(client) } From dc4de41e57a1313e5f6088f76b465417d52e24b7 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 19:19:24 -0700 Subject: [PATCH 23/28] int instead of uint --- android/build.gradle | 20 ++++++++++---------- ios/Wrappers/AuthParamsWrapper.swift | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index 87789ba68..b5fc17af2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -103,14 +103,14 @@ dependencies { implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1" // xmtp-android local testing setup below (comment org.xmtp:android above) -// implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') -// implementation 'com.google.crypto.tink:tink-android:1.8.0' -// implementation 'io.grpc:grpc-kotlin-stub:1.4.1' -// implementation 'io.grpc:grpc-okhttp:1.62.2' -// implementation 'io.grpc:grpc-protobuf-lite:1.62.2' -// implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' -// implementation 'org.web3j:crypto:5.0.0' -// implementation "net.java.dev.jna:jna:5.14.0@aar" -// api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' -// api 'org.xmtp:proto-kotlin:3.62.1' + // implementation files('/xmtp-android/library/build/outputs/aar/library-debug.aar') + // implementation 'com.google.crypto.tink:tink-android:1.8.0' + // implementation 'io.grpc:grpc-kotlin-stub:1.4.1' + // implementation 'io.grpc:grpc-okhttp:1.62.2' + // implementation 'io.grpc:grpc-protobuf-lite:1.62.2' + // implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0' + // implementation 'org.web3j:crypto:5.0.0' + // implementation "net.java.dev.jna:jna:5.14.0@aar" + // api 'com.google.protobuf:protobuf-kotlin-lite:3.22.3' + // api 'org.xmtp:proto-kotlin:3.62.1' } diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index f3995a1fd..b8f784270 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -15,10 +15,10 @@ struct AuthParamsWrapper { let dbDirectory: String? let historySyncUrl: String? let walletType: WalletType - let chainId: UInt64? - let blockNumber: UInt64? + let chainId: Int64? + let blockNumber: Int64? - init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, walletType: WalletType, chainId: UInt64?, blockNumber: UInt64?) { + init(environment: String, appVersion: String?, enableV3: Bool, dbDirectory: String?, historySyncUrl: String?, walletType: WalletType, chainId: Int64?, blockNumber: Int64?) { self.environment = environment self.appVersion = appVersion self.enableV3 = enableV3 From fd6e6d1d7ea43885d8ca9fd770325f4c42c58273 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 19:21:12 -0700 Subject: [PATCH 24/28] fix the signer --- ios/ReactNativeSigner.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index 753279b0b..2f05687f1 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -14,16 +14,16 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { var module: XMTPModule var address: String - var isSmartContractWallet: Bool - var chainId: UInt64? - var blockNumber: UInt64? + var walletType: WalletType + var chainId: Int64? + var blockNumber: Int64? var continuations: [String: CheckedContinuation] = [:] var scwContinuations: [String: CheckedContinuation] = [:] - init(module: XMTPModule, address: String, isSmartContractWallet: Bool = false, chainId: UInt64? = nil, blockNumber: UInt64? = nil) { + init(module: XMTPModule, address: String, walletType: WalletType = WalletType.EOA, chainId: Int64? = nil, blockNumber: Int64? = nil) { self.module = module self.address = address - self.isSmartContractWallet = isSmartContractWallet + self.walletType = walletType self.chainId = chainId self.blockNumber = blockNumber } From b42a54b2edea5334d913c72b2c2297d428512e96 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 20:00:01 -0700 Subject: [PATCH 25/28] get iOS compiling correctyl --- example/ios/Podfile.lock | 24 ++++++++++++------------ example/src/tests/v3OnlyTests.ts | 15 +++++++++++++-- ios/Wrappers/AuthParamsWrapper.swift | 19 +++++++++++-------- ios/XMTPModule.swift | 2 +- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index d7fcd2753..ee02ff527 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,12 +56,12 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (0.5.9-beta4) + - LibXMTP (0.5.10) - Logging (1.0.0) - MessagePacker (0.4.7) - - MMKV (1.3.9): - - MMKVCore (~> 1.3.9) - - MMKVCore (1.3.9) + - MMKV (2.0.0): + - MMKVCore (~> 2.0.0) + - MMKVCore (2.0.0) - OpenSSL-Universal (1.1.2200) - RCT-Folly (2021.07.22.00): - boost @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.15.2-alpha0): + - XMTP (0.15.2): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 0.5.9-beta4) + - LibXMTP (= 0.5.10) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 0.15.2-alpha0) + - XMTP (= 0.15.2) - Yoga (1.14.0) DEPENDENCIES: @@ -711,11 +711,11 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: f74da41ab513ff52c5529dc21531509440a7c3b5 + LibXMTP: 3b64b0b1e4157ff73c37cde60fe943f89e6f8693 Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 - MMKV: 817ba1eea17421547e01e087285606eb270a8dcb - MMKVCore: af055b00e27d88cd92fad301c5fecd1ff9b26dd9 + MMKV: f7d1d5945c8765f97f39c3d121f353d46735d801 + MMKVCore: c04b296010fcb1d1638f2c69405096aac12f6390 OpenSSL-Universal: 6e1ae0555546e604dbc632a2b9a24a9c46c41ef6 RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: e9df143e880d0e879e7a498dc06923d728809c79 @@ -763,8 +763,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 6c2eeb87f247ed652c10e68bea4ef6a3c35d4657 - XMTPReactNative: df42709a1f7ecb8dbe65a00d18d295a82df80bba + XMTP: 7d47e6bc507db66dd01116ce2b4ed04dd3560a4f + XMTPReactNative: 1a946cd697598fb4bc560a637094e63c4d553df3 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 0e6fe50018f34e575d38dc6a1fdf1f99c9596cdd diff --git a/example/src/tests/v3OnlyTests.ts b/example/src/tests/v3OnlyTests.ts index f673dfbea..8f3a03469 100644 --- a/example/src/tests/v3OnlyTests.ts +++ b/example/src/tests/v3OnlyTests.ts @@ -39,8 +39,20 @@ test('can make a V3 only client', async () => { client.inboxId === inboxId, `inboxIds should match but were ${client.inboxId} and ${inboxId}` ) - const canMessageV3 = await client.canGroupMessage([client.address]) + const client2 = await Client.buildV3(client.address, { + env: 'local', + appVersion: 'Testing/0.0.0', + enableV3: true, + dbEncryptionKey: keyBytes, + }) + + assert( + client.inboxId === client2.inboxId, + `inboxIds should match but were ${client.inboxId} and ${client2.inboxId}` + ) + + const canMessageV3 = await client.canGroupMessage([client.address]) assert( canMessageV3[client.address.toLowerCase()] === true, `canMessageV3 should be true` @@ -51,7 +63,6 @@ test('can make a V3 only client', async () => { } catch (error) { return true } - throw new Error('should throw error when hitting V2 api') }) diff --git a/ios/Wrappers/AuthParamsWrapper.swift b/ios/Wrappers/AuthParamsWrapper.swift index b8f784270..e5fed3096 100644 --- a/ios/Wrappers/AuthParamsWrapper.swift +++ b/ios/Wrappers/AuthParamsWrapper.swift @@ -41,13 +41,16 @@ struct AuthParamsWrapper { let dbDirectory = jsonOptions["dbDirectory"] as? String let historySyncUrl = jsonOptions["historySyncUrl"] as? String let walletTypeString = jsonOptions["walletType"] as? String ?? "EOA" - let chainId = jsonOptions["chainId"] as? Int - let blockNumber = jsonOptions["blockNumber"] as? Int + let chainId = jsonOptions["chainId"] as? Int64 + let blockNumber = jsonOptions["blockNumber"] as? Int64 - let walletType = switch walletTypeString { - case "SCW" -> return WalletType.SCW - default: return WalletType.EOA - } + let walletType = { switch walletTypeString { + case "SCW": + return WalletType.SCW + default: + return WalletType.EOA + } + }() return AuthParamsWrapper( @@ -57,8 +60,8 @@ struct AuthParamsWrapper { dbDirectory: dbDirectory, historySyncUrl: historySyncUrl, walletType: walletType, - chainId: chainId != nil ? UInt64(chainId!) : nil, - blockNumber: blockNumber != nil ? UInt64(blockNumber!) : nil + chainId: chainId, + blockNumber: blockNumber ) } } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index 8807d42f6..5ec9831e9 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -323,7 +323,7 @@ public class XMTPModule: Module { AsyncFunction("createV3") { (address: String, hasCreateIdentityCallback: Bool?, hasEnableIdentityCallback: Bool?, hasAuthenticateToInboxCallback: Bool?, dbEncryptionKey: [UInt8]?, authParams: String) in let authOptions = AuthParamsWrapper.authParamsFromJson(authParams) - let signer = ReactNativeSigner(module: self, address: address, isSmartContractWallet: authOptions.isSmartContractWallet, chainId: authOptions.chainId, blockNumber: authOptions.blockNumber) + let signer = ReactNativeSigner(module: self, address: address, walletType: authOptions.walletType, chainId: authOptions.chainId, blockNumber: authOptions.blockNumber) self.signer = signer if(hasCreateIdentityCallback ?? false) { self.preCreateIdentityCallbackDeferred = DispatchSemaphore(value: 0) From bf4370194a2c13501bc96435fa14065daa0f2f8e Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Wed, 23 Oct 2024 20:18:44 -0700 Subject: [PATCH 26/28] add back limit --- .../src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt | 2 +- .../expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt | 2 +- ios/Wrappers/GroupWrapper.swift | 2 +- ios/XMTPModule.swift | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt index 8f2054a85..1b0104bd9 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/XMTPModule.kt @@ -685,7 +685,7 @@ class XMTPModule : Module() { val sortedGroupList = if (order == ConversationOrder.LAST_MESSAGE) { client.conversations.listGroups() .sortedByDescending { group -> - group.decryptedMessages().firstOrNull()?.sentAt + group.decryptedMessages(limit = 1).firstOrNull()?.sentAt } .let { groups -> if (limit != null && limit > 0) groups.take(limit) else groups diff --git a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt index 5fdb142af..b75c58c4f 100644 --- a/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt +++ b/android/src/main/java/expo/modules/xmtpreactnativesdk/wrappers/GroupWrapper.kt @@ -37,7 +37,7 @@ class GroupWrapper { put("consentState", consentStateToString(group.consentState())) } if (groupParams.lastMessage) { - val lastMessage = group.decryptedMessages().firstOrNull() + val lastMessage = group.decryptedMessages(limit = 1).firstOrNull() if (lastMessage != null) { put("lastMessage", DecodedMessageWrapper.encode(lastMessage)) } diff --git a/ios/Wrappers/GroupWrapper.swift b/ios/Wrappers/GroupWrapper.swift index f00f73aeb..928fdd6d5 100644 --- a/ios/Wrappers/GroupWrapper.swift +++ b/ios/Wrappers/GroupWrapper.swift @@ -48,7 +48,7 @@ struct GroupWrapper { result["consentState"] = ConsentWrapper.consentStateToString(state: try group.consentState()) } if groupParams.lastMessage { - if let lastMessage = try await group.decryptedMessages().first { + if let lastMessage = try await group.decryptedMessages(limit: 1).first { result["lastMessage"] = try DecodedMessageWrapper.encode(lastMessage, client: client) } } diff --git a/ios/XMTPModule.swift b/ios/XMTPModule.swift index d3a88d7c0..5ec9831e9 100644 --- a/ios/XMTPModule.swift +++ b/ios/XMTPModule.swift @@ -571,7 +571,7 @@ public class XMTPModule: Module { var groupsWithMessages: [(Group, Date)] = [] for group in groups { do { - let firstMessage = try await group.decryptedMessages().first + let firstMessage = try await group.decryptedMessages(limit: 1).first let sentAt = firstMessage?.sentAt ?? Date.distantPast groupsWithMessages.append((group, sentAt)) } catch { From 230db03eadc1d37929443061a836ee281d388f4d Mon Sep 17 00:00:00 2001 From: Peter Ferguson Date: Thu, 24 Oct 2024 22:09:50 +0100 Subject: [PATCH 27/28] fix: ios type <-> walletType field name mismatch --- ios/ReactNativeSigner.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/ReactNativeSigner.swift b/ios/ReactNativeSigner.swift index 2f05687f1..e147c12a9 100644 --- a/ios/ReactNativeSigner.swift +++ b/ios/ReactNativeSigner.swift @@ -14,7 +14,7 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { var module: XMTPModule var address: String - var walletType: WalletType + var type: WalletType var chainId: Int64? var blockNumber: Int64? var continuations: [String: CheckedContinuation] = [:] @@ -23,7 +23,7 @@ class ReactNativeSigner: NSObject, XMTP.SigningKey { init(module: XMTPModule, address: String, walletType: WalletType = WalletType.EOA, chainId: Int64? = nil, blockNumber: Int64? = nil) { self.module = module self.address = address - self.walletType = walletType + self.type = walletType self.chainId = chainId self.blockNumber = blockNumber } From 7d6d62ddc79b3a94d8ec25f42fd8ced0380ee9d1 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 24 Oct 2024 14:46:01 -0700 Subject: [PATCH 28/28] feat: Smart Contract Wallet Support