Now and Nawoo

NFTの制作記録、技術メモ → C#, Solidity, Blockchain, Bitcoin, Ethereum, NFT

ethers.js 使い方メモ

Hardhatではethers.jsを使っているので、Web UIサイトを作成するときにもweb3.jsではなくethers.jsを使ってみることにしました。

ethers.js ドキュメント

コントラクトを扱うには、Provider作成→Signer作成→Contract作成、という流れになります。Read-onlyならSignerは不要です。

Provider

Ethereumネットワーク → DefaultProvider

// APIキーを指定
const provider = ethers.getDefaultProvider("homestead", {etherscan: "XXX", infura: "XXX", alchemy: "XXX"});
// APIキーを省略
const provider = ethers.getDefaultProvider("homestead");

ネットワーク名は "homestead", "rinkeby", "ropsten" のような名前か chainIDを指定します。

オプションで、etherscan, infura, alchemyなどのAPIキーを指定できます。 (省略しても使えますが、共有のAPIキーが使われるので遅くなります。)

ローカルネットワーク → DefaultProvider

const provider = ethers.getDefaultProvider("http://localhost:8545");

PolygonやBSCなど → JsonRpcProvider

JsonRpcProviderでRPC URL を指定します。

const provider = new ethers.providers.JsonRpcProvider(rpcURL);

MetaMaskと接続 → Web3Provider

const provider = new ethers.providers.Web3Provider(window.ethereum)

Signer (Wallet)

Signerとは署名するためのクラスで、WalletはSignerの一種です。

秘密鍵からWalletを作成

const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

ニモニックからWalletを作成

const wallet = ethers.Wallet.fromMnemonic(MNEMONIC).connect(provider);

MetaMaskのアカウントを使う

const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();

コントラクトを扱う

コントラクトアドレス、ABI、ProviderまたはSignerからContractを作成します。

const contract = new ethers.Contract(contractAddress, abi, provider); // read-only
const contract = new ethers.Contract(contractAddress, abi, signer); // read/writeの場合

後は、関数を呼び出すだけです。

Read

Read関数なら、そのままawaitで値を取得できます。

const value = await contract.getValue();
console.log(value);

Write

Write関数の場合はtransactionが返ってきます。

const tx = await contract.setValue(123);
const receipt = await tx.wait(); // マイニングされるまで待つ

イベント

イベントはcontract.onで受信します。

contract.on("event_name", (params)=>{
  // イベント発生時の処理
}) 
// contract.once(...)なら一度だけ

ABIについて

従来のJSON形式のABIファイルももちろん使えますが、ethers.jsではHuman-Readable ABIというのにも対応していて、 Solidityの関数の1行目だけを切り取ったような形式を用意するだけでよいので便利です。

ABI Formats

// Human-Readable ABI (シンプル)
const abi = [
  "function transferFrom(address from, address to, uint value)",
  "function balanceOf(address owner) view returns (uint balance)",
  "event Transfer(address indexed from, address indexed to, address value)"
];
// 従来のABI (長い)
const abi = `[
  {
    "type": "function",
    "name": "transferFrom",
    "constant": false,
    "payable": false,
    "inputs": [
      { "type": "address", "name": "from" },
      { "type": "address", "name": "to" },
      { "type": "uint256", "name": "value" }
    ],
    "outputs": [ ]
  },
...