MetaMask调用eth_getEncryptionPublicKey获取公钥为空报错解决
问题根因
报错Missing publicKey parameter是异步执行时序问题导致的:
ethereum.request()是异步API,返回Promise对象,你写的.then()回调会在RPC请求返回后才执行,但你在发起请求后立刻同步执行了读取encryptionPublicKey、调用加密函数的逻辑,此时回调还没触发,encryptionPublicKey还是初始的undefined,自然会报公钥缺失错误。- 额外问题:
window.ethereum.enable()是已废弃的旧版连接API,eth_requestAccounts已经完全覆盖其功能,不需要重复调用。
修复代码
推荐用async/await写法,逻辑更清晰,不会出现时序问题:
// 依赖说明:ethereumjs-util处理buffer转hex,@metamask/eth-sig-util是MetaMask官方维护的加密工具包,替代已废弃的旧版eth-sig-util import { bufferToHex } from 'ethereumjs-util'; import { encrypt } from '@metamask/eth-sig-util'; // 1. 请求连接钱包,获取用户地址 const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); const userAddress = accounts[0]; // 2. 等待用户授权后获取加密公钥,必须加await等待请求返回 const encryptionPublicKey = await window.ethereum.request({ method: 'eth_getEncryptionPublicKey', params: [userAddress], }); // 3. 公钥拿到后再执行加密逻辑 const encryptedMessage = bufferToHex( Buffer.from( JSON.stringify( encrypt({ publicKey: encryptionPublicKey, data: 'hello world!', version: 'x25519-xsalsa20-poly1305', }) ), 'utf8' ) ); // 后续可以把encryptedMessage上传到链上存储 console.log('加密完成:', encryptedMessage);
如果习惯用Promise链式写法,必须把所有依赖公钥的加密逻辑放到.then()回调内部,保证公钥返回后再执行:
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); window.ethereum .request({ method: 'eth_getEncryptionPublicKey', params: [accounts[0]], }) .then((encryptionPublicKey) => { // 加密逻辑必须写在then回调内 const encryptedMessage = ethUtil.bufferToHex( Buffer.from( JSON.stringify( sigUtil.encrypt({ publicKey: encryptionPublicKey, data: 'hello world!', version: 'x25519-xsalsa20-poly1305', }) ), 'utf8' ) ); console.log('加密完成:', encryptedMessage); }) .catch((error) => { if (error.code === 4001) { // 用户拒绝授权的场景 console.log("用户拒绝授权获取加密公钥,无法继续操作"); } else { console.error('加密流程出错:', error); } });
补充说明
- 调用
eth_getEncryptionPublicKey时MetaMask会弹出独立的授权窗口,必须用户手动确认后才能拿到公钥,必须做好拒绝授权的异常兼容。 - 该方案全程不需要接触用户私钥,后续解密时只需要调用
eth_decryptRPC方法,MetaMask会自动调起用户签名确认解密,符合钱包安全规范。 - 旧版
eth-sig-util已经停止维护,建议替换为@metamask/eth-sig-util避免版本兼容问题。
内容的提问来源于stack exchange,提问作者fabricdev
相关产品推荐
相关产品推荐

