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
            }
        }
    }

钱包三方登录流程

相关推荐
2501_915918411 小时前
uni-app 项目 iOS 上架效率优化 从工具选择到流程改进的实战经验
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张1 小时前
如何在不同 iOS 设备上测试和上架 uni-app 应用 实战全流程解析
android·ios·小程序·https·uni-app·iphone·webview
wjm0410062 小时前
ios面试八股文
ios·面试
张较瘦_4 小时前
[论文阅读] 人工智能 + 软件工程 | 大模型破局跨平台测试!LLMRR让iOS/安卓/鸿蒙脚本无缝迁移
论文阅读·人工智能·ios
m0_6410310514 小时前
在选择iOS代签服务前,你必须了解的三大安全风险
ios
开开心心loky15 小时前
[iOS] push 和 present Controller 的区别
ui·ios·objective-c·cocoa
白玉cfc21 小时前
【iOS】push,pop和present,dismiss
macos·ios·cocoa
低调小一1 天前
iOS 开发入门指南-HelloWorld
ios
2501_915918411 天前
iOS 开发全流程实战 基于 uni-app 的 iOS 应用开发、打包、测试与上架流程详解
android·ios·小程序·https·uni-app·iphone·webview
用户870568130451 天前
iOS 异步渲染:从 CALayer 切入的实现与优化
ios