Back

blockchain - 使用 infura, ipfs 创建NFT(erc721) truffle compile deploy exec mint

发布时间: 2022-06-19 22:59:00

refer to:  https://docs.infura.io/infura/tutorials/ethereum/create-an-nft-using-truffle

1. 需要创建一个IPFS 项目,在infura上。

如下图所示。

点击确认后,有一个绑定信用卡的过程。

绑定后,创建项目,增加 subdomain, 例如我的叫bigbanana

2. 上传LOGO文件到 IPFS

然后找到一个LOGO文件(例如叫做 bigbanana.png , 放到当前目录下),上传到IPFS 服务器上:

(记得把下面的??? 替换成你自己的。 前面的是project id, 后面的是project secret )

$ curl "https://ipfs.infura.io:5001/api/v0/add" -X POST -F file=@"bigbanana.png"    \
   -u "2AodumQVzetdQryc6A3PMg?????:deee615b42df210a945d49da39b?????"    

结果:

{"Name":"bigbanana.png","Hash":"QmUfZohadE7vYABSpR97gVyUWu1DuTUeAq4Y1HVcGVyxXR","Size":"15895"}

打开网址,就可以看到对应的结果了:

3. 创建metadata的JSON 文件

metadata.json 内容如下;

{
  "name": "Big Big Banana",
  "description": "The Banana is big! ",
  "image": "https://bigbanana.infura-ipfs.io/ipfs/QmUfZohadE7vYABSpR97gVyUWu1DuTUeAq4Y1HVcGVyxXR",
  "attributes": [
    { "trait_type": "taste", "value": "So good so sweet"},
    { "trait_type": "event", "value": "2022 , year , to , study , solidity contract"}
  ]
}

然后给它上传到远程

$ curl "https://ipfs.infura.io:5001/api/v0/add" \
-X POST \
-F file=@"metadata.json" \
-u "2AodumQVzetdQryc6A3PMg?????:deee615b42df210a945d49da39b?????"

结果如下:
{"Name":"metadata.json","Hash":"QmX6RYeTT8W4MymKaY6eBtoReHCFkVTV2XByctjV91aERu","Size":"349"}

然后访问对应的web url ,就可以看到该json文件了:

4. 创建truffle 文件夹

编辑package.json

{
  "dependencies": {
    "@openzeppelin/contracts": "^4.6.0",
    "@truffle/hdwallet-provider": "^2.0.9",
    "dotenv": "^16.0.1",
    "solc": "^0.8.14-fixed",
    "web3": "^1.7.3"
  },
  "devDependencies": {
    "truffle-plugin-verify": "^0.5.26"
  }
}

$ npm install (注意这里可能需要梯子)

truffle init

创建contract:   contracts/BigBigBanana.sol

$ cat contracts/BigBigBanana.sol
//Contract based on [https://docs.openzeppelin.com/contracts/4.x/erc721](https://docs.openzeppelin.com/contracts/4.x/erc721)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract BigBigBanana is ERC721URIStorage, Ownable {
  using Counters for Counters.Counter;
  Counters.Counter private _tokenIds;

  constructor() ERC721("Big Big Banana", "BBB") {}
  function mintNFT(address recipient, string memory tokenURI) public returns (uint256){
    _tokenIds.increment();
    uint256 newItemId = _tokenIds.current();
    _safeMint(recipient, newItemId);
    _setTokenURI(newItemId, tokenURI);
    return newItemId;
  }
}

修改truffle-config.js

require('dotenv').config();
const HDWalletProvider = require('@truffle/hdwallet-provider');
const { INFURA_API_URL, MNEMONIC } = process.env;

module.exports = {
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*"
    },
    goerli: {
      provider: () => new HDWalletProvider(MNEMONIC, INFURA_API_URL),
      network_id: '5',
      gas: 5500000,
//      gasPrice: 50000000000, // 50 gwei
      networkCheckTimeout: 1000000,
      timeoutBlocks: 200,
      addressIndex: 2
    }
  },
  compilers: {
    solc: {
      version: '0.8.15'
    }
  }
};

.env 文件内容为:

# 下面几个是调用的时候使用
ETHEREUM_NETWORK = "goerli"
INFURA_PROJECT_ID = "6d5b3edb39ed4ac39731a6f10754????"
# address: 0xc0dD5021e298dB57bEF361C735cd1C04cef2????
SIGNER_PRIVATE_KEY = "a7d856cf836a71422df6a76837e1c67022aba9bda349b0a9e85a496c????????"

