WalletConnectV2 ---- dapp 使用

集成 WalletConnectSwiftV2 按照官方文档就可以(github.com/WalletConne... WalletConnect Inc 现已更名为 Reown。作为此次过渡的一部分,我们将弃用我们支持的平台上的大量存储库/软件包,并过渡到 Reown 组织下发布的等效版本。 此存储库现已被视为已弃用,并将于 2025 年 2 月 17 日终止使用。有关更多详细信息(包括迁移指南),请参阅:docs.reown.com/advanced/wa...),

WalletConnectSwiftV2(reown-swift)是用swift实现的,所有项目用swift会方便很多 git库 github.com/WalletConne...改为github.com/reown-com/r...

pod WalletConnectSwiftV2

但有些依赖库会缺少, 需要单独pod 如:

pod 'WalletConnectSwiftV2/Web3Wallet', '1.6.6' pod 'WalletConnectSwiftV2/WalletConnectRouter', '1.6.6' pod 'WalletConnectSwiftV2/WalletConnectIdentity', '1.6.6'

dapp使用

创建DappConnect.swift 实现回调方法

swift 复制代码
@objc protocol DappConnectDelegate {
    @objc func dappWalletList(_ succeed:Bool,_ type:Int)
    @objc func dappSelectConnect()
    @objc func failedToConnect()
    @objc func didConnect(_ dict:NSDictionary)
    @objc func didDisconnect()
    @objc func didUpdate(_ dict:NSDictionary)
    
}
swift 复制代码
  @objc public func start() {
        var isDapp = true
        //创建AppMetadata对象
        let metadata = AppMetadata(
            name: ExName,
            description: ExName,
            url: String(format: "https://www.%@/favicon.ico", DomainSwithTool.currentDomain()),
            icons: [String(format: "https://www.%@/favicon.ico", DomainSwithTool.currentDomain())]
        )

        Pair.configure(metadata: metadata)
      
        
#if DEBUG
        if CommandLine.arguments.contains("-cleanInstall") {
            try? Sign.instance.cleanup()
        }
#endif
          //已断链回调
        Sign.instance.sessionDeletePublisher
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] (topic, reason) in
                //self.delegate.didDisconnect()
            }.store(in: &publishers)
        //返回数据回调
        Sign.instance.sessionResponsePublisher
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] response in
                presentResponse(for: response)
            }.store(in: &publishers)
        //地址(address)/链(chainId)变更回调
        Sign.instance.sessionUpdatePublisher
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] (topic, namespaces) in
                onSessionUpdateNamespaces(topic, namespaces)
            }.store(in: &publishers)
        
       //连接成功返回支账户信息(链,方法名称,地址0x)
        Sign.instance.sessionSettlePublisher
            .receive(on: DispatchQueue.main)
            .sink { [unowned self] session in
                if isDapp{
                    isDapp = false
                    showAccountsScreen(session,false)
                }
               
            }.store(in: &publishers)

    }

获取所有支持钱包列表

swift 复制代码
   func getListings() async throws -> [Listing] {
        
        let httpClient = HTTPNetworkClient(host: "explorer-api.walletconnect.com")
        let response = try await httpClient.request(
            ListingsResponse.self,
            at: ExplorerAPI.getListings(
                projectId: Web3Modal.config.projectId,
                metadata: Web3Modal.config.metadata
            )
        )
    
        return response.listings.values.compactMap { $0 }
    }

获取某个钱包logo url

swift 复制代码
  
    private func imageURL(for wallet: Listing?) -> URL? {
       
        guard let wallet else { return nil }
        // case small = "sm"  case medium = "md"   case large = "lg"
        let urlString = "https://explorer-api.walletconnect.com/v3/logo/\("md")/\(wallet.imageId)?projectId=\(InputConfig.projectId)"
       
        
        return URL(string: urlString)
    }

Listing 类型转 WalletModel类型

swift 复制代码
 self.walletList.removeAll()
 for wallet:Listing in self.wallets!{
     let model:WalletModel = WalletModel()
      model.id = wallet.id
      model.name = wallet.name
      model.homepage = wallet.homepage
      model.order = wallet.order ?? 0
      model.imageId = wallet.imageId
      model.app.ios = wallet.app.ios ?? ""
      model.app.mac = wallet.app.mac ?? ""
      model.app.safari = wallet.app.safari ?? ""
      model.mobile.native = wallet.mobile.native ?? ""
      model.mobile.universal = wallet.mobile.universal ?? ""
      model.imageUrl = imageURL(for: wallet)!
      self.walletList .append(model)
}

连接钱包

swift 复制代码
  @objc func connect() {
        let chain = String(format: "eip155:%@",WalletNodeManager.shared().currentNode.chainID)
        let namespaces: [String: ProposalNamespace] = [
            "eip155": ProposalNamespace(
                chains: [
                    Blockchain(chain)!
                ],
                methods: [
                    "eth_sendTransaction",
                    "personal_sign",
                    "eth_signTypedData"
                ], events: []
            )
        ]
        let optionalNamespaces: [String: ProposalNamespace] = [:
        ]
        let sessionProperties: [String: String] = [
            "caip154-mandatory": "true"
        ]
        
        Task {
            Web3Modal.set(sessionParams: .init(
                requiredNamespaces: namespaces,
                optionalNamespaces: optionalNamespaces,
                sessionProperties: sessionProperties
            ))

            let uri = try await Web3Modal.instance.connect(topic: nil)
            self.uri = uri
            self.uriStr = uri!.absoluteString
            self.deeplinkUri = "\(uri!.deeplinkUri)"
            delegate.dappSelectConnect()
        }
        
    }

