実践!ジェネラティブNFT開発
はじめに
本記事はジェネラティブNFT開発案件の実務で得たノウハウを纏めたものです。
対象読者は
・「誰でもできる!ジェネラティブNFT開発」
・「仕事でつかえるジェネラティブNFT構築」
を修了し、これから実務に取り掛かろうとしている人です。
実践で躓きそうなポイントをメインに、ジェネラティブNFT開発のクライアントワークの全体像を解説します。
クライアントワークでは突発的な要望が発生します。
・画像差し替え
・日程変更
・当初予定の中止
...etc
要望毎に何らかの判断が必要ですが、判断の支えになるのが「技術の本質的な理解」になります。「誰でもできる!ジェネラティブNFT開発」(以降誰ジェネ)では「設定ファイルを〇〇に書き替えてください」のように変更内容を記載頂いてますが、それに対する「なぜ?」が説明できるかが1つの基準です。それが出来た上で初めて要望の工数もわかり、別料金かサービスでやるか等の判断も出来ます。誰ジェネに従えば確かに成果物は出来るのですが、それと合わせてHashLipsのソース等にも目を通し、技術理解を深めておくことをお勧めします。
仕様調整
想定の擦り合わせ
想定しているゴールは、MintサイトでクライアントのNFTを販売することです。
クライアントに画像素材提供や仕上がりのチェックをお願いし、
他の技術的な作業は全てこちらで実施する想定です。
具体的な作業内容のベースは誰ジェネ準拠です。
最初の作業はクライアントとの認識の擦り合わせです。
ここが案件の性質の全てを決める、最重要項目です。集中して進めてください。
資料提供
HashLipsを改修するのが楽なやり方で予算も抑えられるので、こちらから提案したほうが良いでしょう。先に要求を聞くと人によってはサイトデザイン等に拘る等、目的とずれる可能性が高いです。けいすけさんが作成した資料に一部加筆修正した調整用の資料を用意したので、こちらをご参照ください。以降はこの資料を共有した前提で話を進めます。
要求検討
全てこちらの希望通りであればそのまま進めて問題ないですが、大抵は何かしらの要求があります。それを現実的な範囲に落とし込む必要があります。またクライアントの知識量によっては、用語やフローの丁寧な説明が必要です。私の場合は先方に不明点があったようで、けいすけさんも交えてDiscordで通話しました。重要なのは無理なものに対して、「無理」と言うことです。そのためには技術の深い理解が必要です。
見積もり
単価
要件が決まったら工数と照らし合わせて単価を決めます。自分で決めていいですが、高すぎるのも安すぎるのも良くないと思います。けいすけさんはHashLips準拠で基本20万円で、他に要件があれば別料金の形にしているそうです。この「別料金」を事前に盛り込んでおかないと、追加の作業が大量に発生した時にこちらが一方的に損をしてしまいます。
請求
料金の請求方法ですが、私の場合前金と後金で半々に分けました。前金のみは先方に逃亡リスクを負わせるし、後金のみはこちらが逃亡リスクを負います。請求には請求書の発行が必要になりますが、私はfreeeという会計ソフトで発行しました。作業を始める前に前金を請求しましょう。
実務
ジェネラティブ画像作成
画像素材を頂いたら作業開始です。基本は誰ジェネの通りです。私の場合は一括で提出頂きましたが、例えば先に100体のテスト作成をするケースもあると思います。ファイルのやりとりにはGigaファイル便を使いました。生成時間は私のマシンで1000点辺り約7分30秒程度かかりました。
動作前チェック
画像生成後に不具合が見つかるとやり直しで時間がかかるため、出来ればプログラム実行前に取り除いておきたいです。主に下記の点を確認します。
- 生成数
- layers設定
- ファイル名
生成数
config.jsのgrowEditionSizeToが仕様の通りになっているか?私のケースでは「ジェネラティブ画像」の一部を、後で「1枚絵の画像」に差し替える作業がありました。この場合は「ジェネラティブ画像」+「1枚絵の画像」の数量を指定しておくと、jsonの扱いが後々楽になります。「全供給量を指定する」と覚えておけば良いと思います。
layers設定
フォルダ名とconfig.jsのlayersOrderの名前の一致と、レイヤー順が仕様の通りになっているか?
ファイル名
「名前#数値.png」になっているか?私の場合は1点ファイルの先頭にスペースが入っていて、誤字と思われるため先方に指摘しこちらで修正しました。
バックアップ
生成プログラムを実行するとbuildフォルダのファイル一式は削除(再作成)されます。先方に提出しないファイルは消えて問題ないですが、一度提出したファイルはその後やりとりで使うことがあるので、大切に保管しておきましょう。私はzipファイルに日付(2022xxyy)の情報を入れていましたが、後で見てわかれば何でも良いと思います。また前述の「1枚絵の差し替え」のように失敗する可能性のある作業前には、戻せる環境を整えておくことを推奨します。
確認依頼
生成が終わったらGigaファイル便等のファイル保管サービスで提出しましょう。前述のとおり提出したファイルは保管必須です。NGが出たら「動作前チェック」まで戻り、OKが出るまで同じ手順の繰り返しになります。
コントラクト作成
こちらも基本は誰ジェネの通りです。私はERC721を使ったのですが、これは失敗でした。ERC721Aを使えばガス代が減らせたからです。運営確保用のMintにガス代がかかりすぎたため、運営確保数を減らす事態になりました。けいすけさんの解説動画もあるのでこちらを参考にERC721Aの検討をお勧めします。
運営用NFTの確保
大抵のPJは運営用にNFTを確保します。先方から送付先のウォレットを確認し、ERC721Aを使うのであればコンストラクタで_mint()してしまうのが楽です。
エアドロ
先方から運営用NFTの追加の要望もあるかもしれません。この場合けいすけさんのgithubにあるairdropMint()を入れておけば、要望があった際に対応できると思います。
ホワイトリスト設定
当初ホワイトリストセール有りでしたが、私の場合は途中で無しになりました。なので実践的な内容は把握してないのですが、しごジェネにホワリス解説があるので、そちらをご参考ください。
リビール設定
URI設定
リビール有のPJではコントラクトにも考慮が必要です。HashLipsではbaseUriとnotRevealedUriのようにURLが分かれていますが、コンストラクタでbaseUriを設定した場合はリビール前にipfsのURLが公開されてしまいます。(verifyするとコンストラクタの引数も公開される)事前に画像がばれると何番付近でレアが出る等もわかってしまうため、リビールはnotRevealedUriを使わずにsetBaseUri()で書き換える方法をお勧めします。なお書き換えテストの際は既存コレクション等のipfsのurlを指定すると、画像UPの手間が省けます。
リビール前URI設定
リビール有PJのデプロイ時は、リビール前用のURIをbaseUriに設定する想定です。下記作業を進めて、2をbaseUriに設定しました。
- リビール前の固定画像1枚をIPFSにUP
- 画像の参照先のみ1に書き換えた本番用jsonファイル一式をIPFSにUP
画像の差し替え
私の場合はジェネラティブ画像の一部を「1枚絵」に差し替える作業があったため、画像に加えてExcelでファイルNoとパーツの属性値を受け取り、それをjsonに反映させました。反映は簡単なプログラムで対応しました。(今回のケースでは属性値は「None」固定)けいすけさんも他PJで「csv」⇔「json」の相互変換するプログラムを組んだようですが、ある程度数が多い場合はプログラムで自動化したほうが安全だと思います。
Pinata
アカウントのレンタル
先方からIDとパスワードを借ります。
料金
無料プランは100ファイル1GBまでですが、恐らくジェネラティブではそれ以上になるため有料プラン登録が必要です。先方にその旨伝える必要があります。
ファイルUP
画像をIPFSにUPするとbaseUri(ipfs://[CID]/)が決まります。art_engineのconfig.jsのnamePrefix, description, baseUriも仕様の通りに書き換えてutils/update_info.jsを実行してください。なおdescriptionテキストに改行が入っている場合があります。これをOpenseaで改行として認識させるには、「改行箇所」→「スペーススペース\n」のように半角スペース2個+改行文字に書き換える必要があります。jsonが出来上がったらIPFSにUPし、CIDを控えておいてください。
ウォレット
個人でもウォレットを持っていると思いますが、それと別に新規ウォレットを用意したほうが良いです。コントラクトの発行者としてウォレットアドレスが残るのと、ガス代用に先方からETHを受け取るのが私用と混ざるのも問題と思われるためです。案件用の作業ウォレットです。
レビュー
私的にはコントラクトは一度デプロイしたら動かせないため、レビュー必須と思ってます。依頼出来る環境があるなら利用しましょう。非公開案件の場合は公の場で聞くのはまずいので、その点だけ注意してください。
デプロイ
新規ウォレットでデプロイします。この時点までに先方からガス代用のETHを取得しておいてください。デプロイにかかるETHの目安は0.1~0.2ETHくらいです。ガス代の価格も変動していて朝は比較的安い傾向にあるようですが、考えすぎると時間的な制約が生まれるので頭の片隅に置く程度で良いと思います。
コレクション
表示
Openseaでのコレクション表示は、デプロイではなく初回ミント時に行われるようです。2次流通手数料や振込先ウォレットの設定にはコレクションが必要になるため、運営用等でミントをしないPJは工夫が必要になります。
設定
コレクションページの「Edit」からウォレットをCollaboratorsに設定すると編集権限を付与できるので、先方のウォレットを追加して設定してもらいましょう。「Creator earnings」(2次流通支払設定)はオーナー権限を持つ人しか出来ないので、ウォレットアドレスと料率を聞いてこちらで設定しましょう。
ミントサイト作成
コード修正
基本は誰ジェネの通りです。しごジェネの「320ガス代の自動設定」のガス代自動設定と「330_ホワイトリストに対応したミントサイト」のセール前に購入できなくする処理も入れておいたほうが良いです。私の場合はミントサイトをセール前に公開したい要望があったのですが、仮にpausedを参照してボタンをdisableする処理を入れていなければ、ユーザーに無駄なガス代を支払わせてしまったと思います。
サーバー準備
ミントサイトを配置する、サーバーとドメイン名が必要になります。
私はたまたま借りていたサーバがあったためそれを使いましたが、セール直後に全て売り切れる保証もないため基本的には先方に用意してもらったほうが良いと思います。私の場合はセール後にNetlifyという無料のホスティングサービスのアカウント取得してもらい、アカウントを借りて私のほうでファイルUPして元ファイル一式も先方に送りました。
Netlifyへデプロイ
「Sites」→「Add new site」→「Deploy manually」で「npm build」で出来たフォルダを指定する。
Netlifyのドメイン変更
「Sites」→「Site Settings」→「Change site name」で新ドメインを指定する(末尾の「netlify.app」は変更不可)。ドメインは念のため先方に確認を取りましょう。
セール
セール直前
セール時間の30秒ほど前にpause(false)を実行する想定です。15-30分ほど前に、予定通り実行する旨を先方に伝えておくと、より親切だと思います。セール直後は想定外の事態が起こることがあるため、セールから30分後くらいまではユーザーの反応やサーバの監視等が必要と思われます。
リビール(ある場合)
画像差し替えの要望
リビール前は画像差し替えの要望が来ることがあります。私も要望があり、その際は手動で画像とjsonファイルを書き換えてPinataに再UPしました。軽微な修正だったため、追加料金は取りませんでした。
最終画像共有
私の場合はジェネラティブで作成した後に1枚絵の差し替えがあったため、差し替え後も含めたリビール後画像の一式を念のため先方に送りました。
リビール直前
リビール時間の30秒ほど前にsetBaseUri()を実行する想定です。こちらも15-30分ほど前に先方にリビール予告をしておくと親切だと思います。
後処理
出金
私はフリーミントなのでこのプロセスは無かったのですが、有料ミントの場合はwithdraw()が必要になると思います。セールで売り切れなかったら、先方にwithdraw()のやり方の説明が必要になるかもしれません。
コレクションオーナーの譲渡
譲渡先アドレスを聞いて、transferOwnership()でオーナー権限を譲渡しましょう。
ETH返却
振込先アドレスを聞いて送金しましょう。
請求
後金を請求しましょう。
Discussion