From 4e43786498a0ae0fafe945e2f495ea9c3ef83b31 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Fri, 20 Sep 2024 16:46:02 -0600 Subject: [PATCH] add implementation --- Sources/XMTPiOS/Client.swift | 27 ++++++++++++++++++++++++++- Sources/XMTPiOS/SigningKey.swift | 11 +++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/Sources/XMTPiOS/Client.swift b/Sources/XMTPiOS/Client.swift index e0da501d..423a1a2c 100644 --- a/Sources/XMTPiOS/Client.swift +++ b/Sources/XMTPiOS/Client.swift @@ -247,7 +247,14 @@ public final class Client { if let signingKey = signingKey { do { let signedData = try await signingKey.sign(message: signatureRequest.signatureText()) - try await signatureRequest.addEcdsaSignature(signatureBytes: signedData.rawData) + if signingKey.isSmartContractWallet { + guard isValidAccountID(signingKey.address) else { + throw ClientError.creationError("Account address must conform to CAIP format") + } + try await signatureRequest.addScwSignature(signatureBytes: signedData.rawData, address: signingKey.address, chainId: signingKey.chainId, blockNumber: signingKey.blockNumber) + } else { + try await signatureRequest.addEcdsaSignature(signatureBytes: signedData.rawData) + } try await v3Client.registerIdentity(signatureRequest: signatureRequest) } catch { throw ClientError.creationError("Failed to sign the message: \(error.localizedDescription)") @@ -696,4 +703,22 @@ public final class Client { } return InboxState(ffiInboxState: try await client.inboxState(refreshFromNetwork: refreshFromNetwork)) } + + // See for more details https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md + public func isValidAccountID(_ accountAddress: String) -> Bool { + // Define the regular expressions for chain_id and account_address + let chainIDPattern = "[-a-z0-9]{3,8}:[-_a-zA-Z0-9]{1,32}" + let accountAddressPattern = "[-.%a-zA-Z0-9]{1,128}" + + // Combine them to match the entire account_id format + let accountIDPattern = "^\(chainIDPattern):\(accountAddressPattern)$" + + let regex = try? NSRegularExpression(pattern: accountIDPattern) + + if let match = regex?.firstMatch(in: accountAddress, options: [], range: NSRange(location: 0, length: accountAddress.utf16.count)) { + return match.range.location != NSNotFound + } else { + return false + } + } } diff --git a/Sources/XMTPiOS/SigningKey.swift b/Sources/XMTPiOS/SigningKey.swift index 4acd7011..9a2b0cca 100644 --- a/Sources/XMTPiOS/SigningKey.swift +++ b/Sources/XMTPiOS/SigningKey.swift @@ -24,7 +24,10 @@ public protocol SigningKey { var isSmartContractWallet: Bool { get } /// The name of the chainId for example "eip155:1" - var chainId: String { get } + var chainId: UInt64 { get } + + /// The blockNumber of the chain for example "1" + var blockNumber: UInt64 { get } /// Sign the data and return a secp256k1 compact recoverable signature. func sign(_ data: Data) async throws -> Signature @@ -39,7 +42,11 @@ extension SigningKey { return false } - public var chainId: String { + public var chainId: UInt64 { + return "eip155:1" + } + + public var blockNumber: UInt64 { return "eip155:1" }