分类 Blockchain 下的文章

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Add network to keplr</title>
    <style>
      input {width: 256px; padding: 5px}
      td {padding: 5px}
    </style>
    <link rel="icon" type="image/svg+xml" href="https://docs.keplr.app/favicon-svg.svg">
  </head>
  <body>
    <div style="max-width: 512px; margin: 0 auto; padding-top: 100px">
      <table border="0">
        <tr>
          <td>chainId</td>
          <td><input id="chainId" value="xxxChain"></td>
        </tr>
        <tr>
          <td>rpc</td>
          <td><input id="rpc" value="http://ip:26657"></td>
        </tr>
        <tr>
          <td>rest</td>
          <td><input id="rest" value="http://ip:1317"></td>
        </tr>
        <tr>
          <td>prefix</td>
          <td><input id="prefix" value="jolt"></td>
        </tr>
        <tr>
          <td>coinDenom</td>
          <td><input id="coinDenom" value="VUSD"></td>
        </tr>
        <tr>
          <td>coinDecimals</td>
          <td><input id="coinDecimals" value="0"></td>
        </tr>
        <tr>
          <td>gasPriceStep</td>
          <td><input id="gasPriceStep" value="0.01"></td>
        </tr>
        <tr>
          <td>walletUrlForStaking</td>
          <td><input id="walletUrlForStaking" value="url"></td>
        </tr>
        <tr>
          <td><button onclick="submit()">Submit</button></td>
          <td></td>
        </tr>
      </table>
      <p>Usage: https://docs.keplr.app/api/suggest-chain.html</p>
    </div>
    <script>
      submit = async () => {
        if (!keplr) {
          alert("Please install keplr extension"); return
        }
        const prefix = document.getElementById('prefix').value
        const coinDenom = document.getElementById('coinDenom').value
        const coinDecimals = parseInt(document.getElementById('coinDecimals').value)
        const gasPriceStep = Number(document.getElementById('gasPriceStep').value)
        await keplr.experimentalSuggestChain({
          chainId: document.getElementById('chainId').value,
          chainName: document.getElementById('chainId').value,
          rpc: document.getElementById('rpc').value,
          rest: document.getElementById('rest').value,
          bip44: {
            coinType: 118,
          },
          bech32Config: {
            bech32PrefixAccAddr: prefix,
            bech32PrefixAccPub: prefix + "pub",
            bech32PrefixValAddr: prefix + "valoper",
            bech32PrefixValPub: prefix + "valoperpub",
            bech32PrefixConsAddr: prefix + "valcons",
            bech32PrefixConsPub: prefix + "valconspub",
          },
          currencies: [
            { 
              coinDenom: coinDenom,
              coinMinimalDenom: coinDenom,
              coinDecimals: coinDecimals
            }, 
          ],
          feeCurrencies: [
            {
              coinDenom: coinDenom, 
              coinMinimalDenom: coinDenom,
              coinDecimals: coinDecimals
            },
          ],
          stakeCurrency: {
            coinDenom: coinDenom,
            coinMinimalDenom: coinDenom,
            coinDecimals: coinDecimals
          },
          coinType: 118,
          gasPriceStep: { 
            low: gasPriceStep,
            average: gasPriceStep*2,
            high: gasPriceStep*3,
          },
          walletUrlForStaking: document.getElementById('walletUrlForStaking').value
        })
      }
    </script>
  </body>
</html>

npm install -g truffle-flattener

because some new features in solidity 0.8.x might go wrong by truffle-flattener@1.5.0, so after installed, run code below again:

inpm nstall -g https://github.com/jplew/truffle-flattener

usage:

truffle-flattener ./contracts/MyContract.sol > ./flatten/MyContractFlatten.sol

and then put faltten code as single solidity file to bscscan

  • open your truffle project folder, and then run:
npm init -y

it will generate a file package.json in the root folder

  • install openzeppelin contracts:
npm install @openzeppelin/contracts
  • add a test solidity file called MyToken.sol to folder contracts/, and then put these test code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyToken is ERC20, Ownable {
    constructor() ERC20("MyToken", "MTK") {}
    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }
}

