调用Alchemy执行合约转账时遇eth_sendTransaction不支持错误
问题描述
调用Alchemy服务触发智能合约转账时出现错误:
[Error: Returned error: Unsupported method: eth_sendTransaction. Alchemy does not hold users' private keys.]
相关代码:
import Web3 from 'web3'; const web3 = new Web3("https://eth-goerli.g.alchemy.com/v2/YPhlCYJ_fLdms1LpSRNs1n6rfcIqGHT9"); const payDrink = (async () => { console.log("ethAmount"); try{ const contract = new web3.eth.Contract(ContractAbi,contractAddress); const transaction = await contract.methods.transfer().send({ from: '0x9126de09872d12c4f6d417e2cb6061d1ad9e4708', value: web3.utils.toWei("0.0001", 'ether'), }); const transactionReciept = await transaction.wait(); console.log(transactionReciept); } catch(err){ console.log("eee",err); } })
错误截图显示上述提示信息。
解决方案
Alchemy作为节点服务不托管用户私钥,因此不支持eth_sendTransaction方法——该方法要求节点代为签名并发送交易,而Alchemy没有权限处理用户私钥。
方案1:前端集成钱包(如MetaMask)
让用户通过钱包完成签名和交易发送,无需自行管理私钥:
// 替换原web3初始化逻辑 if (window.ethereum) { const web3 = new Web3(window.ethereum); // 请求用户授权账户 await window.ethereum.request({ method: 'eth_requestAccounts' }); const payDrink = async () => { try{ const contract = new web3.eth.Contract(ContractAbi,contractAddress); // 钱包会自动填充from字段,无需手动指定 const transaction = await contract.methods.transfer().send({ value: web3.utils.toWei("0.0001", 'ether'), }); console.log(transaction); } catch(err){ console.log("eee",err); } } }
方案2:后端离线签名交易
若为后端服务,需自行管理私钥,先离线签名交易再通过Alchemy发送:
import Web3 from 'web3'; const web3 = new Web3("https://eth-goerli.g.alchemy.com/v2/YPhlCYJ_fLdms1LpSRNs1n6rfcIqGHT9"); // 注意:私钥需安全存储,禁止硬编码在代码中 const privateKey = "你的账户私钥"; const account = web3.eth.accounts.privateKeyToAccount(privateKey); const payDrink = async () => { try{ const contract = new web3.eth.Contract(ContractAbi,contractAddress); // 编码合约方法调用数据 const txData = contract.methods.transfer().encodeABI(); // 组装交易参数 const txParams = { from: account.address, to: contractAddress, value: web3.utils.toWei("0.0001", 'ether'), data: txData, gas: await web3.eth.estimateGas({ to: contractAddress, data: txData }), gasPrice: await web3.eth.getGasPrice(), nonce: await web3.eth.getTransactionCount(account.address), chainId: 5 // Goerli测试网Chain ID }; // 离线签名交易 const signedTx = await web3.eth.accounts.signTransaction(txParams, privateKey); // 发送已签名的交易 const transactionReceipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); console.log(transactionReceipt); } catch(err){ console.log("eee",err); } }
内容的提问来源于stack exchange,提问作者Hashmi
相关产品推荐
相关产品推荐