# 下面2个是发布的时候使用  
INFURA_API_URL = "wss://goerli.infura.io/ws/v3/427a8f460d514ebfadf0d6c60b09ef27"
MNEMONIC = "margin blouse tenant chat hub chef addict club rather prize ???? ????

5. 编译: truffle compile

$ truffle compile

Compiling your contracts...
===========================
> Compiling ./contracts/BigBigBanana.sol
> Compiling ./contracts/Migrations.sol
> Compiling @openzeppelin/contracts/access/Ownable.sol
> Compiling @openzeppelin/contracts/token/ERC721/ERC721.sol
> Compiling @openzeppelin/contracts/token/ERC721/IERC721.sol
> Compiling @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol
> Compiling @openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol
> Compiling @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol
> Compiling @openzeppelin/contracts/utils/Address.sol
> Compiling @openzeppelin/contracts/utils/Context.sol
> Compiling @openzeppelin/contracts/utils/Counters.sol
> Compiling @openzeppelin/contracts/utils/Strings.sol
> Compiling @openzeppelin/contracts/utils/introspection/ERC165.sol
> Compiling @openzeppelin/contracts/utils/introspection/IERC165.sol
> Artifacts written to /mnt/d/workspace/test_erc_721_bigbanana_infura/build/contracts
> Compiled successfully using:
   - solc: 0.8.15+commit.e14f2714.Emscripten.clang

6. 发布 truffle deploy --network goerli --interactive

2_deploy_contract.js
====================

   Deploying 'BigBigBanana'
   ------------------------
   > transaction hash:    0x66efcaff257688c4fc272289e2cdea7c61e0621a0043a61e0f6aea9870c008a1
   > Blocks: 0            Seconds: 8
   > contract address:    0x3223BBDf275782d54587E3520183Ad3DFE033D46
   > block number:        7088953
   > block timestamp:     1655690375
   > account:             0xc0dD5021e298dB57bEF361C735cd1C04cef2E48A
   > balance:             5.443236181770190214
   > gas used:            2880887 (0x2bf577)
   > gas price:           2.500000008 gwei
   > value sent:          0 ETH
   > total cost:          0.007202217523047096 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:     0.007202217523047096 ETH

Summary
=======
> Total deployments:   2
> Final cost:          0.007827602525048328 ETH

7. 创建一个 脚本: mint.js  内容如下:

const TOKEN_URI = "https://bigbanana.infura-ipfs.io/ipfs/QmX6RYeTT8W4MymKaY6eBtoReHCFkVTV2XByctjV91aERu"
const CONTRACT_ADDRESS = "0x3223BBDf275782d54587E3520183Ad3DFE033D46"
const PUBLIC_ADDRESS = "0xc0dD5021e298dB57bEF361C735cd1C04cef2E48A"

// Loading the compiled contract Json
const contractJson = require('./build/contracts/BigBigBanana.json')

module.exports = async function (callback) {
  // web3 是Truffle的自动引入的对象
  const contract = new web3.eth.Contract( contractJson.abi, CONTRACT_ADDRESS );

  // 获得 network , 这个是根据参数传入的
  const network = await web3.eth.net.getNetworkType()

  // 生成一个tx, 该tx是调用了 mintNFT产生的
  const tx = contract.methods.mintNFT(PUBLIC_ADDRESS, TOKEN_URI)

  // 发送!
  const receipt = await tx
  .send({
    from: (await web3.eth.getAccounts())[0],// 使用了HD wallet中的第一个account
    gas: await tx.estimateGas(),
  })
  .on('transactionHash', (txhash) => {
    console.log(`Mining transaction ...`)
    console.log(`https://${network}.etherscan.io/tx/${txhash}`)
  })
  .on('error', function(error){
    console.error(`An error happened: ${error}`)
    callback()
  })
  .then(function(receipt){
    // Success, you've minted the NFT. The transaction is now on chain!
    console.log(
        `Success: The NFT has been minted and mined in block ${receipt.blockNumber}`)
    callback()
  })
}

8 .运行该mint 脚本 (在truffle 环境中;  truffle exec mint.js --network goerli)

$ truffle exec mint.js --network goerli
Using network 'goerli'.

Mining transaction ...
https://goerli.etherscan.io/tx/0x6b61670c5dccd8fa46814546df06ffe7150bcbd399f5626ee31597cbcbb37a26
Success: The NFT has been minted and mined in block 7089096

就可以发现,我们的NFT已经被挖掘出来了,给到了对应的账户地址中

看下面的 transfer data, 可以看到, mint的时候,是传入了2个参数的:

Back