唤醒钱包App

swift 复制代码
 @objc public func onListingTap(_ wallet: WalletModel) {
        navigateToDeepLink(
            universalLink: wallet.mobile.universal,
            nativeLink: wallet.mobile.native
        )
    }
    
    func navigateToDeepLink(universalLink: String, nativeLink: String) {
        do {
            let nativeUrlString = formatNativeUrlString(nativeLink)
            let universalUrlString = formatUniversalUrlString(universalLink)
            
            if let nativeUrl = nativeUrlString?.toURL() {
                DispatchQueue.main.async {
                    UIApplication.shared.open(nativeUrl, options: [:]) { [weak self] _ in

                    }
                }
            } else if let universalUrl = universalUrlString?.toURL() {
                DispatchQueue.main.async {
                    UIApplication.shared.open(universalUrl, options: [:]) { [weak self] _ in

                    }
                }
            } else {
                //throw
            }
        } catch {
           // toast = Toast(style: .error, message: error.localizedDescription)
        }
    }
    
    func  isInstall(universalLink: String, nativeLink: String) -> Bool {
        do {
            let nativeUrlString = formatNativeUrlString(nativeLink)
            let universalUrlString = formatUniversalUrlString(universalLink)
            
            if let nativeUrl = nativeUrlString?.toURL() {
                return  UIApplication.shared.canOpenURL(nativeUrl)
            } else if let universalUrl = universalUrlString?.toURL() {
                return  UIApplication.shared.canOpenURL(universalUrl)
            } else {
                return  false
            }
        } catch {
            return  false
        }
    }
    
    
    func isHttpUrl(url: String) -> Bool {
        return url.hasPrefix("http://") || url.hasPrefix("https://")
    }
        
    func formatNativeUrlString(_ string: String) -> String? {
        if string.isEmpty { return nil }
            
        if isHttpUrl(url: string) {
            return formatUniversalUrlString(string)
        }
            
        var safeAppUrl = string
        if !safeAppUrl.contains("://") {
            safeAppUrl = safeAppUrl.replacingOccurrences(of: "/", with: "").replacingOccurrences(of: ":", with: "")
            safeAppUrl = "\(safeAppUrl)://"
        }
        
        guard self.deeplinkUri.length > 0 else { return nil }
            
        return "\(safeAppUrl)wc?uri=\(deeplinkUri)"
    }
        
    func formatUniversalUrlString(_ string: String) -> String? {
        if string.isEmpty { return nil }
            
        if !isHttpUrl(url: string) {
            return formatNativeUrlString(string)
        }
            
        var plainAppUrl = string
        if plainAppUrl.hasSuffix("/") {
            plainAppUrl = String(plainAppUrl.dropLast())
        }
        
        guard self.deeplinkUri.length > 0 else { return nil }
            
        return "\(plainAppUrl)/wc?uri=\(deeplinkUri)"
    }

发起签名授权

swift 复制代码
 @objc func personal_sign(sign:String ,complete:@escaping (_ signHex: String)->()) {
        self.completePersonal_signBlock = complete
        guard let session = self.session,let chainId = self.chainId else {
            return
        }
        let requestParams = AnyCodable([sign, self.account])

        let request = Request(topic: session.topic, method: "personal_sign", params: requestParams, chainId: Blockchain(chainId)!)
        Task {
            do {
                try await Sign.instance.request(params: request)
                DispatchQueue.main.async { [weak self] in
                    
                }
            } catch {
                print(error)
                // show failure alert
            }
        }
    }

发起交易授权

swift 复制代码
 @objc func eth_sendTransaction(dict:[String:String],complete:@escaping (_ dict: NSDictionary)->()){
        self.completeEth_sendTransactionBlock = complete
        guard let session = self.session,let chainId = self.chainId else {
            return
        }
        let tx = [TransactionDapp(from:self.account!,
                                  to: dict["to"]!,
                                  data: dict["data"]!,
                                  chainId: dict["chainId"]!,
                                  gas: dict["gas"]!,
                                  gasPrice: dict["gasPrice"]!,
                                  value: dict["value"]!,
                                  nonce: dict["nonce"]!
                                 )]
    
        let requestParams = AnyCodable(tx)
        
        
        let request = Request(topic: session.topic, method: "eth_sendTransaction", params: requestParams, chainId: Blockchain(chainId)!)
        
        Task {
            do {
                try await Sign.instance.request(params: request)
                DispatchQueue.main.async { [weak self] in
                   
                }
            } catch {
                print(error)
                // show failure alert
            }
        }
    }

钱包三方登录流程

相关推荐
/**书香门第*/6 小时前
Laya ios接入goole广告,搭建环境 1
ios
wakangda12 小时前
React Native 集成 iOS 原生功能
react native·ios·cocoa
crasowas1 天前
iOS - 超好用的隐私清单修复脚本(持续更新)
ios·app store
ii_best1 天前
ios按键精灵脚本开发:ios悬浮窗命令
ios
Code&Ocean2 天前
iOS从Matter的设备认证证书中获取VID和PID
ios·matter·chip
/**书香门第*/2 天前
Laya ios接入goole广告,开始接入 2
ios
恋猫de小郭2 天前
什么?Flutter 可能会被 SwiftUI/ArkUI 化?全新的 Flutter Roadmap
flutter·ios·swiftui
网安墨雨2 天前
iOS应用网络安全之HTTPS
web安全·ios·https
福大大架构师每日一题3 天前
37.1 prometheus管理接口源码讲解
ios·iphone·prometheus
二流小码农3 天前
鸿蒙开发:简单了解属性动画
android·ios·harmonyos