Metamaskでログイン&フロントアプリからNFTを発行する
前回は、NFTを発行する独自コントラクトをInfuraのテストネット(Ropsten)にデプロイするところまでやりました。
もしまだやってない人は前回書いた記事からやってください。
この記事では、ローカルからそのスマコンにアクセスし、NFTを発行してみたいと思います。
必要なもの
- Node
- Metamask
- ropstenネットワークの残高が必要になります。無料配布してくれているサイトがいくつかあるので、そこからクレクレしておいてください。
- RopstenネットワークのETH残高
出来上がり
以下リポジトリにデプロイまで行ったコードを入れてあります。
https://github.com/tkyatg/nft-front-example
プロジェクト作成
Nuxtアプリで進めていきます。React触ったことないので、お許しを。
$ npx create-nuxt-app
Need to install the following packages:
create-nuxt-app
Ok to proceed? (y) y
create-nuxt-app v3.7.1
✨ Generating Nuxt.js project in .
? Project name: nuxt
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert se
lection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert sele
ction)
? Testing framework: None
? Rendering mode: Single Page App
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using
typescript)
? What is your GitHub username?
? Version control system: None
実装の準備
layouts/default.vue
を以下のように書き換えます。
(不要コードを削除しただけです)
<template>
<v-app>
<v-main>
<nuxt />
</v-main>
</v-app>
</template>
web3jsのインストール
npm install web3
Metamaskでログイン
pages/index.vue
を以下のように書き換えて、初期表示時にwallet
の情報を取得するようにします。
<template>
<v-container></v-container>
</template>
<script>
import Web3 from "web3";
export default {
data() {
return {
web3: null,
};
},
async created() {
const web3 = new Web3(this.endpoint);
this.web3 = web3;
try {
const newAccounts = await ethereum.request({
method: "eth_requestAccounts",
});
const accounts = newAccounts;
if (accounts[0] !== "") {
this.web3.eth.defaultAccount = accounts[0];
} else {
console.error("ログインに失敗");
}
} catch (error) {
console.error(error);
}
},
};
</script>
アプリ起動
yarn dev
アプリ起動後、localhost:3000
にアクセスすると、Metamask
のログイン画面が開きます。
既にログインしている場合&Metamask
がインストールされていない場合も何も起きません。(エラーハンドリング可)
contractアクセス用のABIをコピーしてくる
前回作成したプロジェクトの/artifacts/contracts/Nft.sol/Nft.json
にABIが作成されています。
ABIとは
イーサリアムエコシステム内でコントラクトに接続するスタンダードなインターフェースのこと
もし無い場合は以下コマンドで作成できます。
npx hardhat compile
hadhatプロジェクトの/artifacts/contracts/Nft.sol/Nft.json
のNft.json
を今回のアプリの/abi/Nft.json
にコピーします。
contractに接続
pages/index.vue
を以下のように編集して、対象のコントラクトに接続します。
data() {
return {
web3: null,
+ nftContract: null,
+ endpoint: "{infura の endpoint}",
+ contractAddress: "{infura へ contract deploy する時に表示される文字列}",
};
},
async created() {
const web3 = new Web3(this.endpoint);
+ const json = require("../abi/Nft.json");
+ const nftContract = new web3.eth.Contract(json.abi, this.contractAddress);
this.web3 = web3;
+ this.nftContract = nftContract;
try {
const newAccounts = await ethereum.request({
method: "eth_requestAccounts",
});
dataの部分のみ以下のように変更してください。
- endpoint
- infura のダッシュボードに記載されている
https://ropsten.infura.io/v3/...
- infura のダッシュボードに記載されている
- contract address
- local から infura へデプロイした際に log に表示される文字列
この変更後、検証を開いて、エラーが出ていなければ接続自体は成功しています。
NFT作成コードの追記
実際にNFTを作ってみます。
NFT作成するコードをpages/index.vue
に追記します。
<template>
<v-container>
+ <v-row>
+ <v-col cols="12">
+ <v-card>
+ <v-list-item>
+ <v-list-item-title> NFT作成 </v-list-item-title>
+ </v-list-item>
+ <v-list-item>
+ <v-text-field v-model="uri" label="URI"></v-text-field>
+ </v-list-item>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn rounded color="primary" large @click="createNft()">
+ 作成
+ </v-btn>
+ </v-card-actions>
+ </v-card>
+ </v-col>
+ </v-row>
</v-container>
</template>
<script>
import Web3 from "web3";
export default {
...
+ methods: {
+ async createNft() {
+ const tx = {
+ from: this.web3.eth.defaultAccount,
+ to: this.contractAddress,
+ data: this.nftContract.methods.mint(this.uri).encodeABI(),
+ };
+ try {
+ await window.ethereum.request({
+ method: "eth_sendTransaction",
+ params: [tx],
+ });
+ alert("NFT作成成功");
+ } catch (error) {
+ alert("NFT作成失敗");
+ }
+ },
+ },
};
</script>
NFT作成してみる
localhost:3000
からぽちぽちする。
-
画面表示
-
「作成」ボタン押下
-
Metamask
でのSign
を求められる。「確認」ボタンを押下(ropsten残高が必要)
-
作成完了(したっぽい
作成したNFTを確認してみる
メッセージ的には作成完了したっぽいが
ひねくれ者たちは、作成できたのか信用できないと思うので、実際にスマコンに問い合わせてみる。
作成したコントラクトでは取得methodは書いてないが、継承元に処理が書いてあるため取得できます。
詳しく知りたい人はopenzeppelin
のコードを読んでください。
async created() {
.....
+ await this.getMyNfts();
},
methods: {
+ async getMyNfts() {
+ const myNftCount = await this.nftContract.methods
+ .balanceOf(this.web3.eth.defaultAccount)
+ .call();
+ for (let i = 0; i < myNftCount; i++) {
+ let myNftTokenId = await this.nftContract.methods
+ .tokenOfOwnerByIndex(this.web3.eth.defaultAccount, i)
+ .call();
+ let myNftTokenUri = await this.nftContract.methods
+ .tokenURI(myNftTokenId)
+ .call();
+ console.log("あなたのNFT");
+ console.log("tokenId: " + myNftTokenId);
+ console.log("tokenUri: " + myNftTokenUri);
+ }
+ },
async createNft() {
初期表示時に、tokenを取得しに行くと
検証>コンソール
で、以下のように表示されるはずです。
これでテストネットにデプロイした独自コントラクトをlocalのアプリから実行し、NFTを作成するところまで完了しました!
最後に
NFT生成してみるだけなら割と簡単にできる。
フロントアプリからスマコン実行するなら、ローカルで開発するよりもテストネットにあげて開発した方が何かと便利だなーと思いました。
twitterのフォローお願いします!
https://twitter.com/takuya_develop
あと定期的に渋谷でブロックチェーンもくもく会やるので、ぜひ参加してください〜。
ブロックチェーンについて語り合いましょう!
https://block-chain.connpass.com/event/236396/
Discussion