golang nft

在快速上手的文章內已經有大致介紹怎麼去產生一個ntf,今天background 補一補就可以來寫一下了,在網路上找了一下都是nodejs 去呼叫,能不能用golang呼叫呢我們來看一下 https://ithelp.ithome.com.tw/articles/10269418 https://blog.aotoki.me/posts/2021/09/21/getting-started-nft/

https://blog.csdn.net/qq_37133717/article/details/80516917

https://ksin751119.medium.com/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-golang-%E5%91%BC%E5%8F%AB-solidity-contract-call-function-%E4%B8%8D%E6%9C%83%E7%9C%9F%E6%AD%A3%E5%9F%B7%E8%A1%8C-transaction-269648eb4a5

https://www.twblogs.net/a/5f04eaa0ca069a6e811d298f

Hardhat

經過幾年的發展區塊鏈相關的開發工具越來越成熟,我們可以直接透過 Hardhat 這個套件撰寫測試、部署智慧型合約。

code
mkdir MyNFT
yarn add -D hardhat && npx hardhat

OpenZeppelin 實作 ECR721 非常的簡單,我們先將基礎合約加入專案。

code
yarn add @openzeppelin/contracts

在部屬的方面我們使用nodejs 來部屬

deploy

code
.
├── README.md
├── artifacts
│   ├── @openzeppelin
│   ├── build-info
│   ├── contracts
│   └── hardhat
├── cache
│   └── solidity-files-cache.json
├── contracts
│   ├── Greeter.sol
│   ├── MyNFT.sol
│   ├── README.md
│   └── package.json
├── hardhat.config.js
├── package-lock.json
├── package.json
├── scripts
│   ├── deploy.js
│   ├── mint.js
│   └── sample-script.js
├── sol
│   └── output 
├── sources
│   ├── MyNFT.sol
│   ├── Store.sol
│   ├── contracts
│   ├── golangMyNFT.sol
│   └── output
├── test   └── sample-test.js
└── yarn.lock

OpenZeppelin gen ECR721 nodejs

code
yarn add @openzeppelin/contracts
code
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFT is ERC721, Ownable {
  using Counters for Counters.Counter;
  using Strings for uint256;
  Counters.Counter private _tokenIds;
  mapping (uint256 => string) private _tokenURIs;

  constructor() ERC721("MyNFT", "MNFT") {}
  function _setTokenURI(uint256 tokenId, string memory _tokenURI)
    internal
    virtual
  {
    _tokenURIs[tokenId] = _tokenURI;
  }

  function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
    string memory _tokenURI = _tokenURIs[tokenId];
    return _tokenURI;
  }

  function mint(address recipient, string memory uri)
    public
    returns (uint256)
  {
    _tokenIds.increment();
    uint256 newItemId = _tokenIds.current();
    _mint(recipient, newItemId);
    _setTokenURI(newItemId, uri);
    return newItemId;
  }
}

gen ECR721 nodejs to golang

OpenZeppelin 因為安全因素寫了模板那麼這些模板

code
import "@openzeppelin\....

實際上就是nodejs專案里的sol 那麼我們只要移出來基本上就可以進行編譯

code
pragma solidity ^0.8.0;
import "/contracts/token/ERC721/ERC721.sol";
import "/contracts/utils/Counters.sol";
import "/contracts/access/Ownable.sol";
contract MyNFT is ERC721, Ownable {
  using Counters for Counters.Counter;
  using Strings for uint256;
  Counters.Counter private _tokenIds;
  mapping (uint256 => string) private _tokenURIs;

  constructor() ERC721("MyNFT", "MNFT") {}
  function _setTokenURI(uint256 tokenId, string memory _tokenURI)
    internal
    virtual
  {
    _tokenURIs[tokenId] = _tokenURI;
  }

  function tokenURI(uint256 tokenId)
    public
    view
    virtual
    override
    returns (string memory)
  {
    require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
    string memory _tokenURI = _tokenURIs[tokenId];
    return _tokenURI;
  }

  function mint(address recipient, string memory uri)
    public
    returns (uint256)
  {
    _tokenIds.increment();
    uint256 newItemId = _tokenIds.current();
    _mint(recipient, newItemId);
    _setTokenURI(newItemId, uri);
    return newItemId;
  }
}

