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

钱包三方登录流程

相关推荐
HarderCoder3 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
叽哥13 小时前
Flutter Riverpod上手指南
android·flutter·ios
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
权咚2 天前
阿权的开发经验小集
git·ios·xcode
用户092 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间3 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918413 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张3 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h3 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa