如何使用web3及/或Moralis调用智能合约函数
存在的问题
- 顶级
await语法错误:const web3 = await Moralis.enableWeb3()直接写在async函数外部,浏览器环境默认不支持顶级await,会直接抛出语法异常无法执行。
- 顶级
- Promise 异常捕获语法错误:
await Moralis.executeFunction(options)后面直接跟console.log,单独写的.catch没有绑定到对应的Promise对象上,属于语法错误。同时异常处理里的console(error)写法错误,正确应为console.error(error)。
- Promise 异常捕获语法错误:
- DOM绑定风险:脚本执行时如果
mint_SoftHands按钮还未完成DOM渲染,document.getElementById会返回null,导致点击事件绑定失败。
- DOM绑定风险:脚本执行时如果
- mint逻辑不完整:你当前调用的
create函数仅发起VRF随机数请求,需要等链上VRF回调完成后,再调用finishMint才能完成完整的NFT mint流程,且调用地址需要持有对应链的足够LINK代币作为VRF手续费。
- mint逻辑不完整:你当前调用的
修正后的代码
<body> <!-- 确保按钮在脚本之前加载 --> <button id="mint_SoftHands">Mint NFT</button> <script> async function mintToken() { try { // 把enableWeb3移到函数内部,避免顶级await问题 const web3 = await Moralis.enableWeb3(); const ABI = [{"inputs":[{"internalType":"address","name":"_VRFCoordinator","type":"address"},{"internalType":"address","name":"_LinkToken","type":"address"},{"internalType":"bytes32","name":"_keyhash","type":"bytes32"},{"internalType":"uint256","name":"_fee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"tokenURI","type":"string"}],"name":"CreatedRandomSVG","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"randomNumber","type":"uint256"}],"name":"CreatedUnfinishedRandomSVG","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestId","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"requestedRandomSVG","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_bytes32","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"colors","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"create","outputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"finishMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"imageURI","type":"string"}],"name":"formatTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_randomness","type":"uint256"}],"name":"generatePath","outputs":[{"internalType":"string","name":"pathSvg","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_randomness","type":"uint256"}],"name":"generatePathCommand","outputs":[{"internalType":"string","name":"pathCommand","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_randomness","type":"uint256"}],"name":"generateSVG","outputs":[{"internalType":"string","name":"finalSvg","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxNumberOfPathCommands","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxNumberOfPaths","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pathCommands","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToSender","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"requestIdToTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"size","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"svg","type":"string"}],"name":"svgToImageURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenIdToRandomNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]; const options = { contractAddress: "0xC677b7A473aAA91B3c6a1D9433f5943AF0b04B11", functionName: "create", abi: ABI, params: {} }; console.log("Starting mint process"); const transaction = await Moralis.executeFunction(options); // 等待交易上链确认 const receipt = await transaction.wait(); console.log("VRF request submitted, transaction receipt: ", receipt); // 后续可在这里加监听VRF回调完成的逻辑,再调用finishMint完成mint /* 监听示例: setTimeout(async () => { // 从create交易的event中解析出生成的tokenId const event = receipt.events.find(item => item.event === 'requestedRandomSVG'); const tokenId = event.args.tokenId.toNumber(); const finishOptions = { contractAddress: "0xC677b7A473aAA91B3c6a1D9433f5943AF0b04B11", functionName: "finishMint", abi: ABI, params: { tokenId: tokenId } }; await Moralis.executeFunction(finishOptions); console.log("Mint completed"); }, 60000); // 等待60秒让VRF回调完成,可根据对应链出块速度调整 */ } catch (error) { console.error("Mint failed: ", error); } } // 确保DOM加载完成后再绑定事件 document.addEventListener('DOMContentLoaded', () => { const mintBtn = document.getElementById("mint_SoftHands"); if (mintBtn) { mintBtn.onclick = mintToken; } else { console.error("Mint button not found"); } }); </script> </body>
额外注意事项
- 调用前请确认当前连接的钱包所属链和合约部署链一致,且钱包内有足够的原生代币作为gas费,同时持有足够的LINK代币作为VRF调用手续费。
- 如果需要获取生成的NFT信息,可以在
finishMint交易确认后调用合约的tokenURI方法查询对应的NFT元数据。
内容的提问来源于stack exchange,提问作者gotnoshoeson
相关产品推荐
相关产品推荐

