見出し画像

【完全保存版】SolanaでPYUSDを送付してみよう!

この記事では、Solana Playgroundを使って、PYUSDの送付を行っています。

エンジニアでない方も、第3章までの実際の送付までは行うことができます。

1 Solana Playgroundの立ち上げ

まずは、こちらからSolana Playgroundを立ち上げてください。

すでに今回のサンプルコードが入っています。

初めての場合は、下の「Not connected」を押してください。

すると、キーペア(公開鍵と秘密鍵)を保存する旨が出るので、保存して接続してください。

注意
このキーペアには実際の資金を入れずに、テスト用で運用することを強くお勧めします。
実際の資金を入れる場合には、キーペアは厳重に保管してください。

接続を行うと、このようになります。

2 テストトークンの取得について

1 SOLの取得

初めての場合は、まずはテストトークンを取得します。

Githubアカウントがすでにある場合は、接続の上、こちらのサイトから、取得ができます。

もしくは、下のように、「solana airdrop 5」と入力することで、テストトークンを取得できます。

2 PYUSDの取得

では、今回送付のテストを行う、PYUSDも取得してみましょう。

こちらからアドレスを入れて、「Send 100 Tokens」を選択

できましたら、念の為、こちらの「here」から確認します。

このように、「History」にトランザクションがあるので、直前のトランザクションを選択します。

(第1節のSOLの取得のトランザクションも直前にあると思いますが、直前の方です。)

このように、「Token Balances」を見ると、100トークンが追加されていました。

ちなみに、その「CXK…ynM」がPayPal USDのアドレスです。

https://explorer.solana.com/address/CXk2AMBfi3TwaEL2468s6zP8xq9NxTXjp9gjMgzeUynM?cluster=devnet

3 実行してみよう

1 プログラムのデプロイ

では、すでにあるプログラムをデプロイしてみましょう。

まずはこちらで「Build」を行います。

続きまして、こちらから「Deploy」を選択します。(私の画面ではすでに「Upgrade」になっていますが)

これでデプロイが完了しました。

2 トランザクションの実行

では、トランザクションを実行してみましょう。

今回は任意の2つのアカウントに、先ほどのPYUSDトークンを1トークンずつ送ります。

まずは、ここから、「Program ID」をコピーします。

こちらの、「client.ts」の下の部分に先ほどコピーしたアドレスを貼り付けます。

ちなみにこちらでは、先ほど作ったプログラムの公開鍵のオブジェクトを作っています。

(普段エンジニアではない方は、先ほどのプログラムの公開鍵を操作するためのもの、というくらいのイメージで良いと思います。)

次にこの部分を修正します。

ここは、このプログラムを作った人の秘密鍵です。(もちろん資産は入っていないとのことです。)

上の部分を、下のように書き換えます。

このSolana Playgroundで使っているウォレットの秘密鍵という意味です。

pg.wallet.keypair.secretKey;

これで準備は完了です。

「Run」を押すと、このように実行されました。

Solana Explorerで検索してみましょう。

https://explorer.solana.com/tx/huEDMGwT9fe5ttsgSYa5xSLDSHSTVyYrQMnuNZTQEgwu53ywXknbYCXesBnmtscAKwVGC52Ft2tL3AMMczPc7c6?cluster=devnet

下の方の「Token Balances」を見ると、このように任意のアドレスにトークンが送付されていることを確認できました。

4 プログラムを確認しよう

ここでは、プログラムを簡単に紹介していきます。

1 プログラム名

今回のプログラム名はこちらの「splitter」になります。

2 関数について

この関数には、「send_to_all」という名前の関数があります。

ctxの部分で、どのようなアカウントをこの関数に渡すのかがわかります。(「SendTokens」という構造体で渡します。)

また、「amount(量)」という引数も渡します。

ちなみに、「SendTokens」の構造体はこちらになります。

3 アカウントの型の変換

それぞれ取得したアカウントは、下のように「AccountInfo」の型に変換しています。

最終的に、こちらのTransferChecked「AccountInfo」の型を要求しているためです。

https://docs.rs/anchor-spl/latest/anchor_spl/token_2022/struct.TransferChecked.html

4 remaining_accountでの反復

今回、任意の2つのアカウントに対して、送付するというように、同じ処理を複数繰り返します。

このような繰り返しの際には、remaining_accountsでアカウントを渡し、下のように処理を繰り返します。

ちなみに、「ctx.remaining_accounts」で取得することについては、下で参照できます。

