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

1.19.1 #1367

Merged
merged 13 commits into from
Jun 4, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ extension SessionAccountPresenter {
}

private func getRequest(for method: String) throws -> AnyCodable {
let account = session.namespaces.first!.value.accounts.first!.absoluteString
let account = session.namespaces.first!.value.accounts.first!.address
if method == "eth_sendTransaction" {
let tx = Stub.tx
return AnyCodable(tx)
Expand Down
2 changes: 1 addition & 1 deletion Example/DApp/Modules/Sign/SignPresenter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ extension AuthRequestParams {
domain: String = "lab.web3modal.com",
chains: [String] = ["eip155:1", "eip155:137"],
nonce: String = "32891756",
uri: String = "https://app.web3inbox.com/login",
uri: String = "https://lab.web3modal.com",
nbf: String? = nil,
exp: String? = nil,
statement: String? = "I accept the ServiceOrg Terms of Service: https://app.web3inbox.com/tos",
Expand Down
16 changes: 13 additions & 3 deletions Example/DApp/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,28 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
projectId: InputConfig.projectId,
metadata: metadata,
crypto: DefaultCryptoProvider(),
customWallets: [
authRequestParams: .stub(), customWallets: [
.init(
id: "swift-sample",
name: "Swift Sample Wallet",
homepage: "https://walletconnect.com/",
imageUrl: "https://avatars.githubusercontent.com/u/37784886?s=200&v=4",
order: 1,
mobileLink: "walletapp://"
mobileLink: "walletapp://",
linkMode: "https://lab.web3modal.com/wallet"
)
]
)


Web3Modal.instance.authResponsePublisher.sink { (id, result) in
switch result {
case .success((_, _)):
AlertPresenter.present(message: "User Authenticted with SIWE", type: .success)
case .failure(_):
break
}
}.store(in: &publishers)

WalletConnectModal.configure(
projectId: InputConfig.projectId,
metadata: metadata
Expand Down
2 changes: 1 addition & 1 deletion Example/ExampleApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3280,7 +3280,7 @@
repositoryURL = "https://github.com/WalletConnect/web3modal-swift";
requirement = {
kind = revision;
revision = c73ce390bc249af155b7320346b7045e53b89866;
revision = 3baac675811b5fdeb689cef703e3dfc7682704e6;
};
};
A5434021291E6A270068F706 /* XCRemoteSwiftPackageReference "solana-swift" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
"repositoryURL": "https://github.com/WalletConnect/web3modal-swift",
"state": {
"branch": null,
"revision": "c73ce390bc249af155b7320346b7045e53b89866",
"revision": "3baac675811b5fdeb689cef703e3dfc7682704e6",
"version": null
}
}
Expand Down
6 changes: 6 additions & 0 deletions Example/WalletApp/ApplicationLayer/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ final class SceneDelegate: UIResponder, UIWindowSceneDelegate, UNUserNotificatio
if case WalletConnectURI.Errors.expired = error {
AlertPresenter.present(message: error.localizedDescription, type: .error)
} else {
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = components.queryItems,
queryItems.contains(where: { $0.name == "wc_ev" }) else {
return
}

do {
try Web3Wallet.instance.dispatchEnvelope(url.absoluteString)
} catch {
Expand Down
2 changes: 1 addition & 1 deletion Sources/WalletConnectModal/Modal/Screens/WalletList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ struct WalletList: View {
.stroke(.gray.opacity(0.4), lineWidth: 1)
)

Text(String(wallet.name.split(separator: " ").first!))
Text(String(wallet.name.split(separator: " ").first ?? " "))
.font(.system(size: 12))
.foregroundColor(.foreground1)
.multilineTextAlignment(.center)
Expand Down
12 changes: 0 additions & 12 deletions Sources/WalletConnectPairing/PairingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import Foundation
import Combine

public class PairingClient: PairingRegisterer, PairingInteracting, PairingClientProtocol {
enum Errors: Error {
case pairingDoesNotSupportRequiredMethod
}
public var pingResponsePublisher: AnyPublisher<(String), Never> {
pingResponsePublisherSubject.eraseToAnyPublisher()
}
Expand Down Expand Up @@ -139,15 +136,6 @@ public class PairingClient: PairingRegisterer, PairingInteracting, PairingClient
_ = try pairingsProvider.getPairing(for: topic)
}

public func validateMethodSupport(topic: String, method: String) throws {
_ = try pairingsProvider.getPairing(for: topic)
let pairing = pairingStorage.getPairing(forTopic: topic)
guard let methods = pairing?.methods,
methods.contains(method) else {
throw Errors.pairingDoesNotSupportRequiredMethod
}
}

public func register<RequestParams>(method: ProtocolMethod) -> AnyPublisher<RequestSubscriptionPayload<RequestParams>, Never> {
logger.debug("Pairing Client - registering for \(method.method)")
return pairingRequestsSubscriber.subscribeForRequest(method)
Expand Down
2 changes: 1 addition & 1 deletion Sources/WalletConnectPairing/Types/AppMetadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public struct AppMetadata: Codable, Equatable {
/// Universal link URL string.
public let universal: String?

public let linkMode: Bool
public let linkMode: Bool?

/**
Creates a new Redirect object with the specified information.
Expand Down
2 changes: 1 addition & 1 deletion Sources/WalletConnectRelay/PackageConfig.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "1.19.0"}
{"version": "1.19.1"}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class LinkAuthRequestSubscriber {

private func subscribeForRequest() {

envelopesDispatcher.requestSubscription(on: SessionAuthenticatedProtocolMethod().method)
envelopesDispatcher
.requestSubscription(on: SessionAuthenticatedProtocolMethod.responseApprove().method)
.sink { [unowned self] (payload: RequestSubscriptionPayload<SessionAuthenticateRequestParams>) in

logger.debug("LinkAuthRequestSubscriber: Received request")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ actor LinkAuthRequester {
var params = params
let pubKey = try kms.createX25519KeyPair()
let responseTopic = pubKey.rawRepresentation.sha256().toHexString()
let protocolMethod = SessionAuthenticatedProtocolMethod(ttl: params.ttl)
let protocolMethod = SessionAuthenticatedProtocolMethod.responseApprove(ttl: params.ttl)
guard let chainNamespace = Blockchain(params.chains.first!)?.namespace,
chainNamespace == "eip155"
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,15 @@ class AuthResponseSubscriber {
}

private func subscribeForResponse() {
networkingInteractor.responseErrorSubscription(on: SessionAuthenticatedProtocolMethod())
networkingInteractor
.responseErrorSubscription(on: SessionAuthenticatedProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionErrorPayload<SessionAuthenticateRequestParams>) in
guard let error = AuthError(code: payload.error.code) else { return }
authResponsePublisherSubject.send((payload.id, .failure(error)))
}.store(in: &publishers)

networkingInteractor.responseSubscription(on: SessionAuthenticatedProtocolMethod())
networkingInteractor
.responseSubscription(on: SessionAuthenticatedProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionPayload<SessionAuthenticateRequestParams, SessionAuthenticateResponseParams>) in

let transportType = getTransportTypeUpgradeIfPossible(peerMetadata: payload.response.responder.metadata, requestId: payload.id)
Expand Down Expand Up @@ -86,13 +88,13 @@ class AuthResponseSubscriber {
}

private func subscribeForLinkResponse() {
linkEnvelopesDispatcher.responseErrorSubscription(on: SessionAuthenticatedProtocolMethod())
linkEnvelopesDispatcher.responseErrorSubscription(on: SessionAuthenticatedProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionErrorPayload<SessionAuthenticateRequestParams>) in
guard let error = AuthError(code: payload.error.code) else { return }
authResponsePublisherSubject.send((payload.id, .failure(error)))
}.store(in: &publishers)

linkEnvelopesDispatcher.responseSubscription(on: SessionAuthenticatedProtocolMethod())
linkEnvelopesDispatcher.responseSubscription(on: SessionAuthenticatedProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionPayload<SessionAuthenticateRequestParams, SessionAuthenticateResponseParams>) in

let pairingTopic = payload.topic
Expand Down Expand Up @@ -140,10 +142,10 @@ class AuthResponseSubscriber {

private func getTransportTypeUpgradeIfPossible(peerMetadata: AppMetadata, requestId: RPCID) -> WCSession.TransportType {
// upgrade to link mode only if dapp requested universallink because dapp may not be prepared for handling a response - add this to doc]
// remove record

if let peerRedirect = peerMetadata.redirect,
peerRedirect.linkMode,
let peerLinkMode = peerRedirect.linkMode,
peerLinkMode == true,
let universalLink = peerRedirect.universal,
supportLinkMode {
linkModeLinksStore.set(true, forKey: universalLink)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ class AuthenticateTransportTypeSwitcher {
// Continue with relay if the error is walletLinkSupportNotProven
}

let pairingURI = try await pairingClient.create(methods: [SessionAuthenticatedProtocolMethod().method])
let pairingURI = try await pairingClient.create(
methods: [SessionAuthenticatedProtocolMethod.responseApprove().method]
)
logger.debug("Requesting Authentication on existing pairing")
try await appRequestService.request(params: params, topic: pairingURI.topic)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ actor SessionAuthRequestService {
var params = params
let pubKey = try kms.createX25519KeyPair()
let responseTopic = pubKey.rawRepresentation.sha256().toHexString()
let protocolMethod = SessionAuthenticatedProtocolMethod(ttl: params.ttl)
let protocolMethod = SessionAuthenticatedProtocolMethod.responseApprove(ttl: params.ttl)
guard let chainNamespace = Blockchain(params.chains.first!)?.namespace,
chainNamespace == "eip155"
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class AuthRequestSubscriber {
}

private func subscribeForRequest() {
pairingRegisterer.register(method: SessionAuthenticatedProtocolMethod())
pairingRegisterer.register(method: SessionAuthenticatedProtocolMethod.responseApprove())
.sink { [unowned self] (payload: RequestSubscriptionPayload<SessionAuthenticateRequestParams>) in

guard !payload.request.isExpired() else {
Expand Down Expand Up @@ -70,10 +70,15 @@ class AuthRequestSubscriber {
}.store(in: &publishers)
}

func respondError(payload: SubscriptionPayload, reason: SignReasonCode) {
private func respondError(payload: SubscriptionPayload, reason: SignReasonCode) {
Task(priority: .high) {
do {
try await networkingInteractor.respondError(topic: payload.topic, requestId: payload.id, protocolMethod: SessionAuthenticatedProtocolMethod(), reason: reason)
try await networkingInteractor.respondError(
topic: payload.topic,
requestId: payload.id,
protocolMethod: SessionAuthenticatedProtocolMethod.responseAutoReject(),
reason: reason
)
} catch {
logger.error("Respond Error failed with: \(error.localizedDescription)")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ actor SessionAuthenticateResponder {
let responseParams = SessionAuthenticateResponseParams(responder: selfParticipant, cacaos: auths)

let response = RPCResponse(id: requestId, result: responseParams)
try await networkingInteractor.respond(topic: responseTopic, response: response, protocolMethod: SessionAuthenticatedProtocolMethod(), envelopeType: .type1(pubKey: responseKeys.publicKey.rawRepresentation))

try await networkingInteractor.respond(
topic: responseTopic,
response: response,
protocolMethod: SessionAuthenticatedProtocolMethod.responseApprove(),
envelopeType: .type1(pubKey: responseKeys.publicKey.rawRepresentation)
)


let session = try util.createSession(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
import Foundation

struct SessionAuthenticatedProtocolMethod: ProtocolMethod {

enum Tag: Int {
case sessionAuthenticate = 1116
case sessionAuthenticateResponseApprove = 1117
case sessionAuthenticateResponseReject = 1118
case sessionAuthenticateResponseAutoReject = 1119
}

let method: String = "wc_sessionAuthenticate"

let requestConfig = RelayConfig(tag: 1116, prompt: true, ttl: 3600)

let responseConfig = RelayConfig(tag: 1117, prompt: false, ttl: 3600)


static let defaultTtl: TimeInterval = 3600
private let ttl: Int
let requestConfig: RelayConfig

let responseConfig: RelayConfig

init(ttl: TimeInterval = Self.defaultTtl) {
self.ttl = Int(ttl)
static let defaultTtl: TimeInterval = 300

private init(
ttl: TimeInterval,
responseTag: Tag
) {
self.requestConfig = RelayConfig(
tag: Tag.sessionAuthenticate.rawValue,
prompt: true,
ttl: Int(ttl)
)
self.responseConfig = RelayConfig(
tag: responseTag.rawValue,
prompt: false,
ttl: Int(ttl)
)
}

static func responseApprove(ttl: TimeInterval = Self.defaultTtl) -> Self {
Self(ttl: ttl, responseTag: .sessionAuthenticateResponseApprove)
}

static func responseReject(ttl: TimeInterval = Self.defaultTtl) -> Self {
Self(ttl: ttl, responseTag: .sessionAuthenticateResponseReject)
}

static func responseAutoReject(ttl: TimeInterval = Self.defaultTtl) -> Self {
Self(ttl: ttl, responseTag: .sessionAuthenticateResponseAutoReject)
}
}
25 changes: 16 additions & 9 deletions Sources/WalletConnectSign/Engine/Common/ApproveEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ final class ApproveEngine {
async let proposeResponseTask: () = networkingInteractor.respond(
topic: payload.topic,
response: response,
protocolMethod: SessionProposeProtocolMethod()
protocolMethod: SessionProposeProtocolMethod.responseApprove()
)

async let settleRequestTask: WCSession = settle(
Expand Down Expand Up @@ -146,8 +146,13 @@ final class ApproveEngine {
guard let payload = try proposalPayloadsStore.get(key: proposerPubKey) else {
throw Errors.proposalNotFound
}

try await networkingInteractor.respondError(topic: payload.topic, requestId: payload.id, protocolMethod: SessionProposeProtocolMethod(), reason: reason)

try await networkingInteractor.respondError(
topic: payload.topic,
requestId: payload.id,
protocolMethod: SessionProposeProtocolMethod.responseReject(),
reason: reason
)

if let pairingTopic = rpcHistory.get(recordId: payload.id)?.topic,
let pairing = pairingStore.getPairing(forTopic: pairingTopic),
Expand Down Expand Up @@ -216,12 +221,14 @@ final class ApproveEngine {
private extension ApproveEngine {

func setupRequestSubscriptions() {
pairingRegisterer.register(method: SessionProposeProtocolMethod())
pairingRegisterer.register(method: SessionProposeProtocolMethod.responseAutoReject())
.sink { [unowned self] (payload: RequestSubscriptionPayload<SessionType.ProposeParams>) in
guard let pairing = pairingStore.getPairing(forTopic: payload.topic) else { return }
let responseApproveMethod = SessionAuthenticatedProtocolMethod.responseApprove().method
if let methods = pairing.methods,
methods.flatMap({ $0 })
.contains(SessionAuthenticatedProtocolMethod().method), authRequestSubscribersTracking.hasSubscribers() {
methods.contains(responseApproveMethod),
authRequestSubscribersTracking.hasSubscribers()
{
logger.debug("Ignoring Session Proposal")
// respond with an error?
return
Expand All @@ -236,7 +243,7 @@ private extension ApproveEngine {
}

func setupResponseSubscriptions() {
networkingInteractor.responseSubscription(on: SessionProposeProtocolMethod())
networkingInteractor.responseSubscription(on: SessionProposeProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionPayload<SessionType.ProposeParams, SessionType.ProposeResponse>) in
handleSessionProposeResponse(payload: payload)
}.store(in: &publishers)
Expand All @@ -248,7 +255,7 @@ private extension ApproveEngine {
}

func setupResponseErrorSubscriptions() {
networkingInteractor.responseErrorSubscription(on: SessionProposeProtocolMethod())
networkingInteractor.responseErrorSubscription(on: SessionProposeProtocolMethod.responseApprove())
.sink { [unowned self] (payload: ResponseSubscriptionErrorPayload<SessionType.ProposeParams>) in
handleSessionProposeResponseError(payload: payload)
}.store(in: &publishers)
Expand Down Expand Up @@ -340,7 +347,7 @@ private extension ApproveEngine {
logger.debug("Received Session Proposal")
let proposal = payload.request
do { try Namespace.validate(proposal.requiredNamespaces) } catch {
return respondError(payload: payload, reason: .invalidUpdateRequest, protocolMethod: SessionProposeProtocolMethod())
return respondError(payload: payload, reason: .invalidUpdateRequest, protocolMethod: SessionProposeProtocolMethod.responseAutoReject())
}
proposalPayloadsStore.set(payload, forKey: proposal.proposer.publicKey)

Expand Down
Loading
Loading