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

钱包三方登录流程

相关推荐
StarkCoder5 小时前
打造炫酷浮动式 TabBar:让 iOS 应用导航更有格调!
前端·ios
2501_940094027 小时前
索尼PSP游戏资源下载 推荐中文汉化ios格式合集分享开源掌机模拟器都支持
游戏·ios·cocoa
2501_9160074710 小时前
iOS性能调试工具终极指南,从系统底层到多端协同的全方位优化实践(2025版)
android·ios·小程序·https·uni-app·iphone·webview
私人珍藏库10 小时前
Miraplay – iOS端类TVbox可添加解析源的影视聚合播放器+解析影视源
ios·应用·tv·影视
2501_9159214310 小时前
iOS崩溃日志深度分析与工具组合实战,从符号化到自动化诊断的完整体系
android·ios·小程序·uni-app·自动化·cocoa·iphone
2501_9160088917 小时前
没有源码如何加密 IPA 实战流程与多工具组合落地指南
android·ios·小程序·https·uni-app·iphone·webview
CocoaKier20 小时前
微信与苹果就小程序支付达成和解,iOS用户有望在小程序内直接使用苹果支付
ios·apple
QuantumLeap丶21 小时前
《uni-app跨平台开发完全指南》- 07 - 数据绑定与事件处理
vue.js·ios·uni-app
ajassi20001 天前
开源 Objective-C IOS 应用开发(五)iOS操作(action)和输出口(Outlet)
ios·开源·objective-c