wallet connect 是設(shè)計(jì)給Dapp 與 Wallet App 交互的協(xié)議见间。
本文主要介紹集成v1 版本與v2 版本的一些差異欣尼,還有https://github.com/WalletConnect/WalletConnectSwiftV2遷移v2 的方案溢豆。
概要
接入swift wallet connect 主要是與Wallet App 進(jìn)行連接盏浙,簽名交易。
下圖是使用Wallet connect 協(xié)議調(diào)用錢包App 進(jìn)行簽名交易的交互流程础嫡。
Config
在接入SDK 進(jìn)入項(xiàng)目之后挂谍,我們要理解使用 wallet connect swift 協(xié)議通過(guò)錢包簽名交易的流程是會(huì)通過(guò) WalletConnect 的Relay Server。意味著我們不是直接與錢包App 建立連接繁堡,而且是通過(guò)中繼服務(wù)器建立連接沈善。
所以在使用SDK 的第一步就是如何建立與Relay Server的連接乡数,這需要我們?cè)谶B接前完成配置。v1 與 v2 版本的配置方式有不同的重點(diǎn)闻牡,下面我們各自介紹一下不同與相似之處净赴。
- v1 Config
v1 版本配置會(huì)簡(jiǎn)單一些,主要包括用于 展示的 MetaInfo罩润。這個(gè)信息會(huì)被錢包App 接受并使用玖翅。這通常作為在錢包App連接頁(yè)面展示的所需要的信息,所以下面代碼中的config 就需要對(duì)應(yīng)自己的Dapp做自定義了割以。
let clientMeta = Session.ClientMeta(name: "ExampleDApp",
description: "WalletConnectSwift",
icons: [],
url: URL(string: "you url"))
let dAppInfo = Session.DAppInfo(peerId: UUID().uuidString, peerMeta: clientMeta)
client = Client(delegate: self, dAppInfo: dAppInfo)
之前我們有說(shuō)過(guò)Relay Server金度,這是我們配置的重點(diǎn),我們使用Wallet Connect連接與發(fā)送請(qǐng)求需要通過(guò)中繼服務(wù)器轉(zhuǎn)發(fā)严沥。而在v1 版本中猜极,配置Relay Server 是在建立連接前進(jìn)行配置。
let wcUrl = WCURL(topic: UUID().uuidString,
bridgeURL: URL(string: "https://safe-walletconnect.gnosis.io/"),
key: randomKey())
其中bridgeURL
參數(shù)配置的url祝峻,就是Relay Server 的地址魔吐。
- v2 Config
v2 的 wallet connect swift 將Relay Server 細(xì)節(jié)隱藏了起來(lái),使用 Networking
類代替了v1中WCURL的配置莱找,同時(shí)酬姆,v2 要求一個(gè)projectId
這需要去他們的網(wǎng)站上申請(qǐng)。
Networking.configure(projectId: InputConfig.projectId, socketFactory: DefaultSocketFactory())
其中 socketFactory
是配置網(wǎng)絡(luò)中具體使用的 websocket 實(shí)例的地方奥溺。這里可以使用 Starscream
或者 URLSession
Dapp 的meta info辞色,在v2 是在Pair
這里配置
let metadata = AppMetadata(name: <String>,
description: <String>,
url: <String>,
icons: <[String]>)
Pair.configure(metadata: metadata)
和v1一樣,這些信息主要用于在Wallet App 上的展示浮定。
連接
向錢包簽名交易前相满,我們需要通過(guò)Wallet Connect 協(xié)議與錢包App 建立連接,連接一旦建立桦卒,意味著Dapp與Wallet App 擁有會(huì)話關(guān)系立美,其中的Session
是我們需要特別關(guān)注的東西。
- v1
連接過(guò)程是先創(chuàng)建好WCURL
方灾, 然后向中轉(zhuǎn)層發(fā)起連接的請(qǐng)求建蹄,最后通過(guò)Deeplink
或者Universal Links
的方式去把WCURL 攜帶在跳轉(zhuǎn)Link的參數(shù)里面跳轉(zhuǎn)到目標(biāo)的 Wallet App。也可以把 WCURL
生成QRCode 然后通過(guò)Wallet App 去掃碼連接裕偿。
// 創(chuàng)建連接
let wcUrl = WCURL(topic: UUID().uuidString,
bridgeURL: bridgeURL,
key: randomKey)
//發(fā)起 Connect
do {
try client.connect(to: wcUrl)
} catch {
callback?(.failed(error))
}
//跳轉(zhuǎn)Wallet App
let deepLink = self.getDeepLink(wallet: type, wcURL: wcUrl)
guard let url = URL(string: deepLink), UIApplication.shared.canOpenURL(url) else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
- v2
v2 的過(guò)程與上面相似洞慎,功能會(huì)更加復(fù)雜和強(qiáng)大,但是我們現(xiàn)在還不需要關(guān)心這些嘿棘。
// namespaces 定義了連接需要的信息劲腿,這些是v2協(xié)議的特性,可以支持多鏈多賬號(hào)
let namespaces: [String: ProposalNamespace] = [
"eip155": ProposalNamespace(
chains: [
Blockchain(ChainIdV2)!
],
methods: [
"eth_sendTransaction",
"personal_sign",
"eth_estimateGas",
"eth_getTransactionReceipt",
"eth_call"
], events: [WCSessionEvent.chainChanged.rawValue, WCSessionEvent.accountsChanged.rawValue]
)
]
let date: Int = Int(Date().dateByAdding(day: 7)?.timeIntervalSince1970 ?? 0)
let sessionProperties: [String: String] = [
"sessionExpiry": String(date)
]
Task {
do {
disconnectUnusedPairings()
// 創(chuàng)建連接
let uri = try await Pair.instance.create()
// 發(fā)起connect
try await Sign.instance.connect(
requiredNamespaces: namespaces,
optionalNamespaces: [:],
sessionProperties: sessionProperties,
topic: uri.topic
)
callback?(.succes(uri.absoluteString))
} catch {
callback?(.failed(error))
}
}
//跳轉(zhuǎn)Wallet App
let deepLink = self.getDeepLink(wallet: type, wcURL: wcUrl)
guard let url = URL(string: deepLink), UIApplication.shared.canOpenURL(url) else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)
發(fā)送Request
到了我們使用Wallet Connect 的重頭戲了鸟妙。我們連接之后就可以向 Wallet App 發(fā)送簽名請(qǐng)求進(jìn)行交易了焦人。
這里主要展示 ethSendTransaction的使用挥吵,signMessage 方法我們也會(huì)經(jīng)常用到,但是是類似的垃瞧,就不再體現(xiàn)了蔫劣。
我們需要認(rèn)識(shí)到坪郭,在Dapp端發(fā)送了交易是向中繼層發(fā)送消息个从,所以在收到中繼層收到的回復(fù)后,我們還需要主動(dòng)打開(kāi)Wallet App 這樣歪沃,建立過(guò)連接的Wallet App會(huì)主動(dòng)向中繼層拉取消息嗦锐,拉取成功后就會(huì)展示我們發(fā)起的簽名請(qǐng)求,等待用戶的確定沪曙。
- v1
在v1奕污,我們發(fā)消息的要攜帶的標(biāo)識(shí)是 WCURL,所以我們需要把建立過(guò)連接的 Session
緩存在Dapp中液走。通過(guò)讀取Session
中的URL信息碳默。
func ethSendTransaction(_ transaction: Transaction, session: WCSession, callback: ((WCSendRequestResult) -> ())?) {
guard let v1Session = getSession(for: session) else {
callback?(.failed(WCConnectError.invaildSession))
return
}
do {
try client.eth_sendTransaction(url: v1Session.url, transaction: transaction.convertV1Transaction()) { Response in
if let error = Response.error {
callback?(.failed(error))
} else {
do {
let result = try Response.result(as: String.self)
callback?(.success(result))
} catch {
callback?(.failed(error))
}
}
}
} catch {
callback?(.failed(error))
}
}
請(qǐng)求成功后會(huì)收到回調(diào),result 就是這次交易的Hash
- v2
v2 SDK 會(huì)自動(dòng)管理我們的 Session
缘眶。所以我們只需要保持好當(dāng)前連接的Topic
即可獲取 Session
去完成交易嘱根。
func ethSendTransaction(_ transaction: DGTransaction, session: WCSession, sendSuccess: (() -> ())?, callback: ((WCSendRequestResult) -> ())?) {
let method = "eth_sendTransaction"
let requestParams = AnyCodable([transaction])
let request = Request(topic: session.topic, method: method, params: requestParams, chainId: Blockchain(session.chainId)!)
sendRequest(request, sendSuccess: sendSuccess, callback: callback)
}
// 通過(guò)request id 標(biāo)識(shí)請(qǐng)求
private func sendRequest(_ request: Request, sendSuccess: (() -> ())?, callback: ((WCSendRequestResult) -> ())?) {
let id = request.id.string
if let cb = callback {
callBackPool[id] = cb
}
Task {
do {
try await Sign.instance.request(params: request)
sendSuccess?()
} catch {
callBackPool[id]?(.failed(error))
callBackPool[id] = nil
}
}
}
v2的請(qǐng)求回調(diào)會(huì)通過(guò)Sign.instance.sessionResponsePublisher
通知返回,在返回里面我們r(jià)equest id 去處理對(duì)應(yīng)的回調(diào)巷懈。
總結(jié)
上面我們從 配置 - 連接 - 請(qǐng)求 三步流程该抒,簡(jiǎn)單得概述 v1 向 v2遷移的處理方案,這里面也有很多很重要的點(diǎn)沒(méi)討論到顶燕。同時(shí)v2協(xié)議的設(shè)計(jì)理念更加先進(jìn)凑保,但是很多Wallet App 對(duì) v2 協(xié)議支持情況實(shí)現(xiàn)程度都不同,所以其中還是有很多坑點(diǎn)可以討論的