Swift Wallet Connect V1 遷移 V2

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)行簽名交易的交互流程础嫡。

交互流程.png

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)可以討論的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涌攻,一起剝皮案震驚了整個(gè)濱河市欧引,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌恳谎,老刑警劉巖芝此,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異惠爽,居然都是意外死亡癌蓖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門婚肆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)租副,“玉大人,你說(shuō)我怎么就攤上這事较性∮蒙” “怎么了结胀?”我有些...
    開(kāi)封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)责循。 經(jīng)常有香客問(wèn)我糟港,道長(zhǎng),這世上最難降的妖魔是什么院仿? 我笑而不...
    開(kāi)封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任秸抚,我火速辦了婚禮,結(jié)果婚禮上歹垫,老公的妹妹穿的比我還像新娘剥汤。我一直安慰自己,他們只是感情好排惨,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布吭敢。 她就那樣靜靜地躺著,像睡著了一般暮芭。 火紅的嫁衣襯著肌膚如雪鹿驼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天辕宏,我揣著相機(jī)與錄音畜晰,去河邊找鬼。 笑死匾效,一個(gè)胖子當(dāng)著我的面吹牛舷蟀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播面哼,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼野宜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了魔策?” 一聲冷哼從身側(cè)響起匈子,我...
    開(kāi)封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎闯袒,沒(méi)想到半個(gè)月后虎敦,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡政敢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年其徙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喷户。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡唾那,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出褪尝,到底是詐尸還是另有隱情闹获,我是刑警寧澤期犬,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站避诽,受9級(jí)特大地震影響龟虎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沙庐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一鲤妥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轨功,春花似錦旭斥、人聲如沸容达。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)花盐。三九已至羡滑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間算芯,已是汗流浹背柒昏。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熙揍,地道東北人职祷。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像届囚,于是被迫代替她去往敵國(guó)和親有梆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容