2024-07-08

			コントラクトの関数で読み込み専用の関数=Solidityにおいてview returnsの関数=は、トランザクション不要で呼んでデータプロパティを取得できる。
web3.jsでパラメータのABIエンコード処理を行い、window.ethereumで関数コールの実行を行う。
自分の作成したERC-721仕様のコントラクトで、呼びたい関数ownerOf,balanceOfを以下abi.jsonで定義しているとする。
| JSON | abi.json | GitHub 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個所有しているようだ、というのがわかる。
※本記事内容の無断転載を禁じます。
ご連絡は以下アドレスまでお願いします★
Wav2Lipのオープンソース版を改造して外部から呼べるAPI化する
Wav2Lipのオープンソース版で静止画の口元のみを動かして喋らせる
【iOS】アプリアイコン・ロゴ画像の作成・設定方法
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【2】
オープンソースリップシンクエンジンSadTalkerをAPI化してアプリから呼ぶ【1】
【Xcode】iPhone is not available because it is unpairedの対処法
【Let's Encrypt】Failed authorization procedure 503の対処法
【Debian】古いバージョンでapt updateしたら404 not foundでエラーになる場合
ファイアウォール内部のWindows11 PCにmacOS Sequoiaからリモートデスクトップする
【Windows10】リモートデスクトップ間のコピー&ペーストができなくなった場合の対処法
Windows11+WSL2でUbuntuを使う【2】ブリッジ接続+固定IPの設定
Windows11のコマンドプロンプトでテキストをコピーする
【Apache】サーバーに同時接続可能なクライアント数を調整する
Androidホームで左にスワイプすると出てくるニュース共を一切表示させない方法
【Linux】mkfsコマンドでProceed anyway?と確認を求められるのを回避する
タスクスケジューラで変更を適用できません。ユーザーアカウントが不明であるか、パスワードが正しくないか、またはユーザーアカウントにタスクを変更する許可がありません。と出た
【Debian】古いバージョンでapt updateしたら404 not foundでエラーになる場合
apt upgradeしたあとnvidia-smiがダメになった場合