照以前的編譯流程

code
 docker run -v ~/golang/nodejs/sources:/sources ethereum/solc:stable -o /sources/output --abi --bin /sources/Store.sol
 abigen --bin=MyNFT.bin --abi=MyNFT.abi --pkg=store --out=MyNFT.go

到這邊我們就得到了合約檔案

hardhat.config.js

我們先用nodejs 進行部屬

code
require("@nomiclabs/hardhat-waffle");

// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
const PRIVATE_KEY = process.env.PRIVATE_KEY;
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
  const accounts = await hre.ethers.getSigners();

  for (const account of accounts) {
    console.log(account.address);
  }
});

// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more

/**
 * @type import('hardhat/config').HardhatUserConfig
 */
module.exports = {
  solidity: "0.8.3",
  // defaultNetwork: "hardhat",
  networks: {
    matic: {
      url: "http://172.20.64.1:7545", //這邊填入我們的ganache server
      accounts: ["f34d7cf0277f16e5b3a17a6f4997447c95e15510dacaa7b584171a75c45d7a7e"],
        //accounts 填入我們的  ganache 的帳號
    },
  }
};

/script/deploy.js

包括之前的目錄架構 我們還要把智能合約編成 golang 部屬合約

code
const hre = require("hardhat");

async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");
  const nft = await NFT.deploy();
    await nft.deployed();

    console.log("NFT deployed to:", nft.address);
}

main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

/script/mint.js

其中 url使用的一般的網址 https://cf.shopee.tw/file/fa65fb72e2b17594b3f1f5b6dec89382_tn

code
npx hardhat run scripts/mint.js --network matic

進行發布 nft

code
const hre = require("hardhat");
require("dotenv").config();

const WALLET_ADDRESS ="0x2ae127Cc29590d09A72B40F00b9802163aB3B248"; //我們的錢包
const CONTRACT_ADDRESS = "0x66Ed606D1359468258fd60267D0D4041CDBD13f8" //我們的合約地址

async function main() {
  const NFT = await hre.ethers.getContractFactory("MyNFT");

  const URI = "https://cf.shopee.tw/file/fa65fb72e2b17594b3f1f5b6dec89382_tn" //test

    const contract = NFT.attach(CONTRACT_ADDRESS);
    await contract.mint(WALLET_ADDRESS, URI);

  console.log("NFT minted:", contract);

}

main().then(() => process.exit(0)).catch(error => {
  console.error(error);
  process.exit(1);
});

check ntf smart Contracts

https://blockcast.it/2019/10/21/mica-research-1-min-intro-of-ipfs/ 我們知道最夯的 ntf 它裡面只是把url 換成 ipfs那麼我們來看怎麼取得 剛才ECR721合約裡的 url

code
func main (){
    address := common.HexToAddress("0x66Ed606D1359468258fd60267D0D4041CDBD13f8")
    instance, err := NewStore(address, client)
    if err != nil {
        log.Fatal(err)
    }
    // var number []byte
    // number = abi.U256(big.NewInt(0))
    fmt.Println("contract is loaded")
    a := big.NewInt(1)
    // CallOpts := new(bind.CallOpts)
    fmt.Println(a)

    geturl, err := instance.TokenURI(nil, a)
    if err != nil {
        log.Fatal(err)
    }
    // // _ = instance
    fmt.Println(instance)
    fmt.Println(geturl)

}

到此比較新型的區塊鏈技術應該就完成,ipfs 應該也可以自己架設,一個類似nft dapp 原理大致是這樣,其他應用就看大家的創意了,更多技術原理看這篇 for nodejs https://ithelp.ithome.com.tw/articles/10278782 它裡面包含應用的原理與實現我覺得講得很讚 大致上的意思就是大家挖的礦變成其他東西給替代,類似於抽獎大家每次挖的地方都不一樣,到最後可能合約某些value 會對應到某個帳號,有看到幾篇文章就是你可以識別那些eth 是你的。 https://medium.com/7sevencoin/erc20%E5%92%8Cerc721%E4%B8%8D%E4%B8%80%E6%A8%A3%E5%9C%A8%E5%93%AA%E8%A3%A1-2e550bb0bea3