Flutter中通过MetaMask完成消息签名并获取签名的方法
Flutter 基于walletconnect_dart实现MetaMask消息签名方案
你已经完成WalletConnect和MetaMask的连接建立的前提下,按以下步骤实现签名功能即可:
核心注意事项
- 不要使用已被MetaMask禁用的
eth_sign方法,优先用适配最广的personal_sign方法做普通文本签名,如果是结构化数据签名用eth_signTypedData_v4 personal_sign的参数顺序有严格要求,顺序写反会直接触发MetaMask报错- 移动端必须提前配置MetaMask的跳转白名单,否则无法成功唤起App
具体实现步骤
- 第一步:前置状态校验
发起签名前先确认当前WalletConnect会话处于连接状态,拿到已授权的钱包地址,避免会话过期导致调用失败。 - 第二步:待签名消息格式转换
MetaMask要求待签名的明文消息必须转为0x开头的UTF-8十六进制格式,不能直接传原始字符串,转换代码参考:import 'dart:convert'; import 'dart:typed_data'; import 'package:convert/convert.dart'; String _messageToHex(String message) { final Uint8List messageBytes = utf8.encode(message); final String hexStr = hex.encode(messageBytes); return '0x$hexStr'; } - 第三步:构造请求参数唤起签名
调用walletconnect_dart实例的sendCustomRequest方法发起签名请求,调用后会自动唤起MetaMask,参数按顺序传入:转码后的十六进制消息、用户钱包地址、空字符串(可选密码位,一般传空)。 - 第四步:结果与异常处理
用户在MetaMask端确认签名后,签名结果会直接以字符串形式返回;如果用户拒绝签名、网络异常或者参数错误,会抛出对应异常,需要做catch捕获。
完整可运行代码示例
// 假设_connector是你已经初始化、完成连接的WalletConnect实例 // walletAddress是已经拿到的用户授权的钱包地址 Future<String?> signMessageWithMetaMask(String rawMessage) async { try { // 校验会话状态 if (!_connector.connected) { throw Exception('WalletConnect会话未连接'); } // 消息转十六进制 final String hexMsg = _messageToHex(rawMessage); // 发起签名请求,自动唤起MetaMask final dynamic signature = await _connector.sendCustomRequest( method: 'personal_sign', params: [hexMsg, walletAddress, ""], ); // 签名成功,返回结果 return signature.toString(); } catch (e) { // 处理异常:用户拒绝、参数错误、跳转失败等 print('签名失败: $e'); return null; } }
常见踩坑排查
- 无法唤起MetaMask:检查iOS的Info.plist是否在
LSApplicationQueriesSchemes中添加了metamask,安卓是否在Manifest的queries节点下配置了MetaMask的包名和scheme - 签名返回无效参数:检查参数顺序是否正确,消息是否正确转成0x开头的十六进制格式
- MetaMask提示方法不支持:检查是不是用了
eth_sign,替换成personal_sign即可
内容的提问来源于stack exchange,提问作者mr.SoSerious
相关产品推荐
相关产品推荐

