👋

AIエージェントフレームワーク Solana Agent Kit v2 解説(2): 組み込みウォレット

に公開

はじめに

こんにちは!今回は4月18日に公開されたSolana Agent Kit v2に関してv1からの変更点を中心に私自身のキャッチアップも兼ねて調査したので解説していきます。
今回は組み込みウォレットの対応についてです。

AIエージェントフレームワーク Solana Agent Kit v2 解説記事

AIエージェントフレームワーク Solana Agent Kit v2 解説(1): 新アーキテクチャでNFT作成
https://zenn.dev/yukiki01/articles/481f075c90fbc2
AIエージェントフレームワーク Solana Agent Kit v2 解説(3): モバイル対応とプロンプトパフォーマンス向上
https://zenn.dev/yukiki01/articles/d8ae09e8b16b3c
AIエージェントフレームワーク Solana Agent Kit v2 解説(4): MCPサーバーを立ててみる
https://zenn.dev/yukiki01/articles/07e78ee5194f9d

組み込みウォレットとは?

既存の秘密鍵やシードフレーズを管理するようなウォレットとは異なり、メールアドレスやソーシャルアカウントで取得できるアプリケーション内に組み込まれたウォレットです。ユーザー側で秘密鍵やシードフレーズの管理は必要なく、ブロックチェーンアプリケーションの利用経験がないユーザーでも簡単に利用できるようになります。
Solana Agent Kit v2では組み込みウォレットに対応しました。

組み込みウォレット対応

公式ドキュメント
https://docs.sendai.fun/docs/v2/setup/embedded-wallets
公式ドキュメントをみるとSolanaAgentKitをインスタンス化する際にウォレットの署名やトランザクション送信などの操作の関数をあらかじめ定義しておくようです。

// --- 一部抜粋
const agent = new SolanaAgentKit(
  {
    publicKey: new PublicKey(wallet.address),
    signTransaction: async (tx) => {
      const signed = await wallet.signTransaction(tx);
      return signed;
    },
    signMessage: async (msg) => {
      const signed = await wallet.signMessage(msg);
      return signed;
    },
    sendTransaction: async (tx) => {
      const connection = new Connection(
        "YOUR_RPC_URL",
        "confirmed"
      );
      return await wallet.sendTransaction(tx, connection);
    },
    signAllTransactions: async (txs) => {
      const signed = await wallet.signAllTransactions(txs);
      return signed;
    },
    signAndSendTransaction: async (tx) => {
      const signed = await wallet.signTransaction(tx);
      const connection = new Connection(
        "YOUR_RPC_URL",
        "confirmed"
      );
      const sig = await wallet.sendTransaction(signed, connection);
      return { signature: sig };
    },
  },
  "YOUR_RPC_URL",
  {}
)
// --- 一部抜粋

AIエージェントが各プラグインのツールを呼び出して処理を実行する時にウォレット操作が必要な類のものに関してはここで定義した関数が呼び出されます。
SolanaAgentKitインスタンス化時に定義した関数を利用して署名またはトランザクション送信をする関数signOrSendTXが各種プラグインの中のツールで呼び出されています。

signOrSendTX関数
https://github.com/sendaifun/solana-agent-kit/blob/e72c9df23eb9d42d80950f4b10d288d1a2a65596/packages/core/src/types/wallet.ts#L82-L177
MetaplexでNFTコレクションを作るツールでsignOrSendTX関数が呼び出されている例
https://github.com/sendaifun/solana-agent-kit/blob/e72c9df23eb9d42d80950f4b10d288d1a2a65596/packages/plugin-nft/src/metaplex/tools/deploy_collection.ts#L70
Solana Agent Kit v2のGitHub内にPhantomやPrivyといった組み込みウォレットのサンプルコードがあるので、実装する時はそちらのコードを参考に実装することができます。
https://github.com/sendaifun/solana-agent-kit/tree/v2/examples/embedded-wallets
ここではPhantomの組み込みウォレットサンプルコードを動かしてどう動くのか見ていきたいと思います。

Phantomの組み込みウォレットで動かしてみる

phantom/wallet-sdkを利用することでPhantomでも組み込みウォレットを作ることができます。

事前準備

phantom-agent-starterのコードをローカルに取得します。
nodeのバージョン

node -v
v23.11.1

.env.local作成

cp .env.example .env.local

OPENAI APIキーを取得して設定

NEXT_PUBLIC_OPENAI_API_KEY="sk-"

NEXT_PUBLIC_RPC_URL="https://api.devnet.solana.com"

ライブラリインストール

pnpm install

起動

pnpm dev

動作確認

http://localhost:3000にアクセスすると下記のようにPhantom組み込みウォレットが表示され、Google認証でウォレット作成できます。

ウォレットを作ったばかりなのでWhat is my wallet balance?と質問してウォレットの残高を確認してみるとまだ残高がないようです。

Please faucet 5 SOL on devnet to my walletと指示するとfaucetをリクエストしたという回答がありました。

再度What is my wallet balance?と質問してみると先ほどfaucetした5SOLが残高となっている回答がありました。

本当に存在しているのかSolscanで確認してみると確かに5SOLの残高があります!

どうやってウォレットと連携しているのか?

公式ドキュメントにあるようにSolanaAgentKitをインスタンス化する際にsignTransaction/signMessage/sendTransaction/signAllTransactions/signAndSendTransactionにそれぞれphantomのメソッドを定義していました。
https://github.com/sendaifun/solana-agent-kit/blob/e9a28e01dfbdc3750536734580bfae5e50a5a5d2/examples/embedded-wallets/phantom-agent-starter/src/app/components/Chat.tsx#L47-L106
PrivyのようなProviderが標準で実装されていないため、PhantomWalletProviderを独自に定義しているようです。
https://github.com/sendaifun/solana-agent-kit/blob/v2/examples/embedded-wallets/phantom-agent-starter/src/app/components/PhantomWallet.tsx

別のサンプルコードでPrivyの例もあったので掲載します。
基本的にはPhantomの例と変わらず、トランザクション送信等のウォレット操作で利用するメソッドをSolanaAgentKitインスタンス化時に定義しています。
https://github.com/sendaifun/solana-agent-kit/blob/e9a28e01dfbdc3750536734580bfae5e50a5a5d2/examples/embedded-wallets/privy-agent-tanstack-starter/src/hooks/useChat.ts#L17-L19
https://github.com/sendaifun/solana-agent-kit/blob/e9a28e01dfbdc3750536734580bfae5e50a5a5d2/examples/embedded-wallets/privy-agent-tanstack-starter/src/hooks/useChat.ts#L74
https://github.com/sendaifun/solana-agent-kit/blob/e9a28e01dfbdc3750536734580bfae5e50a5a5d2/examples/embedded-wallets/privy-agent-tanstack-starter/src/hooks/useChat.ts#L83-L119

まとめ

SolanaAgentKitをインスタンス化する時に、必要なウォレット操作のメソッドを定義しておくことでAIエージェントが利用するツール内でトランザクション送信などが必要でも組み込みウォレットで対応できるようになりました。
秘密鍵やシードフレーズを保管せずとも自分の組み込みウォレットを用いてAIエージェントに処理をしてもらうことができ、クリプトに馴染みのないユーザーにも使いやすいDeFAIアプリなどが作れそうですね。
一方で今回記事内で実施したdevnetトークンのfaucetはすぐに成功しましたが、トークンの価格取得やスワップは私がサンプルプログラムを操作した限りだと成功率に差があり、本番利用する際はサンプルプログラムから精度を改善する余地がありそうです。

Discussion