WalletConnectSwift
WalletConnectSwift copied to clipboard
Rainbow opens, but connection is not made
I'm trying to integrate the WalletConnect v2 Swift SDK into out iOS App.
The code below does not create any runtime errors that I can see. A uri is created and Rainbow does open, but there's no connection attempt.
Can you help me debug please?
I set up WalletConnect as follows
Networking.configure(projectId: Self.ProjectId, socketFactory: WebSocketWrapper(url: url))
let metadata = AppMetadata(name: "Source",
description: "A mobile application acting as a Dapp to connect to a crypto wallet using the WalletConnect SDK",
url: Self.ClientUrl.absoluteString,
icons: ["https://i.ebayimg.com/images/g/5qgAAOSwoBtW3zvq/s-l400.jpg"])
Pair.configure(metadata: metadata)
Auth.configure(crypto: Web3Signer())
And I then initiate the contact with this. The RequestParams code is taken from your demo project and needs amended slightly.
private func connect(wallet: WalletConnectType) {
Task {
let uri = try await Pair.instance.create()
try await Auth.instance.request(.stub(), topic: uri.topic)
var urlComponents = URLComponents()
urlComponents.scheme = "https"
urlComponents.host = "rnbwapp.com"
urlComponents.path = "/wc"
urlComponents.queryItems = [URLQueryItem(name: "uri", value: uri.deeplinkUri)]
let url = urlComponents.url
await UIApplication.shared.open(url!)
}
}
private extension RequestParams {
static func stub(
domain: String = "service.invalid",
chainId: String = "eip155:1",
nonce: String = "32891756",
aud: String = "https://service.invalid/login",
nbf: String? = nil,
exp: String? = nil,
statement: String? = "I accept the ServiceOrg Terms of Service: https://service.invalid/tos",
requestId: String? = nil,
resources: [String]? = ["ipfs://bafybeiemxf5abjwjbikoz4mc3a3dla6ual3jsgpdr4cjr3oz3evfyavhwq/", "https://example.com/my-web2-claim.json"]
) -> RequestParams {
return RequestParams(
domain: domain,
chainId: chainId,
nonce: nonce,
aud: aud,
nbf: nbf,
exp: exp,
statement: statement,
requestId: requestId,
resources: resources
)
}
}
Here's the Web3Signer
public struct Web3Signer: EthereumSigner, CryptoProvider {
public func sign(message: Data, with key: Data) throws -> EthereumSignature {
let privateKey = try EthereumPrivateKey(privateKey: [UInt8](key))
let signature = try privateKey.sign(message: message.bytes)
return EthereumSignature(v: UInt8(signature.v), r: signature.r, s: signature.s)
}
public func recoverPubKey(signature: EthereumSignature, message: Data) throws -> Data {
let publicKey = try EthereumPublicKey(
message: message.bytes,
v: EthereumQuantity(quantity: BigUInt(signature.v)),
r: EthereumQuantity(signature.r),
s: EthereumQuantity(signature.s)
)
return Data(publicKey.rawPublicKey)
}
public func keccak256(_ data: Data) -> Data {
let digest = SHA3(variant: .keccak256)
let hash = digest.calculate(for: [UInt8](data))
return Data(hash)
}
}
And the SocketFactory
struct SocketFactory: WebSocketFactory {
func create(with url: URL) -> WebSocketConnecting {
return WebSocketWrapper(url: url)
}
}
enum WebSocketWrapperError: Error {
case disconnected(String, UInt16)
}
class WebSocketWrapper {
private let websocket: WebSocket
var request: URLRequest {
didSet {
websocket.request = request
}
}
var isConnected: Bool = false
var onConnect: (() -> Void)?
var onDisconnect: ((Error?) -> Void)?
var onText: ((String) -> Void)?
init(url: URL) {
request = URLRequest(url: url)
request.addValue("relay.walletconnect.com", forHTTPHeaderField: "Origin")
websocket = WebSocket(request: request)
websocket.delegate = self
}
}
extension WebSocketWrapper: WebSocketDelegate {
func didReceive(event: Starscream.WebSocketEvent, client: Starscream.WebSocket) {
switch event {
case .connected(_):
isConnected = true
onConnect?()
case let .disconnected(string, code):
isConnected = false
onDisconnect?(WebSocketWrapperError.disconnected(string, code))
case .text(let text):
onText?(text)
case .binary(_): break
case .cancelled: break
case .error(_): break
case .ping(_): break
case .pong(_): break
case .reconnectSuggested(_): break
case .viabilityChanged(_): break
}
}
}
extension WebSocketWrapper: WebSocketConnecting {
func connect() {
websocket.connect()
}
func disconnect() {
websocket.disconnect()
}
func write(string: String, completion: (() -> Void)?) {
websocket.write(data: string.data(using: .utf8) ?? Data(), completion: completion)
}
}
To give more information we need to use WalletConnect for two reasons
- verify that a user has access to a wallet - I assume I use
Auth
here? - sign a transaction - I assume I use
Sign
here
So, in total can you
- confirm that these assumptions are correct?
- help us diagnose the issue with the code above?
- help us understand what data is required for
RequestParams
- advise on how we use Sign to sign a transaction