From 5384070c2bf91971c5080f5cdaadf80c6f450969 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 27 Feb 2024 08:32:35 +0100 Subject: [PATCH 01/27] add notify recap --- Sources/WalletConnectIdentity/IdentityClient.swift | 2 +- Sources/WalletConnectIdentity/IdentityService.swift | 11 +++++++++-- .../Client/Wallet/NotifyClient.swift | 12 +++++++++--- .../WalletConnectUtils/SIWE/SIWECacaoFormatter.swift | 2 +- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Sources/WalletConnectIdentity/IdentityClient.swift b/Sources/WalletConnectIdentity/IdentityClient.swift index 8958b5112..10b0dc922 100644 --- a/Sources/WalletConnectIdentity/IdentityClient.swift +++ b/Sources/WalletConnectIdentity/IdentityClient.swift @@ -24,7 +24,7 @@ public final class IdentityClient { public func prepareRegistration(account: Account, domain: String, - statement: String, + statement: String? = nil, resources: [String]) async throws -> IdentityRegistrationParams { let registration = try await identityService.prepareRegistration(account: account, domain: domain, statement: statement, resources: resources) diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index 96cd34215..17e86197f 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -27,15 +27,17 @@ actor IdentityService { func prepareRegistration(account: Account, domain: String, - statement: String, + statement: String? = nil, resources: [String]) throws -> IdentityRegistrationParams { let identityKey = SigningPrivateKey() + let uri = buildUri(domain: domain, didKey: identityKey.publicKey.did) + let payload = CacaoPayload( iss: account.did, domain: domain, - aud: identityKey.publicKey.did, + aud: uri, version: getVersion(), nonce: getNonce(), iat: iatProvader.iat, @@ -50,6 +52,11 @@ actor IdentityService { return IdentityRegistrationParams(message: message, payload: payload, privateIdentityKey: identityKey) } + func buildUri(domain: String, didKey: String) -> String { + let identityKey = SigningPrivateKey() + return "\(domain)?walletconnect_identity_token=\(didKey)" + } + // TODO: Verifications func registerIdentity(params: IdentityRegistrationParams, signature: CacaoSignature) async throws -> String { let account = try params.account diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 6b5aa22fc..7aa2b24b0 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -1,6 +1,7 @@ import Foundation import Combine + public class NotifyClient { private var publishers = Set() @@ -87,15 +88,20 @@ public class NotifyClient { self.subscriptionWatcher = subscriptionWatcher } - public func prepareRegistration(account: Account, domain: String, allApps: Bool = true) async throws -> IdentityRegistrationParams { + public func prepareRegistration(account: Account, domain: String) async throws -> IdentityRegistrationParams { return try await identityClient.prepareRegistration( account: account, domain: domain, - statement: makeStatement(allApps: allApps), - resources: [keyserverURL.absoluteString] + resources: [keyserverURL.absoluteString, createAuthorizationRecap()] ) } + /// returns notify recap for all apps + public func createAuthorizationRecap() -> String { + // {"att":{"walletconnect-notify":{"manage/all-apps-notifications":[{}]}}} + "urn:recap:eyJhdHQiOnsid2FsbGV0Y29ubmVjdC1ub3RpZnkiOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" + } + public func register(params: IdentityRegistrationParams, signature: CacaoSignature) async throws { try await identityClient.register(params: params, signature: signature) notifyAccountProvider.setAccount(try params.account) diff --git a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift index 4721f69db..1abd44997 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift @@ -5,7 +5,7 @@ public protocol SIWECacaoFormatting { } public extension SIWECacaoFormatting { func formatMessage(from payload: CacaoPayload) throws -> String { - return try formatMessage(from: payload, includeRecapInTheStatement: false) + return try formatMessage(from: payload, includeRecapInTheStatement: true) } } public struct SIWECacaoFormatter: SIWECacaoFormatting { From 15f96c2d9c40ae93336fc0fe6fe8b2cbc0d3bc2f Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 27 Feb 2024 08:40:26 +0100 Subject: [PATCH 02/27] savepoint --- Example/IntegrationTests/Push/NotifyTests.swift | 2 +- .../Client/Wallet/NotifyClient.swift | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 66718151c..08369e9cf 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -281,7 +281,7 @@ private extension NotifyTests { private extension NotifyClient { - func register(account: Account, domain: String, isLimited: Bool = false, onSign: @escaping (String) -> CacaoSignature) async throws { + func register(account: Account, domain: String, onSign: @escaping (String) -> CacaoSignature) async throws { let params = try await prepareRegistration(account: account, domain: domain) let signature = onSign(params.message) try await register(params: params, signature: signature) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 7aa2b24b0..761b0c66f 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -96,12 +96,6 @@ public class NotifyClient { ) } - /// returns notify recap for all apps - public func createAuthorizationRecap() -> String { - // {"att":{"walletconnect-notify":{"manage/all-apps-notifications":[{}]}}} - "urn:recap:eyJhdHQiOnsid2FsbGV0Y29ubmVjdC1ub3RpZnkiOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" - } - public func register(params: IdentityRegistrationParams, signature: CacaoSignature) async throws { try await identityClient.register(params: params, signature: signature) notifyAccountProvider.setAccount(try params.account) @@ -178,6 +172,12 @@ public class NotifyClient { return messages.count == limit } + + /// returns notify recap for all apps + private func createAuthorizationRecap() -> String { + // {"att":{"walletconnect-notify":{"manage/all-apps-notifications":[{}]}}} + "urn:recap:eyJhdHQiOnsid2FsbGV0Y29ubmVjdC1ub3RpZnkiOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" + } } private extension NotifyClient { From 57b8eb991b4bf3ae2ee6cfe19ebf3bab4be0e594 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 27 Feb 2024 08:57:13 +0100 Subject: [PATCH 03/27] savepoint --- Sources/WalletConnectIdentity/IdentityService.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index 17e86197f..efc5ff3b7 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -53,7 +53,6 @@ actor IdentityService { } func buildUri(domain: String, didKey: String) -> String { - let identityKey = SigningPrivateKey() return "\(domain)?walletconnect_identity_token=\(didKey)" } From 47746a83e5184e059000fd537125d07d1004ac0d Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Fri, 8 Mar 2024 13:00:08 +0100 Subject: [PATCH 04/27] update capbox --- Sources/WalletConnectIdentity/IdentityService.swift | 2 +- Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index efc5ff3b7..dde7af412 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -53,7 +53,7 @@ actor IdentityService { } func buildUri(domain: String, didKey: String) -> String { - return "\(domain)?walletconnect_identity_token=\(didKey)" + return "\(domain)?walletconnect_identity_key=\(didKey)" } // TODO: Verifications diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index 761b0c66f..f143b91cd 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -175,8 +175,8 @@ public class NotifyClient { /// returns notify recap for all apps private func createAuthorizationRecap() -> String { - // {"att":{"walletconnect-notify":{"manage/all-apps-notifications":[{}]}}} - "urn:recap:eyJhdHQiOnsid2FsbGV0Y29ubmVjdC1ub3RpZnkiOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" + // {"att":{"https://notify.walletconnect.com":{"manage/all-apps-notifications":[{}]}}} + "urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9ub3RpZnkud2FsbGV0Y29ubmVjdC5jb20iOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" } } From 343942ec038e1d5d23d7b377811369c57e22bbab Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 13:56:57 +0100 Subject: [PATCH 05/27] add recap merging service --- .../IntegrationTests/Push/NotifyTests.swift | 4 +- .../Client/Wallet/NotifyClient.swift | 2 +- .../SIWE/RecapStatementBuilder.swift | 29 +++--- .../SIWE/RecapUrnMergingService.swift | 44 +++++++++ .../WalletConnectUtils/SIWE/SIWEMessage.swift | 4 +- .../SIWEMessageFormatterTests.swift | 2 +- .../RecapStatementBuilderTests.swift | 95 +------------------ .../RecapUrnMergingServiceTests.swift | 67 +++++++++++++ 8 files changed, 134 insertions(+), 113 deletions(-) create mode 100644 Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift create mode 100644 Tests/WalletConnectUtilsTests/RecapUrnMergingServiceTests.swift diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index 08369e9cf..f16e5550f 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -124,9 +124,9 @@ final class NotifyTests: XCTestCase { expectation.fulfill() }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: "https://\(gmDappDomain)", onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) - try! await clientB.register(account: account, domain: gmDappDomain, onSign: sign) + try! await clientB.register(account: account, domain: "https://\(gmDappDomain)", onSign: sign) await fulfillment(of: [expectation], timeout: InputConfig.defaultTimeout) diff --git a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift index f143b91cd..7664d62f4 100644 --- a/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift +++ b/Sources/WalletConnectNotify/Client/Wallet/NotifyClient.swift @@ -176,7 +176,7 @@ public class NotifyClient { /// returns notify recap for all apps private func createAuthorizationRecap() -> String { // {"att":{"https://notify.walletconnect.com":{"manage/all-apps-notifications":[{}]}}} - "urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9ub3RpZnkud2FsbGV0Y29ubmVjdC5jb20iOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0=" + "urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9ub3RpZnkud2FsbGV0Y29ubmVjdC5jb20iOnsibWFuYWdlL2FsbC1hcHBzLW5vdGlmaWNhdGlvbnMiOlt7fV19fX0" } } diff --git a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift index e3561c644..663589e1d 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift @@ -28,7 +28,7 @@ struct RecapUrn { } } -struct RecapData: Decodable { +struct RecapData: Codable { var att: [String: [String: [AnyCodable]]]? var prf: [String]? } @@ -36,18 +36,16 @@ struct RecapData: Decodable { struct RecapStatementBuilder { enum Errors: Error { case noActionsAuthorized - case emptyRecapsForbidden } - static func buildRecapStatement(recapUrns: [RecapUrn]) throws -> String { - guard recapUrns.count > 0 else { throw Errors.emptyRecapsForbidden } - var statementParts: [String] = [] - var actionCounter = 1 + static func buildRecapStatement(recapUrn: RecapUrn) throws -> String { + var statementParts: [String] = [] + var actionCounter = 1 - recapUrns.forEach { urn in - let decodedRecap = urn.recapData + // Processing only the last URN. + let decodedRecap = recapUrn.recapData - guard let attValue = decodedRecap.att else { return } + guard let attValue = decodedRecap.att else { throw Errors.noActionsAuthorized } let sortedResourceKeys = attValue.keys.sorted() @@ -67,13 +65,12 @@ struct RecapStatementBuilder { actionCounter += 1 } } - } - if statementParts.isEmpty { - throw Errors.noActionsAuthorized - } else { - let formattedStatement = statementParts.joined(separator: ". ") - return "I further authorize the stated URI to perform the following actions on my behalf: \(formattedStatement)." + if statementParts.isEmpty { + throw Errors.noActionsAuthorized + } else { + let formattedStatement = statementParts.joined(separator: ". ") + return "I further authorize the stated URI to perform the following actions on my behalf: \(formattedStatement)." + } } - } } diff --git a/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift new file mode 100644 index 000000000..b19a0c8d4 --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift @@ -0,0 +1,44 @@ +import Foundation + +class RecapUrnMergingService { + enum Errors: Error { + case emptyRecapUrns + case encodingFailed + } + + static func merge(recapUrns: [RecapUrn]) throws -> RecapUrn { + guard !recapUrns.isEmpty else { + throw Errors.emptyRecapUrns + } + + if recapUrns.count == 1 { + return recapUrns.first! + } + + var mergedAtt: [String: [String: [AnyCodable]]] = [:] + + for recapUrn in recapUrns { + guard let att = recapUrn.recapData.att else { continue } + for (key, value) in att { + if var existingValue = mergedAtt[key] { + for (actionKey, actionValue) in value { + existingValue[actionKey] = (existingValue[actionKey] ?? []) + actionValue + } + mergedAtt[key] = existingValue + } else { + mergedAtt[key] = value + } + } + } + + // Assuming RecapData can be encoded back to JSON and then to a Base64 string + let mergedData = RecapData(att: mergedAtt, prf: nil) + guard let jsonData = try? JSONEncoder().encode(mergedData), + let jsonBase64 = jsonData.base64EncodedString().addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { + throw Errors.encodingFailed + } + + let mergedUrnString = "urn:recap:\(jsonBase64)" + return try RecapUrn(urn: mergedUrnString) + } +} diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift index 6d1d2a936..d95860abc 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift @@ -47,9 +47,9 @@ public struct SIWEMessage: Equatable { private func getStatementLine() throws -> String { if let recaps = resources?.compactMap({ try? RecapUrn(urn: $0) }), - !recaps.isEmpty { + let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recaps) { do { - let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrns: recaps) + let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrn: mergedRecap) if let statement = statement { return "\n\(statement) \(recapStatement)" } else { diff --git a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift index 57c877fc9..3b3a96e81 100644 --- a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift @@ -149,7 +149,7 @@ class SIWEMessageFormatterTests: XCTestCase { let payload = try AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil,resources: [validRecapUrn]) ).cacaoPayload(account: Account.stub()) - +x let message = try sut.formatMessage(from: payload, includeRecapInTheStatement: true) XCTAssertEqual(message, expectedMessage) } diff --git a/Tests/WalletConnectUtilsTests/RecapStatementBuilderTests.swift b/Tests/WalletConnectUtilsTests/RecapStatementBuilderTests.swift index b5cf40478..66fe838f1 100644 --- a/Tests/WalletConnectUtilsTests/RecapStatementBuilderTests.swift +++ b/Tests/WalletConnectUtilsTests/RecapStatementBuilderTests.swift @@ -17,7 +17,7 @@ class RecapStatementBuilderTests: XCTestCase { let expectedStatement = "I further authorize the stated URI to perform the following actions on my behalf: (1) 'request': 'eth_sendTransaction', 'personal_sign' for 'eip155'." - let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrns: [urn]) + let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrn: urn) XCTAssertEqual(recapStatement, expectedStatement) } @@ -36,98 +36,11 @@ class RecapStatementBuilderTests: XCTestCase { let expectedStatement = "I further authorize the stated URI to perform the following actions on my behalf: (1) 'request': 'eth_sendTransaction', 'personal_sign' for 'eip155'." - let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrns: [urn]) + let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrn: urn) XCTAssertEqual(recapStatement, expectedStatement) } - func testMultipleRecaps() { - // First recap structure - let decodedRecap1: [String: [String: [String: [String]]]] = [ - "att": [ - "eip155": [ - "request/eth_sendTransaction": [], - "request/personal_sign": [] - ] - ] - ] - - // Second recap structure, as provided - let decodedRecap2: [String: [String: [String: [String]]]] = [ - "att": [ - "https://example.com/pictures/": [ - "crud/delete": [], - "crud/update": [], - "other/action": [] - ] - ] - ] - - // Encoding both recaps - let encoded1 = try! JSONEncoder().encode(decodedRecap1).base64EncodedString() - let encoded2 = try! JSONEncoder().encode(decodedRecap2).base64EncodedString() - - // Creating URNs - let urn1 = try! RecapUrn(urn: "urn:recap:\(encoded1)") - let urn2 = try! RecapUrn(urn: "urn:recap:\(encoded2)") - - // Expected statement combining both recaps - let expectedStatement = "I further authorize the stated URI to perform the following actions on my behalf: (1) 'request': 'eth_sendTransaction', 'personal_sign' for 'eip155'. (2) 'crud': 'delete', 'update' for 'https://example.com/pictures/'. (3) 'other': 'action' for 'https://example.com/pictures/'." - - // Generating the recap statement from both URNs - let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrns: [urn1, urn2]) - - // Asserting the generated statement against the expected statement - XCTAssertEqual(recapStatement, expectedStatement) - } - - func testRecapNotifyAndSign() throws { - let notifyRecapJson = """ - { - "att":{ - "https://notify.walletconnect.com/all-apps":{ - "crud/notifications": [{}], - "crud/subscriptions": [{}] - } - } - } - """ - - let signRecapJson = """ - { - "att":{ - "eip155":{ - "request/eth_sendTransaction": [{}], - "request/personal_sign": [{}] - } - } - } - """ - - // Correctly constructing Data from JSON strings - guard let notifyRecapData = notifyRecapJson.data(using: .utf8), - let signRecapData = signRecapJson.data(using: .utf8) else { - XCTFail("Failed to create Data from JSON strings") - return - } - - let encodedNotify = notifyRecapData.base64EncodedString() - let encodedSign = signRecapData.base64EncodedString() - - let urn1 = try RecapUrn(urn: "urn:recap:\(encodedSign)") - let urn2 = try RecapUrn(urn: "urn:recap:\(encodedNotify)") - - let expectedStatement = """ - I further authorize the stated URI to perform the following actions on my behalf: (1) 'request': 'eth_sendTransaction', 'personal_sign' for 'eip155'. (2) 'crud': 'notifications', 'subscriptions' for 'https://notify.walletconnect.com/all-apps'. - """ - - // Generating the recap statement from both URNs, with 'sign' recap first - let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrns: [urn1, urn2]) - - // Asserting the generated statement against the expected statement - XCTAssertEqual(recapStatement, expectedStatement) - - } func testComplexRecap() { @@ -166,7 +79,7 @@ class RecapStatementBuilderTests: XCTestCase { let expectedStatement = "I further authorize the stated URI to perform the following actions on my behalf: (1) 'crud': 'delete', 'update' for 'https://example.com/pictures/'. (2) 'other': 'action' for 'https://example.com/pictures/'. (3) 'msg': 'receive', 'send' for 'mailto:username@example.com'." - let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrns: [urn]) + let recapStatement = try! RecapStatementBuilder.buildRecapStatement(recapUrn: urn) // Asserting the generated statement against the expected statement XCTAssertEqual(recapStatement, expectedStatement) @@ -183,7 +96,7 @@ class RecapStatementBuilderTests: XCTestCase { let urn = try! RecapUrn(urn: "urn:recap:\(encoded)") // Assert that building a statement with no actions throws an error - XCTAssertThrowsError(try RecapStatementBuilder.buildRecapStatement(recapUrns: [urn])) { error in + XCTAssertThrowsError(try RecapStatementBuilder.buildRecapStatement(recapUrn: urn)) { error in XCTAssertEqual(error as? RecapStatementBuilder.Errors, RecapStatementBuilder.Errors.noActionsAuthorized) } } diff --git a/Tests/WalletConnectUtilsTests/RecapUrnMergingServiceTests.swift b/Tests/WalletConnectUtilsTests/RecapUrnMergingServiceTests.swift new file mode 100644 index 000000000..719cf7a45 --- /dev/null +++ b/Tests/WalletConnectUtilsTests/RecapUrnMergingServiceTests.swift @@ -0,0 +1,67 @@ +import XCTest +@testable import WalletConnectUtils + +class RecapUrnMergingTests: XCTestCase { + func testMergeRecapUrns() throws { + // Encode your test data to Base64 + let notifyRecapJson = """ + { + "att":{ + "https://notify.walletconnect.com/all-apps":{ + "crud/notifications": [{}], + "crud/subscriptions": [{}] + } + } + } + """ + let signRecapJson = """ + { + "att":{ + "eip155":{ + "request/eth_sendTransaction": [{}], + "request/personal_sign": [{}] + } + } + } + """ + + guard let notifyBase64 = notifyRecapJson.data(using: .utf8)?.base64EncodedString(), + let signBase64 = signRecapJson.data(using: .utf8)?.base64EncodedString() else { + XCTFail("Failed to encode JSON strings to Base64") + return + } + + // Create URNs from Base64 encoded strings + let urn1 = try RecapUrn(urn: "urn:recap:\(notifyBase64)") + let urn2 = try RecapUrn(urn: "urn:recap:\(signBase64)") + + // Merge the URNs using your merging logic + let mergedRecap = try RecapUrnMergingService.merge(recapUrns: [urn1, urn2]) + + // Define the expected merged structure + let expectedMergeJson = """ + { + "att":{ + "https://notify.walletconnect.com/all-apps":{ + "crud/notifications": [{}], + "crud/subscriptions": [{}] + }, + "eip155":{ + "request/eth_sendTransaction": [{}], + "request/personal_sign": [{}] + } + } + } + """ + + // Convert expected JSON to `RecapData` + let expectedMergeData = expectedMergeJson.data(using: .utf8)! + let expectedMergeRecap = try! JSONDecoder().decode(RecapData.self, from: expectedMergeData) + + // Perform your assertions + XCTAssertEqual(mergedRecap.recapData.att?.count, expectedMergeRecap.att?.count) + for (key, value) in mergedRecap.recapData.att ?? [:] { + XCTAssertEqual(value.keys.sorted(), expectedMergeRecap.att?[key]?.keys.sorted()) + } + } +} From 207e41d4b8aef4bb6826ef4534f66b7ca64859e0 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 14:22:50 +0100 Subject: [PATCH 06/27] Add SiweMessageFormatter --- .../Auth/Services/CacaosBuilder.swift | 25 +++++++ .../Auth/Services/CacaosProvider.swift | 10 --- .../Auth/Types/AuthPayload.swift | 16 ----- .../WalletConnectSign/Sign/SignClient.swift | 2 +- .../SIWE/SIWECacaoFormatter.swift | 2 +- .../WalletConnectUtils/SIWE/SIWEMessage.swift | 70 +++++++------------ .../SIWEMessageFormatterTests.swift | 2 +- 7 files changed, 52 insertions(+), 75 deletions(-) create mode 100644 Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift delete mode 100644 Sources/WalletConnectSign/Auth/Services/CacaosProvider.swift diff --git a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift new file mode 100644 index 000000000..e5654af23 --- /dev/null +++ b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift @@ -0,0 +1,25 @@ + +import Foundation + +struct CacaosBuilder { + public func makeCacao(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: WalletConnectUtils.Account) throws -> Cacao { + let statement = + + let cacaoPayload = CacaoPayload( + iss: account.did, + domain: authPayload.domain, + aud: authPayload.aud, + version: authPayload.version, + nonce: authPayload.nonce, + iat: authPayload.iat, + nbf: authPayload.nbf, + exp: authPayload.exp, + statement: statement, + requestId: authPayload.requestId, + resources: authPayload.resources + ) + let header = CacaoHeader(t: "eip4361") + return Cacao(h: header, p: cacaoPayload, s: signature) + } + +} diff --git a/Sources/WalletConnectSign/Auth/Services/CacaosProvider.swift b/Sources/WalletConnectSign/Auth/Services/CacaosProvider.swift deleted file mode 100644 index 5ab42d879..000000000 --- a/Sources/WalletConnectSign/Auth/Services/CacaosProvider.swift +++ /dev/null @@ -1,10 +0,0 @@ - -import Foundation - -struct CacaosProvider { - public func makeCacao(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: WalletConnectUtils.Account) throws -> Cacao { - let payload = try authPayload.cacaoPayload(account: account) - let header = CacaoHeader(t: "eip4361") - return Cacao(h: header, p: payload, s: signature) - } -} diff --git a/Sources/WalletConnectSign/Auth/Types/AuthPayload.swift b/Sources/WalletConnectSign/Auth/Types/AuthPayload.swift index 6c13e9002..8edab5317 100644 --- a/Sources/WalletConnectSign/Auth/Types/AuthPayload.swift +++ b/Sources/WalletConnectSign/Auth/Types/AuthPayload.swift @@ -57,20 +57,4 @@ public struct AuthPayload: Codable, Equatable { self.requestId = requestParams.requestId self.resources = requestParams.resources } - - func cacaoPayload(account: Account) throws -> CacaoPayload { - return CacaoPayload( - iss: account.did, - domain: domain, - aud: aud, - version: version, - nonce: nonce, - iat: iat, - nbf: nbf, - exp: exp, - statement: statement, - requestId: requestId, - resources: resources - ) - } } diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index e57b62324..8eb664fdd 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -352,7 +352,7 @@ public final class SignClient: SignClientProtocol { } public func buildSignedAuthObject(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: Account) throws -> AuthObject { - try CacaosProvider().makeCacao(authPayload: authPayload, signature: signature, account: account) + try CacaosBuilder().makeCacao(authPayload: authPayload, signature: signature, account: account) } public func buildAuthPayload(payload: AuthPayload, supportedEVMChains: [Blockchain], supportedMethods: [String]) throws -> AuthPayload { diff --git a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift index 1abd44997..280b4f045 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift @@ -28,7 +28,7 @@ public struct SIWECacaoFormatter: SIWECacaoFormatting { requestId: payload.requestId, resources: payload.resources ) - return try message.formatted() + return try SiweMessageFormatter.format(message) } } diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift index d95860abc..a366acd8c 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift @@ -28,29 +28,32 @@ public struct SIWEMessage: Equatable { self.requestId = requestId self.resources = resources } +} - public func formatted() throws -> String { +import Foundation - let statementLine = try getStatementLine() +public class SiweMessageFormatter { + public static func format(_ message: SIWEMessage) throws -> String { + let statementLine = try getStatementLine(for: message) return """ - \(domain) wants you to sign in with your Ethereum account: - \(address) + \(message.domain) wants you to sign in with your Ethereum account: + \(message.address) \(statementLine) - URI: \(uri) - Version: \(version) - Chain ID: \(chainId) - Nonce: \(nonce) - Issued At: \(iat)\(expLine)\(nbfLine)\(requestIdLine)\(resourcesSection) + URI: \(message.uri) + Version: \(message.version) + Chain ID: \(message.chainId) + Nonce: \(message.nonce) + Issued At: \(message.iat)\(getExpLine(for: message))\(getNbfLine(for: message))\(getRequestIdLine(for: message))\(getResourcesSection(for: message)) """ } - private func getStatementLine() throws -> String { - if let recaps = resources?.compactMap({ try? RecapUrn(urn: $0) }), + private static func getStatementLine(for message: SIWEMessage) throws -> String { + if let recaps = message.resources?.compactMap({ try? RecapUrn(urn: $0) }), let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recaps) { do { let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrn: mergedRecap) - if let statement = statement { + if let statement = message.statement { return "\n\(statement) \(recapStatement)" } else { return "\n\(recapStatement)" @@ -59,53 +62,28 @@ public struct SIWEMessage: Equatable { throw error } } else { - guard let statement = statement else { return "" } + guard let statement = message.statement else { return "" } return "\n\(statement)" } - - } - - - - private func decodeUrnToJson(urn: String) -> [String: [String: [String: [String]]]]? { - // Check if the URN is in the correct format - guard urn.starts(with: "urn:recap:") else { return nil } - - // Extract the Base64 encoded JSON part from the URN - let base64EncodedJson = urn.replacingOccurrences(of: "urn:recap:", with: "") - - // Decode the Base64 encoded JSON - guard let jsonData = Data(base64Encoded: base64EncodedJson) else { return nil } - - // Deserialize the JSON data into the desired dictionary - do { - let decodedDictionary = try JSONDecoder().decode([String: [String: [String: [String]]]].self, from: jsonData) - return decodedDictionary - } catch { - return nil - } } -} - -private extension SIWEMessage { - var expLine: String { - guard let exp = exp else { return "" } + private static func getExpLine(for message: SIWEMessage) -> String { + guard let exp = message.exp else { return "" } return "\nExpiration Time: \(exp)" } - var nbfLine: String { - guard let nbf = nbf else { return "" } + private static func getNbfLine(for message: SIWEMessage) -> String { + guard let nbf = message.nbf else { return "" } return "\nNot Before: \(nbf)" } - var requestIdLine: String { - guard let requestId = requestId else { return "" } + private static func getRequestIdLine(for message: SIWEMessage) -> String { + guard let requestId = message.requestId else { return "" } return "\nRequest ID: \(requestId)" } - var resourcesSection: String { - guard let resources = resources else { return "" } + private static func getResourcesSection(for message: SIWEMessage) -> String { + guard let resources = message.resources else { return "" } return resources.reduce("\nResources:") { $0 + "\n- \($1)" } } } diff --git a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift index 3b3a96e81..57c877fc9 100644 --- a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift @@ -149,7 +149,7 @@ class SIWEMessageFormatterTests: XCTestCase { let payload = try AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil,resources: [validRecapUrn]) ).cacaoPayload(account: Account.stub()) -x + let message = try sut.formatMessage(from: payload, includeRecapInTheStatement: true) XCTAssertEqual(message, expectedMessage) } From 83b4b8601505cd5d8ed3fb803c3a65d79181efb4 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 15:28:20 +0100 Subject: [PATCH 07/27] update siwe formatting --- .../Auth/Signer/CacaoSignerTests.swift | 2 +- .../IntegrationTests/Chat/RegistryTests.swift | 2 +- .../IdentityClientFactory.swift | 2 +- .../IdentityService.swift | 4 +- .../Services/App/AuthResponseSubscriber.swift | 4 +- .../Auth/Services/CacaosBuilder.swift | 20 ++++-- .../Auth/Services/Wallet/AuthResponder.swift | 4 +- .../WalletConnectSign/Sign/SignClient.swift | 2 +- .../Sign/SignClientFactory.swift | 2 +- .../Signer/MessageSigner.swift | 4 +- .../SIWE/RecapStatementBuilder.swift | 6 +- .../SIWE/RecapUrnMergingService.swift | 6 +- ...ft => SIWEFromCacaoPayloadFormatter.swift} | 8 +-- .../WalletConnectUtils/SIWE/SIWEMessage.swift | 57 --------------- .../SIWE/SiweMessageFormatter.swift | 45 ++++++++++++ .../SIWE/SiweStatementBuilder.swift | 22 ++++++ ... SIWEFromCacaoPayloadFormatterTests.swift} | 72 ++++++++++--------- 17 files changed, 145 insertions(+), 117 deletions(-) rename Sources/WalletConnectUtils/SIWE/{SIWECacaoFormatter.swift => SIWEFromCacaoPayloadFormatter.swift} (81%) create mode 100644 Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift create mode 100644 Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift rename Tests/WalletConnectSignTests/{SIWEMessageFormatterTests.swift => SIWEFromCacaoPayloadFormatterTests.swift} (76%) diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index 90a17b00e..d7634155f 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -51,7 +51,7 @@ class CacaoSignerTest: XCTestCase { func testCacaoSign() throws { let account = Account("eip155:1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")! let cacaoPayload = try payload.cacaoPayload(account: account) - let formatted = try SIWECacaoFormatter().formatMessage(from: cacaoPayload) + let formatted = try SIWEFromCacaoPayloadFormatter().formatMessage(from: cacaoPayload) XCTAssertEqual(formatted, message) XCTAssertEqual(try signer.sign(payload: cacaoPayload, privateKey: privateKey, type: .eip191), signature) } diff --git a/Example/IntegrationTests/Chat/RegistryTests.swift b/Example/IntegrationTests/Chat/RegistryTests.swift index 0c659241f..178c63be4 100644 --- a/Example/IntegrationTests/Chat/RegistryTests.swift +++ b/Example/IntegrationTests/Chat/RegistryTests.swift @@ -27,7 +27,7 @@ final class RegistryTests: XCTestCase { storage: storage, networkService: identityNetworkService, iatProvader: DefaultIATProvider(), - messageFormatter: SIWECacaoFormatter() + messageFormatter: SIWEFromCacaoPayloadFormatter() ) signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() } diff --git a/Sources/WalletConnectIdentity/IdentityClientFactory.swift b/Sources/WalletConnectIdentity/IdentityClientFactory.swift index 236a939f7..57720a4f8 100644 --- a/Sources/WalletConnectIdentity/IdentityClientFactory.swift +++ b/Sources/WalletConnectIdentity/IdentityClientFactory.swift @@ -11,7 +11,7 @@ public final class IdentityClientFactory { let httpService = HTTPNetworkClient(host: keyserver.host!) let identityStorage = IdentityStorage(keychain: keychain) let identityNetworkService = IdentityNetworkService(httpService: httpService) - let identityService = IdentityService(keyserverURL: keyserver, kms: kms, storage: identityStorage, networkService: identityNetworkService, iatProvader: DefaultIATProvider(), messageFormatter: SIWECacaoFormatter()) + let identityService = IdentityService(keyserverURL: keyserver, kms: kms, storage: identityStorage, networkService: identityNetworkService, iatProvader: DefaultIATProvider(), messageFormatter: SIWEFromCacaoPayloadFormatter()) return IdentityClient( identityService: identityService, identityStorage: identityStorage, diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index dde7af412..9483a9545 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -7,7 +7,7 @@ actor IdentityService { private let storage: IdentityStorage private let networkService: IdentityNetworking private let iatProvader: IATProvider - private let messageFormatter: SIWECacaoFormatting + private let messageFormatter: SIWEFromCacaoFormatting init( keyserverURL: URL, @@ -15,7 +15,7 @@ actor IdentityService { storage: IdentityStorage, networkService: IdentityNetworking, iatProvader: IATProvider, - messageFormatter: SIWECacaoFormatting + messageFormatter: SIWEFromCacaoFormatting ) { self.keyserverURL = keyserverURL self.kms = kms diff --git a/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift b/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift index 8a533f9be..a57be3a44 100644 --- a/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift +++ b/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift @@ -6,7 +6,7 @@ class AuthResponseSubscriber { private let logger: ConsoleLogging private let rpcHistory: RPCHistory private let signatureVerifier: MessageVerifier - private let messageFormatter: SIWECacaoFormatting + private let messageFormatter: SIWEFromCacaoFormatting private let pairingRegisterer: PairingRegisterer private var publishers = [AnyCancellable]() private let sessionStore: WCSessionStorage @@ -25,7 +25,7 @@ class AuthResponseSubscriber { pairingRegisterer: PairingRegisterer, kms: KeyManagementServiceProtocol, sessionStore: WCSessionStorage, - messageFormatter: SIWECacaoFormatting, + messageFormatter: SIWEFromCacaoFormatting, sessionNamespaceBuilder: SessionNamespaceBuilder, authResponseTopicRecordsStore: CodableStore) { self.networkingInteractor = networkingInteractor diff --git a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift index e5654af23..5b8d34d10 100644 --- a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift +++ b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift @@ -1,11 +1,23 @@ import Foundation +import WalletConnectUtils struct CacaosBuilder { - public func makeCacao(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: WalletConnectUtils.Account) throws -> Cacao { - let statement = + public static func makeCacao(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: WalletConnectUtils.Account) throws -> Cacao { + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload(authPayload: authPayload, account: account) + let header = CacaoHeader(t: "eip4361") + return Cacao(h: header, p: cacaoPayload, s: signature) + } + +} + +struct CacaoPayloadBuilder { + public static func makeCacaoPayload(authPayload: AuthPayload, account: WalletConnectUtils.Account) throws -> CacaoPayload { + let recapUrns = authPayload.resources?.compactMap { try? RecapUrn(urn: $0)} ?? [] - let cacaoPayload = CacaoPayload( + let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) + let statement = try SiweStatementBuilder.buildSiweStatement(statement: authPayload.statement, mergedRecapUrn: mergedRecap) + return CacaoPayload( iss: account.did, domain: authPayload.domain, aud: authPayload.aud, @@ -18,8 +30,6 @@ struct CacaosBuilder { requestId: authPayload.requestId, resources: authPayload.resources ) - let header = CacaoHeader(t: "eip4361") - return Cacao(h: header, p: cacaoPayload, s: signature) } } diff --git a/Sources/WalletConnectSign/Auth/Services/Wallet/AuthResponder.swift b/Sources/WalletConnectSign/Auth/Services/Wallet/AuthResponder.swift index bec7e6502..3d9ae4304 100644 --- a/Sources/WalletConnectSign/Auth/Services/Wallet/AuthResponder.swift +++ b/Sources/WalletConnectSign/Auth/Services/Wallet/AuthResponder.swift @@ -8,7 +8,7 @@ actor AuthResponder { } private let networkingInteractor: NetworkInteracting private let kms: KeyManagementService - private let messageFormatter: SIWECacaoFormatting + private let messageFormatter: SIWEFromCacaoFormatting private let signatureVerifier: MessageVerifier private let rpcHistory: RPCHistory private let verifyContextStore: CodableStore @@ -25,7 +25,7 @@ actor AuthResponder { kms: KeyManagementService, rpcHistory: RPCHistory, signatureVerifier: MessageVerifier, - messageFormatter: SIWECacaoFormatting, + messageFormatter: SIWEFromCacaoFormatting, verifyContextStore: CodableStore, walletErrorResponder: WalletErrorResponder, pairingRegisterer: PairingRegisterer, diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index 8eb664fdd..9b4b4d311 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -348,7 +348,7 @@ public final class SignClient: SignClientProtocol { } public func formatAuthMessage(payload: AuthPayload, account: Account) throws -> String { - return try SIWECacaoFormatter().formatMessage(from: payload.cacaoPayload(account: account), includeRecapInTheStatement: true) + return try SIWEFromCacaoPayloadFormatter().formatMessage(from: payload.cacaoPayload(account: account), includeRecapInTheStatement: true) } public func buildSignedAuthObject(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: Account) throws -> AuthObject { diff --git a/Sources/WalletConnectSign/Sign/SignClientFactory.swift b/Sources/WalletConnectSign/Sign/SignClientFactory.swift index c55c29467..e07c86816 100644 --- a/Sources/WalletConnectSign/Sign/SignClientFactory.swift +++ b/Sources/WalletConnectSign/Sign/SignClientFactory.swift @@ -95,7 +95,7 @@ public struct SignClientFactory { //Auth let authResponseTopicRecordsStore = CodableStore(defaults: keyValueStorage, identifier: SignStorageIdentifiers.authResponseTopicRecord.rawValue) - let messageFormatter = SIWECacaoFormatter() + let messageFormatter = SIWEFromCacaoPayloadFormatter() let appRequestService = SessionAuthRequestService(networkingInteractor: networkingClient, kms: kms, appMetadata: metadata, logger: logger, iatProvader: iatProvider, authResponseTopicRecordsStore: authResponseTopicRecordsStore) let messageVerifierFactory = MessageVerifierFactory(crypto: crypto) diff --git a/Sources/WalletConnectSigner/Signer/MessageSigner.swift b/Sources/WalletConnectSigner/Signer/MessageSigner.swift index b1c8efc4c..fed68c3e2 100644 --- a/Sources/WalletConnectSigner/Signer/MessageSigner.swift +++ b/Sources/WalletConnectSigner/Signer/MessageSigner.swift @@ -7,9 +7,9 @@ public struct MessageSigner { } private let signer: EthereumSigner - private let messageFormatter: SIWECacaoFormatting + private let messageFormatter: SIWEFromCacaoFormatting - init(signer: EthereumSigner, messageFormatter: SIWECacaoFormatting) { + init(signer: EthereumSigner, messageFormatter: SIWEFromCacaoFormatting) { self.signer = signer self.messageFormatter = messageFormatter } diff --git a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift index 663589e1d..8b4d122ef 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift @@ -1,6 +1,6 @@ import Foundation -struct RecapUrn { +public struct RecapUrn { enum Errors: Error { case invalidUrn case invalidPayload @@ -10,7 +10,7 @@ struct RecapUrn { let urn: String let recapData: RecapData - init(urn: String) throws { + public init(urn: String) throws { guard urn.hasPrefix("urn:recap") else { throw Errors.invalidUrn } let components = urn.components(separatedBy: ":") @@ -28,7 +28,7 @@ struct RecapUrn { } } -struct RecapData: Codable { +public struct RecapData: Codable { var att: [String: [String: [AnyCodable]]]? var prf: [String]? } diff --git a/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift index b19a0c8d4..9fc6662d6 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift @@ -1,12 +1,12 @@ import Foundation -class RecapUrnMergingService { - enum Errors: Error { +public class RecapUrnMergingService { + public enum Errors: Error { case emptyRecapUrns case encodingFailed } - static func merge(recapUrns: [RecapUrn]) throws -> RecapUrn { + public static func merge(recapUrns: [RecapUrn]) throws -> RecapUrn { guard !recapUrns.isEmpty else { throw Errors.emptyRecapUrns } diff --git a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift similarity index 81% rename from Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift rename to Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift index 280b4f045..8f6ffbf0f 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWECacaoFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift @@ -1,14 +1,14 @@ import Foundation -public protocol SIWECacaoFormatting { +public protocol SIWEFromCacaoFormatting { func formatMessage(from payload: CacaoPayload, includeRecapInTheStatement: Bool) throws -> String } -public extension SIWECacaoFormatting { +public extension SIWEFromCacaoFormatting { func formatMessage(from payload: CacaoPayload) throws -> String { return try formatMessage(from: payload, includeRecapInTheStatement: true) } } -public struct SIWECacaoFormatter: SIWECacaoFormatting { +public struct SIWEFromCacaoPayloadFormatter: SIWEFromCacaoFormatting { public init() { } @@ -28,7 +28,7 @@ public struct SIWECacaoFormatter: SIWECacaoFormatting { requestId: payload.requestId, resources: payload.resources ) - return try SiweMessageFormatter.format(message) + return try SiweMessageFormatter.format(siwe: message) } } diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift index a366acd8c..88cf98c27 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift @@ -30,60 +30,3 @@ public struct SIWEMessage: Equatable { } } -import Foundation - -public class SiweMessageFormatter { - public static func format(_ message: SIWEMessage) throws -> String { - let statementLine = try getStatementLine(for: message) - return """ - \(message.domain) wants you to sign in with your Ethereum account: - \(message.address) - \(statementLine) - - URI: \(message.uri) - Version: \(message.version) - Chain ID: \(message.chainId) - Nonce: \(message.nonce) - Issued At: \(message.iat)\(getExpLine(for: message))\(getNbfLine(for: message))\(getRequestIdLine(for: message))\(getResourcesSection(for: message)) - """ - } - - private static func getStatementLine(for message: SIWEMessage) throws -> String { - if let recaps = message.resources?.compactMap({ try? RecapUrn(urn: $0) }), - let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recaps) { - do { - let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrn: mergedRecap) - if let statement = message.statement { - return "\n\(statement) \(recapStatement)" - } else { - return "\n\(recapStatement)" - } - } catch { - throw error - } - } else { - guard let statement = message.statement else { return "" } - return "\n\(statement)" - } - } - - private static func getExpLine(for message: SIWEMessage) -> String { - guard let exp = message.exp else { return "" } - return "\nExpiration Time: \(exp)" - } - - private static func getNbfLine(for message: SIWEMessage) -> String { - guard let nbf = message.nbf else { return "" } - return "\nNot Before: \(nbf)" - } - - private static func getRequestIdLine(for message: SIWEMessage) -> String { - guard let requestId = message.requestId else { return "" } - return "\nRequest ID: \(requestId)" - } - - private static func getResourcesSection(for message: SIWEMessage) -> String { - guard let resources = message.resources else { return "" } - return resources.reduce("\nResources:") { $0 + "\n- \($1)" } - } -} diff --git a/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift b/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift new file mode 100644 index 000000000..2f9cb3d52 --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift @@ -0,0 +1,45 @@ +import Foundation + +public class SiweMessageFormatter { + public static func format(siwe: SIWEMessage) throws -> String { + let recapUrns = siwe.resources?.compactMap { try? RecapUrn(urn: $0)} ?? [] + + let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) + let statementLine = try SiweStatementBuilder.buildSiweStatement(statement: siwe.statement, mergedRecapUrn: mergedRecap) + return """ + \(siwe.domain) wants you to sign in with your Ethereum account: + \(siwe.address) + \(statementLine) + + URI: \(siwe.uri) + Version: \(siwe.version) + Chain ID: \(siwe.chainId) + Nonce: \(siwe.nonce) + Issued At: \(siwe.iat)\(siwe.expLine)\(siwe.nbfLine)\(siwe.requestIdLine)\(siwe.resourcesSection) + """ + } +} + +private extension SIWEMessage { + + var expLine: String { + guard let exp = exp else { return "" } + return "\nExpiration Time: \(exp)" + } + + var nbfLine: String { + guard let nbf = nbf else { return "" } + return "\nNot Before: \(nbf)" + } + + var requestIdLine: String { + guard let requestId = requestId else { return "" } + return "\nRequest ID: \(requestId)" + } + + var resourcesSection: String { + guard let resources = resources else { return "" } + let resourcesList = resources.reduce("") { $0 + "\n- \($1)" } + return resources.isEmpty ? "" : "\nResources:" + resourcesList + } +} diff --git a/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift new file mode 100644 index 000000000..bfdcfb923 --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift @@ -0,0 +1,22 @@ + +import Foundation + +public class SiweStatementBuilder { + public static func buildSiweStatement(statement: String?, mergedRecapUrn: RecapUrn?) throws -> String { + var finalStatement = statement ?? "" + + if let mergedRecapUrn = mergedRecapUrn { + // Generate recap statement from the merged RecapUrn + let recapStatement = try RecapStatementBuilder.buildRecapStatement(recapUrn: mergedRecapUrn) + // Append recap statement to the original statement, if it exists + if !finalStatement.isEmpty { + finalStatement += " \(recapStatement)" + } else { + finalStatement = recapStatement + } + } + + return finalStatement.isEmpty ? "" : "\n\(finalStatement)" + } +} + diff --git a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift similarity index 76% rename from Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift rename to Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift index 57c877fc9..f84fd03c5 100644 --- a/Tests/WalletConnectSignTests/SIWEMessageFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift @@ -3,12 +3,12 @@ import Foundation @testable import WalletConnectSign import XCTest -class SIWEMessageFormatterTests: XCTestCase { - var sut: SIWECacaoFormatter! +class SIWEFromCacaoPayloadFormatterTests: XCTestCase { + var sut: SIWEFromCacaoPayloadFormatter! let address = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" override func setUp() { - sut = SIWECacaoFormatter() + sut = SIWEFromCacaoPayloadFormatter() } func testFormatMessage() throws { @@ -28,7 +28,8 @@ class SIWEMessageFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let message = try sut.formatMessage(from: AuthPayload.stub().cacaoPayload(account: Account.stub())) + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload(authPayload: AuthPayload.stub(), account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -48,11 +49,12 @@ class SIWEMessageFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let message = try sut.formatMessage( - from: AuthPayload.stub( + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil) - ).cacaoPayload(account: Account.stub()) - ) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -70,10 +72,12 @@ class SIWEMessageFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let message = try sut.formatMessage( - from: AuthPayload.stub( - requestParams: AuthRequestParams.stub(resources: nil)).cacaoPayload(account: Account.stub()) - ) + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(resources: nil) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -90,10 +94,12 @@ class SIWEMessageFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let message = try sut.formatMessage( - from: AuthPayload.stub( - requestParams: AuthRequestParams.stub(statement: nil, resources: nil)).cacaoPayload(account: Account.stub()) - ) + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(statement: nil, resources: nil) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -117,12 +123,13 @@ class SIWEMessageFormatterTests: XCTestCase { """ + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(resources: [validRecapUrn]) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) - let payload = try AuthPayload.stub( - requestParams: AuthRequestParams.stub(resources: [validRecapUrn]) - ).cacaoPayload(account: Account.stub()) - - let message = try sut.formatMessage(from: payload, includeRecapInTheStatement: true) XCTAssertEqual(message, expectedMessage) } @@ -145,12 +152,12 @@ class SIWEMessageFormatterTests: XCTestCase { - urn:recap:eyJhdHQiOiB7ImVpcDE1NSI6IHsicmVxdWVzdC9ldGhfc2VuZFRyYW5zYWN0aW9uIjogW10sICJyZXF1ZXN0L3BlcnNvbmFsX3NpZ24iOiBbXX19fQ== """ - - let payload = try AuthPayload.stub( - requestParams: AuthRequestParams.stub(statement: nil,resources: [validRecapUrn]) - ).cacaoPayload(account: Account.stub()) - - let message = try sut.formatMessage(from: payload, includeRecapInTheStatement: true) + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(statement: nil, resources: [validRecapUrn]) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -178,11 +185,12 @@ class SIWEMessageFormatterTests: XCTestCase { let uri = "https://service.invalid?walletconnect_notify_key=did:key:z6MktW4hKdsvcXgt9wXmYbSD5sH4NCk5GmNZnokP9yh2TeCf" - let payload = try AuthPayload.stub( - requestParams: AuthRequestParams.stub(uri: uri, statement: nil,resources: [recap1, recap2]) - ).cacaoPayload(account: Account.stub()) - - let message = try sut.formatMessage(from: payload, includeRecapInTheStatement: true) + let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(statement: nil, resources: [recap1, recap2]) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } } From a640357b12b7c0e33daacb38e42f14699fbe977a Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 15:36:36 +0100 Subject: [PATCH 08/27] fix sign build --- Sources/WalletConnectSign/Sign/SignClient.swift | 5 +++-- .../Signer/MessageSignerFactory.swift | 2 +- .../SIWEFromCacaoPayloadFormatterTests.swift | 14 +++++++------- .../Stub/SIWEMessageFormatterMock.swift | 2 +- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Sources/WalletConnectSign/Sign/SignClient.swift b/Sources/WalletConnectSign/Sign/SignClient.swift index 9b4b4d311..b0fe8caf7 100644 --- a/Sources/WalletConnectSign/Sign/SignClient.swift +++ b/Sources/WalletConnectSign/Sign/SignClient.swift @@ -348,11 +348,12 @@ public final class SignClient: SignClientProtocol { } public func formatAuthMessage(payload: AuthPayload, account: Account) throws -> String { - return try SIWEFromCacaoPayloadFormatter().formatMessage(from: payload.cacaoPayload(account: account), includeRecapInTheStatement: true) + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload(authPayload: payload, account: account) + return try SIWEFromCacaoPayloadFormatter().formatMessage(from: cacaoPayload) } public func buildSignedAuthObject(authPayload: AuthPayload, signature: WalletConnectUtils.CacaoSignature, account: Account) throws -> AuthObject { - try CacaosBuilder().makeCacao(authPayload: authPayload, signature: signature, account: account) + try CacaosBuilder.makeCacao(authPayload: authPayload, signature: signature, account: account) } public func buildAuthPayload(payload: AuthPayload, supportedEVMChains: [Blockchain], supportedMethods: [String]) throws -> AuthPayload { diff --git a/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift b/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift index 0506e6fa1..5fc0a5eb4 100644 --- a/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift +++ b/Sources/WalletConnectSigner/Signer/MessageSignerFactory.swift @@ -11,7 +11,7 @@ public struct MessageSignerFactory { public func create() -> MessageSigner { return MessageSigner( signer: signerFactory.createEthereumSigner(), - messageFormatter: SIWECacaoFormatter() + messageFormatter: SIWEFromCacaoPayloadFormatter() ) } } diff --git a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift index f84fd03c5..fb9532440 100644 --- a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift @@ -28,7 +28,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload(authPayload: AuthPayload.stub(), account: Account.stub()) + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload(authPayload: AuthPayload.stub(), account: Account.stub()) let message = try sut.formatMessage(from: cacaoPayload) XCTAssertEqual(message, expectedMessage) } @@ -49,7 +49,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { - ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/ - https://example.com/my-web2-claim.json """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil) ), @@ -72,7 +72,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(resources: nil) ), @@ -94,7 +94,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil, resources: nil) ), @@ -123,7 +123,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(resources: [validRecapUrn]) ), @@ -152,7 +152,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { - urn:recap:eyJhdHQiOiB7ImVpcDE1NSI6IHsicmVxdWVzdC9ldGhfc2VuZFRyYW5zYWN0aW9uIjogW10sICJyZXF1ZXN0L3BlcnNvbmFsX3NpZ24iOiBbXX19fQ== """ - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil, resources: [validRecapUrn]) ), @@ -185,7 +185,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { let uri = "https://service.invalid?walletconnect_notify_key=did:key:z6MktW4hKdsvcXgt9wXmYbSD5sH4NCk5GmNZnokP9yh2TeCf" - let cacaoPayload = CacaoPayloadBuilder.makeCacaoPayload( + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( requestParams: AuthRequestParams.stub(statement: nil, resources: [recap1, recap2]) ), diff --git a/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift b/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift index 3fd5658aa..c18bb9b89 100644 --- a/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift +++ b/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift @@ -1,7 +1,7 @@ import Foundation @testable import WalletConnectUtils -class SIWEMessageFormatterMock: SIWECacaoFormatting { +class SIWEMessageFormatterMock: SIWEFromCacaoFormatting { func formatMessage(from payload: WalletConnectUtils.CacaoPayload, includeRecapInTheStatement: Bool) throws -> String { fatalError() } From d5e5fa2e3eb5903f363658f82aba5d20df2bde30 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 17:23:35 +0100 Subject: [PATCH 09/27] savepoint --- .../IntegrationTests.xctestplan | 1 - .../Auth/Signer/CacaoSignerTests.swift | 2 +- .../Auth/Services/CacaosBuilder.swift | 21 ++++++- .../SIWE/RecapStatementBuilder.swift | 4 +- .../SIWE/RecapUrnMergingService.swift | 21 ++++++- .../SIWE/SIWEFromCacaoPayloadFormatter.swift | 61 +++++++++++++------ .../SIWE/SiweMessageFormatter.swift | 45 -------------- .../SIWE/SiweStatementBuilder.swift | 2 +- .../SIWEFromCacaoPayloadFormatterTests.swift | 5 +- 9 files changed, 86 insertions(+), 76 deletions(-) delete mode 100644 Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift diff --git a/Example/ExampleApp.xcodeproj/IntegrationTests.xctestplan b/Example/ExampleApp.xcodeproj/IntegrationTests.xctestplan index 955607e33..40b79df1d 100644 --- a/Example/ExampleApp.xcodeproj/IntegrationTests.xctestplan +++ b/Example/ExampleApp.xcodeproj/IntegrationTests.xctestplan @@ -58,7 +58,6 @@ "ChatTests", "ENSResolverTests", "HistoryTests", - "SignClientTests\/testEIP1271SessionAuthenticated()", "SyncDerivationServiceTests", "SyncTests" ], diff --git a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift index d7634155f..c35cd57d5 100644 --- a/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift +++ b/Example/IntegrationTests/Auth/Signer/CacaoSignerTests.swift @@ -50,7 +50,7 @@ class CacaoSignerTest: XCTestCase { func testCacaoSign() throws { let account = Account("eip155:1:0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2")! - let cacaoPayload = try payload.cacaoPayload(account: account) + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload(authPayload: payload, account: account) let formatted = try SIWEFromCacaoPayloadFormatter().formatMessage(from: cacaoPayload) XCTAssertEqual(formatted, message) XCTAssertEqual(try signer.sign(payload: cacaoPayload, privateKey: privateKey, type: .eip191), signature) diff --git a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift index 5b8d34d10..5a97e8e9c 100644 --- a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift +++ b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift @@ -16,7 +16,23 @@ struct CacaoPayloadBuilder { let recapUrns = authPayload.resources?.compactMap { try? RecapUrn(urn: $0)} ?? [] let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) - let statement = try SiweStatementBuilder.buildSiweStatement(statement: authPayload.statement, mergedRecapUrn: mergedRecap) + var statement: String? + if let mergedRecapUrn = mergedRecap { + // If there's a merged recap, generate its statement + statement = try SiweStatementBuilder.buildSiweStatement(statement: authPayload.statement, mergedRecapUrn: mergedRecapUrn) + } else { + // If no merged recap, use the original statement + statement = authPayload.statement + } + + // Filter out any resources starting with "urn:recap:", then if mergedRecap exists, add its URN as the last element + var resources = authPayload.resources?.filter { !$0.starts(with: "urn:recap:") } ?? [] + if let mergedRecapUrn = mergedRecap { + // Assuming RecapUrn can be converted back to its string representation + let mergedRecapUrnString = mergedRecapUrn.urn + resources.append(mergedRecapUrnString) + } + return CacaoPayload( iss: account.did, domain: authPayload.domain, @@ -28,8 +44,7 @@ struct CacaoPayloadBuilder { exp: authPayload.exp, statement: statement, requestId: authPayload.requestId, - resources: authPayload.resources + resources: resources ) } - } diff --git a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift index 8b4d122ef..dcf404ef5 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift @@ -7,8 +7,8 @@ public struct RecapUrn { case invalidJsonStructure } - let urn: String - let recapData: RecapData + public let urn: String + public let recapData: RecapData public init(urn: String) throws { guard urn.hasPrefix("urn:recap") else { throw Errors.invalidUrn } diff --git a/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift index 9fc6662d6..02c7452d8 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapUrnMergingService.swift @@ -11,12 +11,14 @@ public class RecapUrnMergingService { throw Errors.emptyRecapUrns } + // If there's only one URN, return it directly. if recapUrns.count == 1 { return recapUrns.first! } var mergedAtt: [String: [String: [AnyCodable]]] = [:] + // Aggregate all actions under their respective keys for recapUrn in recapUrns { guard let att = recapUrn.recapData.att else { continue } for (key, value) in att { @@ -31,9 +33,22 @@ public class RecapUrnMergingService { } } - // Assuming RecapData can be encoded back to JSON and then to a Base64 string - let mergedData = RecapData(att: mergedAtt, prf: nil) - guard let jsonData = try? JSONEncoder().encode(mergedData), + // Sort and then ensure actions are also sorted, if necessary. + let sortedMergedAtt = mergedAtt + .sorted { $0.key < $1.key } + .reduce(into: [String: [String: [AnyCodable]]]()) { (result, pair) in + let (resource, actions) = pair + let sortedActions = actions + .sorted { $0.key < $1.key } + .reduce(into: [String: [AnyCodable]]()) { (actionsResult, actionPair) in + actionsResult[actionPair.key] = actionPair.value + } + result[resource] = sortedActions + } + + let encoder = JSONEncoder() + encoder.outputFormatting = [.sortedKeys] + guard let jsonData = try? encoder.encode(RecapData(att: sortedMergedAtt, prf: nil)), let jsonBase64 = jsonData.base64EncodedString().addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else { throw Errors.encodingFailed } diff --git a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift index 8f6ffbf0f..4851966a6 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift @@ -8,27 +8,54 @@ public extension SIWEFromCacaoFormatting { return try formatMessage(from: payload, includeRecapInTheStatement: true) } } + + public struct SIWEFromCacaoPayloadFormatter: SIWEFromCacaoFormatting { - public init() { } + public init() {} public func formatMessage(from payload: CacaoPayload, includeRecapInTheStatement: Bool) throws -> String { let iss = try DIDPKH(did: payload.iss) - let message = SIWEMessage( - domain: payload.domain, - uri: payload.aud, - address: iss.account.address, - version: payload.version, - nonce: payload.nonce, - chainId: iss.account.reference, - iat: payload.iat, - nbf: payload.nbf, - exp: payload.exp, - statement: payload.statement, - requestId: payload.requestId, - resources: payload.resources - ) - return try SiweMessageFormatter.format(siwe: message) + let address = iss.account.address + let chainId = iss.account.reference + + // Directly use the statement from payload, add a newline if it exists + let statementLine = payload.statement.flatMap { "\n\($0)" } ?? "" + + // Format the message with all details + let formattedMessage = """ + \(payload.domain) wants you to sign in with your Ethereum account: + \(address) + \(statementLine) + + URI: \(payload.aud) + Version: \(payload.version) + Chain ID: \(chainId) + Nonce: \(payload.nonce) + Issued At: \(payload.iat)\(formatExpLine(exp: payload.exp))\(formatNbfLine(nbf: payload.nbf))\(formatRequestIdLine(requestId: payload.requestId))\(formatResourcesSection(resources: payload.resources)) + """ + return formattedMessage + } + + // Helper methods for formatting individual parts of the message + private func formatExpLine(exp: String?) -> String { + guard let exp = exp else { return "" } + return "\nExpiration Time: \(exp)" + } + + private func formatNbfLine(nbf: String?) -> String { + guard let nbf = nbf else { return "" } + return "\nNot Before: \(nbf)" } -} + private func formatRequestIdLine(requestId: String?) -> String { + guard let requestId = requestId else { return "" } + return "\nRequest ID: \(requestId)" + } + + private func formatResourcesSection(resources: [String]?) -> String { + guard let resources = resources else { return "" } + let resourcesList = resources.reduce("") { $0 + "\n- \($1)" } + return resources.isEmpty ? "" : "\nResources:" + resourcesList + } +} diff --git a/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift b/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift deleted file mode 100644 index 2f9cb3d52..000000000 --- a/Sources/WalletConnectUtils/SIWE/SiweMessageFormatter.swift +++ /dev/null @@ -1,45 +0,0 @@ -import Foundation - -public class SiweMessageFormatter { - public static func format(siwe: SIWEMessage) throws -> String { - let recapUrns = siwe.resources?.compactMap { try? RecapUrn(urn: $0)} ?? [] - - let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) - let statementLine = try SiweStatementBuilder.buildSiweStatement(statement: siwe.statement, mergedRecapUrn: mergedRecap) - return """ - \(siwe.domain) wants you to sign in with your Ethereum account: - \(siwe.address) - \(statementLine) - - URI: \(siwe.uri) - Version: \(siwe.version) - Chain ID: \(siwe.chainId) - Nonce: \(siwe.nonce) - Issued At: \(siwe.iat)\(siwe.expLine)\(siwe.nbfLine)\(siwe.requestIdLine)\(siwe.resourcesSection) - """ - } -} - -private extension SIWEMessage { - - var expLine: String { - guard let exp = exp else { return "" } - return "\nExpiration Time: \(exp)" - } - - var nbfLine: String { - guard let nbf = nbf else { return "" } - return "\nNot Before: \(nbf)" - } - - var requestIdLine: String { - guard let requestId = requestId else { return "" } - return "\nRequest ID: \(requestId)" - } - - var resourcesSection: String { - guard let resources = resources else { return "" } - let resourcesList = resources.reduce("") { $0 + "\n- \($1)" } - return resources.isEmpty ? "" : "\nResources:" + resourcesList - } -} diff --git a/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift index bfdcfb923..fceed8b05 100644 --- a/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift +++ b/Sources/WalletConnectUtils/SIWE/SiweStatementBuilder.swift @@ -16,7 +16,7 @@ public class SiweStatementBuilder { } } - return finalStatement.isEmpty ? "" : "\n\(finalStatement)" + return finalStatement.isEmpty ? "" : "\(finalStatement)" } } diff --git a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift index fb9532440..d36d02e43 100644 --- a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift @@ -179,15 +179,14 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { Nonce: 32891756 Issued At: 2021-09-30T16:25:24Z Resources: - - urn:recap:ewogICAiYXR0Ijp7CiAgICAgICJlaXAxNTUiOnsKICAgICAgICAgInJlcXVlc3QvZXRoX3NlbmRUcmFuc2FjdGlvbiI6IFt7fV0sCiAgICAgICAgICJyZXF1ZXN0L3BlcnNvbmFsX3NpZ24iOiBbe31dCiAgICAgIH0KICAgfQp9 - - urn:recap:ewogICAiYXR0Ijp7CiAgICAgICJodHRwczovL25vdGlmeS53YWxsZXRjb25uZWN0LmNvbS9hbGwtYXBwcyI6ewogICAgICAgICAiY3J1ZC9ub3RpZmljYXRpb25zIjogW3t9XSwKICAgICAgICAgImNydWQvc3Vic2NyaXB0aW9ucyI6IFt7fV0KICAgICAgfQogICB9Cn0= + - urn:recap:eyJhdHQiOnsiZWlwMTU1Ijp7InJlcXVlc3RcL2V0aF9zZW5kVHJhbnNhY3Rpb24iOlt7fV0sInJlcXVlc3RcL3BlcnNvbmFsX3NpZ24iOlt7fV19LCJodHRwczpcL1wvbm90aWZ5LndhbGxldGNvbm5lY3QuY29tXC9hbGwtYXBwcyI6eyJjcnVkXC9ub3RpZmljYXRpb25zIjpbe31dLCJjcnVkXC9zdWJzY3JpcHRpb25zIjpbe31dfX19 """ let uri = "https://service.invalid?walletconnect_notify_key=did:key:z6MktW4hKdsvcXgt9wXmYbSD5sH4NCk5GmNZnokP9yh2TeCf" let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( authPayload: AuthPayload.stub( - requestParams: AuthRequestParams.stub(statement: nil, resources: [recap1, recap2]) + requestParams: AuthRequestParams.stub(uri: uri, statement: nil, resources: [recap1, recap2]) ), account: Account.stub()) let message = try sut.formatMessage(from: cacaoPayload) From 50dbfb57e7c88f14f152c0afc579faff709b1c08 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 17:27:52 +0100 Subject: [PATCH 10/27] savepoint --- .../SIWE/RecapStatementBuilder.swift | 33 ---------- .../WalletConnectUtils/SIWE/RecapUrn.swift | 63 +++++++++++++++++++ .../SIWEFromCacaoPayloadFormatterTests.swift | 2 +- .../RecapUrnTests.swift | 2 +- 4 files changed, 65 insertions(+), 35 deletions(-) create mode 100644 Sources/WalletConnectUtils/SIWE/RecapUrn.swift diff --git a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift index dcf404ef5..859a01521 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapStatementBuilder.swift @@ -1,38 +1,5 @@ import Foundation -public struct RecapUrn { - enum Errors: Error { - case invalidUrn - case invalidPayload - case invalidJsonStructure - } - - public let urn: String - public let recapData: RecapData - - public init(urn: String) throws { - guard urn.hasPrefix("urn:recap") else { throw Errors.invalidUrn } - - let components = urn.components(separatedBy: ":") - guard components.count > 2, let jsonData = Data(base64Encoded: components.dropFirst(2).joined(separator: ":")) else { - throw Errors.invalidPayload - } - - do { - self.recapData = try JSONDecoder().decode(RecapData.self, from: jsonData) - } catch { - throw Errors.invalidJsonStructure - } - - self.urn = urn - } -} - -public struct RecapData: Codable { - var att: [String: [String: [AnyCodable]]]? - var prf: [String]? -} - struct RecapStatementBuilder { enum Errors: Error { case noActionsAuthorized diff --git a/Sources/WalletConnectUtils/SIWE/RecapUrn.swift b/Sources/WalletConnectUtils/SIWE/RecapUrn.swift new file mode 100644 index 000000000..64d1068d3 --- /dev/null +++ b/Sources/WalletConnectUtils/SIWE/RecapUrn.swift @@ -0,0 +1,63 @@ +import Foundation + +public struct RecapData: Codable { + var att: [String: [String: [AnyCodable]]]? + var prf: [String]? +} + +public struct RecapUrn { + enum Errors: Error { + case invalidUrn + case invalidPayload + case invalidJsonStructure + } + + public let urn: String + public let recapData: RecapData + + public init(urn: String) throws { + guard urn.hasPrefix("urn:recap") else { throw Errors.invalidUrn } + + let components = urn.components(separatedBy: ":") + guard components.count > 2 else { + throw Errors.invalidPayload + } + + let base64urlEncodedPayload = components.dropFirst(2).joined(separator: ":") + guard let jsonData = Data(base64urlEncoded: base64urlEncodedPayload) else { + throw Errors.invalidPayload + } + + do { + self.recapData = try JSONDecoder().decode(RecapData.self, from: jsonData) + } catch { + throw Errors.invalidJsonStructure + } + + self.urn = urn + } +} + +extension Data { + /// Initializes a Data object with a base64url encoded String. + init?(base64urlEncoded: String) { + var base64 = base64urlEncoded + .replacingOccurrences(of: "-", with: "+") + .replacingOccurrences(of: "_", with: "/") + + // Add padding if necessary + while base64.count % 4 != 0 { + base64 += "=" + } + + self.init(base64Encoded: base64) + } + + /// Returns a base64url encoded String. + func base64urlEncodedString() -> String { + return self.base64EncodedString() + .replacingOccurrences(of: "+", with: "-") + .replacingOccurrences(of: "/", with: "_") + .trimmingCharacters(in: ["="]) // Remove any padding + } +} diff --git a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift index d36d02e43..d5ad69c69 100644 --- a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift @@ -164,7 +164,7 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { func testWithSignAndNotifyRecaps() throws { let recap1 = "urn:recap:ewogICAiYXR0Ijp7CiAgICAgICJlaXAxNTUiOnsKICAgICAgICAgInJlcXVlc3QvZXRoX3NlbmRUcmFuc2FjdGlvbiI6IFt7fV0sCiAgICAgICAgICJyZXF1ZXN0L3BlcnNvbmFsX3NpZ24iOiBbe31dCiAgICAgIH0KICAgfQp9" - let recap2 = "urn:recap:ewogICAiYXR0Ijp7CiAgICAgICJodHRwczovL25vdGlmeS53YWxsZXRjb25uZWN0LmNvbS9hbGwtYXBwcyI6ewogICAgICAgICAiY3J1ZC9ub3RpZmljYXRpb25zIjogW3t9XSwKICAgICAgICAgImNydWQvc3Vic2NyaXB0aW9ucyI6IFt7fV0KICAgICAgfQogICB9Cn0=" + let recap2 = "urn:recap:ewogICAiYXR0Ijp7CiAgICAgICJodHRwczovL25vdGlmeS53YWxsZXRjb25uZWN0LmNvbS9hbGwtYXBwcyI6ewogICAgICAgICAiY3J1ZC9ub3RpZmljYXRpb25zIjogW3t9XSwKICAgICAgICAgImNydWQvc3Vic2NyaXB0aW9ucyI6IFt7fV0KICAgICAgfQogICB9Cn0" let expectedMessage = """ diff --git a/Tests/WalletConnectUtilsTests/RecapUrnTests.swift b/Tests/WalletConnectUtilsTests/RecapUrnTests.swift index 08e098a3b..9d7b87a49 100644 --- a/Tests/WalletConnectUtilsTests/RecapUrnTests.swift +++ b/Tests/WalletConnectUtilsTests/RecapUrnTests.swift @@ -14,7 +14,7 @@ class RecapUrnTests: XCTestCase { let invalidPayloadUrn = "urn:recap:invalidPayload" XCTAssertThrowsError(try RecapUrn(urn: invalidPayloadUrn)) { error in - XCTAssertEqual(error as? RecapUrn.Errors, RecapUrn.Errors.invalidPayload) + XCTAssertEqual(error as? RecapUrn.Errors, RecapUrn.Errors.invalidJsonStructure) } } From bdf280dc12d83d262298d51d0edc7acc3cef7cb1 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Sun, 10 Mar 2024 17:52:20 +0100 Subject: [PATCH 11/27] fix notify tests --- Example/IntegrationTests/Push/NotifyTests.swift | 6 +++--- .../WalletConnectIdentity/IdentityService.swift | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Example/IntegrationTests/Push/NotifyTests.swift b/Example/IntegrationTests/Push/NotifyTests.swift index f16e5550f..2b08baca7 100644 --- a/Example/IntegrationTests/Push/NotifyTests.swift +++ b/Example/IntegrationTests/Push/NotifyTests.swift @@ -124,9 +124,9 @@ final class NotifyTests: XCTestCase { expectation.fulfill() }.store(in: &publishers) - try! await walletNotifyClientA.register(account: account, domain: "https://\(gmDappDomain)", onSign: sign) + try! await walletNotifyClientA.register(account: account, domain: gmDappDomain, onSign: sign) try! await walletNotifyClientA.subscribe(appDomain: gmDappDomain, account: account) - try! await clientB.register(account: account, domain: "https://\(gmDappDomain)", onSign: sign) + try! await clientB.register(account: account, domain: gmDappDomain, onSign: sign) await fulfillment(of: [expectation], timeout: InputConfig.defaultTimeout) @@ -282,7 +282,7 @@ private extension NotifyTests { private extension NotifyClient { func register(account: Account, domain: String, onSign: @escaping (String) -> CacaoSignature) async throws { - let params = try await prepareRegistration(account: account, domain: domain) + let params = try await prepareRegistration(account: account, domain: "https://\(domain)") let signature = onSign(params.message) try await register(params: params, signature: signature) } diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index 9483a9545..0e58ecab9 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -34,6 +34,18 @@ actor IdentityService { let uri = buildUri(domain: domain, didKey: identityKey.publicKey.did) + let recapUrns = resources.compactMap { try? RecapUrn(urn: $0)} + + let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) + var payloadStatement: String? + if let mergedRecapUrn = mergedRecap { + // If there's a merged recap, generate its statement + payloadStatement = try SiweStatementBuilder.buildSiweStatement(statement: statement, mergedRecapUrn: mergedRecapUrn) + } else { + // If no merged recap, use the original statement + payloadStatement = statement + } + let payload = CacaoPayload( iss: account.did, domain: domain, @@ -42,7 +54,7 @@ actor IdentityService { nonce: getNonce(), iat: iatProvader.iat, nbf: nil, exp: nil, - statement: statement, + statement: payloadStatement, requestId: nil, resources: resources ) From 7c8f162c34e557ac56cce56bc1989d150b6c4e5a Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Mar 2024 09:26:26 +0100 Subject: [PATCH 12/27] savepoint --- Example/ExampleApp.xcodeproj/project.pbxproj | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index ee3931981..65b54643f 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -2897,11 +2897,9 @@ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = PNDecryptionService/PNDecryptionServiceRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; + DEVELOPMENT_TEAM = W5R8AG9K22; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = PNDecryptionService/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = PNDecryptionService; @@ -2916,7 +2914,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp.PNDecryptionService; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp.PNDecryptionService"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -3115,12 +3112,10 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WalletApp/WalletAppRelease.entitlements; - CODE_SIGN_IDENTITY = "Apple Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 7; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = W5R8AG9K22; + DEVELOPMENT_TEAM = W5R8AG9K22; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WalletApp/Other/Info.plist; @@ -3139,7 +3134,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.walletconnect.walletapp; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore com.walletconnect.walletapp"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; From d52a98671e7232d4b153d6c8e00d68e1aae589bd Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Mar 2024 15:33:42 +0100 Subject: [PATCH 13/27] savepoint --- .../WalletConnectSign/Auth/Services/AuthPayloadBuilder.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectSign/Auth/Services/AuthPayloadBuilder.swift b/Sources/WalletConnectSign/Auth/Services/AuthPayloadBuilder.swift index 1db2dc9b5..19685d83a 100644 --- a/Sources/WalletConnectSign/Auth/Services/AuthPayloadBuilder.swift +++ b/Sources/WalletConnectSign/Auth/Services/AuthPayloadBuilder.swift @@ -6,12 +6,13 @@ public struct AuthPayloadBuilder { public static func build(payload: AuthPayload, supportedEVMChains: [Blockchain], supportedMethods: [String]) throws -> AuthPayload { // Attempt to find a valid session recap URN from the resources - guard let existingSessionRecapUrn = payload.resources?.first(where: { (try? SignRecap(urn: $0)) != nil }) else { + guard let recap = payload.resources?.last, + let _ = try? SignRecap(urn: recap) else { return payload } // Use SessionRecapBuilder to create a new session recap based on the existing valid URN - let newSessionRecap = try SignRecapBuilder.build(requestedSessionRecap: existingSessionRecapUrn, requestedChains: payload.chains, supportedEVMChains: supportedEVMChains, supportedMethods: supportedMethods) + let newSessionRecap = try SignRecapBuilder.build(requestedSessionRecap: recap, requestedChains: payload.chains, supportedEVMChains: supportedEVMChains, supportedMethods: supportedMethods) // Encode the new session recap to its URN format let newSessionRecapUrn = newSessionRecap.urn From 5bcb2e8346f122cb87a8bb80425731e45feb79f6 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Mar 2024 15:43:29 +0100 Subject: [PATCH 14/27] fix recap --- Sources/WalletConnectIdentity/IdentityService.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectIdentity/IdentityService.swift b/Sources/WalletConnectIdentity/IdentityService.swift index 0e58ecab9..179ee478f 100644 --- a/Sources/WalletConnectIdentity/IdentityService.swift +++ b/Sources/WalletConnectIdentity/IdentityService.swift @@ -65,7 +65,7 @@ actor IdentityService { } func buildUri(domain: String, didKey: String) -> String { - return "\(domain)?walletconnect_identity_key=\(didKey)" + return "bundleid://\(domain)?walletconnect_identity_key=\(didKey)" } // TODO: Verifications From 1b1cb91679d846d1dda2c369e7b8c012bbd19374 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Mar 2024 15:47:30 +0100 Subject: [PATCH 15/27] savepoint --- .../Stub/SIWEMessageFormatterMock.swift | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift diff --git a/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift b/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift deleted file mode 100644 index c18bb9b89..000000000 --- a/Tests/WalletConnectSignTests/Stub/SIWEMessageFormatterMock.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation -@testable import WalletConnectUtils - -class SIWEMessageFormatterMock: SIWEFromCacaoFormatting { - func formatMessage(from payload: WalletConnectUtils.CacaoPayload, includeRecapInTheStatement: Bool) throws -> String { - fatalError() - } - - - var formattedMessage: String! - - func formatMessages(from payload: CacaoPayload) throws -> String { - return formattedMessage - } -} From 3e0260727f4a002e0a82478e5dea1f2d76fa82b3 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Mon, 11 Mar 2024 15:55:05 +0100 Subject: [PATCH 16/27] fix missing resources in siwe --- .../SIWE/SIWEFromCacaoPayloadFormatter.swift | 5 ++- .../WalletConnectUtils/SIWE/SIWEMessage.swift | 32 ------------------- 2 files changed, 2 insertions(+), 35 deletions(-) delete mode 100644 Sources/WalletConnectUtils/SIWE/SIWEMessage.swift diff --git a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift index 4851966a6..c26be1ee1 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift @@ -54,8 +54,7 @@ public struct SIWEFromCacaoPayloadFormatter: SIWEFromCacaoFormatting { } private func formatResourcesSection(resources: [String]?) -> String { - guard let resources = resources else { return "" } - let resourcesList = resources.reduce("") { $0 + "\n- \($1)" } - return resources.isEmpty ? "" : "\nResources:" + resourcesList + let resourcesList = resources?.reduce("") { $0 + "\n- \($1)" } ?? "" + return "\nResources:" + resourcesList } } diff --git a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift b/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift deleted file mode 100644 index 88cf98c27..000000000 --- a/Sources/WalletConnectUtils/SIWE/SIWEMessage.swift +++ /dev/null @@ -1,32 +0,0 @@ -import Foundation - -public struct SIWEMessage: Equatable { - public let domain: String - public let uri: String // aud - public let address: String - public let version: String - public let nonce: String - public let chainId: String - public let iat: String - public let nbf: String? - public let exp: String? - public let statement: String? - public let requestId: String? - public let resources: [String]? - - public init(domain: String, uri: String, address: String, version: String, nonce: String, chainId: String, iat: String, nbf: String?, exp: String?, statement: String?, requestId: String?, resources: [String]?) { - self.domain = domain - self.uri = uri - self.address = address - self.version = version - self.nonce = nonce - self.chainId = chainId - self.iat = iat - self.nbf = nbf - self.exp = exp - self.statement = statement - self.requestId = requestId - self.resources = resources - } -} - From 2d45e2de4c4f1107c021f3ecf1f6177ed6fc53ef Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 08:38:59 +0100 Subject: [PATCH 17/27] fix recap encoding issue --- Sources/WalletConnectSign/Auth/Services/SignRecap.swift | 2 +- Sources/WalletConnectUtils/SIWE/RecapUrn.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/WalletConnectSign/Auth/Services/SignRecap.swift b/Sources/WalletConnectSign/Auth/Services/SignRecap.swift index 973378553..bcda4fdba 100644 --- a/Sources/WalletConnectSign/Auth/Services/SignRecap.swift +++ b/Sources/WalletConnectSign/Auth/Services/SignRecap.swift @@ -20,7 +20,7 @@ struct SignRecap { } let base64Part = urn.dropFirst("urn:recap:".count) - guard let jsonData = Data(base64Encoded: String(base64Part)), + guard let jsonData = Data(base64urlEncoded: String(base64Part)), let decodedData = try? JSONDecoder().decode(RecapData.self, from: jsonData) else { throw Errors.invalidRecapStructure } diff --git a/Sources/WalletConnectUtils/SIWE/RecapUrn.swift b/Sources/WalletConnectUtils/SIWE/RecapUrn.swift index 64d1068d3..161c80530 100644 --- a/Sources/WalletConnectUtils/SIWE/RecapUrn.swift +++ b/Sources/WalletConnectUtils/SIWE/RecapUrn.swift @@ -38,7 +38,7 @@ public struct RecapUrn { } } -extension Data { +public extension Data { /// Initializes a Data object with a base64url encoded String. init?(base64urlEncoded: String) { var base64 = base64urlEncoded From febad38754b7052dc8fa6a846eba6f38e9d4a906 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 08:57:07 +0100 Subject: [PATCH 18/27] savepoint --- .../Auth/Services/App/AuthResponseSubscriber.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift b/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift index a57be3a44..e223dd142 100644 --- a/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift +++ b/Sources/WalletConnectSign/Auth/Services/App/AuthResponseSubscriber.swift @@ -57,7 +57,6 @@ class AuthResponseSubscriber { let requestId = payload.id let cacaos = payload.response.cacaos - let authRequestPayload = payload.request.authPayload Task { do { @@ -66,7 +65,7 @@ class AuthResponseSubscriber { authResponsePublisherSubject.send((requestId, .failure(error as! AuthError))) return } - let session = try createSession(from: payload.response, selfParticipant: payload.request.requester, pairingTopic: pairingTopic, authRequestPayload: authRequestPayload) + let session = try createSession(from: payload.response, selfParticipant: payload.request.requester, pairingTopic: pairingTopic) authResponsePublisherSubject.send((requestId, .success((session, cacaos)))) } @@ -98,8 +97,7 @@ class AuthResponseSubscriber { private func createSession( from response: SessionAuthenticateResponseParams, selfParticipant: Participant, - pairingTopic: String, - authRequestPayload: AuthPayload + pairingTopic: String ) throws -> Session? { let selfPublicKey = try AgreementPublicKey(hex: selfParticipant.publicKey) From a5851020bc3fbc491a354b88a92112e7c9fb4c80 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 10:22:50 +0100 Subject: [PATCH 19/27] savepoint --- .../Auth/Services/CacaosBuilder.swift | 28 ++++++++++--------- .../SIWE/SIWEFromCacaoPayloadFormatter.swift | 5 ++-- .../SIWEFromCacaoPayloadFormatterTests.swift | 24 ++++++++++++++++ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift index 5a97e8e9c..572eba175 100644 --- a/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift +++ b/Sources/WalletConnectSign/Auth/Services/CacaosBuilder.swift @@ -13,24 +13,24 @@ struct CacaosBuilder { struct CacaoPayloadBuilder { public static func makeCacaoPayload(authPayload: AuthPayload, account: WalletConnectUtils.Account) throws -> CacaoPayload { - let recapUrns = authPayload.resources?.compactMap { try? RecapUrn(urn: $0)} ?? [] + var mergedRecap: RecapUrn? + var resources: [String]? = nil - let mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) - var statement: String? + if let recapUrns = authPayload.resources?.compactMap({ try? RecapUrn(urn: $0) }), !recapUrns.isEmpty { + mergedRecap = try? RecapUrnMergingService.merge(recapUrns: recapUrns) + } + + var statement: String? = authPayload.statement if let mergedRecapUrn = mergedRecap { - // If there's a merged recap, generate its statement statement = try SiweStatementBuilder.buildSiweStatement(statement: authPayload.statement, mergedRecapUrn: mergedRecapUrn) - } else { - // If no merged recap, use the original statement - statement = authPayload.statement } - // Filter out any resources starting with "urn:recap:", then if mergedRecap exists, add its URN as the last element - var resources = authPayload.resources?.filter { !$0.starts(with: "urn:recap:") } ?? [] - if let mergedRecapUrn = mergedRecap { - // Assuming RecapUrn can be converted back to its string representation - let mergedRecapUrnString = mergedRecapUrn.urn - resources.append(mergedRecapUrnString) + // Initialize resources with the filtered list only if authPayload.resources was not nil + if authPayload.resources != nil { + resources = authPayload.resources?.filter { !$0.starts(with: "urn:recap:") } + if let mergedRecapUrnString = mergedRecap?.urn { + resources?.append(mergedRecapUrnString) + } } return CacaoPayload( @@ -48,3 +48,5 @@ struct CacaoPayloadBuilder { ) } } + + diff --git a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift index c26be1ee1..70a7f2dec 100644 --- a/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift +++ b/Sources/WalletConnectUtils/SIWE/SIWEFromCacaoPayloadFormatter.swift @@ -54,7 +54,8 @@ public struct SIWEFromCacaoPayloadFormatter: SIWEFromCacaoFormatting { } private func formatResourcesSection(resources: [String]?) -> String { - let resourcesList = resources?.reduce("") { $0 + "\n- \($1)" } ?? "" - return "\nResources:" + resourcesList + guard let resources = resources else { return "" } + let resourcesList = resources.reduce("") { $0 + "\n- \($1)" } + return resources.isEmpty ? "\nResources:" : "\nResources:" + resourcesList } } diff --git a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift index d5ad69c69..53773cbb2 100644 --- a/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift +++ b/Tests/WalletConnectSignTests/SIWEFromCacaoPayloadFormatterTests.swift @@ -81,6 +81,30 @@ class SIWEFromCacaoPayloadFormatterTests: XCTestCase { XCTAssertEqual(message, expectedMessage) } + func testResourcesEmptyArray() throws { + let expectedMessage = + """ + service.invalid wants you to sign in with your Ethereum account: + 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 + + I accept the ServiceOrg Terms of Service: https://service.invalid/tos + + URI: https://service.invalid/login + Version: 1 + Chain ID: 1 + Nonce: 32891756 + Issued At: 2021-09-30T16:25:24Z + Resources: + """ + let cacaoPayload = try CacaoPayloadBuilder.makeCacaoPayload( + authPayload: AuthPayload.stub( + requestParams: AuthRequestParams.stub(resources: []) + ), + account: Account.stub()) + let message = try sut.formatMessage(from: cacaoPayload) + XCTAssertEqual(message, expectedMessage) + } + func testNilAllOptionalParams() throws { let expectedMessage = """ From fcb0c26dce9ea69b36207a3bebc12ed4196ddb66 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 10:50:59 +0100 Subject: [PATCH 20/27] savepoint --- Example/DApp/Modules/Sign/SignPresenter.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/DApp/Modules/Sign/SignPresenter.swift b/Example/DApp/Modules/Sign/SignPresenter.swift index 656a5be23..a02612d54 100644 --- a/Example/DApp/Modules/Sign/SignPresenter.swift +++ b/Example/DApp/Modules/Sign/SignPresenter.swift @@ -83,7 +83,7 @@ final class SignPresenter: ObservableObject { Task { do { ActivityIndicatorManager.shared.start() - let uri = try await Sign.instance.authenticate(.stub()) + let uri = try await Sign.instance.authenticate(.stub(resources: ["urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9ub3RpZnkud2FsbGV0Y29ubmVjdC5jb20iOnsibWFuYWdlL3BhbmNha2Vzd2FwLmNvbS1ub3RpZmljYXRpb25zIjpbe31dfX19"])) walletConnectUri = uri ActivityIndicatorManager.shared.stop() router.presentNewPairing(walletConnectUri: walletConnectUri!) From 87209e054b77375fc4601a4119bb970249c96009 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 11:00:51 +0100 Subject: [PATCH 21/27] fix auth build --- Sources/Auth/AuthClient.swift | 2 +- Sources/Auth/AuthClientFactory.swift | 2 +- Sources/Auth/Services/App/AppRespondSubscriber.swift | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Auth/AuthClient.swift b/Sources/Auth/AuthClient.swift index 34cad9e0c..d1e34537d 100644 --- a/Sources/Auth/AuthClient.swift +++ b/Sources/Auth/AuthClient.swift @@ -103,7 +103,7 @@ public class AuthClient: AuthClientProtocol { @available(*, deprecated, message: "Use SignClient or Web3Wallet for message formatting.") public func formatMessage(payload: AuthPayload, address: String) throws -> String { - return try SIWECacaoFormatter().formatMessage(from: payload.cacaoPayload(address: address)) + return try SIWEFromCacaoPayloadFormatter().formatMessage(from: payload.cacaoPayload(address: address)) } private func setUpPublishers() { diff --git a/Sources/Auth/AuthClientFactory.swift b/Sources/Auth/AuthClientFactory.swift index c2748c5bd..ae73f8d7e 100644 --- a/Sources/Auth/AuthClientFactory.swift +++ b/Sources/Auth/AuthClientFactory.swift @@ -42,7 +42,7 @@ public struct AuthClientFactory { ) -> AuthClient { let kms = KeyManagementService(keychain: keychainStorage) let history = RPCHistoryFactory.createForNetwork(keyValueStorage: keyValueStorage) - let messageFormatter = SIWECacaoFormatter() + let messageFormatter = SIWEFromCacaoPayloadFormatter() let appRequestService = AppRequestService(networkingInteractor: networkingClient, kms: kms, appMetadata: metadata, logger: logger, iatProvader: iatProvider) let verifyClient = VerifyClientFactory.create() let verifyContextStore = CodableStore(defaults: keyValueStorage, identifier: VerifyStorageIdentifiers.context.rawValue) diff --git a/Sources/Auth/Services/App/AppRespondSubscriber.swift b/Sources/Auth/Services/App/AppRespondSubscriber.swift index 0973e1cf1..25c7917e0 100644 --- a/Sources/Auth/Services/App/AppRespondSubscriber.swift +++ b/Sources/Auth/Services/App/AppRespondSubscriber.swift @@ -6,7 +6,7 @@ class AppRespondSubscriber { private let logger: ConsoleLogging private let rpcHistory: RPCHistory private let signatureVerifier: MessageVerifier - private let messageFormatter: SIWECacaoFormatting + private let messageFormatter: SIWEFromCacaoPayloadFormatter private let pairingRegisterer: PairingRegisterer private var publishers = [AnyCancellable]() @@ -17,7 +17,7 @@ class AppRespondSubscriber { rpcHistory: RPCHistory, signatureVerifier: MessageVerifier, pairingRegisterer: PairingRegisterer, - messageFormatter: SIWECacaoFormatting) { + messageFormatter: SIWEFromCacaoPayloadFormatter) { self.networkingInteractor = networkingInteractor self.logger = logger self.rpcHistory = rpcHistory From f5c67e61ad78720241b8eb864191903dc6dcd291 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 11:37:32 +0100 Subject: [PATCH 22/27] remove unused files --- Example/ExampleApp.xcodeproj/project.pbxproj | 20 -- Example/IntegrationTests/Auth/AuthTests.swift | 212 ------------------ Example/IntegrationTests/Chat/ChatTests.swift | 169 -------------- .../IntegrationTests/Chat/RegistryTests.swift | 64 ------ 4 files changed, 465 deletions(-) delete mode 100644 Example/IntegrationTests/Auth/AuthTests.swift delete mode 100644 Example/IntegrationTests/Chat/ChatTests.swift delete mode 100644 Example/IntegrationTests/Chat/RegistryTests.swift diff --git a/Example/ExampleApp.xcodeproj/project.pbxproj b/Example/ExampleApp.xcodeproj/project.pbxproj index 65b54643f..9f5e8dba5 100644 --- a/Example/ExampleApp.xcodeproj/project.pbxproj +++ b/Example/ExampleApp.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 767DC83528997F8E00080FA9 /* EthSendTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */; }; - 7694A5262874296A0001257E /* RegistryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7694A5252874296A0001257E /* RegistryTests.swift */; }; 842B1D132B988BC5007F1EF8 /* Web3Modal in Frameworks */ = {isa = PBXBuildFile; productRef = 842B1D122B988BC5007F1EF8 /* Web3Modal */; }; 842B1D152B988BC5007F1EF8 /* Web3ModalUI in Frameworks */ = {isa = PBXBuildFile; productRef = 842B1D142B988BC5007F1EF8 /* Web3ModalUI */; }; 842B1D172B988BF0007F1EF8 /* Web3ModalUI in Frameworks */ = {isa = PBXBuildFile; productRef = 842B1D162B988BF0007F1EF8 /* Web3ModalUI */; }; @@ -56,7 +55,6 @@ 84CE642B27981DF000142511 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84CE642927981DF000142511 /* LaunchScreen.storyboard */; }; 84CEC64628D89D6B00D081A8 /* PairingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84CEC64528D89D6B00D081A8 /* PairingTests.swift */; }; 84D093EB2B4EA6CB005B1925 /* ActivityIndicatorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D093EA2B4EA6CB005B1925 /* ActivityIndicatorManager.swift */; }; - 84D2A66628A4F51E0088AE09 /* AuthTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D2A66528A4F51E0088AE09 /* AuthTests.swift */; }; 84DB38F32983CDAE00BFEE37 /* PushRegisterer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84DB38F22983CDAE00BFEE37 /* PushRegisterer.swift */; }; 84E6B84A29787A8000428BAF /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E6B84929787A8000428BAF /* NotificationService.swift */; }; 84E6B84E29787A8000428BAF /* PNDecryptionService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 84E6B84729787A8000428BAF /* PNDecryptionService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -211,7 +209,6 @@ A5E03DFD286465D100888481 /* Stubs.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03DFC286465D100888481 /* Stubs.swift */; }; A5E03DFF2864662500888481 /* WalletConnect in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03DFE2864662500888481 /* WalletConnect */; }; A5E03E01286466EA00888481 /* WalletConnectChat in Frameworks */ = {isa = PBXBuildFile; productRef = A5E03E00286466EA00888481 /* WalletConnectChat */; }; - A5E03E03286466F400888481 /* ChatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E02286466F400888481 /* ChatTests.swift */; }; A5E03E1128646F8000888481 /* KeychainStorageMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E03E1028646F8000888481 /* KeychainStorageMock.swift */; }; A5E22D1A2840C62A00E36487 /* Engine.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D192840C62A00E36487 /* Engine.swift */; }; A5E22D1C2840C85D00E36487 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E22D1B2840C85D00E36487 /* App.swift */; }; @@ -397,7 +394,6 @@ 764E1D5526F8DADE00A1FB15 /* WalletConnectSwiftV2 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = WalletConnectSwiftV2; path = ..; sourceTree = ""; }; 764E1D5626F8DB6000A1FB15 /* WalletConnectSwiftV2 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = WalletConnectSwiftV2; path = ..; sourceTree = ""; }; 767DC83428997F8E00080FA9 /* EthSendTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthSendTransaction.swift; sourceTree = ""; }; - 7694A5252874296A0001257E /* RegistryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistryTests.swift; sourceTree = ""; }; 84310D04298BC980000C15B6 /* MainInteractor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainInteractor.swift; sourceTree = ""; }; 8439CB88293F658E00F2F2E2 /* PushMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushMessage.swift; sourceTree = ""; }; 844749F329B9E5B9005F520B /* RelayIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RelayIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -438,7 +434,6 @@ 84CE6453279FFE1100142511 /* Wallet.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Wallet.entitlements; sourceTree = ""; }; 84CEC64528D89D6B00D081A8 /* PairingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PairingTests.swift; sourceTree = ""; }; 84D093EA2B4EA6CB005B1925 /* ActivityIndicatorManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorManager.swift; sourceTree = ""; }; - 84D2A66528A4F51E0088AE09 /* AuthTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthTests.swift; sourceTree = ""; }; 84D72FC62B4692770057EAF3 /* DApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DApp.entitlements; sourceTree = ""; }; 84DB38F029828A7C00BFEE37 /* WalletApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WalletApp.entitlements; sourceTree = ""; }; 84DB38F129828A7F00BFEE37 /* PNDecryptionService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PNDecryptionService.entitlements; sourceTree = ""; }; @@ -569,7 +564,6 @@ A5E03DED286464DB00888481 /* IntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; A5E03DF9286465C700888481 /* SignClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignClientTests.swift; sourceTree = ""; }; A5E03DFC286465D100888481 /* Stubs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stubs.swift; sourceTree = ""; }; - A5E03E02286466F400888481 /* ChatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatTests.swift; sourceTree = ""; }; A5E03E1028646F8000888481 /* KeychainStorageMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainStorageMock.swift; sourceTree = ""; }; A5E22D192840C62A00E36487 /* Engine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Engine.swift; sourceTree = ""; }; A5E22D1B2840C85D00E36487 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; @@ -981,7 +975,6 @@ children = ( A58A1ECA29BF457800A82A20 /* ENS */, A54195992934BFDD0035AD19 /* Signer */, - 84D2A66528A4F51E0088AE09 /* AuthTests.swift */, ); path = Auth; sourceTree = ""; @@ -1462,21 +1455,11 @@ 84CEC64728D8A98900D081A8 /* Pairing */, A5E03E0A28646A8A00888481 /* Stubs */, A5E03E0928646A8100888481 /* Sign */, - A5E03E0828646A7B00888481 /* Chat */, 84D2A66728A4F5260088AE09 /* Auth */, ); path = IntegrationTests; sourceTree = ""; }; - A5E03E0828646A7B00888481 /* Chat */ = { - isa = PBXGroup; - children = ( - A5E03E02286466F400888481 /* ChatTests.swift */, - 7694A5252874296A0001257E /* RegistryTests.swift */, - ); - path = Chat; - sourceTree = ""; - }; A5E03E0928646A8100888481 /* Sign */ = { isa = PBXGroup; children = ( @@ -2414,12 +2397,9 @@ A541959E2934BFEF0035AD19 /* CacaoSignerTests.swift in Sources */, A59CF4F6292F83D50031A42F /* DefaultSignerFactory.swift in Sources */, 847F08012A25DBFF00B2A5A4 /* XPlatformW3WTests.swift in Sources */, - A5E03E03286466F400888481 /* ChatTests.swift in Sources */, 849D7A93292E2169006A2BD4 /* NotifyTests.swift in Sources */, 845B8D8C2934B36C0084A966 /* Account.swift in Sources */, - 84D2A66628A4F51E0088AE09 /* AuthTests.swift in Sources */, 84FE684628ACDB4700C893FF /* RequestParams.swift in Sources */, - 7694A5262874296A0001257E /* RegistryTests.swift in Sources */, A541959F2934BFEF0035AD19 /* SignerTests.swift in Sources */, A58A1ECC29BF458600A82A20 /* ENSResolverTests.swift in Sources */, A5E03DFA286465C700888481 /* SignClientTests.swift in Sources */, diff --git a/Example/IntegrationTests/Auth/AuthTests.swift b/Example/IntegrationTests/Auth/AuthTests.swift deleted file mode 100644 index aed8cba64..000000000 --- a/Example/IntegrationTests/Auth/AuthTests.swift +++ /dev/null @@ -1,212 +0,0 @@ -// -//import Foundation -//import XCTest -//@testable import WalletConnectUtils -//@testable import WalletConnectKMS -//import WalletConnectRelay -//import Combine -//@testable import Auth -//import WalletConnectPairing -//import WalletConnectNetworking -//import WalletConnectVerify -// -//final class AuthTests: XCTestCase { -// var appPairingClient: PairingClient! -// var walletPairingClient: PairingClient! -// -// var appAuthClient: AuthClient! -// var walletAuthClient: AuthClient! -// -// let walletAccount = Account(chainIdentifier: "eip155:1", address: "0x724d0D2DaD3fbB0C168f947B87Fa5DBe36F1A8bf")! -// let prvKey = Data(hex: "462c1dad6832d7d96ccf87bd6a686a4110e114aaaebd5512e552c0e3a87b480f") -// let eip1271Signature = "0xc1505719b2504095116db01baaf276361efd3a73c28cf8cc28dabefa945b8d536011289ac0a3b048600c1e692ff173ca944246cf7ceb319ac2262d27b395c82b1c" -// private var publishers = [AnyCancellable]() -// -// override func setUp() { -// setupClients() -// } -// -// private func setupClients(iatProvider: IATProvider = DefaultIATProvider()) { -// (appPairingClient, appAuthClient) = makeClients(prefix: "🤖 App", iatProvider: iatProvider) -// (walletPairingClient, walletAuthClient) = makeClients(prefix: "🐶 Wallet", iatProvider: iatProvider) -// } -// -// func makeClients(prefix: String, iatProvider: IATProvider) -> (PairingClient, AuthClient) { -// let logger = ConsoleLogger(prefix: prefix, loggingLevel: .debug) -// let keyValueStorage = RuntimeKeyValueStorage() -// let keychain = KeychainStorageMock() -// let relayClient = RelayClientFactory.create( -// relayHost: InputConfig.relayHost, -// projectId: InputConfig.projectId, -// keyValueStorage: keyValueStorage, -// keychainStorage: keychain, -// socketFactory: DefaultSocketFactory(), -// networkMonitor: NetworkMonitor(), -// logger: logger) -// -// let networkingClient = NetworkingClientFactory.create( -// relayClient: relayClient, -// logger: logger, -// keychainStorage: keychain, -// keyValueStorage: keyValueStorage) -// -// let pairingClient = PairingClientFactory.create( -// logger: logger, -// keyValueStorage: keyValueStorage, -// keychainStorage: keychain, -// networkingClient: networkingClient) -// -// let authClient = AuthClientFactory.create( -// metadata: AppMetadata(name: name, description: "", url: "", icons: [""], redirect: AppMetadata.Redirect(native: "", universal: nil)), -// projectId: InputConfig.projectId, -// crypto: DefaultCryptoProvider(), -// logger: logger, -// keyValueStorage: keyValueStorage, -// keychainStorage: keychain, -// networkingClient: networkingClient, -// pairingRegisterer: pairingClient, -// iatProvider: iatProvider) -// -// let clientId = try! networkingClient.getClientId() -// logger.debug("My client id is: \(clientId)") -// -// return (pairingClient, authClient) -// } -// -// func testRequest() async { -// let requestExpectation = expectation(description: "request delivered to wallet") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams.stub(), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { _ in -// requestExpectation.fulfill() -// }.store(in: &publishers) -// wait(for: [requestExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testEIP191RespondSuccess() async { -// let responseExpectation = expectation(description: "successful response delivered") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams.stub(), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { [unowned self] request in -// Task(priority: .high) { -// let signerFactory = DefaultSignerFactory() -// let signer = MessageSignerFactory(signerFactory: signerFactory).create(projectId: InputConfig.projectId) -// let payload = try! request.0.payload.cacaoPayload(address: walletAccount.address) -// let signature = try! signer.sign(payload: payload, privateKey: prvKey, type: .eip191) -// try! await walletAuthClient.respond(requestId: request.0.id, signature: signature, from: walletAccount) -// } -// } -// .store(in: &publishers) -// appAuthClient.authResponsePublisher.sink { (_, result) in -// guard case .success = result else { XCTFail(); return } -// responseExpectation.fulfill() -// } -// .store(in: &publishers) -// wait(for: [responseExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testEIP1271RespondSuccess() async { -// setupClients(iatProvider: IATProviderMock()) -// -// let account = Account(chainIdentifier: "eip155:1", address: "0x2faf83c542b68f1b4cdc0e770e8cb9f567b08f71")! -// -// let responseExpectation = expectation(description: "successful response delivered") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams( -// domain: "localhost", -// chainId: "eip155:1", -// nonce: "1665443015700", -// aud: "http://localhost:3000/", -// nbf: nil, -// exp: "2022-10-11T23:03:35.700Z", -// statement: nil, -// requestId: nil, -// resources: nil -// ), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { [unowned self] request in -// Task(priority: .high) { -// let signature = CacaoSignature(t: .eip1271, s: eip1271Signature) -// try! await walletAuthClient.respond(requestId: request.0.id, signature: signature, from: account) -// } -// } -// .store(in: &publishers) -// appAuthClient.authResponsePublisher.sink { (_, result) in -// guard case .success = result else { XCTFail(); return } -// responseExpectation.fulfill() -// } -// .store(in: &publishers) -// wait(for: [responseExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testEIP191RespondError() async { -// let responseExpectation = expectation(description: "error response delivered") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams.stub(), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { [unowned self] request in -// Task(priority: .high) { -// let signature = CacaoSignature(t: .eip1271, s: eip1271Signature) -// try! await walletAuthClient.respond(requestId: request.0.id, signature: signature, from: walletAccount) -// } -// } -// .store(in: &publishers) -// appAuthClient.authResponsePublisher.sink { (_, result) in -// guard case let .failure(error) = result, error == .signatureVerificationFailed else { XCTFail(); return } -// responseExpectation.fulfill() -// } -// .store(in: &publishers) -// wait(for: [responseExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testUserRespondError() async { -// let responseExpectation = expectation(description: "error response delivered") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams.stub(), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { [unowned self] request in -// Task(priority: .high) { -// try! await walletAuthClient.reject(requestId: request.0.id) -// } -// } -// .store(in: &publishers) -// appAuthClient.authResponsePublisher.sink { (_, result) in -// guard case .failure(let error) = result else { XCTFail(); return } -// XCTAssertEqual(error, .userRejeted) -// responseExpectation.fulfill() -// } -// .store(in: &publishers) -// wait(for: [responseExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testRespondSignatureVerificationFailed() async { -// let responseExpectation = expectation(description: "invalid signature response delivered") -// let uri = try! await appPairingClient.create() -// try! await appAuthClient.request(RequestParams.stub(), topic: uri.topic) -// -// try? await walletPairingClient.pair(uri: uri) -// walletAuthClient.authRequestPublisher.sink { [unowned self] request in -// Task(priority: .high) { -// let invalidSignature = "438effc459956b57fcd9f3dac6c675f9cee88abf21acab7305e8e32aa0303a883b06dcbd956279a7a2ca21ffa882ff55cc22e8ab8ec0f3fe90ab45f306938cfa1b" -// let cacaoSignature = CacaoSignature(t: .eip191, s: invalidSignature) -// try! await walletAuthClient.respond(requestId: request.0.id, signature: cacaoSignature, from: walletAccount) -// } -// } -// .store(in: &publishers) -// appAuthClient.authResponsePublisher.sink { (_, result) in -// guard case .failure(let error) = result else { XCTFail(); return } -// XCTAssertEqual(error, .signatureVerificationFailed) -// responseExpectation.fulfill() -// } -// .store(in: &publishers) -// wait(for: [responseExpectation], timeout: InputConfig.defaultTimeout) -// } -//} -//>>>>>>> bd8835437254fb808be3ac89fdcff43fa13c3b87 diff --git a/Example/IntegrationTests/Chat/ChatTests.swift b/Example/IntegrationTests/Chat/ChatTests.swift deleted file mode 100644 index 09c96faf0..000000000 --- a/Example/IntegrationTests/Chat/ChatTests.swift +++ /dev/null @@ -1,169 +0,0 @@ -// -//import Foundation -//import XCTest -//@testable import WalletConnectChat -//import WalletConnectUtils -//@testable import WalletConnectKMS -//@testable import WalletConnectSync -//import WalletConnectRelay -//import Combine -//import Web3 -// -//final class ChatTests: XCTestCase { -// var invitee1: ChatClient! -// var inviter1: ChatClient! -// var invitee2: ChatClient! -// var inviter2: ChatClient! -// private var publishers = [AnyCancellable]() -// -// var inviteeAccount: Account { -// return Account("eip155:1:" + pk1.address.hex(eip55: true))! -// } -// -// var inviterAccount: Account { -// return Account("eip155:1:" + pk2.address.hex(eip55: true))! -// } -// -// let pk1 = try! EthereumPrivateKey() -// let pk2 = try! EthereumPrivateKey() -// -// var privateKey1: Data { -// return Data(pk1.rawPrivateKey) -// } -// var privateKey2: Data { -// return Data(pk2.rawPrivateKey) -// } -// -// override func setUp() async throws { -// invitee1 = makeClient(prefix: "🦖 Invitee", account: inviteeAccount) -// inviter1 = makeClient(prefix: "🍄 Inviter", account: inviterAccount) -// -// try await invitee1.register(account: inviteeAccount, domain: "") { message in -// return self.sign(message, privateKey: self.privateKey1) -// } -// try await inviter1.register(account: inviterAccount, domain: "") { message in -// return self.sign(message, privateKey: self.privateKey2) -// } -// } -// -// func makeClient(prefix: String, account: Account) -> ChatClient { -// let keyserverURL = URL(string: "https://keys.walletconnect.com")! -// let logger = ConsoleLogger(prefix: prefix, loggingLevel: .debug) -// let keyValueStorage = RuntimeKeyValueStorage() -// let keychain = KeychainStorageMock() -// let relayClient = RelayClientFactory.create( -// relayHost: InputConfig.relayHost, -// projectId: InputConfig.projectId, -// keyValueStorage: keyValueStorage, -// keychainStorage: keychain, -// socketFactory: DefaultSocketFactory(), -// networkMonitor: NetworkMonitor(), -// logger: logger) -// -// let networkingInteractor = NetworkingClientFactory.create( -// relayClient: relayClient, -// logger: logger, -// keychainStorage: keychain, -// keyValueStorage: keyValueStorage) -// -// let syncClient = SyncClientFactory.create( -// networkInteractor: networkingInteractor, -// bip44: DefaultBIP44Provider(), -// keychain: keychain -// ) -// -// let clientId = try! networkingInteractor.getClientId() -// logger.debug("My client id is: \(clientId)") -// -// return ChatClientFactory.create(keyserverURL: keyserverURL, relayClient: relayClient, networkingInteractor: networkingInteractor, keychain: keychain, logger: logger, storage: keyValueStorage, syncClient: syncClient) -// } -// -// func testInvite() async throws { -// let inviteExpectation = expectation(description: "invitation expectation") -// inviteExpectation.expectedFulfillmentCount = 2 -// -// invitee1.newReceivedInvitePublisher.sink { _ in -// inviteExpectation.fulfill() -// }.store(in: &publishers) -// -// inviter1.newSentInvitePublisher.sink { _ in -// inviteExpectation.fulfill() -// }.store(in: &publishers) -// -// let inviteePublicKey = try await inviter1.resolve(account: inviteeAccount) -// let invite = Invite(message: "", inviterAccount: inviterAccount, inviteeAccount: inviteeAccount, inviteePublicKey: inviteePublicKey) -// _ = try await inviter1.invite(invite: invite) -// -// wait(for: [inviteExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testAcceptAndCreateNewThread() async throws { -// let newThreadInviterExpectation = expectation(description: "new thread on inviting client expectation") -// let newThreadinviteeExpectation = expectation(description: "new thread on invitee client expectation") -// -// invitee1.newReceivedInvitePublisher.sink { [unowned self] invite in -// Task { try! await invitee1.accept(inviteId: invite.id) } -// }.store(in: &publishers) -// -// invitee1.newThreadPublisher.sink { _ in -// newThreadinviteeExpectation.fulfill() -// }.store(in: &publishers) -// -// inviter1.newThreadPublisher.sink { _ in -// newThreadInviterExpectation.fulfill() -// }.store(in: &publishers) -// -// let inviteePublicKey = try await inviter1.resolve(account: inviteeAccount) -// let invite = Invite(message: "", inviterAccount: inviterAccount, inviteeAccount: inviteeAccount, inviteePublicKey: inviteePublicKey) -// try await inviter1.invite(invite: invite) -// -// wait(for: [newThreadinviteeExpectation, newThreadInviterExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// func testMessage() async throws { -// let messageExpectation = expectation(description: "message received") -// messageExpectation.expectedFulfillmentCount = 4 -// -// invitee1.newReceivedInvitePublisher.sink { [unowned self] invite in -// Task { try! await invitee1.accept(inviteId: invite.id) } -// }.store(in: &publishers) -// -// invitee1.newThreadPublisher.sink { [unowned self] thread in -// Task { try! await invitee1.message(topic: thread.topic, message: "message1") } -// }.store(in: &publishers) -// -// inviter1.newThreadPublisher.sink { [unowned self] thread in -// Task { try! await inviter1.message(topic: thread.topic, message: "message2") } -// }.store(in: &publishers) -// -// inviter1.newMessagePublisher.sink { message in -// if message.authorAccount == self.inviterAccount { -// XCTAssertEqual(message.message, "message2") -// } else { -// XCTAssertEqual(message.message, "message1") -// } -// messageExpectation.fulfill() -// }.store(in: &publishers) -// -// invitee1.newMessagePublisher.sink { message in -// if message.authorAccount == self.inviteeAccount { -// XCTAssertEqual(message.message, "message1") -// } else { -// XCTAssertEqual(message.message, "message2") -// } -// messageExpectation.fulfill() -// }.store(in: &publishers) -// -// let inviteePublicKey = try await inviter1.resolve(account: inviteeAccount) -// let invite = Invite(message: "", inviterAccount: inviterAccount, inviteeAccount: inviteeAccount, inviteePublicKey: inviteePublicKey) -// try await inviter1.invite(invite: invite) -// -// wait(for: [messageExpectation], timeout: InputConfig.defaultTimeout) -// } -// -// private func sign(_ message: String, privateKey: Data) -> SigningResult { -// let signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create(projectId: InputConfig.projectId) -// return .signed(try! signer.sign(message: message, privateKey: privateKey, type: .eip191)) -// } -//} -//>>>>>>> bd8835437254fb808be3ac89fdcff43fa13c3b87 diff --git a/Example/IntegrationTests/Chat/RegistryTests.swift b/Example/IntegrationTests/Chat/RegistryTests.swift deleted file mode 100644 index 178c63be4..000000000 --- a/Example/IntegrationTests/Chat/RegistryTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -import XCTest -import WalletConnectNetworking -import WalletConnectKMS -import WalletConnectUtils -@testable import WalletConnectChat -@testable import WalletConnectIdentity - -final class RegistryTests: XCTestCase { - - let account = Account("eip155:1:0x15bca56b6e2728aec2532df9d436bd1600e86688")! - let privateKey = Data(hex: "305c6cde3846927892cd32762f6120539f3ec74c9e3a16b9b798b1e85351ae2a") - - var sut: IdentityService! - var storage: IdentityStorage! - var signer: MessageSigner! - - override func setUp() { - let keyserverURL = URL(string: "https://keys.walletconnect.com")! - let httpService = HTTPNetworkClient(host: keyserverURL.host!) - let identityNetworkService = IdentityNetworkService(httpService: httpService) - let keychain = KeychainStorageMock() - let ksm = KeyManagementService(keychain: keychain) - storage = IdentityStorage(keychain: keychain) - sut = IdentityService ( - keyserverURL: keyserverURL, - kms: ksm, - storage: storage, - networkService: identityNetworkService, - iatProvader: DefaultIATProvider(), - messageFormatter: SIWEFromCacaoPayloadFormatter() - ) - signer = MessageSignerFactory(signerFactory: DefaultSignerFactory()).create() - } - -// func testRegisterIdentityAndInviteKey() async throws { -// let publicKey = try await sut.registerIdentity(account: account, onSign: onSign) -// -// let iss = DIDKey(rawData: Data(hex: publicKey)).did(variant: .ED25519) -// let resolvedAccount = try await sut.resolveIdentity(iss: iss) -// XCTAssertEqual(resolvedAccount, account) -// -// let recovered = try storage.getIdentityKey(for: account).publicKey.hexRepresentation -// XCTAssertEqual(publicKey, recovered) -// -// let inviteKey = try await sut.registerInvite(account: account) -// -// let recoveredKey = try storage.getInviteKey(for: account) -// XCTAssertEqual(inviteKey, recoveredKey) -// -// let resolvedKey = try await sut.resolveInvite(account: account) -// XCTAssertEqual(inviteKey.did, resolvedKey) -// -// _ = try await sut.goPrivate(account: account) -// try await sut.unregister(account: account, onSign: onSign) -// } -} - -private extension RegistryTests { - - func onSign(_ message: String) -> SigningResult { - let signature = try! signer.sign(message: message, privateKey: privateKey, type: .eip191) - return .signed(signature) - } -} From 5b1563a99ba9272e56e55d7a365cda6e2dd1b7b2 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 15:05:13 +0100 Subject: [PATCH 23/27] fix signclient tests --- Example/IntegrationTests/Sign/SignClientTests.swift | 9 +++++++-- .../WalletConnectSign/Engine/Common/SessionEngine.swift | 1 - 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index 59b5afa59..a6327897c 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -196,7 +196,9 @@ final class SignClientTests: XCTestCase { let requestParams = [EthSendTransaction.stub()] let responseParams = "0xdeadbeef" let chain = Blockchain("eip155:1")! - + + // sleep is needed as emitRequestIfPending() will be called on client init and then on request itself, second request would be debouced + sleep(1) wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { do { @@ -247,6 +249,8 @@ final class SignClientTests: XCTestCase { let chain = Blockchain("eip155:1")! + // sleep is needed as emitRequestIfPending() will be called on client init and then on request itself, second request would be debouced + sleep(1) wallet.sessionProposalPublisher.sink { [unowned self] (proposal, _) in Task(priority: .high) { try await wallet.approve(proposalId: proposal.id, namespaces: sessionNamespaces) @@ -973,7 +977,8 @@ final class SignClientTests: XCTestCase { let requestParams = [EthSendTransaction.stub()] let responseParams = "0xdeadbeef" let chain = Blockchain("eip155:1")! - + // sleep is needed as emitRequestIfPending() will be called on client init and then on request itself, second request would be debouced + sleep(1) wallet.authRequestPublisher.sink { [unowned self] (request, _) in Task(priority: .high) { let signerFactory = DefaultSignerFactory() diff --git a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift index 82b1d0a53..435f34f98 100644 --- a/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift +++ b/Sources/WalletConnectSign/Engine/Common/SessionEngine.swift @@ -52,7 +52,6 @@ final class SessionEngine { setupUpdateSubscriptions() setupExpirationSubscriptions() DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in - guard let self = self else {return} sessionRequestsProvider.emitRequestIfPending() } } From 21ca87604499ad0ed6ea94bf469fe5e023e32406 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 15:10:14 +0100 Subject: [PATCH 24/27] update solana caip --- .../Contents.json | 0 .../solana (1).png | Bin Example/DApp/Modules/Sign/SignInteractor.swift | 2 +- Example/DApp/Modules/Sign/SignPresenter.swift | 2 +- Example/IntegrationTests/Sign/SignClientTests.swift | 6 +++--- .../AutoNamespacesValidationTests.swift | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) rename Example/DApp/Assets.xcassets/{solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset => solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset}/Contents.json (100%) rename Example/DApp/Assets.xcassets/{solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset => solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset}/solana (1).png (100%) diff --git a/Example/DApp/Assets.xcassets/solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset/Contents.json b/Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json similarity index 100% rename from Example/DApp/Assets.xcassets/solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset/Contents.json rename to Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json diff --git a/Example/DApp/Assets.xcassets/solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset/solana (1).png b/Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png similarity index 100% rename from Example/DApp/Assets.xcassets/solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ.imageset/solana (1).png rename to Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png diff --git a/Example/DApp/Modules/Sign/SignInteractor.swift b/Example/DApp/Modules/Sign/SignInteractor.swift index 8fa7d0e2b..29c1e3dba 100644 --- a/Example/DApp/Modules/Sign/SignInteractor.swift +++ b/Example/DApp/Modules/Sign/SignInteractor.swift @@ -20,7 +20,7 @@ enum Proposal { static let optionalNamespaces: [String: ProposalNamespace] = [ "solana": ProposalNamespace( chains: [ - Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")! + Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")! ], methods: [ "solana_signMessage", diff --git a/Example/DApp/Modules/Sign/SignPresenter.swift b/Example/DApp/Modules/Sign/SignPresenter.swift index a02612d54..402e6e5b8 100644 --- a/Example/DApp/Modules/Sign/SignPresenter.swift +++ b/Example/DApp/Modules/Sign/SignPresenter.swift @@ -16,7 +16,7 @@ final class SignPresenter: ObservableObject { let chains = [ Chain(name: "Ethereum", id: "eip155:1"), Chain(name: "Polygon", id: "eip155:137"), - Chain(name: "Solana", id: "solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ") + Chain(name: "Solana", id: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp") ] private let interactor: SignInteractor diff --git a/Example/IntegrationTests/Sign/SignClientTests.swift b/Example/IntegrationTests/Sign/SignClientTests.swift index a6327897c..1d68f9305 100644 --- a/Example/IntegrationTests/Sign/SignClientTests.swift +++ b/Example/IntegrationTests/Sign/SignClientTests.swift @@ -459,7 +459,7 @@ final class SignClientTests: XCTestCase { events: ["any"] ), "solana": ProposalNamespace( - chains: [Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + chains: [Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!], methods: ["solana_signMessage"], events: ["any"] ) @@ -481,12 +481,12 @@ final class SignClientTests: XCTestCase { Blockchain("eip155:137")!, Blockchain("eip155:1")!, Blockchain("eip155:5")!, - Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")! + Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")! ], methods: ["personal_sign", "eth_sendTransaction", "solana_signMessage"], events: ["any"], accounts: [ - Account(blockchain: Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, address: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, + Account(blockchain: Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!, address: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!, Account(blockchain: Blockchain("eip155:1")!, address: "0x00")!, Account(blockchain: Blockchain("eip155:137")!, address: "0x00")!, Account(blockchain: Blockchain("eip155:5")!, address: "0x00")! diff --git a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift index f7c65f72d..f0c0a9fc3 100644 --- a/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift +++ b/Tests/WalletConnectSignTests/AutoNamespacesValidationTests.swift @@ -803,7 +803,7 @@ final class AutoNamespacesValidationTests: XCTestCase { func testAutoNamespacesDifferentChainEmptyOptinalEvents() { let accounts = [ Account(blockchain: Blockchain("eip155:1")!, address: "0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")!, - Account(blockchain: Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, address: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")! + Account(blockchain: Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!, address: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")! ] let requiredNamespaces = [ "eip155": ProposalNamespace( @@ -818,7 +818,7 @@ final class AutoNamespacesValidationTests: XCTestCase { events: [] ), "solana": ProposalNamespace( - chains: [Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + chains: [Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!], methods: ["solana_signMessage"], events: [] ) @@ -827,7 +827,7 @@ final class AutoNamespacesValidationTests: XCTestCase { let sessionNamespaces = try! AutoNamespaces.build( sessionProposal: sessionProposal, - chains: [Blockchain("eip155:1")!, Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + chains: [Blockchain("eip155:1")!, Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!], methods: ["personal_sign", "eth_sendTransaction", "eth_signTypedData_v4", "eth_signTransaction", "eth_signTypedData", "eth_sign", "solana_signMessage", "solana_signMessage"], events: ["chainChanged", "accountsChanged"], accounts: accounts @@ -842,9 +842,9 @@ final class AutoNamespacesValidationTests: XCTestCase { events: ["chainChanged", "accountsChanged"] ), "solana": SessionNamespace( - chains: [Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!], + chains: [Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!], accounts: Set([ - Account(blockchain: Blockchain("solana:4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, address: "4sGjMW1sUnHzSxGspuhpqLDx6wiyjNtZ")!, + Account(blockchain: Blockchain("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!, address: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp")!, ]), methods: ["solana_signMessage"], events: [] From 453eacad2cdf907c0071efb2e5a34bda23c78160 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Tue, 12 Mar 2024 15:19:22 +0100 Subject: [PATCH 25/27] remove trash --- .../Contents.json | 0 .../solana (1).png | Bin Tests/ChatTests/RegistryServiceTests.swift | 106 ------------------ 3 files changed, 106 deletions(-) rename Example/DApp/Assets.xcassets/{solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset => solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset}/Contents.json (100%) rename Example/DApp/Assets.xcassets/{solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset => solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset}/solana (1).png (100%) delete mode 100644 Tests/ChatTests/RegistryServiceTests.swift diff --git a/Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json b/Example/DApp/Assets.xcassets/solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json similarity index 100% rename from Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json rename to Example/DApp/Assets.xcassets/solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/Contents.json diff --git a/Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png b/Example/DApp/Assets.xcassets/solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png similarity index 100% rename from Example/DApp/Assets.xcassets/solana: 5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png rename to Example/DApp/Assets.xcassets/solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp.imageset/solana (1).png diff --git a/Tests/ChatTests/RegistryServiceTests.swift b/Tests/ChatTests/RegistryServiceTests.swift deleted file mode 100644 index 8f6cb51b7..000000000 --- a/Tests/ChatTests/RegistryServiceTests.swift +++ /dev/null @@ -1,106 +0,0 @@ -import Foundation -import XCTest -@testable import WalletConnectChat -import WalletConnectUtils -import WalletConnectNetworking -import WalletConnectKMS -@testable import TestingUtils -@testable import WalletConnectIdentity - -final class RegistryServiceTests: XCTestCase { - var resubscriptionService: ResubscriptionService! - var identityClient: IdentityClient! - var identityStorage: IdentityStorage! - var networkService: IdentityNetwotkServiceMock! - var networkingInteractor: NetworkingInteractorMock! - var kms: KeyManagementServiceMock! - - let account = Account("eip155:1:0x1AAe9864337E821f2F86b5D27468C59AA333C877")! - let privateKey = "4dc0055d1831f7df8d855fc8cd9118f4a85ddc05395104c4cb0831a6752621a8" - - let cacaoStub: Cacao = { - return Cacao(h: .init(t: ""), p: .init(iss: "", domain: "", aud: "", version: "", nonce: "", iat: "", nbf: "", exp: nil, statement: nil, requestId: nil, resources: nil), s: .init(t: .eip191, s: "")) - }() - - let inviteKeyStub = "62720d14643acf0f7dd87513b079502f56be414a2f2ea4719342cf088c794173" - - override func setUp() { - networkingInteractor = NetworkingInteractorMock() - kms = KeyManagementServiceMock() - identityStorage = IdentityStorage(keychain: KeychainStorageMock()) - networkService = IdentityNetwotkServiceMock(cacao: cacaoStub, inviteKey: inviteKeyStub) - - let identitySevice = IdentityService( - keyserverURL: URL(string: "https://www.url.com")!, - kms: kms, - storage: identityStorage, - networkService: networkService, - iatProvader: DefaultIATProvider(), - messageFormatter: SIWECacaoFormatter() - ) - identityClient = IdentityClient(identityService: identitySevice, identityStorage: identityStorage, logger: ConsoleLoggerMock()) - - resubscriptionService = ResubscriptionService(networkingInteractor: networkingInteractor, kms: kms, logger: ConsoleLoggerMock()) - } - -// func testRegister() async throws { -// let pubKey = try await identityClient.register(account: account, onSign: onSign) -// -// XCTAssertTrue(networkService.callRegisterIdentity) -// -// let identityKey = try identityStorage.getIdentityKey(for: account) -// XCTAssertEqual(identityKey.publicKey.hexRepresentation, pubKey) -// } - -// func testGoPublic() async throws { -// XCTAssertTrue(networkingInteractor.subscriptions.isEmpty) -// -// _ = try await identityClient.register(account: account, onSign: onSign) -// let inviteKey = try await identityClient.goPublic(account: account) -// try await resubscriptionService.subscribeForInvites(inviteKey: inviteKey) -// -// XCTAssertNoThrow(try identityStorage.getInviteKey(for: account)) -// XCTAssertTrue(networkService.callRegisterInvite) -// -// XCTAssertEqual(networkingInteractor.subscriptions.count, 1) -// XCTAssertNotNil(kms.getPublicKey(for: networkingInteractor.subscriptions[0])) -// } - -// func testUnregister() async throws { -// XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) -// -// _ = try await identityClient.register(account: account, onSign: onSign) -// XCTAssertNoThrow(try identityStorage.getIdentityKey(for: account)) -// -// try await identityClient.unregister(account: account, onSign: onSign) -// XCTAssertThrowsError(try identityStorage.getIdentityKey(for: account)) -// XCTAssertTrue(networkService.callRemoveIdentity) -// } - - func testGoPrivate() async throws { - let invitePubKey = try AgreementPublicKey(hex: inviteKeyStub) - try identityStorage.saveInviteKey(invitePubKey, for: account) - - let identityKey = SigningPrivateKey() - try identityStorage.saveIdentityKey(identityKey, for: account) - - let topic = invitePubKey.rawRepresentation.sha256().toHexString() - try await networkingInteractor.subscribe(topic: topic) - - let inviteKey = try await identityClient.goPrivate(account: account) - resubscriptionService.unsubscribeFromInvites(inviteKey: inviteKey) - - XCTAssertThrowsError(try identityStorage.getInviteKey(for: account)) - XCTAssertTrue(networkingInteractor.unsubscriptions.contains(topic)) - } - - func testResolve() async throws { - let inviteKey = try await identityClient.resolveInvite(account: account) - - XCTAssertEqual(inviteKey, inviteKeyStub) - } - - private func onSign(_ message: String) -> SigningResult { - return .signed(CacaoSignature(t: .eip191, s: "")) - } -} From 4da0bd9808a0aac201b236ad1e6bfa5a267acb70 Mon Sep 17 00:00:00 2001 From: Bartosz Rozwarski Date: Wed, 13 Mar 2024 13:44:37 +0100 Subject: [PATCH 26/27] fix siwe fallback --- Example/DApp/Modules/Sign/SignInteractor.swift | 13 +++++++++++-- Example/DApp/Modules/Sign/SignPresenter.swift | 4 ++-- .../Auth/Services/ProposalNamespaceBuilder.swift | 7 +++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Example/DApp/Modules/Sign/SignInteractor.swift b/Example/DApp/Modules/Sign/SignInteractor.swift index 29c1e3dba..8c35d79c1 100644 --- a/Example/DApp/Modules/Sign/SignInteractor.swift +++ b/Example/DApp/Modules/Sign/SignInteractor.swift @@ -6,8 +6,7 @@ enum Proposal { static let requiredNamespaces: [String: ProposalNamespace] = [ "eip155": ProposalNamespace( chains: [ - Blockchain("eip155:1")!, - Blockchain("eip155:137")! + Blockchain("eip155:1")! ], methods: [ "eth_sendTransaction", @@ -26,6 +25,16 @@ enum Proposal { "solana_signMessage", "solana_signTransaction" ], events: [] + ), + "eip155": ProposalNamespace( + chains: [ + Blockchain("eip155:137")! + ], + methods: [ + "eth_sendTransaction", + "personal_sign", + "eth_signTypedData" + ], events: [] ) ] } diff --git a/Example/DApp/Modules/Sign/SignPresenter.swift b/Example/DApp/Modules/Sign/SignPresenter.swift index 402e6e5b8..a4e58c95a 100644 --- a/Example/DApp/Modules/Sign/SignPresenter.swift +++ b/Example/DApp/Modules/Sign/SignPresenter.swift @@ -83,7 +83,7 @@ final class SignPresenter: ObservableObject { Task { do { ActivityIndicatorManager.shared.start() - let uri = try await Sign.instance.authenticate(.stub(resources: ["urn:recap:eyJhdHQiOnsiaHR0cHM6Ly9ub3RpZnkud2FsbGV0Y29ubmVjdC5jb20iOnsibWFuYWdlL3BhbmNha2Vzd2FwLmNvbS1ub3RpZmljYXRpb25zIjpbe31dfX19"])) + let uri = try await Sign.instance.authenticate(.stub()) walletConnectUri = uri ActivityIndicatorManager.shared.stop() router.presentNewPairing(walletConnectUri: walletConnectUri!) @@ -98,7 +98,7 @@ final class SignPresenter: ObservableObject { Task { do { ActivityIndicatorManager.shared.start() - let uri = try await Sign.instance.authenticate(.stub(methods: nil)) + let uri = try await Sign.instance.authenticate(.stub(methods: ["personal_sign"])) walletConnectUri = uri ActivityIndicatorManager.shared.stop() router.presentNewPairing(walletConnectUri: walletConnectUri!) diff --git a/Sources/WalletConnectSign/Auth/Services/ProposalNamespaceBuilder.swift b/Sources/WalletConnectSign/Auth/Services/ProposalNamespaceBuilder.swift index eb11fc983..3c4ca0861 100644 --- a/Sources/WalletConnectSign/Auth/Services/ProposalNamespaceBuilder.swift +++ b/Sources/WalletConnectSign/Auth/Services/ProposalNamespaceBuilder.swift @@ -9,16 +9,19 @@ struct ProposalNamespaceBuilder { } static func buildNamespace(from params: AuthRequestParams) throws -> [String: ProposalNamespace] { + var methods = Set(params.methods ?? []) + if methods.isEmpty { + methods = ["personal_sign"] + } let chains: Set = Set(params.chains.compactMap { Blockchain($0) }) guard chains.allSatisfy({$0.namespace == "eip155"}) else { throw Errors.unsupportedChain } - let methods = Set(params.methods ?? []) return [ "eip155": ProposalNamespace( chains: chains, methods: methods, - events: [] + events: ["chainChanged", "accountsChanged"] )] } } From 8b6aac5dfb5405e333f71c81eae263b41116f61e Mon Sep 17 00:00:00 2001 From: llbartekll Date: Wed, 13 Mar 2024 12:54:35 +0000 Subject: [PATCH 27/27] Set User Agent --- Sources/WalletConnectRelay/PackageConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/WalletConnectRelay/PackageConfig.json b/Sources/WalletConnectRelay/PackageConfig.json index eca36dd02..25d66792e 100644 --- a/Sources/WalletConnectRelay/PackageConfig.json +++ b/Sources/WalletConnectRelay/PackageConfig.json @@ -1 +1 @@ -{"version": "1.14.0"} +{"version": "1.15.0"}