Amazon Web Services ブログ

Amazon Managed Blockchain でフルスタックサーバーレス NFT アプリケーションを開発する – Part 1

このブログは、Rafia Tapia と Forrest Colyer と Charles Okochu によって書かれた Develop a Full Stack Serverless NFT Application with Amazon Managed Blockchain – Part 1 を翻訳したものです。

ブロックチェーン技術の出現、またデジタルアセットの作成やピアツーピアでのやり取りを可能にした分散型台帳により、所有権に関する従来からの認識が変わりました。多くの場合、これらのデジタルアセットはトークンと呼ばれ、通貨のような流通貨幣、物理またはデジタルのアイテムの表現、あるいは運転免許証のような ID 属性として使用することができます。

イーサリアムは、時価総額第 2 位のブロックチェーンであり、初めてスマートコントラクトを実装したブロックチェーンです。ネイティブなスクリプト言語である Solidity とイーサリアム仮想マシンを使って分散型アプリケーションを構築するための柔軟なプラットフォームを提供するブロックチェーンネットワークです。この分散型アプリケーションは、スマートコントラクトと呼ばれるプログラム可能なロジックで構成されており、トークンの新規発行、さまざまな条件に基づくアカウント間のトークン移動、トークンの交換など、トークンのトランザクションを実現することが可能です。スマートコントラクトはプログラム可能であるため、開発者はさまざまな形態のデジタルアセットやトークンを作成することができます。例えば人気なものとしては、米ドルの価値と連動する代替可能な暗号通貨であるUSDCが挙げられます。最近では、デジタルアート、コレクション、評価証明書や権威証明書などのデジタルアセットが、別の形態のトークンである非代替性トークン (NFT) の採用により盛んになってきました。

このブログは、2 部構成シリーズの第 1 部です。フルスタック NFT アプリケーションのために、Amazon Managed Blockchain を使用した開発環境を設定する方法を説明し、 NFT アプリケーションの開発とテストに役立つさまざまなライブラリやコンセプトを紹介します。第 2 部では、このブログで説明したコンセプトのいくつかを実行するフルスタック NFT アプリケーションのサンプルについて説明します。

ソリューション概要

他のトークンと同様、NFT はスマートコントラクトを使用して発行・管理されます。イーサリアムエコシステムの共通規格の1つに ERC-721 トークン規格があります。ERC-721 トークン規格は、一意の識別子 (トークン) をユーザーのパブリックアドレスにマッピングします。そしてそのトークンと、NFT の元となるメディアまたはメタデータが保存されているストレージのロケーションをマッピングします。例えば、多くの NFT は、分散型ファイルストレージネットワークである Interplanetary File System (IPFS) に格納された画像などのメディアアセットを指し示します。Amazon Simple Storage Service (Amazon S3) も、NFT のメタデータを保存するための選択肢になり得ます。NFT の詳細な説明については、Non-Fungible Tokens (NFTs) Explained をご覧ください。

まず、フルスタック NFT アプリケーションのリファレンスアーキテクチャを紹介します。以下のアーキテクチャは、本番環境向けにテストされた NFT アプリケーションを AWS インフラストラクチャ上にデプロイする方法を示しています。

NFT フルスタックアプリケーションは、3 つの層で構成されています。最初の層は、プレゼンテーション層で、Amazon S3 にデプロイし、Amazon CloudFront 経由でアクセスすることが可能です。中間層は、ビジネスロジックの実装と、フロントエンドのクライアントアプリケーションをブロックチェーンネットワークに接続する役割を担っています。リファレンスアーキテクチャでは、中間層は Amazon API GatewayAmazon CognitoAWS Lambda を使用して、高い安全性と拡張性を備えたソリューションを提供します。このソリューションを他のデータベースと接続することで、ブロックチェーンネットワークの外部にデータを保存することができます。この層の Lambda 関数は、Amazon Managed Blockchain と連携し、トランザクションの送信と監視のためにイーサリアムネットワークへのシームレスなアクセスを行います。最後に第 3 層は、NFT の仕様を実装するスマートコントラクトです。

事前準備