more usage, see node_modules/@openzeppelin/contracts/README.md

note: pragma solidity in the MyToken.sol above is ^0.8.4, and it is 0.8.0 in "@openzeppelin/contracts/token/ERC20/ERC20.sol", but it also compile successful

  • compile this project:
truffle compile

more details, watch this: /playlist?list=PLbbtODcOYIoFdQ37ydykQNO-MNGER6mtd

  • 安装
npm install -g truffle
  • 新建一个文件夹,在文件夹里执行:
truffle init
  • 在 contracts/ 文件夹新建自己的.sol文件,例如 Storage.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Storage {
    uint256 number;
    function store(uint256 num) public {
        number = num;
    }
    function retrieve() public view returns (uint256){
        return number;
    }
}
  • 编译
truffle compile

如果报错Cannot find module '@truffle/hdwallet-provider'就执行npm install @truffle/hdwallet-provider安装一下

编译成功就可以在 build/contracts/ 文件夹看到一些.json文件,里面包含了编译后的abi

编译前可以在truffle-config.js里配置solc版本,例如version: "0.8.4"

第一次编译可能需要很久,cmd界面一直显示 Compiling your contracts...,耐心等待一般没问题。

  • 在 test/ 文件夹添加测试文件,例如 Storage.js
const Storage = artifacts.require('Storage.sol');
contract('Storage', () => {
  it('Should update data', async () => {
    const storage = await Storage.new();
    await storage.store(10);
    const data = await storage.retrieve();
    assert(data.toString() === '10');
  });
});
  • 进行测试验证
truffle test
  • 在 migrations/ 文件夹新建 2_deploy_contracts.js,内容如下:
const Storage = artifacts.require('Storage.sol');
module.exports = function (deployer) {
  deployer.deploy(Storage);
};

如果文件名为deploy_contracts.js会导致后面的deploy没有结果,因此文件名前面要放“2_”。文件夹里自带的1_initial_migration.js可以删除,否则后续deploy也会deploy其对应的contract

  • 运行本地block chain net
truffle develop

如果没有ganache可能会报错,可能得先用npm安装ganache

启动成功就会进入truffle命令行状态,以 truffle(develop)> 开头

启动后会创建10个测试账号,这10个账号在下次启动时不会变

  • 在truffle命令行状态下,deploy之前编写的solidity:
migrate --reset

deploy成功就可以看到contract address了

  • deploy到bsc test net前,先去faucet领取一个BNB test coin
  • 安装
npm install @truffle/hdwallet-provider
  • 编辑truffle-config.js,在module.exports之前添加:
const fs = require('fs');
const HDWalletProvider = require('@truffle/hdwallet-provider');
let privateKey = fs.readFileSync(".privateKey").toString().trim();
if (-1===privateKey.toLowerCase().indexOf('0x')) {
  privateKey = '0x' + privateKey
}
const privateKeys = [privateKey]

私钥放在.privateKey文件里,注意添加到.gitignore

如果没有安装truffle/hdwallet-provider,需要先npm安装一下

在networks节点添加:

bscTestnet: {
  provider: ()=> new HDWalletProvider(privateKeys, 'https://data-seed-prebsc-2-s2.binance.org:8545/'),
  network_id: 97, skipDryRun: true
}

如果deploy到其它节点,按照上述格式添加其它节点信息即可

  • deploy 到bsc test net
truffle migrate --reset --network bscTestnet

deploy成功可以看到transaction hash和contract address等信息,到bscscan就可以查到相应信息

  • 用truffle console去跟bsc test交互
truffle console --network bscTestnet

成功就会进入truffle命令行状态,以 truffle(bscTestnet)> 开头。不过因为oversea,经常断线退出truffle命令行状态

  • 用truffle console进行交互
truffle(bscTestnet)> storage = await Storage.deployed()
truffle(bscTestnet)> storage.address
'log contract address here'
truffle(bscTestnet)> await storage.store(10)
truffle(bscTestnet)> data = await storage.retrieve()
truffle(bscTestnet)> data.toString()
'10'