仮想通貨初学者のブログ

気が向いたら書きます。主にDefiに興味があります。

MetaMaskを使わずに署名する方法

javascriptでMetaMaskを使ってトランザクションに署名する事は良くあると思いますが、開発の際はMetaMask以外から署名したいという時もあるのではないでしょうか。

たとえば、バックエンドで定期的にコントラクトを叩きたい時とか、いちいちMetaMaskの認証をするのは面倒なので勝手にやってほしい。そんな時に使えるやり方を紹介します。 単純にイーサを送信するケースとコントラクトを叩くケースの二つを紹介します。

ライブラリのバージョンは以下です。

ethereumjs-tx: ^2.1.2
ethers: ^5.6.2

秘密鍵やAPIKEYはdotenvに置いてあります。

イーサをsendTransactionする

単純にイーサを特定のアドレスに送りたい時に使うコードです。ethereumjs-txを使う事でできます。 ここではetherscanのAPIKEYをProviderに設定していますが、何も設定しなくても問題ないです。

const Tx = require("ethereumjs-tx").Transaction;
const ethers = require("ethers");
require("dotenv").config();

let to = '送り先アドレス';
let from = '送り元アドレス';

// etherscanのapikeyは必須ではないです。
let provider = ethers.getDefaultProvider('rinkeby',{'etherscan': process.env.apiKey});
const sendEths = async (
  to,
  from,
  fromPrivateKey,
  value,
  gasPrice,
  gasLimit = ethers.utils.hexlify(21000),
) => {

  const txCount = await provider.getTransactionCount(from);

  const txData = {
    nonce: ethers.utils.hexlify(txCount),
    to,
    value: ethers.utils.parseEther(value).toHexString(),
    gasLimit,
    gasPrice,
  }
  const tx = new Tx(txData, { chain: 'rinkeby', hardfork: 'petersburg' });
  // 署名
  tx.sign(Buffer.from(fromPrivateKey, "hex"));
  console.log('signed.')

  // トランザクションを送る
  const { hash } = await provider.sendTransaction(
    "0x" + tx.serialize().toString("hex")
  );  
  console.log('send transaction.');

  // マイニングされるまで待機
  await provider.waitForTransaction(hash);
  console.log('did it.')
};


sendEths(to, 
         from,
         process.env.PRIVATE_KEY,
         '0.01',
         ethers.utils.hexlify(2000000000),
         ethers.utils.hexlify(21000)
        );

コントラクトを叩く

コントラクトを叩くには以下のような感じ。 ethers.Walletを使って署名します。

import { ethers } from 'ethers';
// スマートコントラクトのJSONファイルをインポート
import contract from './contract/Contract.json';

const abi = contract.abi;

const serverProvider = ethers.getDefaultProvider('rinkeby',{'etherscan': process.env.API_KEY});
const txCount =  await serverProvider.getTransactionCount(from);
// イーサリアムアドレスの秘密鍵を設定
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, serverProvider);
  
// コントラクトを設定
const anyContract = new ethers.Contract(contractAddress, abi, wallet);

const overrides = {
          nonce: ethers.utils.hexlify(txCount),
          gasLimit: ethers.utils.hexlify(gasLimit),
          gasPrice: ethers.utils.hexlify(gasPrice),
}

// コントラクトの好きな関数を実行
const tx = await anyContract.function(args, overrides);
tx.wait();

参考記事

docs.ethers.io

github.com