区块链变更 + 应付交易 Ethers.js
Blockchain altering + payable transactions with Ethers.js
我正在尝试在我的 dapp 上创建一个 mint 功能,用户可以在其中连接他们的 metamask 钱包,连接到适当的网络(在这种情况下,我只是在测试它所以它是 Goerli,chainID:5)然后单击一个 mint 按钮并被要求接受交易,目前我正在努力获取正确的语法并为交易对象设置正确的值,我收到错误:
TypeError: DenOfDragonsSigned.mint(...) is not a function
尽管这是因为我相信我已经正确设置了 ABI
和:
MetaMask - RPC Error: execution reverted: Insufficient funds!
即使我已经正确设置了“值:”并且有足够的交易测试 eth
这是我的 ABI:
[
{
"inputs": [],
"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"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "approve1TokenForStaking",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "approveAllTokensForStaking",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_merkleRoot",
"type": "bytes32"
}
],
"name": "changeMerkleROOT",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_address",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32[]",
"name": "_merkleProof",
"type": "bytes32[]"
},
{
"internalType": "uint256",
"name": "_mintAmount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_mintAmount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_receiver",
"type": "address"
}
],
"name": "mintForAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"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": [
{
"internalType": "uint256",
"name": "_cost",
"type": "uint256"
}
],
"name": "setCost",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_hiddenMetadataUri",
"type": "string"
}
],
"name": "setHiddenMetadataUri",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxMintAmountPerTx",
"type": "uint256"
}
],
"name": "setMaxMintAmountPerTx",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_max",
"type": "uint256"
}
],
"name": "setMaxPresaleMintAmount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_open",
"type": "bool"
}
],
"name": "setOpenToPublic",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_state",
"type": "bool"
}
],
"name": "setPaused",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_state",
"type": "bool"
}
],
"name": "setRevealed",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_contractAddress",
"type": "address"
}
],
"name": "setStakingAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_uriPrefix",
"type": "string"
}
],
"name": "setUriPrefix",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_uriSuffix",
"type": "string"
}
],
"name": "setUriSuffix",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"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"
},
{
"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": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "cost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hiddenMetadataUri",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"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": "maxMintAmountPerTx",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxPresaleMintAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxSupply",
"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": "OpenToPublic",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"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": [],
"name": "paused",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "revealed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "root",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "stakingContract",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "uriPrefix",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "uriSuffix",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
}
],
"name": "walletOfOwner",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "whitelistClaimed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
我的App.js:
import React, { useState, useEffect } from 'react';
import "./styles.css";
import { ethers } from "ethers";
import DenOfDragonsABI from "contracts/DenOfDragons.json";
import { parseEther, parseUnits } from 'ethers/lib/utils';
let signer;
let provider;
let DenOfDragonsContract;
const DenOfDragonsAddress = "0x93e581BE9BDcCD0Cd96f5F4cbA6E5ADeA79c65ee"; // make sure this is correct
const DenOfDragonsAbi = DenOfDragonsABI;
export default function App() {
const [metaMaskIntalled, setMetaMaskInstalled] = useState();
const [activeAccount, setActiveAccount] = useState();
const [activeChainID, setActiveChainID] = useState();
const [connected, setConnected] = useState();
const [errorMessage, setErrorMessage] = useState();
const [balance, setBalance] = useState(0);
const [totalSupply, setTotalSupply] = useState(0);
//start of web3
const ConnectToMetaMask = async () => {
provider = new ethers.providers.Web3Provider(window.ethereum, "any")
if (typeof provider !== "undefined") {
setMetaMaskInstalled(true);
await provider.send("eth_requestAccounts", []).then(accounts => {
if (typeof accounts !== "undefined") {
setActiveAccount(accounts[0]);
console.log("Active account is:" , accounts[0]);
setConnected(true);
} else {
setConnected(false);
setActiveChainID("0")
}
}).catch(err => {
console.log(err);
});
getSigner()
window.ethereum.on("accountsChanged", function (accounts) {
setActiveAccount(accounts[0]);
if (typeof accounts[0] !== "undefined") {
console.log("Active account changed to:" , accounts[0]);
setConnected(true);
getSigner();
}
else {
console.log("Disconnected");
setConnected(false);
setActiveChainID("0");
}
})
window.ethereum.on("chainChanged", function (chainID) {
setActiveChainID(parseInt(chainID, 16));
console.log("Active chainID changed to:", parseInt(chainID, 16));
getTotalSupply();
})
DenOfDragonsContract = new ethers.Contract(
DenOfDragonsAddress,
DenOfDragonsAbi,
provider
);
}
else {setMetaMaskInstalled(false)
};
}
const getSigner = async () => {
signer = provider.getSigner();
await signer.getChainId().then(chainID => {
if (typeof chainID !== "undefined") {
setActiveChainID(chainID);
console.log("Active chainID is:", chainID);
}
}).catch(err => {
console.log(err);
})
}
const mintNft = async (mintAmmount) => {
if (connected & activeChainID === 5) {
let cost = String((0.07 * mintAmmount) * (10 ** 18));
console.log("Total cost:", cost);
let gas = String(285000 * mintAmmount);
console.log("Total gas:", gas);
const DenOfDragonsSigned = new ethers.Contract(
DenOfDragonsAddress,
DenOfDragonsAbi,
signer
)
const tx = DenOfDragonsSigned.mint([], mintAmmount) ({
gasLimit: gas,
to: DenOfDragonsAddress,
from: activeAccount,
value: cost,
nonse: provider.getTransactionCount(activeAccount, "latest")
});
const signedTransaction = await signer.signTransaction(tx)
.catch(err => {
console.log(err)
setErrorMessage(err["message"])
});
const transaction = await provider.sendTransaction(signedTransaction)
.catch(err => {
console.log(err)
setErrorMessage(err["message"])
});
console.log(transaction);
} else {
ConnectToMetaMask();
};
}
const getOwnBalance = async () => {
if (connected & activeChainID === 1) {
const result = await DenOfDragonsContract.balanceOf(activeAccount)
.catch(err => {
console.log(err);
});
const balanceT = parseInt(result, 16)
setBalance(balanceT);
return(balanceT);
} else {
ConnectToMetaMask();
};
}
const getTotalSupply = async () => {
if (connected & activeChainID === 1) {
const result = await DenOfDragonsContract.totalSupply()
.catch(err => {
console.log(err);
});
const totalSupplyT = parseInt(result, 16)
setTotalSupply(totalSupplyT);
return(totalSupplyT)
}
}
//end of web3
const fetchBalance = () => {
console.log("getting balance...")
getOwnBalance().then(balance => {
console.log("NFT Balance Is:", balance)
setBalance(balance);
});
}
return (
<>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
</style>
<div className='backdrop'>
<div className='mainBox'>
<div className='textBox'>
<h1 className='supply'>
{totalSupply} / 1,000
</h1>
<a className="etherScanLink" href="https://etherscan.io/token/0x1897D69cc0088D89C1e94889fBD2eFFfCEfEd778">
0x1897D6...</a>
<h2 className='price'>
1 (NFT Name) costs (Price) ETH
</h2>
<h4 className='extraText'>
Mint a (...) and become a (...) today!
</h4>
</div>
<div className='mintButtonContainer'>
{!connected ?
<button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button> :
<>
{activeChainID === 5 ?
<>
<h4 className='errMsg'>
{errorMessage}
</h4>
<button className ="mintButton" onClick={() =>mintNft(1)}>Mint</button>
</>:
<>
<h4 className='changeNetwork'>
Change Netwrok To Ethereum
</h4>
<button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button>
</> }
</>}
</div>
</div>
</div>
</>
)
}
坦率地说,我不知道我做错了什么,因为这类事情非常缺乏教程,我已经阅读了 solidity、ethers.js、MetaMask 和 Ethereum 的文档,但我只是看不出问题出在哪里,感谢您提供的任何帮助
你重复调用了 mint 函数。
此外,以太币和合约工厂已经知道你不需要的地址:to
、from
或 nonce
。
您可以将您的 mint 调用更改为:
const tx = DenOfDragonsSigned.mint([], mintAmmount,{
value: cost
});
const txHash = tx.wait();
console.log(txHash);
你应该设置好了 ;)
我正在尝试在我的 dapp 上创建一个 mint 功能,用户可以在其中连接他们的 metamask 钱包,连接到适当的网络(在这种情况下,我只是在测试它所以它是 Goerli,chainID:5)然后单击一个 mint 按钮并被要求接受交易,目前我正在努力获取正确的语法并为交易对象设置正确的值,我收到错误:
TypeError: DenOfDragonsSigned.mint(...) is not a function
尽管这是因为我相信我已经正确设置了 ABI
和:
MetaMask - RPC Error: execution reverted: Insufficient funds!
即使我已经正确设置了“值:”并且有足够的交易测试 eth
这是我的 ABI:
[
{
"inputs": [],
"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"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "approve",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "approve1TokenForStaking",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "approveAllTokensForStaking",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "_merkleRoot",
"type": "bytes32"
}
],
"name": "changeMerkleROOT",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_address",
"type": "address"
}
],
"name": "isApprovedForAll",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32[]",
"name": "_merkleProof",
"type": "bytes32[]"
},
{
"internalType": "uint256",
"name": "_mintAmount",
"type": "uint256"
}
],
"name": "mint",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_mintAmount",
"type": "uint256"
},
{
"internalType": "address",
"name": "_receiver",
"type": "address"
}
],
"name": "mintForAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "previousOwner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "newOwner",
"type": "address"
}
],
"name": "OwnershipTransferred",
"type": "event"
},
{
"inputs": [],
"name": "renounceOwnership",
"outputs": [],
"stateMutability": "nonpayable",
"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": [
{
"internalType": "uint256",
"name": "_cost",
"type": "uint256"
}
],
"name": "setCost",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_hiddenMetadataUri",
"type": "string"
}
],
"name": "setHiddenMetadataUri",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_maxMintAmountPerTx",
"type": "uint256"
}
],
"name": "setMaxMintAmountPerTx",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_max",
"type": "uint256"
}
],
"name": "setMaxPresaleMintAmount",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_open",
"type": "bool"
}
],
"name": "setOpenToPublic",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_state",
"type": "bool"
}
],
"name": "setPaused",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bool",
"name": "_state",
"type": "bool"
}
],
"name": "setRevealed",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_contractAddress",
"type": "address"
}
],
"name": "setStakingAddress",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_uriPrefix",
"type": "string"
}
],
"name": "setUriPrefix",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "_uriSuffix",
"type": "string"
}
],
"name": "setUriSuffix",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"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"
},
{
"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": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "cost",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "getApproved",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "hiddenMetadataUri",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"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": "maxMintAmountPerTx",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxPresaleMintAmount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "maxSupply",
"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": "OpenToPublic",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"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": [],
"name": "paused",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "revealed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "root",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "stakingContract",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "symbol",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_tokenId",
"type": "uint256"
}
],
"name": "tokenURI",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "uriPrefix",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "uriSuffix",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
}
],
"name": "walletOfOwner",
"outputs": [
{
"internalType": "uint256[]",
"name": "",
"type": "uint256[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "whitelistClaimed",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
我的App.js:
import React, { useState, useEffect } from 'react';
import "./styles.css";
import { ethers } from "ethers";
import DenOfDragonsABI from "contracts/DenOfDragons.json";
import { parseEther, parseUnits } from 'ethers/lib/utils';
let signer;
let provider;
let DenOfDragonsContract;
const DenOfDragonsAddress = "0x93e581BE9BDcCD0Cd96f5F4cbA6E5ADeA79c65ee"; // make sure this is correct
const DenOfDragonsAbi = DenOfDragonsABI;
export default function App() {
const [metaMaskIntalled, setMetaMaskInstalled] = useState();
const [activeAccount, setActiveAccount] = useState();
const [activeChainID, setActiveChainID] = useState();
const [connected, setConnected] = useState();
const [errorMessage, setErrorMessage] = useState();
const [balance, setBalance] = useState(0);
const [totalSupply, setTotalSupply] = useState(0);
//start of web3
const ConnectToMetaMask = async () => {
provider = new ethers.providers.Web3Provider(window.ethereum, "any")
if (typeof provider !== "undefined") {
setMetaMaskInstalled(true);
await provider.send("eth_requestAccounts", []).then(accounts => {
if (typeof accounts !== "undefined") {
setActiveAccount(accounts[0]);
console.log("Active account is:" , accounts[0]);
setConnected(true);
} else {
setConnected(false);
setActiveChainID("0")
}
}).catch(err => {
console.log(err);
});
getSigner()
window.ethereum.on("accountsChanged", function (accounts) {
setActiveAccount(accounts[0]);
if (typeof accounts[0] !== "undefined") {
console.log("Active account changed to:" , accounts[0]);
setConnected(true);
getSigner();
}
else {
console.log("Disconnected");
setConnected(false);
setActiveChainID("0");
}
})
window.ethereum.on("chainChanged", function (chainID) {
setActiveChainID(parseInt(chainID, 16));
console.log("Active chainID changed to:", parseInt(chainID, 16));
getTotalSupply();
})
DenOfDragonsContract = new ethers.Contract(
DenOfDragonsAddress,
DenOfDragonsAbi,
provider
);
}
else {setMetaMaskInstalled(false)
};
}
const getSigner = async () => {
signer = provider.getSigner();
await signer.getChainId().then(chainID => {
if (typeof chainID !== "undefined") {
setActiveChainID(chainID);
console.log("Active chainID is:", chainID);
}
}).catch(err => {
console.log(err);
})
}
const mintNft = async (mintAmmount) => {
if (connected & activeChainID === 5) {
let cost = String((0.07 * mintAmmount) * (10 ** 18));
console.log("Total cost:", cost);
let gas = String(285000 * mintAmmount);
console.log("Total gas:", gas);
const DenOfDragonsSigned = new ethers.Contract(
DenOfDragonsAddress,
DenOfDragonsAbi,
signer
)
const tx = DenOfDragonsSigned.mint([], mintAmmount) ({
gasLimit: gas,
to: DenOfDragonsAddress,
from: activeAccount,
value: cost,
nonse: provider.getTransactionCount(activeAccount, "latest")
});
const signedTransaction = await signer.signTransaction(tx)
.catch(err => {
console.log(err)
setErrorMessage(err["message"])
});
const transaction = await provider.sendTransaction(signedTransaction)
.catch(err => {
console.log(err)
setErrorMessage(err["message"])
});
console.log(transaction);
} else {
ConnectToMetaMask();
};
}
const getOwnBalance = async () => {
if (connected & activeChainID === 1) {
const result = await DenOfDragonsContract.balanceOf(activeAccount)
.catch(err => {
console.log(err);
});
const balanceT = parseInt(result, 16)
setBalance(balanceT);
return(balanceT);
} else {
ConnectToMetaMask();
};
}
const getTotalSupply = async () => {
if (connected & activeChainID === 1) {
const result = await DenOfDragonsContract.totalSupply()
.catch(err => {
console.log(err);
});
const totalSupplyT = parseInt(result, 16)
setTotalSupply(totalSupplyT);
return(totalSupplyT)
}
}
//end of web3
const fetchBalance = () => {
console.log("getting balance...")
getOwnBalance().then(balance => {
console.log("NFT Balance Is:", balance)
setBalance(balance);
});
}
return (
<>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
</style>
<div className='backdrop'>
<div className='mainBox'>
<div className='textBox'>
<h1 className='supply'>
{totalSupply} / 1,000
</h1>
<a className="etherScanLink" href="https://etherscan.io/token/0x1897D69cc0088D89C1e94889fBD2eFFfCEfEd778">
0x1897D6...</a>
<h2 className='price'>
1 (NFT Name) costs (Price) ETH
</h2>
<h4 className='extraText'>
Mint a (...) and become a (...) today!
</h4>
</div>
<div className='mintButtonContainer'>
{!connected ?
<button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button> :
<>
{activeChainID === 5 ?
<>
<h4 className='errMsg'>
{errorMessage}
</h4>
<button className ="mintButton" onClick={() =>mintNft(1)}>Mint</button>
</>:
<>
<h4 className='changeNetwork'>
Change Netwrok To Ethereum
</h4>
<button className ="mintButton" onClick={ConnectToMetaMask}>Connect To MetaMask</button>
</> }
</>}
</div>
</div>
</div>
</>
)
}
坦率地说,我不知道我做错了什么,因为这类事情非常缺乏教程,我已经阅读了 solidity、ethers.js、MetaMask 和 Ethereum 的文档,但我只是看不出问题出在哪里,感谢您提供的任何帮助
你重复调用了 mint 函数。
此外,以太币和合约工厂已经知道你不需要的地址:to
、from
或 nonce
。
您可以将您的 mint 调用更改为:
const tx = DenOfDragonsSigned.mint([], mintAmmount,{
value: cost
});
const txHash = tx.wait();
console.log(txHash);
你应该设置好了 ;)