RustでSolanaのNFTマーケットプレイスを自作する道
ぼちぼち
SolanaでNFTマーケットプレイスと自作してみようと思います。
Solanaとは
「イーサリアムキラー」と呼ばれているそうです。
Rustで書けます!!
この辺が詳しい↓
技術スタック
Solanaプログラム(イーサリアムで言うスマートコントラクト)
・Solana
・Metaplex
・Anchor
フロント(Web)
まだ調べてないですがReactで書けたらReactで書く予定
↓この記事と同じ技術スタック
NFTマーケットプレイスの概要
・Solana上にNFTを作成できる
・素材(画像など)はArweaveで永続化
なぜArweave?
Arweaveは分散型ストレージで、長期間データを保存できるらしい。
実際はNFTでもAWSやGCPのクラウドストレージが使われていて、結局中央集権になっちゃってるらしい。そうなると削除されたり変更されたりする可能性があるため、Arweaveなどの分散型ストレージを使った方がいいのではないかと言う感じだ。
↓詳しいこと
参考サイト
独自?のNFTマーケットを運営しているサイト Solana、Arweaveを用いている
Solana Monkeyのメタデータ音楽のNFTサイト、こちらもSolana、Arweaveを用いていて参考になる
SolanaでNFTを作る(Rust, Anchor, Metaplex)
まずは、プログラムからNFTを作るところから。
前回も紹介したこの記事がわかりやすいので、このコードを辿りながら動くか確認してみる。
※ Macでやります
Solana周りの技術をインストール
とてもスムーズに導入できた
Rustをインストール
万が一、Rustをインストールしていなければ、こちらから。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
https://www.rust-lang.org/tools/install より
Solana CLIを導入
sh -c "$(curl -sSfL https://release.solana.com/v1.10.31/install)"
https://docs.solana.com/cli/install-solana-cli-tools より
Anchorを導入
cargo install --git https://github.com/project-serum/anchor avm --locked --force
avm install latest
avm use latest
https://hackmd.io/@ironaddicteddog/solana-anchor-escrow より
これで完了!
Solanaの設定
devnetに設定
devnetを用いて開発を行うので、devnetと設定する。
solana config set --url devnet
Wallet作成
solanaのwalletを入れるディレクトリに、JSONのwalletのkeypairを保存する。
このkeypairを指定してコマンドを打つとpubkeyがいつでも確認できる!
mkdir ~/my-solana-wallet
solana-keygen new --outfile ~/my-solana-wallet/my-keypair.json
solana-keygen pubkey ~/my-solana-wallet/my-keypair.json
公式がとても丁寧!
そしてsolanaの設定にkeypairの場所を入れておこう。
solana config set --keypiar ~/my-solana-wallet/my-keypair.json
設定が合っているか不安になったら、
こちらで簡単に確認できます!
solana config get
雛形を生成!
Solanaプログラムの雛形を簡単に作れるフレームワーク、Anchorで作っていく。
anchor init solana-nft-example
solana-nft-example
の部分は好きなプロジェクト名をつける。
雛形ができたらAnchor.toml
をいじる。
provider
の欄のclusterをdevnet、walletを先ほど作成したkeypairの場所に設定する。
[provider]
cluster = "devnet"
wallet = "/Users/anharu/my-solana-wallet/my-keypair.json"
次に必要なパッケージをインストールしていく。
programs/<project name>/Cargo.toml
を開く
最新のバージョンを設定しておく。
[dependencies]
anchor-lang = "0.25.0"
anchor-spl = "0.25.0"
mpl-token-metadata = {version = "1.3.2", features = ["no-entrypoint"]}
NFTを作れるようにする
programs/<project name>/src/lib.rsをいじる。
https://github.com/anoushk1234/metaplex-anchor-nft/blob/master/programs/metaplex-anchor-nft/src/lib.rs を使ってとりあえず動かしてみた。
mint_nftの関数はこのようになってる。creator_keyは自分のpubkey、uriはNFTの画像URL、titleはNFTのタイトルを意味してる。
これを設定することでJSから呼び出すことができる。
pub fn mint_nft(
ctx: Context<MintNFT>,
creator_key: Pubkey,
uri: String,
title: String,
) -> Result<()> {
mint_nft
を呼び出し
テストからtests/<project name>.ts
でテストを作ろう。
これも、 https://github.com/anoushk1234/metaplex-anchor-nft/blob/master/tests/metaplex-anchor-nft.ts を利用した。
TSからは、 program.methods.mintNft
で先ほどの関数を実行できた。snake caseからcamel caseに変換されていることに注意してください。
このコード↓を利用すると、好きな画像を設定できません。
とりあえず、CLIでarweaveに画像をアップロードしてみよう!
const tx = await program.methods.mintNft(
mintKey.publicKey,
"https://arweave.net/y5e5DJsiwH0s_ayfMwYk-SnrZtVZzHLQDSTZ5dNRUHA",
"NFT Title",
)
.accounts({
mintAuthority: wallet.publicKey,
mint: mintKey.publicKey,
tokenAccount: NftTokenAccount,
tokenProgram: TOKEN_PROGRAM_ID,
metadata: metadataAddress,
tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID,
payer: wallet.publicKey,
systemProgram: SystemProgram.programId,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
masterEdition: masterEdition,
},
)
.rpc();
CLIでarweaveに画像アップロード
Arweaveのwalletを入手
公式サイトのCLAIM A TOKENから、walletを作り、ツイートをすると、ARがもらえる。
CLIをインストールして、
npm install -g arweave-deploy
deployコマンドで、Arweaveのkeyfileの場所と、画像のパスを指定するだけ!
arweave deploy --key-file <arweave key file> <file path>
画像を作ったら次はNFTメタデータJSONを作る。
↓ここに書いてある形式に乗っ取って設定する
私はこのように設定してみた。devnetなので適当に。
{
"name":"My tomie art",
"symbol":"ANHARU",
"description":"My tomie art",
"seller_fee_basis_points":420,
"external_url":"",
"attributes":
[
{
"trait_type": "name",
"value": "My tomie art"
}
],
"properties": {
"category":"image",
"creators":
[
{"address":"GucSuCq7MvzPgwSQLkWi19wJThWpQ6uMy813DAEBUMym","share":100}
],
"files":
[
{"uri":"https://arweave.net/e578yh89yejwPMXLfYMy_6GsqtlsEktKoYfIOYfsCBU?ext=jpg","type":"image/jpeg"}
]
},
"image":"https://arweave.net/e578yh89yejwPMXLfYMy_6GsqtlsEktKoYfIOYfsCBU"
}
これも先ほどと同じようにarweaveにアップロードしよう。
これでオリジナルなarweaveのファイルとタイトルを設定する。
最初間違えて、URLを画像リンクにしてしまったのですが、solscanで確認すると画像が表示されず。
正しくは、ここはNFTのメタデータJSONのリンクを貼る。
const tx = await program.methods.mintNft(
mintKey.publicKey,
"https://arweave.net/wLQwK2ENbXVfQQ-n7tsVbGVREx61oVqSWJFQgoorzug",
"My tomie art",
)
準備ができたらanchor test
でテストを実行!
> anchor test
BPF SDK: /Users/anharu/.local/share/solana/install/releases/1.10.31/solana-release/bin/sdk/bpf
cargo-build-bpf child: rustup toolchain list -v
cargo-build-bpf child: cargo +bpf build --target bpfel-unknown-unknown --release
Finished release [optimized] target(s) in 0.70s
cargo-build-bpf child: /Users/anharu/.local/share/solana/install/releases/1.10.31/solana-release/bin/sdk/bpf/dependencies/bpf-tools/llvm/bin/llvm-readelf --dyn-symbols /Users/anharu/Projects/solana-nft-example/target/deploy/solana_nft_example.so
To deploy this program:
$ solana program deploy /Users/anharu/Projects/solana-nft-example/target/deploy/solana_nft_example.so
The program address will default to this keypair (override with --program-id):
/Users/anharu/Projects/solana-nft-example/target/deploy/solana_nft_example-keypair.json
Deploying workspace: https://api.devnet.solana.com
Upgrade authority: /Users/anharu/my-solana-wallet/my-keypair.json
Deploying program "solana-nft-example"...
Program path: /Users/anharu/Projects/solana-nft-example/target/deploy/solana_nft_example.so...
Program Id: 7mD7Xd7vLfmUb8TocxpJcj1c3EkfGDQfqVkAUyWhxsxc
Deploy success
Found a 'test' script in the Anchor.toml. Running it as a test suite!
Running test suite: "/Users/anharu/Projects/solana-nft-example/Anchor.toml"
yarn run v1.22.17
warning package.json: No license field
$ /Users/anharu/Projects/solana-nft-example/node_modules/.bin/ts-mocha -p ./tsconfig.json -t 1000000 'tests/**/*.ts'
solana_nft_example
NFT Account: 377gZbV7sxmwEGMozWZ45mQRAksQwDRaAhr46QfS5Reg
{
context: { apiVersion: '1.10.29', slot: 149686865 },
value: {
data: { parsed: [Object], program: 'spl-token', space: 82 },
executable: false,
lamports: 1461600,
owner: PublicKey {
_bn: <BN: 6ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a9>
},
rentEpoch: 346
}
}
Account: 5cwP9BdaMvBo2sSdWYiu5GauDAsGXgDwWNVrwKVdDATxHwiMuTa5mkHDLwYGfNEBsBeRzHLioU23VDSQ1JVridHT
Mint key: Hk4usYxqgidgbsUt28ykULreQbPrsK2dEDwg44US7ATs
User: GucSuCq7MvzPgwSQLkWi19wJThWpQ6uMy813DAEBUMym
Metadata address: 5bcBcLdthN5jC3JaLTSkwo2SKyYoRF8YYLzQku7Lxfaw
MasterEdition: BqJmrALKAL3MwUGpoVKRd8Xb84hUyUFEV57JW3G3FtA8
Your transaction signature aZUQyKcomNAxT9UD1jSqmE1ww7aFgahYn6NTRDxWRaBi1NjaFyBoQfMYXLiaiUWCg6HWngtFoTHCnov6x9ate7x
✔ Is initialized! (3357ms)
1 passing (3s)
✨ Done in 9.26s.
このように成功!早速solscanで見てみる
https://solscan.io にアクセスし、
devnetを設定。
ターミナルに表示されたmint key(Hk4usYxqgidgbsUt28ykULreQbPrsK2dEDwg44US7ATs)を検索欄に入れる。
そうすると、、正しく画像が表示されいい感じ!
もしNot foundになるときは、devnetになっているか確認し、なっていれば、根気よくretryする。
メタデータ欄を見るとarweaveのjsonリンクもちゃんと設定されていることがわかる。
今後
arweaveのjsのパッケージでプログラムからアップロードしたり、WebアプリからNFT作れるようにしたい。
追記
ここまでやったのを公開しました。
これからもこれをどんどんカスタマイズしていこうと思います。
NFTマーケットのフロントについて
Anchorを使えば、Solanaのプログラムの操作ができるとわかったので、
フロントエンドのライブラリはなんでも良さそうです。
なので、Reactで行おうと思います。
フロントよりも、学ぶことが多いバックエンドの方を優先的にやっていこうと思う。
NFTを作る機能はほぼ出来上がったので、売買する機能を実装していきたい。
ただ、多くのNFTマーケットプレイスには、オークション機能が備わっている。
オークションのプログラムをとりあえず動かしてみる
オークション機能つけてるいい例ないかなーとGithubを漁っていると発見!!
こちらのリポジトリ。
とりあえずうごがしてみる。
そうすると、こちらのエラーに遭遇
ひたすらエラーが出たフィールドにひたすらこのコメントを追加
/// CHECK: This is not dangerous because we don't read or write from this account
そしてanchor test
をする前に、yarn install
を忘れずに。
自動的にyarn run postinstall
が走って、submoduleの方の設定をしてくれる。
そして、anchor test
をすると、、テストが正常に走りました!
これベースでフロントをつけたらいい感じになるのかな???やってみる