1
1

【Node.js】ethers.jsでトークンを送信する

Last updated at Posted at 2023-10-09

最近話題のweb3を使ったアプリケーション作りたいと思い、とりあえずプログラムでトークンを送信することに挑戦しました。

公式のコードを参考にやってみました。
https://ethereum.org/ja/developers/tutorials/send-token-etherjs/

ほぼこの通りなのですが、このままではエラーが出るので修正しました。(後述)

動作確認環境

  • macOS Ventura
  • Node.js v20.0.0

準備

Remix(トークン作成)

作り方はこちら
https://qiita.com/tatsuya1970/items/b68da529bcf1a92c5d10

トークンを作成したら、トークンのコントラクトアドレスを控える。

そして、トークンのABIをコピーし、

あとで作成する index.js と同じディレクトリに、 abi.json として保存します。


ウォレットの秘密鍵

ここではMetamaskを例にします。
右上の3本点をクリック

アカウントの詳細 > Show Privatekey

この秘密鍵を控えておく。


Infura

Infuraは、Ethereumノードへのアクセスを提供するクラウドサービスです。
https://www.infura.io/

あとで必要なので、Project ID を控えておきます。
Image from Gyazo

なお、その他は触らないこと。
よかれと思い、ここのチェックをオンにしたため、後々凄くハマってしまいました。
Image from Gyazo



開発

ether.js

Ethereumブロックチェーンのライブラリ ethers.js と
環境変数設定のライブラリ dotenv をインストールします。

$ npm install --save ethers
$ npm install --save dotenv

コード

ほぼ公式のコードと同じです。

修正・追加箇所

修正箇所
(修正前) window.ethersProvider
(修正後) provider
追加箇所

同じディレクトリに保存したABIのJSONファイルを読み出す箇所を追加

const fs = require('fs');
const send_abi = JSON.parse(fs.readFileSync('./abi.json', 'utf8'));

コード

環境変数

さきほど控えた環境変数を設定

.env
INFURA_PROJECT_ID=INFURAのプロジェクトID
PRIVATE_KEY=送信元のウォレットのプライベートキー
メイン
index.js
'use strict';
require("dotenv").config();
const { ethers } = require("ethers");
const infuraProjectId = process.env.INFURA_PROJECT_ID;

const provider = new ethers.providers.InfuraProvider('goerli', infuraProjectId);

let private_key = process.env.PRIVATE_KEY;
let send_token_amount = "1";
let to_address = "送信先のアドレス";
let send_address = "送信元のアドレス";
let gas_limit = "0x100000";
let wallet = new ethers.Wallet(private_key);

let walletSigner = wallet.connect(provider);
let contract_address = "先ほど控えたトークンのコントラクトアドレス";

send_token(
  contract_address,
  send_token_amount,
  to_address,
  send_address,
  private_key
);

function send_token(
    contract_address,
    send_token_amount,
    to_address,
    send_account,
    private_key
  ) {

    let wallet = new ethers.Wallet(private_key);
    let walletSigner = wallet.connect(provider);

    provider.getGasPrice().then((currentGasPrice) => {  
     let gas_price = ethers.utils.hexlify(parseInt(currentGasPrice));
     console.log(`gas_price: ${gas_price}`);

      if (contract_address) {
        const fs = require('fs');
        const send_abi = JSON.parse(fs.readFileSync('./abi.json', 'utf8'));
        // general token send
        let contract = new ethers.Contract(
          contract_address,
          send_abi,
          walletSigner
        ) ;
        // How many tokens?
        let numberOfTokens = ethers.utils.parseUnits(send_token_amount, 18);
        console.log(`numberOfTokens: ${numberOfTokens}`);
  
        // Send tokens
        contract.transfer(to_address, numberOfTokens).then((transferResult) => {
          console.dir(transferResult);
          console.log("sent token");
        })
      } // ether send
      else {
        const tx = {
          from: send_account,
          to: to_address,
          value: ethers.utils.parseEther(send_token_amount),
          //nonce: window.ethersProvider.getTransactionCount(
          nonce: provider.getTransactionCount(
            send_account,
            "latest"
          ),
          gasLimit: ethers.utils.hexlify(gas_limit), // 100000
          gasPrice: gas_price,
        }

        console.dir(tx);
        try {
          walletSigner.sendTransaction(tx).then((transaction) => {
            console.dir(transaction)
            console.log("Send finished!");
          })
        } catch (error) {
            console.log("failed to send!!");
        }
      }
    });
  }



これで実行すると、

TypeError: Cannot read properties of undefined (reading 'InfuraProvider')

困った。
詰んだと思ったら、このブログにヒントがありました。
https://qiita.com/Voldemort/items/b53d9bfe50db5920c425

バージョン5.xにダウングレードするとうまくいきました。

$ npm uninstall ethers
$ npm i -S ethers@5.7.2

結果

送金できました。
https://goerli.etherscan.io/tx/0x8238bc31332f2694767afd6adbceb1eaf39f24b8980428a267bd5965d7be6fd9

Image from Gyazo

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1