//tips
//smart contract
Solidityの記述に移る前に現在のサイトの状況をgithubに保管し、vercel表示できるようにしておく。
vercel9レポジトリをgithubに作成。
git remote rm origin
git reset --hard origin/master
rm -rf .git/
git init
git config --global init.defaultBranch main
git add .
git commit -m
git remote add origin https://github.com/
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push -u origin main
これにてgihubへの保管は完了。
vercelのdeployお祈りタイム。
‘は使えないようとのエラーが出ている。
505:21 Error: `'` can be escaped with `'`, `‘`, `'`, `’`. react/no-unescaped-entities
Module not found: Can't resolve '../../../components/Notecard' in '/vercel/path0/pages/ID/[id]'
Module not found: Can't resolve '../components/layout' in '/vercel/path0/pages'
<Typography >Start chatting!</Typography>のlet’sを削除。NoteCardの大文字化。
Attempted import error: 'addDoc' is not exported from 'firebase/auth' (imported as 'addDoc').
firebase/firestoreの方に移動。
Messageページに残っていた使わなくなった関数が悪さをしていたので削除。
Vercelは同じレポジトリにつなげるのは3回までなのでvercel10を新たに作成してつなぐ。
git remote rm origin
git reset --hard origin/master
rm -rf .git/
git init
git config --global init.defaultBranch main
git add .
git commit -m
git remote add origin https://github.com/
GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push -u origin main
pile.username = data.username?data.details:nullへと変更し、下記エラーへの追加対応。
Error: Error serializing `.ninja[0].username` returned from `getStaticProps` in "/ID/[id]/Message".
これでも突破できない、
データベースには
userid:2
username:nak
でメッセージを送っているものが存在する。
Next.jsでSSRやSSRをする際に使うgetServerSidePropsやgetStaticPropsでは、戻り値をJSONでシリアライズ可能な型に制限しなくてはならない制約がある。
https://qiita.com/sl2/items/4c66ecc265ad9b927018
https://hbsnow.dev/blog/nextjs-blog-ssg/
https://www.kamo-it.org/blog/superjson/
https://stackoverflow.com/questions/66106776/error-how-to-serialize-data-from-getstaticprops-next-js
データベースのtowhomの型が文字列と数字が混在していたのでそちらを数字に統一。
これでもエラー。
難しい問題ではないので、試していけば答えは見つかりそう。2Dアニメーション制作が完了し、アップが終わったらここの最終調整をするか。
Possible Ways to Fix It
-Make sure to move any non-pages out of the pages folder
-Check for any code that assumes a prop is available, even when it might not be
-Set default values for all dynamic pages' props (avoid undefined, use null instead so it can be serialized)
-Check for any out of date modules that you might be relying on
-Make sure your component handles fallback if it is enabled in getStaticPaths. Fallback docs
-Make sure you are not trying to export (next export) pages that have server-side rendering enabled (getServerSideProps)
2Dアニメーションの方は完成まで時間がまだまだかかるので、今はNFTアップロードの方を優先する。
エラーの調整で地味に時間を取ってしまったが、solidityいじりに入っていく。
NFTの前に文字列あたりをethのテストネットrinkbyかropstonにアップすることから始める。
懐かしい。contractをデプロイした後の投票に当たる部分のトランザクションをNFTのURIの登録にあたる部分にすれば良いか。
きちんとmint部分でNFTTOKENの発行を行なっていることは確認できた。
Image画像がなくてもこれはだけでopenseaのテストネットで確認できるよう。
Image部分はURIで別途setBaseURIなどの関数を作りTOKEN内に格納させる必要があるよう。
これを見ながら一度やってみるか。
久しぶりにターミナルを開きnode -v。自身のバージョンを確認。v16.2.0。
mkdir nft-demoでnft-demoフォルダを作成。
Visual studioでこちらのフォルダを開く。今まで作成していたサイトのmuidemoフォルダとはしばしのお別れ。
Vs内のターミナルを開き、 npm init -yでpackage.jsonを作成。ついでにフレームワークのtruffleも入れておく。npm install truffle。
導入できたら初期設定。npx truffle init
これでnft-demoフォルダ内にはmigrationフォルダやtestフォルダなどが生成された。ありがたし。
ganacheも起動。新たなnetworkを追加させnft-demoのtruffle configを読み込ませる。
vsでconfigのdevelopment設定を復活させ、ganacheと同じportに変更。
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 7545, // Standard Ethereum port (default: none)
network_id: "*", // Any network (default: none)
},
ベースはERC721の内容なので、公開されている企画をインストールして内部を自分でカスタマイズすれば良い。
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol
npm install @openzeppelin/contracts
contractsの配下にnehaさんのArtCollectible.solをそのまま作ってしまう。
このコントラクトをデプロイした後に実際のNFTを埋め込んでみると下記のようなmetadata.jsonが作られるのでそれをopenseaが確認してrenderingしているよう。わかりみ。
{
"attributes": [
{
"trait_type": "Color",
"value": "Pink"
}
],
"description": "Paul predicts future!",
"image": "https://ipfs.io/ipfs/QmQYE35JdthxvBZahG77w5XSuPKL2jNkJdtxQo4Pc57U1n",
"name": "Paul The Octopus"
}
このkeyの部分の表示箇所は気になるが後で確認する。
この後にmigrationフォルダ内に2/deoloy…フォルダを作成。
これで一通りの設定ができたので、npx truffle consoleでテスト。続けてmigrateを入力。
Starting migrations...
======================
> Network name: 'development'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0xad8208672c990b5af0378161a15075098b274cb6403991305b112177b3fe1ece
> Blocks: 0 Seconds: 0
> contract address: 0xA063eA570687ae184944c073c3e624233FF06C10
> block number: 1
> block timestamp: 1653807396
> account: 0x5a006B0EDc52AB40618F535bcaA33c4e6eD9f920
> balance: 99.99502292
> gas used: 248854 (0x3cc16)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.00497708 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.00497708 ETH
2_deploy_art_collectible.js
===========================
Deploying 'ArtCollectible'
--------------------------
> transaction hash: 0x887603a5775cd9d91526a76e3fce06909801b189110e53d93d55e4865efe68fd
> Blocks: 0 Seconds: 0
> contract address: 0x29aaC65C2383B4eC87304DFF803aac1dFd5465fa
> block number: 3
> block timestamp: 1653807397
> account: 0x5a006B0EDc52AB40618F535bcaA33c4e6eD9f920
> balance: 99.9385156
> gas used: 2782853 (0x2a7685)
> gas price: 20 gwei
> value sent: 0 ETH
> total cost: 0.05565706 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.05565706 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.06063414 ETH
きちんと動作が確認できた。
Ganacheと接続しているのでこちらのテストdeployにかかったコスト分がganacheの一番上のアカウントから引かれている。
次にIPFSへの画像登録に移る。
pinataを利用。
https://www.pinata.cloud/
以前作ったアカウントが残っていたのでそちらにアップロード。
アップロードしたら.envファイルに書き込む必要がある。
Pinataを機能させるためのスクリプトも組み込む。
pinFileToIPFSの中にはenvから値を引っ張ってくるのでPINATA_API_KEY="YOUR_API_KEY"
PINATA_API_SECRET="YOUR_API_SECRET”などを作成して入れる必要がある。
https://docs.pinata.cloud/
API Keysで新たなキーを作るとこれらの情報を取得できた。
スクリプトから格納したデータをアップロードできるスクリプトだったのでassetsにアップしたいファイルを設置。
const filePath = path.join(__dirname, '../assets/ItsmE1.png');
Infuraで新たなプロジェクトを作り、TH_CLIENT_URL="https://rinkeby.infura.io/v3/YOUR_PROJECT_ID”ととして渡したい。
ちょうど昔rinkbyで作ったinfuraプロジェクトがあったのでそちらのidを利用。
node scripts/runScriptを実行したらError: Cannot find module 'dotenv’のエラーが発生。
これで.envが読み込めるようになったはず。
npm install configが足りなかった。こちらも追加インストール。
これにてnode scripts/runScriptが機能するようになった。
見ていくとopenseaで確認するためにはmetadataの作成も必要そうなので補足していく。
Configフォルダを作成し、dev.jsonを格納。これをfilePathに入れ込み、const filePath = path.join(__dirname, '../data/metadata.json’);でdataフォルダにjsonを生成している。
なので空のdataフォルダも作成しておく。
DataフォルダにIpfsHash.jsonの生成が確認できた。
data: {
IpfsHash: 'QmWG1bTLhNRKEG55nMNNTkAv6mwEyEEpHSiNn4wh2QxpQe',
PinSize: 101397,
Timestamp: '2022-05-29T08:19:07.042Z',
isDuplicate: true
}
そのdataフォルダの中にmetadata.jsonを作成。
"image": "https://ipfs.io/ipfs/QmWG1bTLhNRKEG55nMNNTkAv6mwEyEEpHSiNn4wh2QxpQe”,の部分にはpinataからアップロードした画像のidを取得して入力。
この時点でrunscriptの設定を変更。
設定の変更が早すぎるとエラーになったのでタイミングが重要。
const path = require('path');
const pinFileToIPFS = require('./pinFileToIPFS');
//const filePath = path.join(__dirname, '../assets/ItsmE1.png');
const filePath = path.join(__dirname, '../data/metadata.json');
pinFileToIPFS(filePath);
この上で再度node scripts/runScriptを実行。
ipfsHashが二つ分格納されていることが確認できる。
最終段階。テストネットに接続するための準備。
npm i @truffle/hdwallet-provider
一旦rinkbyのethもゲットしておく。
https://faucet.rinkeby.io/
待っている間に下記をtruffleconfigに追加。
require('dotenv').config()
const HDWalletProvider = require('@truffle/hdwallet-provider');
const mnemonic = process.env.MNEMONIC
const clientURL = process.env.ETH_CLIENT_URL
rinkeby: {
provider: () => new HDWalletProvider(mnemonic, clientURL),
network_id: 4, // Rinkeby's id
gas: 3000000,
confirmations: 2, // # of confs to wait between deployments. (default: 0)
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
skipDryRun: true , // Skip dry run before migrations? (default: false for public nets )
networkCheckTimeout: 10000000,
}
npx truffle console --network rinkebyを実行。その上でmigrate。これでrinkeby上にデプロイできたか。
Deploying 'Migrations'
----------------------
*** Deployment Failed ***
"Migrations" could not deploy due to insufficient funds
* Account: 0x0006C6dCcd3f9808246EAd94BA70f47AB92f75eB
* Balance: 0 wei
* Message: insufficient funds for gas * price + value
十分なファンドがないため無理だとエラーが発生。
メタマスクにはきちんとrinkbeyのethが入っているので設定のまちがいのはず。
https://qiita.com/etou25867873/items/3cad2ac2110889e5550b
ETH_CLIENT_URL="https://rinkeby.infura.io/v3/“の設定がおかしいのかもしれない。
Infuraの設定を作り直す。
それでも資金が足りないとのエラー。
問題はmetamaskの方か。metamaskの方を再設定。うまく通った。
ここからmintを行う。
const art=await ArtCollectible.deployed()
コントラクトをdeployし、関数を実行する。
await art.claimItem(‘https://ipfs.io/ipfs/QmXYfhz3uup6Hd4PnbVsHowiDGoh8yYDhR2QCvXZU7J56Z’)
のなかにipfsのリンク先を格納。
https://ipfs.io/ipfs/に先の"IpfsHash":"QmXYfhz3uup6Hd4PnbVsHowiDGoh8yYDhR2QCvXZU7J56Z”,をつないだもの。
await art.ownerOf(1)で自身のメタマスクアカウントを呼び出せた。
art.addressでチェーンへの格納先を確認。
'0x1C6b57226B96bdd3616Fe26c74DF6f0d6E983857'
Openseaのテストネットにいき、先の格納先アドレスとtokenidを記載。
https://testnets.opensea.io/assets/0x1C6b57226B96bdd3616Fe26c74DF6f0d6E983857/1
オッケーきちんとテストネットに反映させることができた。
https://testnets.opensea.io/assets/rinkeby/0x1C6b57226B96bdd3616Fe26c74DF6f0d6E983857/1
https://rinkeby.etherscan.io/tx/0x84a4c26b9c619daa9121d232cbbee513af989ff167859066f184fd2bda04082a
このコードを理解して本番環境のアップに臨む。本番ではミスると万単位ぐらいで消えるのではないかと思うので慎重にする。
まずは構造理解から。