開発環境において、以下の前提条件が揃っていることを確認してください。

  • AWS アカウント
  • AWS の認証情報の設定
  • js (このブログのコードは node バージョン 14.16.0 でテストされています)
  • Git クライアント (AWS のサンプルリポジトリからサンプルコードをダウンロードする必要があります。)

Visual Studio Code などの IDE は必須ではありませんが、開発作業が楽になるため、強く推奨します。開発環境は、ローカルマシンでも、Amazon Elastic Compute Cloud (Amazon EC2) インスタンスなどのリモートマシンでもセットアップ可能です。このブログでは、EC2 インスタンスを開発マシンとして使用し、Visual Studio Code の Remote Development extension 経由で接続します。

開発環境の構築

開発環境の構築は、以下の手順で行ってください。

  1. ganache-clitruffle を global npm packages としてインストールします。
npm install -g ganache-cli truffle

ganache-cli を実行すると、ポート 8545 でリッスンするローカルのイーサリアムネットワークが作成されます。ganache-cli のデフォルトのパラメータでは、HD ウォレットに 10 個のアカウントを作成し、開発やテスト目的で使用できる各アカウントに 100 Ethers を付与します。CLI コマンドを実行中に異なるオプションのパラメータを指定して、これらのデフォルトの設定を変更することができます。オプションのパラメータについては、ganache-cli の GitHub リポジトリを確認してください。

  1. Metamask ブラウザアドオンをインストールします。

ポート 8545 でリッスンしている開発用イーサリアムネットワークに Metamask を接続することができます。開発用ネットワークに接続した後、ganache-cli で作成したテストアカウントをインポートします。テストアカウントが Metamask にインポートされると、これらのアカウントで利用可能な Ether を見ることができるだけでなく、アカウントから他のアカウントやスマートコントラクトに Ether を送信することができます。VS code Remote Development extension を使用してリモート開発環境を使用している場合、ポート 8545 がラップトップに転送されていることを確認してください。そうでなければ Metamask は Ganache ネットワークに接続できません。ポートの転送方法の詳細は、Remote development over SSH を参照してください。

  1. ターミナルウィンドウを開いて以下のコードを入力し、Ganache ネットワークを立ち上げます。
ganache-cli

ganache-cli は、テストアカウントの公開鍵と秘密鍵のリストを表示します。

  1. これらのアカウントの秘密鍵は、Metamask にインポートできるようにメモしておいてください。

イーサリアム開発ネットワークが稼働したら、フルスタックアプリケーションの 3 層を実装するために 3 つの node プロジェクトを作成します。

まず、ShareToWinContract というスマートコントラクト用の node プロジェクトを作成します。このプロジェクトには、スマートコントラクトのファイルだけでなく、スマートコントラクトを実装するために使用するサードパーティ API も含まれています。

  1. 以下のコマンドを実行し、すべてデフォルトを選択して node プロジェクトを作成します。node プロジェクトを作成した後、truffle を使用してスマートコントラクトプロジェクト用のファイルの雛形を自動生成します。
mkdir ShareToWinContract
cd ShareToWinContract
npm init
truffle init

truffle init コマンドを実行すると、以下のスクリーンショットのようなプロジェクト構成になります。

Truffle は、truffle-config.js ファイルを使用して、ブロックチェーンネットワークと、スマートコントラクトをコンパイルするために使用する solidity のバージョンを設定します。

  1. ganache を開発用 Ethereum ネットワークとして使用しているため、truffle-config.js ファイル内の ganache サーバーの network 設定項目にて、以下の設定が必要です。
development: {
    	host: "127.0.0.1",     // Localhost (default: none)
      	port: 8545,            // Standard Ethereum port (default: none)
      	network_id: "*",       // Any network (default: none)
    	}
  1. OpenZeppelin API をインストールします。
npm install @openzeppelin/contracts

NFT を作成するために、私たちのスマートコントラクトは ERC-721 の仕様を実装する必要があります。OpenZeppelin はスマートコントラクトのオープンソースライブラリで、ERC-721 の仕様のコアが実装されています。そのため、OpenZeppelin SDK のコントラクトを継承することで、NFT の開発を加速させることができます。ERC-721 の仕様の OpenZeppelin 実装の詳細については、ERC721 をご覧ください。npm 経由でコントラクトプロジェクトに OpenZeppelin のライブラリをインストールします。
スマートコントラクトのファイルはすべて contract フォルダに格納します。

  1. NFT 用のスマートコントラクトファイルを contract フォルダに作成します。OpenZeppelin のコントラクトを継承し、アプリケーション固有のロジックをスマートコントラクトに実装します。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

