アプリケーション開発ポータルサイト
ServerNote.NET
Amazon.co.jpでPC関連商品タイムセール開催中!
カテゴリー【JavaScript仮想通貨
web3.jsとwindow.ethereumでコントラクト関数を引数つきでコールしプロパティを取得する
POSTED BY
2023-07-08

コントラクトの関数で読み込み専用の関数=Solidityにおいてview returnsの関数=は、トランザクション不要で呼んでデータプロパティを取得できる。

web3.jsでパラメータのABIエンコード処理を行い、window.ethereumで関数コールの実行を行う。

自分の作成したERC-721仕様のコントラクトで、呼びたい関数ownerOf,balanceOfを以下abi.jsonで定義しているとする。

JSONabi.jsonGitHub Source
[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "tokenId",
        "type": "uint256"
      }
    ],
    "name": "ownerOf",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
]

まずこれをajaxで取得し展開する。

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>//<![CDATA[
var abi_json = null;
$.ajax({
    type: 'GET',
    url: 'abi.json',
    data: '',
    async : true,
  dataType: 'text',
    success: function(data) {
        if(data != null) {
            abi_json = JSON.parse(data);
        }
    }
});
//]]></script>

abi_json[0]は関数balanceOfの定義、abi_json[1]は関数ownerOfの定義が入るはずである。

このコントラクトがNFTであるとして、発行済みのトークンID「2」番の持ち主は誰か?を知りたい=ownerOfをコールする。

関数名と引数はencodeFunctionCallを使ってまとめてABIエンコードできる。

https://web3js.readthedocs.io/en/v1.2.11/web3-eth-abi.html

コントラクトのアドレスが0xFccccccFd3a58c65352cdE9286D8BE2b05aaaaaaであるとすると、

<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
<script>//<![CDATA[

var web3js = null;

if (typeof window.ethereum !== 'undefined' && typeof web3 !== 'undefined') {
  web3js = new Web3();

  var fc_call_param = web3js.eth.abi.encodeFunctionCall(abi_json[1], [2]);

  var send_params = {
    to: '0xFccccccFd3a58c65352cdE9286D8BE2b05aaaaaa',
    data: fc_call_param,
  };

  var owner = await window.ethereum.request({
    method: 'eth_call',
    params: [send_params, "latest"],
  });

  console.log(owner);
}
//]]></script>

encodeFunctionCallの第一引数にはコントラクトの呼びたい関数が定義されたABI JSONを指定する。ownerOfはabi_json[1]であるので、それを指定する。

第二引数には関数ownerOfに渡す引数を配列で指定する。ここでは引数はトークンID整数1つであるので、取得希望のID「2」を指定しているだけ。
もしも複数の引数を取る関数=たとえば第二引数にアドレスを取る関数=の場合、[2, "0xaaaaacccccxxxxx..."] などと指定する。

関数コールデータfc_call_paramが用意できたので、window.ethereumに渡すパラメタにセットする。最終的にはプロパティ読み出し関数「eth_call」をリクエストする。

実行結果例

0x0000000000000000000000005192891f9f446cd42a770aac22771ef242dad2f0

トークン2番の持ち主がowner変数に文字列として返った。では、これをそのまま関数balanceOfに渡せばこの人が持っているこのNFTの数がそのまま取得できるはずである。

しかしここで注意しなくてはいけないのが、先頭から続く0000000...をつけたまま渡すとInvalid addressエラーになる。

よって、replaceなどでこのゼロを取っ払ってから渡さなくてはいけない。以下のように。

0x5192891f9f446cd42a770aac22771ef242dad2f0

ではこのアドレスの人がこのコントラクトNFTトークンを所有している数を求める=balanceOfをコールする。

<script src="https://cdn.jsdelivr.net/gh/ethereum/web3.js/dist/web3.min.js"></script>
<script>//<![CDATA[

var web3js = null;

if (typeof window.ethereum !== 'undefined' && typeof web3 !== 'undefined') {
  web3js = new Web3();

  var fc_call_param = web3js.eth.abi.encodeFunctionCall(abi_json[0], ['0x5192891f9f446cd42a770aac22771ef242dad2f0']);

  var send_params = {
    to: '0xFccccccFd3a58c65352cdE9286D8BE2b05aaaaaa',
    data: fc_call_param,
  };

  var token_counts = await window.ethereum.request({
    method: 'eth_call',
    params: [send_params, "latest"],
  });

  console.log(token_counts);
}
//]]></script>

balanceOfはさきのabi_jsonの配列[0]にて定義されているので、abi_json[0]を指定する。balanceOfの引数は取得希望所有者アドレス文字列であるので、それを指定する。

実行結果

0x0000000000000000000000000000000000000000000000000000000000000002

どうやらこの人は、このコントラクトNFTの発行するトークンを2個所有しているようだ、というのがわかる。

※本記事は当サイト管理人の個人的な備忘録です。本記事の参照又は付随ソースコード利用後にいかなる損害が発生しても当サイト及び管理人は一切責任を負いません。
※本記事内容の無断転載を禁じます。
【WEBMASTER/管理人】
自営業プログラマーです。お仕事ください!
ご連絡は以下アドレスまでお願いします★

☆ServerNote.NETショッピング↓
ShoppingNote / Amazon.co.jp
☆お仲間ブログ↓
一人社長の不動産業務日誌
【キーワード検索】