ConohaWINGでNode.jsを使いGnosisChainからPOAP(NFT)を取得しWordPressで表示する
はじめに
Web3の技術では、DeFiやNFTなど何かとユーザーにコストがかかるサービスが多い一方、POAPという無料のNFTがあることはご存知でしょうか?
POAPは、オンラインやオフライン(実際の会場)でのイベント参加やオープンソースソフトウェアへの貢献をした時に、受け取ったり、配布することができます。
また、通常NFTの発行・受取にはガス代が掛かりますが(無料のものもあります)、POAPの発行・受取は基本的に無料なため非常にリーズナブルです。
※商用利用は有償となっています。詳しくはこちらをご覧ください。
このPOAPは、Gnosis Chain (ノーシス・チェーン)というイーサリアムのサイドチェーンから発行されます。
Gnosis Chain (ノーシス・チェーン)は、1ドルと等価のxDaiが使えたり、1GNOトークンからステーキングで報酬を得ることができるサイドチェーンです。
Gnosis Chain (ノーシス・チェーン)のステーキング報酬は、なんと!年利10%程度となります。お金に余裕があればノード運用によるステーキング報酬ゲットに挑戦してみるのはいかがでしょうか?
※GNOトークンの相場が変動すると思うような報酬が得られないことにご注意ください。
前置きが長くなりましたが、今回はPOAPを直接Gnosis Chainからトラストレスに取得して、WordPressで表示するプログラムを考えました。
POAPは、POAP社が提供するAPIから簡単に取得することができますが、それではブロックチェーンから直接取得するというトラストレスが達成できなく、またNFTに関する知識を深めることができません。
上記理由から、今回はブロックチェーンから直接取得しています。
手順
手順1~2までは、「ConohaWINGでNode.jsを使いイーサリアムの最新ブロック情報を取得しWordPressで表示する」と同様です。
1. ConohaWINGへSSHログイン設定とNode.jsのインストールを行う
ConohaWINGサーバには、残念ながら管理者権限がありません。
そのため、ユーザ権限で使用できるように特殊なインストール作業が必要になります。
SSH設定と管理者権限の無いConohaWINGのユーザーでNode.jsをインストールする手順がイブさんのブログにて公開されています。
こちらを参考にして①SSH設定と③Node.jsのインストールをしてください。
※イブさん、有益な情報ありがとうございました!
2. Web3.jsをインストールする
ConohaWINGで以下コマンドを実行し、Web3.jsをインストールしてください。
$ npm install web3
3. ブロックチェーン・アズ・ア・サービスでイーサリアムメインネットのAPIを作成する
ブロックチェーン・アズ・ア・サービスでGnosis ChainメインネットのAPIを作成してください。
今回は、Gnosis Chainを提供しているサービスであるQuickNodeを利用しました (無料枠)
エンドポイントの作成は、GUIに沿って簡単にできるため割愛します。
「Create Endpoint」で「Gnosis Chain」を作成してください。
※ブロックチェーン・アズ・ア・サービスの利用は、トラストレスではないという意見もあります。
4. XPoapコントラクトのABI (Application Binary Interface) を取得
ブロックチェーンにあるPOAPコントラクトのメソッドにアクセスするにはABIが必要になります。
GitHubで公開されているため、以下から入手しました。
$ curl -O https://raw.githubusercontent.com/poap-xyz/poap-subgraph/master/abis/XPoap.json
5. 自分が所有するPOAPを取得してJSONを出力するJavascriptコードの実装
自分が所有するPOAPを取得するには、以下手順を踏んでいます。
- balanceOfメソッドを使い、自分のアドレスが何個POAPを持っているか調べる。
例:15個POAPを持っていれば15が返ってきます。 - tokenOfOwnerByIndexメソッドを使って、自分のアドレスが持つPOAPのトークンIDを取得します。
例:自分のアドレスと一緒に上記で取得したインデックス(0~14)を渡します。
自分のアドレスが所有している一意のトークンIDが返ってきます(例:4901563)など。
この例だと、インデックスの数の計15回呼び出しが必要になります。 - tokenURIメソッドに上記の「2」で取得したトークンIDを渡し、トークンのURIを取得します。
メタデータがある場所を返してきます。
例:https://api.poap.tech/metadata/127568/6645577
この例だと、保有している15個のトークンIDでtokenURIを取得するため計15回呼び出します。 - 「3」で取得したURIからpromiseによる非同期処理を使って一気にメタデータを取得します。メタデータの取得は、単なるHTTPリクエストなのでQuickNodeの無料枠に設けられているアクセス制限が無いためです。
例:取得したメタデータ
{
"description": "A POAP for anyone who contributed to ethereum.org during 2022.",
"external_url": "https://api.poap.tech/metadata/30173/4901563",
"home_url": "https://app.poap.xyz/token/4901563",
"image_url": "https://assets.poap.xyz/ethereumorg-2022-contributor-2022-logo-1645706565140.png",
"name": "ethereum.org 2022 contributor",
"year": 2022,
"tags": [
"poap",
"event"
],
"attributes": [
{
"trait_type": "startDate",
"value": "01-Jan-2022"
},
{
"trait_type": "endDate",
"value": "31-Dec-2022"
},
{
"trait_type": "virtualEvent",
"value": "true"
},
{
"trait_type": "city",
"value": ""
},
{
"trait_type": "country",
"value": ""
},
{
"trait_type": "eventURL",
"value": "https://ethereum.org/en/"
}
]
}
上記手順を実装したものが以下となります。
※個人利用のプログラムなので、本格的な実装はしていません。
const Web3 = require('web3');
const fs = require('fs');
const contractAddress = '0x22C1f6050E56d2876009903609a2cC3fEf83B415'; // POAPのコントラクトアドレス
const contractAbi = require('[ABIがあるディクトリ]/XPoap.json'); // 「4.」で取得したXPoapのABIを指定
const userAddress = '[自分のウォレットアドレス]'; // 自分のウォレットアドレスを指定
const web3 = new Web3('[エンドポイントURL]'); // 「3.」で取得したエンドポイントのURL
const themePath = '[JSONを出力するWordPressデータのディレクトリ]';
async function getPoapUri() {
let totalToken = 0;
let tokenArray = [];
let tokenUriArray = [];
const poapContract = new web3.eth.Contract(contractAbi, contractAddress);
// Check how many number of POAP I have
try {
totalToken = await poapContract.methods.balanceOf(userAddress).call();
console.log('POAP Token number:', totalToken);
} catch (error) {
console.error('Error:', error);
}
// Get Token Ids I have
for ( let i = 0; i < totalToken; i++ ) {
try {
tokenId = await poapContract.methods.tokenOfOwnerByIndex(userAddress, i).call();
tokenArray.push(tokenId);
console.log('Index:', i,'TokenId:', tokenId);
} catch (error) {
console.error('Error:', error);
}
}
// Get tokenURI
for (const i in tokenArray) {
try {
tokenURI = await poapContract.methods.tokenURI(tokenArray[i]).call();
console.log('Index:', i, 'TokenURI:', tokenURI);
tokenUriArray.push(tokenURI);
} catch (error) {
console.error('Error:', error);
}
}
return tokenUriArray;
}
// Get Meta Data
async function getMetaData() {
metaData = [];
tokenUriArray = await getPoapUri();
Promise.all(
tokenUriArray.map(target => fetch(target).then(result => result.text())))
.then(results => results.forEach(text => metaData.push(JSON.parse(text))))
.then(results => console.log(metaData))
.then(results => fs.writeFile( themePath + 'poapMeta.json', JSON.stringify(metaData), (err, data) => {
if(err) console.log(err);
else console.log('write end');
}));
}
getMetaData();
上記を実行すると、自分が所有するPOAPのメタデータの一覧を取得できます。
6. cronで定期実行
ConohaWINGでは、cronのようなものが使えます。
cronを開き、QuickNodeの上限を超えないように、上記のJavaScriptを毎時で実行します。
$ crontab -e
45 * * * * PATH="$PATH:/home/$USER/[Node.jsインストール先]/share/nodejs/node-v14.13.1-linux-x64/bin" node ~/getPOAPs.js
6. WordPress側のPHPプログラム
WordPressは、BootstrapというCSSデザインフレームワークを使っているので、サーバサイド側のプログラムを書くだけで、ある程度整形して表示してくれます。
今回は、以下をプログラムしました。
<?php
$json = file_get_contents(dirname(__FILE__) . "/poapMeta.json");
$jsonData = json_decode($json);
?>
<div class="col-md-12 col-lg-12">
<div class="card">
<div class="card-header has-icon">
<div class="mt-2">
<h4 class="mb-3 card-title font-weight-bold"><a href="https://poap.xyz/">POAP
<img src="<?php echo get_template_directory_uri(); ?>/assets/imgs/poap-logo.png"
alt="ethorg-img" width="56" height="65"></a></h4>
<span class="line"></span>
</div>
</div>
<div class="card-body">
<div class="container">
<div class="row">
<?php foreach ($jsonData as $key => $val) { ?>
<div class="col-4 col-sm-3 col-md-2 col-lg-2">
<div class="mt-4">
<div data-toggle="popover"
title="<?php echo "Title: " . $val->name . "\nDescription: " . $val->description; ?>">
<a href="<?php echo $val->home_url; ?>">
<img src="<?php echo $val->image_url; ?>" class="img-fluid" alt="Responsive image">
</a>
</div>
</div>
</div>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
以下が表示例です。実際にトップページに実装してますので、ご覧ください。
まとめ
上記にて、ConohaWINGのWordPressでPOAPを表示することができました。
実際にブロックチェーンにアクセスするプログラムを書いてPOAPを表示している人は、意外に少ないと思います。
手を動かして知識を養うついでに、POAPを表示することで実績もアピールすることができます。
他者との差別化に参考にしていただければ幸いです。
最後に、ConohaWINGの契約をしたい場合は、当リンクから申し込みいただけますと幸いです。
また、コードで不明な点や、改善点があれば、ご指摘いただけますと大変ありがたく存じます。
ここまで読んでくださり、ありがとうございました。