# 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 這個套件撰寫測試、部署智慧型合約。 ```bahs mkdir MyNFT yarn add -D hardhat && npx hardhat ``` ![](https://i.imgur.com/AUdnmVB.png) # OpenZeppelin 實作 ECR721 非常的簡單,我們先將基礎合約加入專案。 ```bahs yarn add @openzeppelin/contracts ``` 在部屬的方面我們使用nodejs 來部屬 # deploy ```bash= . ├── 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 ```bash= yarn add @openzeppelin/contracts ``` ```solidity= 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 因為安全因素寫了模板那麼這些模板 ```solidity= import "@openzeppelin\.... ``` 實際上就是nodejs專案里的sol ![](https://i.imgur.com/d0tQqRV.png) 那麼我們只要移出來基本上就可以進行編譯 ```solidity= 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; } } ``` 照以前的編譯流程 ```bash= 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 ``` 到這邊我們就得到了合約檔案 ![](https://i.imgur.com/6VrvES3.png) # hardhat.config.js 我們先用nodejs 進行部屬 ![](https://i.imgur.com/RlIhMrF.png) ```jsx= 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 部屬合約 ```bash= 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); }); ``` ![](https://i.imgur.com/9Ln7KS8.png) ![](https://i.imgur.com/Z0aHy3u.png) # /script/mint.js 其中 url使用的一般的網址 https://cf.shopee.tw/file/fa65fb72e2b17594b3f1f5b6dec89382_tn ``` npx hardhat run scripts/mint.js --network matic ``` 進行發布 nft ![](https://i.imgur.com/OxxsxB3.png) ![](https://i.imgur.com/tMdl0hO.png) ```bash= 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 ```go= 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) } ``` ![](https://i.imgur.com/gcjzFop.png) 到此比較新型的區塊鏈技術應該就完成,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