contract NFTTokenSmartContract is ERC721Enumerable,Ownable

Truffle は、migration フォルダを見て、どのスマートコントラクトをイーサリアムネットワークに移行する必要があるのかを判断します。

  1. migration フォルダーに truffle migration 用の JavaScript ファイルを作成します。以下のコードは、マイグレーションファイルの一例です。
const Migrations = artifacts.require("NFTTokenSmartContract");

module.exports = function (deployer) {
  deployer.deploy(Migrations);
};

truffle migration ファイルの詳細については、truffle migration の実行をご覧ください。

次に、コントラクトをコンパイルしてネットワークに移行します。ganache-cli が実行されており、Ganache ネットワークが稼働していることを確認してください。

  1. 別のターミナルウィンドウで、以下のコマンドを実行します。
truffle compile
truffle migrate 

別の方法として、ネットワークを指定して truffle コンソールを起動し、コンソール内から compilemigrateのコマンドを実行することも可能です。コンソールを実行する利点は、web3 JavaScript ライブラリを介してイーサリアムネットワークと対話できることです。コンソールに接続するには、以下のコードを入力します (truffle-config.js ファイルに設定した development ganache ネットワークを呼び出します) 。

truffle console –network development

truffle があなたのスマートコントラクトをネットワークに移行する際に、デプロイされたコントラクトアドレスを表示します。

  1. このアドレスは、REST API プロジェクトを構築するときに使用するため、メモしておいてください。もし truffle コンソールが実行されている場合、スマートコントラクト内の関数を呼び出すことができます。
  2. このとき、デプロイされたコントラクトをコンソールからテストすることができます。まず、デプロイされたコントラクトのインスタンスを取得し、そのインスタンスを通じて関数を呼び出します。
let instance = await [Name of your Token].deployed() 
instance.[functionDefineInContract]
  1. 前述したリファレンスアーキテクチャの中間層を実装するために REST API プロジェクトを作成します。

このプロジェクトが JavaScript で書かれている場合、イーサリアムネットワークでスマートコントラクトのメソッドを呼び出すために広く使用されている JavaScript ライブラリである web3js を使用することができます。この REST API プロジェクトは、スマートコントラクトの関数を呼び出すために、以下の要件を満たしている必要があります。

  • イーサリアムネットワークにデプロイされたコントラクトアドレスを有していること
  • デプロイされているスマートコントラクトのアプリケーションバイナリインターフェース (ABI)

truffle がスマートコントラクトをコンパイルするとき、スマートコントラクトの名前を持つ JSON ファイルが build フォルダーに保存されます。このファイルには、REST API プロジェクトにコピーする必要がある ABI が含まれており、スマートコントラクトの関数を呼び出すために必要です。スマートコントラクトと通信するために、プロジェクトが取得するコントラクトアドレスを環境変数として格納することができます。以下は、スマートコントラクトの呼び出し方法のサンプルコードです。

this.NFTSmartContract = new this.web3obj.eth.Contract(jsonInterface.abi, process.env.CONTRACTADDRESS, { from: accounts[0], gasPrice: '20000000000', gas: 5000000 });

この jsonInterface は、コントラクト ABI を含む json にアクセスするための javascript オブジェクトです。

  1. 前述のステップで開発した REST API を介してスマートコントラクトと対話するユーザーインターフェースを実装したクライアントアプリケーションを作成します。

まとめ

これで本シリーズの第 1 部は終了です。このブログでは、NFT 開発のための開発環境と各種プロジェクトファイルを作成する手順を紹介しました。次のパートでは、NFT を物理アセットに関連付け、マーケットプレイスアプリケーションを通じて NFT を売買する方法を示すサンプル NFT マーケットプレイスアプリケーションについて説明します。

このブログは、ソリューションアーキテクトの 木村 直登 が翻訳しました。原文はこちらをご覧ください。