Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recap encoding #1345

Merged
merged 3 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,6 @@ final class AuthRequestPresenter: ObservableObject {
}

private func buildAuthObjects() throws -> [AuthObject] {
guard let chain = getCommonAndRequestedChainsIntersection().first else {
throw Errors.noCommonChains
}

let auth = try createAuthObjectForChain(chain: chain)
return [auth]
}

private func buildOneAuthObject() throws -> [AuthObject] {
var auths = [AuthObject]()

try getCommonAndRequestedChainsIntersection().forEach { chain in
Expand All @@ -158,6 +149,15 @@ final class AuthRequestPresenter: ObservableObject {
return auths
}

private func buildOneAuthObject() throws -> [AuthObject] {
guard let chain = getCommonAndRequestedChainsIntersection().first else {
throw Errors.noCommonChains
}

let auth = try createAuthObjectForChain(chain: chain)
return [auth]
}


func getCommonAndRequestedChainsIntersection() -> Set<Blockchain> {
let requestedChains: Set<Blockchain> = Set(request.payload.chains.compactMap { Blockchain($0) })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class AuthenticatedSessionRecapUrnFactory {
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .withoutEscapingSlashes
let jsonData = try jsonEncoder.encode(recap)
let base64Encoded = jsonData.base64EncodedString()
let urn = "urn:recap:\(base64Encoded)"
let base64urlEncoded = jsonData.base64urlEncodedString()
let urn = "urn:recap:\(base64urlEncoded)"
return urn
}
}
20 changes: 9 additions & 11 deletions Sources/WalletConnectSign/Auth/Services/SignRecapBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,35 @@ struct SignRecapBuilder {
throw BuilderError.nonEVMChainNamespace
}

// Convert supportedEVMChains to string array for intersection
let supportedChainStrings = supportedEVMChains.map { $0.absoluteString }

// Find intersection of requestedChains and supportedEVMChains strings
let commonChains = requestedChains.filter(supportedChainStrings.contains)
guard !commonChains.isEmpty else {
throw BuilderError.noCommonChains
}

let requestedRecap = try SignRecap(urn: urn)
var filteredActions = requestedRecap.recapData.att ?? [:]

var filteredActions: [String: [String: [AnyCodable]]] = [:]

if let eip155Actions = requestedRecap.recapData.att?["eip155"] {
if let eip155Actions = filteredActions["eip155"] {
var newEip155Actions: [String: [AnyCodable]] = [:]
for method in supportedMethods {
let actionKey = "request/\(method)"
if eip155Actions.keys.contains(actionKey) {
// Use only common chains for each supported method
filteredActions["eip155", default: [:]][actionKey] = [AnyCodable(["chains": commonChains])]
if let actions = eip155Actions[actionKey] {
newEip155Actions[actionKey] = [AnyCodable(["chains": commonChains])]
}
}
filteredActions["eip155"] = newEip155Actions
}

let modifiedRecapData = SignRecap.RecapData(att: filteredActions, prf: requestedRecap.recapData.prf)
let encoder = JSONEncoder()
guard let jsonData = try? encoder.encode(modifiedRecapData) else {
throw SignRecap.Errors.invalidRecapStructure
}
let jsonBase64String = jsonData.base64EncodedString()
let jsonBase64urlString = jsonData.base64urlEncodedString()

let modifiedUrn = "urn:recap:\(jsonBase64String)"
let modifiedUrn = "urn:recap:\(jsonBase64urlString)"
return try SignRecap(urn: modifiedUrn)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class RecapUrnMergingService {
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 {
let jsonBase64 = jsonData.base64urlEncodedString().addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) else {
throw Errors.encodingFailed
}

Expand Down
27 changes: 27 additions & 0 deletions Tests/WalletConnectSignTests/SignRecapBuilderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,31 @@ class SignRecapBuilderTests: XCTestCase {
XCTAssertFalse(result.recapData.att?["eip155"]?.keys.contains("request/extraUnsupportedMethod") ?? true, "Result should not contain 'extraUnsupportedMethod'")
}

func testSessionRecapBuilder_RetainsAdditionalAttributes() throws {
// Given
let requestedRecap: [String: [String: [String: [[String: [String]]]]]] = [
"att": [
"eip155": [
"request/eth_sendTransaction": [[:]],
"request/personal_sign": [[:]]
],
"https://notify.walletconnect.com": [
"manage/all-apps-notifications": [[:]]
]
]
]
let encoded = try! JSONEncoder().encode(requestedRecap).base64EncodedString()
let urn = "urn:recap:\(encoded)"

let supportedChains = [Blockchain("eip155:1")!, Blockchain("eip155:137")!]
let supportedMethods = ["eth_sendTransaction", "personal_sign"]
let requestedChains = ["eip155:1", "eip155:137"]

// When
let result = try SignRecapBuilder.build(requestedSessionRecap: urn, requestedChains: requestedChains, supportedEVMChains: supportedChains, supportedMethods: supportedMethods)

// Then
XCTAssertNotNil(result.recapData.att?["eip155"], "EIP155 namespace should be present")
XCTAssertNotNil(result.recapData.att?["https://notify.walletconnect.com"], "https://notify.walletconnect.com namespace should be retained")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class RecapUrnMergingTests: XCTestCase {
}
"""

guard let notifyBase64 = notifyRecapJson.data(using: .utf8)?.base64EncodedString(),
let signBase64 = signRecapJson.data(using: .utf8)?.base64EncodedString() else {
guard let notifyBase64 = notifyRecapJson.data(using: .utf8)?.base64urlEncodedString(),
let signBase64 = signRecapJson.data(using: .utf8)?.base64urlEncodedString() else {
XCTFail("Failed to encode JSON strings to Base64")
return
}
Expand Down
Loading