見出し画像

JavaScriptでコントラクトを実行する

この記事では、Hello WorldコントラクトをJavaScriptから実行してみます。


前回の記事からの続きとなります。


こちらのチュートリアルに沿って進めていきます。


0. 事前準備

JavaScriptからコントラクトを実行するにはEthers.jsが必要になります。

Ethers.jsは、Ethereumブロックチェーンとやり取りするためのJavaScriptライブラリです。
軽量で使いやすく、Ethereum開発者にとって非常に人気のあるツールです。

主な用途としてDAppの開発やスマートコントラクトのデプロイと実行、ウォレット管理に使われます。

chatGPT

前の記事で既にインストール済みですが、まだの方はnpmでインストールできます。

$ npm install ethers@5.7.2


1. JavaScriptファイルの作成

「scripts」フォルダーにJSファイルを作成していきます。

$ cd scripts

$ pwd
/hello-world/scripts

$ touch interact.js


作成したJSファイルに環境変数を読み込むコードを追加します。

const API_URL = process.env.API_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;


新しい環境変数を使用するためには、.envを更新する必要があります。
Alchemy API_KEYとCONTRACT_ADDRESSの定義を追加します。

# .env

API_URL = "https://eth-sepolia.g.alchemy.com/v2/<your-api-key>"
API_KEY = "<your-api-key>"
PRIVATE_KEY = "<your-metamask-private-key>"
CONTRACT_ADDRESS = "0x<your contract address>"


2. ABIのコントラクト情報を出力

JavaScriptでスマートコントラクトとやり取りするには、コントラクトABI(Application Binary Interface)というインターフェースが必要になります。

ABIについては、こちらの記事が参考になります。


コントラクトABIは、Hardhatでデプロイすると自動的に作成されます。
この記事では、「artifacts」フォルダにあるHelloWorld.jsonがABIファイルになります。

- artifacts
  - contracts
    - HelloWorld.sol
      - HelloWorld.json


Hello WorldコントラクトのABIをJSで読み込んで、ログを出力してみます。interact.jsにコードを追加します。

// For Hardhat 
const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json");

console.log(JSON.stringify(contract.abi));


プロジェクトディレクトリに移動して、hardhatコマンドでJSを実行します。

$ pwd
/hello-world

$ npx hardhat run scripts/interact.js
[{"inputs":[{"internalType":"string","name":"initMessage","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"oldStr","type":"string"},{"indexed":false,"internalType":"string","name":"newStr","type":"string"}],"name":"UpdatedMessages","type":"event"},{"inputs":[],"name":"message","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"newMessage","type":"string"}],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"}]


出力されたログには、Hello Worldコントラクトに含まれる関数や変数、データ構造などの情報が含まれます。

3. コントラクトのインスタンスを作成

コントラクトとやり取りするには、コントラクトのインスタンスを作成する必要があります。

interact.jsに以下のコードを追加します。

const ethers = require('ethers');

// Provider
const alchemyProvider = new ethers.providers.JsonRpcProvider(API_URL);

// Signer
const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider);

// Contract
const helloWorldContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);


Ethers.js では、次の 3 つのインスタンスを作成する必要があります。

  • Provider- ブロックチェーンへの読み取りおよび書き込みアクセスを提供するノード プロバイダーです。

  • Signer- トランザクションに署名する機能を持つ Ethereum アカウントを表します。

  • Contract - オンチェーンにデプロイされた特定のコントラクトを表す Ethers.js オブジェクトです。


5. 初期化メッセージを読み込む

前回の記事で、"Hello world!"の引数を渡してコントラクトにデプロイしました。

// deploy.js

const hello_world = await HelloWorld.deploy("Hello World!");


message関数を呼び出し、スマートコントラクトに保存されている初期メッセージ("Hello world!")をログに出力します。

// interact.js

// ...

async function main() {
  const message = await helloWorldContract.message();
  console.log("The message is: " + message);
}
main();


実行すると"Hello World!"の文字列が表示されました。

$ npx hardhat run scripts/interact.js
The message is: Hello World!


6.メッセージを更新する

メッセージの読み取りだけでなく、update関数を使用してスマートコントラクトに保存されているメッセージを更新してみます。

interact.jsを以下のコードに変更します。

// interact.js

const API_URL = process.env.API_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const CONTRACT_ADDRESS = process.env.CONTRACT_ADDRESS;
const ethers = require('ethers');

const contract = require("../artifacts/contracts/HelloWorld.sol/HelloWorld.json");

// provider - Alchemy
const alchemyProvider = new ethers.providers.JsonRpcProvider(API_URL);

// signer - you
const signer = new ethers.Wallet(PRIVATE_KEY, alchemyProvider);

// contract instance
const helloWorldContract = new ethers.Contract(CONTRACT_ADDRESS, contract.abi, signer);

async function main() {
    const message = await helloWorldContract.message();
    console.log("The message is: " + message); 

    console.log("Updating the message...");
    const tx = await helloWorldContract.update("this is the new message");
    await tx.wait();

    const newMessage = await helloWorldContract.message();
    console.log("The new message is: " + newMessage); 
}

main();


スクリプトを実行すると古いメッセージ、更新ステータス、新しいメッセージがターミナルに出力されます。

$ npx hardhat run scripts/interact.js --network sepolia

The message is: Hello World!
Updating the message...
The new message is: this is the new message

新しいメッセージの更新に少し時間がかかりました。
これは、コントラクトがガス代を支払いマイニングしてもらうまでの時間となります。

最後にetherscanで、コントラクトの実行を確認してみます。
https://sepolia.etherscan.io/address/0x024CEc0E8aD1E71cC69c0a095B00377174DeD23F


実行したupdateのトランザクションが追加されています。


Logsを見ると旧メッセージと新メッセージがトランザクションに書き込まれているのも確認できました。

以上がJavaScriptでコントラクトを実行する方法です!


この記事が気に入ったらサポートをしてみませんか?