ワークショップ用にブロックチェーンアプリケーションを作ってみた
03/26にSolana Developer Hub Workshop #4というオフラインイベントの開催をしました。
このイベントではNFTをmintするアプリケーションをみんなでわちゃわちゃ作ってみようという会になります。当日はオンライン配信で音声が入っていないことが発覚したり、READMEの間違いが発覚する、急遽撤収作業をお手伝い頂くなどなかなかカオスな会でした。ご参加いただいた方々は本当にありがとうございました。
実はこのワークショップで利用した題材は、せっかく作るならそれもネタにしよう!とXで配信を行っています。
というので、本記事ではそちらの配信を紹介しつつ、どのように作られたのかの解説をしていきます。
配信を通じて伝えたい大事なこと
10年以上エンジニアをやっててもエラーで詰まるよ
問題が起きる→仮説を立てる→検証する のサイクルは大事
配信中に詰まると焦る💦
落ち着いて問題解決をしましょう
配信1回目
やったこと
GitHubでリポジトリを作成する
プロジェクトの設定
npmの初期化
viteの設定
biome/storybookなどの開発補助ツールの設定
MUIとThemeの設定
まずはプロジェクトの設定を行い、開発の土台を作ります。
今回は最近作った構成でReact、MUI、viteの構成があったのでそちらを持ってきて作っています。
フロントエンドの世界はプロジェクト構成の移り変わりが早く、この構成がベストというものはありません。
だいたい1年に1度(早ければ3ヶ月に1度)ぐらいの頻度で最新の構成をキャッチアップしておくと、何か作りたいというときにすぐに始めることができるのでオススメです。
余談ですが、開発でAIを活用するといろいろと捗ります。
AIの使い方には使い分けがあって、僕の場合は下記のように使い分けています。
質問 → チャット系のAI
書いてるコードに関する質問 → GitHub Copilot Chat
コマンドラインに関する質問 → GitHubCopilot CLI
一般的な質問 → GPT-4、Claude3 Opus
コード生成 → GPT-4、Claude3 Opus
コード補完 → GitHub Copilot
エラー解決 → GitHub Copilot Chat、JetBrains AI Assistant、GPT-4
テスト生成 → Codium AI、GPT-4
コメント生成 → GPT-4、Claude3 Opus
コードレビュー → GPT-4
わかりやすいポイントとしては専用のツールがあればそちらを、文章力が必要ならClaude3 Opusを、論理的能力が必要ならGPT-4を使うということが多いです。
配信2回目
やったこと
Index Pageコンポーネントの作成
ウォレットと接続するPaneコンポーネントの作成
@solana/wallet-adapter-react、@solana/wallet-adapter-react-uiを使ってブラウザウォレットと接続
Brave Walletとの繋ぎ方がわからないところで断念
ウォレットの接続ページを作り始めました。
Storybookを使いながらコンポーネント駆動開発を行っています。
コンポーネント駆動なら最小コンポーネントから作っていくのでは?と思うかもしれませんが、今回はMUIを利用しておりある程度コンポーネントが揃っている、必要になるコンポーネントが見えていない、というのがあってページ、またはペインという少し大きな単位で作っていきました。
そのため、適切な形にするためには必要なコンポーネントが見えるようになったところで分割することが必要になります。
MUIのようなCSS/UI Frameworkは便利ですが、一般的にはプリミティブなコンポーネントしか提供されていないことが多いです。
より楽に組みたいというときには、さらに拡張したコンポーネント集だったり、ページテンプレートなどが提供されていることがあるのでそちらを使うと良いです。(ただしこちらは有料なケースが多いです)
今回はウォレット接続を行うのは始めてだったので、Solana Cookbookというサイトを参考に進めています。(これがエラー地獄のはじまりだったけど)
Solana CookbookはSolanaの開発に関する入門情報を全般的に扱っており、Solanaの公式ドキュメントの次に読むとやりたいことに直結して理解しやすいサイトになっているのでオススメです。
配信3回目
やったこと
ブラウザウォレットと接続
NFTをmintするPaneコンポーネントの作成
Umiフレームワークの使い方がわからないところで断念
前回、ウォレットと接続できなくてなんでだろう?と思ったらSolana Cookbookの記載が間違っていました。
修正PRを出しているので、反映されるまではこちらを参考にしてください。
もしくは公式の方を参考にすると最新のコード例が載っているため、こちらを参考にしていただくのも良いかと思います。
また、サンプルを見ていると下記のようなwalletsの設定が行われています。
const wallets = useMemo(
() => [
new PhantomWalletAdapter(),
new SlopeWalletAdapter(),
new TorusWalletAdapter(),
new LedgerWalletAdapter(),
],
[]
);
個人的に勘違いしていたのですが、こちらは接続したいウォレットを指定するのではなく、接続可能なウォレットがないときに案内を出すためのものになります。
そのため、あればUIとして優しくなりますが、指定しなくても動作するため空配列の指定で構いません。(昔は接続したいウォレット指定だった記憶がありますが、どこかで動作が変わったのかも)
配信4回目
やったこと
MetaplexのUmiフレームワーク使ってNFT発行
import周りがうまく動作せずに断念
フレームワークをノリと勢いで使おうとしても失敗するよねということで調べ直して、@metaplex-foundation/mpl-token-metadataを使えばシンプルなNFTのmintができそうということがわかりました。
これで勝った!!と思いきや今度は謎のエラーに苦しめられることに・・・。
だいたい、この手のエラーで問題になるのはNodeJSのモジュール周り、もしくはNodeJSのコアモジュールを利用しているがためにJavaScriptとして利用できないということが多いです。
この辺は昨今のフロントエンド開発の難しいところになるのですが、ざっくり説明すると我々は普段NodeJSを使って開発します。しかし、このNodeJSというのはブラウザで動作するJavaScriptとは別物になります。そのためNodeJS → JavaScriptにコードを変換する必要があるわけですね。
まず、このとき歴史的な経緯によりモジュールの管理方式で問題が発生しやすいです。ここの複雑さは最近出た下記の記事がわかりやすいのでオススメです。
次に、NodeJSではブラウザでは利用できないNodeJSコアモジュールと呼ばれるモジュールがあります。Solanaのweb3.jsやMetaplexのUmiフレームワークではこのコアモジュールに依存しており、Polyfillsと呼ばれるブラウザで動作させるための回避モジュールを使う必要があります。(Polyfillsはブラウザの最新機能を使いつつ古いブラウザでも動作するようにするために使うものでもあります)
経験則的にここは問題になりやすいため、配信中ではこの辺で問題になっているのでは?と仮説を立てて、いろいろ試していた形になります。が、Polyfillsのバージョンが古くて回避できていなかったというのは気づかなかったというか、そのせいで本当にどハマりしました・・・。
配信5回目
やったこと
MetaplexのUmiフレームワーク使ってNFT発行
Polyfillsのバージョンを最新にあげたことで無事にNFTを発行できるようになりました。
実際にSolanaチェーンと通信するさいに上記で公開するエンドポイントを使用することで簡単に遊ぶことができます。
ただし、これには注意点がありDevnet/Testnetでは動作するが、Mainnet-Betaでは動作しないということがよくあります。
これはMainnet-Betaの公開RPCエンドポイントでは実は様々なコマンドが利用できないようになっており、実質アプリケーションとしての利用はできないようになっていると理解いただくと良いかと思います。
ドキュメントに記載の制限は当てはまらないからMainnet-Betaの公開RPCエンドポイントで大丈夫と考えるとハマるのでご注意ください。(これちゃんとドキュメントに載せて欲しい)
実際にMainnet-Betaで遊ぶさいにはRPCプロバイダを使ってRPCエンドポイントを立ち上げるのがオススメです。
RPCプロバイダの比較記事として下記がよくまとまっているのでオススメです。
配信中では前に契約していたQuickNodeを使って開発を進めています。
https://magiceden.io/item-details/9nLFXkrDPtBjkY7h3WUxdZjv2uC7k2avq9qjsrfawSnQ
記念すべき初mintはMagic Edenで販売中です。俺、もしこれが売れたら本気のSolanaを使ったアプリケーション開発をやるんだ・・・!!!
配信6回目
やったこと
GitHub Actionsを使ってGitHub Pagesにデプロイ
アプリケーションとして動作するものができたので、GitHub Actionsを使って、GitHub Pagesへデプロイをしていきます。
継続的に開発する場合はこういったCDや、テストやリントをするCIはプロジェクトのセットアップタイミングでやることが多いです。
開発はやはりサイクルを作ってリズムよく回していくことが重要なので、継続的に開発するならCI/CDは外せません。
まぁ、今回は継続的に開発する気はないので端折っていますけど。
配信7回目
やったこと
コメントの追加
リファクタリング
今回はプログラム初心者向けにコードを読めるように細かいコメントをつけていますが、実際の開発ではここまでのコメントをつけることはないです。(コード読めばわかるので)
実際の開発ではコードを読んでもわからない、なぜそうしたのかというWhyを残すのが望ましいとはよく言われます。
ただ、Whyだけで足りるかというとそうではなく、例えば"Wallet"という概念があるさいにこのWalletは何を責務に持っているのかというのをコメントに書いた方が良いことも多いです。
やはり、人によって"Wallet"と言って何をイメージするのか違ってしまい、責務がブレていくことがチーム開発においてよくあるからです。
配信8回目
やったこと
リファクタリング
今回は前回から引き続きで気になった箇所のリファクタリングを進めています。
今回や前回やったコメントやリファクタリングは経験則やプラクティスへの知識が求められます。
配信中にあれやった、これやったと軽く話していますが、これは僕がその辺の知識を持っているからサクサクとやっているような形ですね。
ここはプログラミング初心者にはハイコンテキストなところであり、自身で調べて、考えて実施するのは難しい領域になります。
そういったときには前回の配信でやっているようにAIを活用するというのがオススメです。
ある程度プログラミングに慣れていても、気づいてなかったり、知識が足りていないというケースがあるので、コードの品質を高め、自身の能力を高めるためにもAI活用はとても大事になります。
配信9回目
やったこと
README.mdを作成
ワークショップはREADME.mdを見ながら進めていく形式にしたかったので、ひたすら手順を書いていきます。
ちょっと前に話題になりましたが、スクリーンショットを撮るツールを使うとこういったマニュアルなどを手軽に作れて便利です。
配信10回目
やったこと
README.mdの流れを実施
最後ということで前回作成してREADME.mdの手順の確認をしていきます。
確認大事。なんか実際にやってみたらうまく行かないということがあるので本当に大事です。
確認したのに当日問題発覚するとか本当によくありますよね。
おわりに
というので実際にこのワークショップをやってみたい方はこちらの動画を参考にしてください。
本当はオフラインのわちゃわちゃ感を動画に残したかったのですが、配信不備により再録になります。悲しい。
ざっくりとフロントエンドベースのブロックチェーンアプリケーションの作成風景でした。
意外に事故ってグダグダしていると思われたのではないでしょうか。
エンジニアのアウトプットはやったことの上澄みをまとめて出すことが多いでサクッとやっていると思われるかもしれませんが、実際にはこんなものです。特に初めてのことをやるときにはこのぐらい事故るのはよくあることです。本当によくあります。嫌というほどあります。
なので、うまくいかないことを気にする必要はありません。そういうものなのだと割り切って、次やるときはうまくやれるようにやっていきましょう。
ちなみにSolana JapanのDiscordではSolanaに関する質問を受け付けています。他にもSolana Stack Exchangeなど質問できる場はあるので、どうにもうまくいかないときはこういう場所で聞いてみましょう。