Flutter中使用Wallet_connect无法选择不同钱包的问题求助
问题描述
我在Flutter中使用walletconnect_dart包连接不同钱包,但点击不同钱包按钮时,所有按钮都会打开同一个钱包(比如全部打开MetaMask或Trust Wallet)。我是Flutter和Web3领域的新手,附上相关代码,希望获得解决方法或替代实现方案。
import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; class Connect extends StatefulWidget { const Connect({Key? key}) : super(key: key); @override State<Connect> createState() => _ConnectState(); } class _ConnectState extends State<Connect> { var connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', clientMeta: const PeerMeta( name: 'IRISA ++', description: 'WalletConnect Developer App', url: 'https://metamask.io/', icons: [ 'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media' ])); loginUsingMetamask(BuildContext context) async { if (!connector.connected) { try { var session = await connector.createSession(onDisplayUri: (uri) async { var _uri = uri; await launchUrlString(uri, mode: LaunchMode.externalApplication); }); print(session.accounts[0]); print(session.chainId); setState(() { var _session = session; }); } catch (exp) { print(exp); } } } loginUsingTrust(BuildContext context) async { if (!connector.connected) { try { var session = await connector.createSession(onDisplayUri: (uri) async { await launchUrlString(uri, mode: LaunchMode.externalApplication); }); setState(() { }); } catch (exp) { print(exp); } } } loginUsingRain(BuildContext context) async { if (!connector.connected) { try { var session = await connector.createSession(onDisplayUri: (uri) async { await launchUrlString(uri, mode: LaunchMode.externalApplication); }); setState(() { }); } catch (exp) { print(exp); } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, //<-- SEE HERE body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('lib/assets/images/wallet.png', width:400, height:200), const SizedBox( height: 60, child:Text('Connect your wallet', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.black)), ), SizedBox( width: 300, // <-- Your width height: 100, // <-- Your height child: ElevatedButton.icon(// <-- OutlinedButton onPressed: () => loginUsingMetamask(context), icon:Image.asset('lib/assets/images/metamask.png', width:50, height:50), label: const Text('MetaMask', style: TextStyle( fontSize: 28, color: Colors.white)), style: ElevatedButton.styleFrom( primary: Colors.brown, side: BorderSide(color: Colors.brown.shade900, width: 3), //<-- SEE HERE ),//elevated btton background ), ), const SizedBox( height: 10, ), SizedBox( width: 300, // <-- Your width height: 100, // <-- Your height child: OutlinedButton.icon( // <-- OutlinedButton onPressed: () => loginUsingTrust(context), icon: Image.asset('lib/assets/images/trustwallet1.png', width:50, height:50), label: const Text('Trust Wallet', style: TextStyle( fontSize: 28, color: Colors.white)), style: ElevatedButton.styleFrom( primary: Colors.grey.shade400, side: BorderSide(color: Colors.blue.shade900, width: 3), //<-- SEE HERE ), ), ), const SizedBox( height: 10, ), SizedBox( width: 300, // <-- Your width height: 100, // <-- Your height child: OutlinedButton.icon( // <-- OutlinedButton onPressed: () => loginUsingRain(context), icon:Image.asset('lib/assets/images/rainbow.png', width:50, height:50), label: const Text('Rainbow', style: TextStyle( fontSize: 28, color: Colors.white)), style: ElevatedButton.styleFrom( primary: Colors.blue, side: BorderSide(color: Colors.blue.shade900, width: 3), //<-- SEE HERE ), ), ), ], ), ) ); } }
问题原因
所有登录方法共用同一个WalletConnect实例,且仅调用通用的createSession()生成URI,该URI会默认唤起设备中优先级最高的钱包应用,而非指定钱包。
解决方法
针对不同钱包构造专属的深层链接(deeplink)替换通用URI,同时优化会话管理避免冲突:
import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:walletconnect_dart/walletconnect_dart.dart'; class Connect extends StatefulWidget { const Connect({Key? key}) : super(key: key); @override State<Connect> createState() => _ConnectState(); } class _ConnectState extends State<Connect> { late WalletConnect connector; @override void initState() { super.initState(); _initConnector(); } void _initConnector() { connector = WalletConnect( bridge: 'https://bridge.walletconnect.org', clientMeta: const PeerMeta( name: 'IRISA ++', description: 'WalletConnect Developer App', url: 'https://metamask.io/', icons: [ 'https://files.gitbook.com/v0/b/gitbook-legacy-files/o/spaces%2F-LJJeCjcLrr53DcT1Ml7%2Favatar.png?alt=media' ], ), ); } // 通用登录方法,传入钱包专属deeplink前缀 Future<void> _loginWithWallet(String walletDeeplinkPrefix) async { // 先断开已有会话,避免冲突 if (connector.connected) { await connector.killSession(); } try { var session = await connector.createSession(onDisplayUri: (uri) async { // 构造钱包专属唤起链接 final walletUri = uri.replaceFirst('wc:', '$walletDeeplinkPrefix://wc?uri='); await launchUrlString(walletUri, mode: LaunchMode.externalApplication); }); if (session.accounts.isNotEmpty) { print('连接账户: ${session.accounts[0]}'); print('链ID: ${session.chainId}'); setState(() {}); } } catch (exp) { print('连接失败: $exp'); // 失败后重置连接器,保证后续连接正常 _initConnector(); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset('lib/assets/images/wallet.png', width: 400, height: 200), const SizedBox( height: 60, child: Text( 'Connect your wallet', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.black, ), ), ), SizedBox( width: 300, height: 100, child: ElevatedButton.icon( onPressed: () => _loginWithWallet('metamask'), icon: Image.asset('lib/assets/images/metamask.png', width: 50, height: 50), label: const Text( 'MetaMask', style: TextStyle(fontSize: 28, color: Colors.white), ), style: ElevatedButton.styleFrom( primary: Colors.brown, side: BorderSide(color: Colors.brown.shade900, width: 3), ), ), ), const SizedBox(height: 10), SizedBox( width: 300, height: 100, child: OutlinedButton.icon( onPressed: () => _loginWithWallet('trust'), icon: Image.asset('lib/assets/images/trustwallet1.png', width: 50, height: 50), label: const Text( 'Trust Wallet', style: TextStyle(fontSize: 28, color: Colors.white), ), style: ElevatedButton.styleFrom( primary: Colors.grey.shade400, side: BorderSide(color: Colors.blue.shade900, width: 3), ), ), ), const SizedBox(height: 10), SizedBox( width: 300, height: 100, child: OutlinedButton.icon( onPressed: () => _loginWithWallet('rainbow'), icon: Image.asset('lib/assets/images/rainbow.png', width: 50, height: 50), label: const Text( 'Rainbow', style: TextStyle(fontSize: 28, color: Colors.white), ), style: ElevatedButton.styleFrom( primary: Colors.blue, side: BorderSide(color: Colors.blue.shade900, width: 3), ), ), ), ], ), ), ); } }
补充说明
- 不同钱包的deeplink前缀需对应官方规范,示例中使用的前缀为:
- MetaMask:
metamask - Trust Wallet:
trust - Rainbow:
rainbow
- MetaMask:
- 若钱包deeplink格式不同,请参考对应钱包的官方文档调整链接构造逻辑。
- 每次登录前断开旧会话,避免会话复用导致的异常;连接失败后重置连接器,保证后续连接可用性。
内容的提问来源于stack exchange,提问作者Tariq B AL-Maashani
相关产品推荐
相关产品推荐