https://solana.com/ja/developers/guides/getstarted/intro-to-anchor#account-macro

5 正しいアカウントかの確認

反復に使うアカウントが正しい形かの確認を行います。

まずは、受け取ったアカウントに対して、「try_borrow_data()」を使って、データを借りようとします。

「try_borrow_data」については、あまり資料がないのですが、アカウント情報を取得しようとし、できなければエラーを返すものと推察できます。

https://docs.rs/solana-program/1.18.11/src/solana_program/account_info.rs.html#118-122

次に、TokenAccountの形にデシリアライズできるかの確認を行います。

できない場合は、エラーを返しています。

つまり、取得したデータが、本当にアカウントなのかを確認しているのですね。

デシリアライズとは、データをバイト列(シリアライズされた形式)から元のオブジェクトやデータ構造に復元するプロセスのことです。
シリアライズとはその逆で、オブジェクトやデータ構造をバイト列に変換するプロセスです。

https://docs.rs/underdog-anchor-spl/latest/underdog_anchor_spl/token/struct.TokenAccount.html#method.try_deserialize_unchecked

最後に「drop」を使用して、借用を明示的に終了しています。

6 CpiContextの作成

最終的にCPI(Cross-Program Invocation)を利用して「transfer_checked」を実行します。

「Token2022」という、別のプログラムの送付を実行するためです。

そのために、下のように、「TransferChecked」という型が必要です。

https://docs.rs/anchor-spl/latest/anchor_spl/token_2022/fn.transfer_checked.html

そのため、まずはこちらで、「TransferChecked」を作っています。

その上で、CpiContextを作っています。

今回使用する「Token2022」のプログラムIDとともに渡しています。

このCpiContextを「transferChecked」に渡します。

https://docs.rs/anchor-lang/latest/anchor_lang/context/struct.CpiContext.html

7 CPIの実行

最後にtoken2022の「transfer_checked」を実行しています。

こちらの必要な情報に基づいて、amountdecimals(小数点以下の桁数)を入れています。

https://docs.rs/anchor-spl/latest/anchor_spl/token_2022/fn.transfer_checked.html

5 トランザクションを実行しよう

では「client.ts」も見てみましょう。

1 公開鍵オブジェクトの作成

まずは、今回作成したプログラムPYUSDのミントアドレス公開鍵のオブジェクトを作成します。

これによって、何を使うのかを特定することができます。

2 送付先アドレス等

まず、「SENDER_SECRET_KEY」では自身の秘密鍵を取得しています。

署名を行うためです。

次に、Keypair()を使って、ランダムな送付先のキーペア(秘密鍵と公開鍵)を作り、送付量も1に設定しています。

3 送付者の関連トークンアカウントの作成

今回のミントアカウントを取得するためのアカウントを作成します。

下のイメージです。

https://note.com/standenglish/n/n9a82544b9cab?magazine_key=mead31fede0e5

これを実行するために、「createAssociatedTokenAccountIdempotent」を実行します。

ただ、この辺りは、実際のコードを見た方がわかりやすいかもしれません。

「getAssociatedTokenAddressSync」でPDAのアドレスを取得し、それを元に、「createAssociatedTokenAccountIdempotentInstruction」を実行しています。

https://github.com/solana-labs/solana-program-library/blob/d72289c79/token/js/src/actions/createAssociatedTokenAccountIdempotent.ts#L21

そして、「createAssociatedTokenAccountIdempotentInstruction」の方は、このように、「buildAssociatedTokenAccountInstruction」を実行しているようです。

https://github.com/solana-labs/solana-program-library/blob/d72289c79/token/js/src/instructions/associatedTokenAccount.ts#L48

結局やっていることは、送付者の関連トークンアカウントを作成しています。

4 受信者の関連トークンアカウントの作成

受信者の方でも、同じことをやっています。

受信者のアドレスを元にmap関数で回しています。

PublicKey(addr)を用いて、公開鍵のオブジェクトとして渡しています。

5 AccountMetasの作成

「remaininigAccounts」に渡すために、取得した受信者の関連トークンアカウントの「AccountMeta」を作成します。

https://solana-labs.github.io/solana-web3.js/types/AccountMeta.html

下のように作成しています。

6 関数の実行

最後に下の部分で関数の実行を行っています。

公式のこの辺りも参考になります。

https://solana.com/ja/developers/guides/getstarted/intro-to-anchor#account-macro


今回は以上です。



サポートをしていただけたらすごく嬉しいです😄 いただけたサポートを励みに、これからもコツコツ頑張っていきます😊