ZendIQ について
ZendIQはSolana取引エージェント向けに、トークン審査、スワップ判定、トランザクション構築を提供します。スコアはホスト型APIで算出され、MCPサーバーはx402決済とローカルの支出台帳にも対応します。
主な機能
- 01無料のトークンリスク審査
- 02スワップ判定と実行案
- 03未署名の最適化スワップ構築
- 04x402決済と予算台帳
- 05シグナル詳細と判定理由
活用シーン
- 01取引前のSolanaトークンリスク確認
- 02署名前のスワップ経路評価
- 03ウォレット確認用トランザクションの構築
- 04自動候補スキャンの支出制限
MCP 対応
MCPサーバーはstdio経由で`zendiq_screen_token`、`zendiq_triage_swap`、`zendiq_optimize_swap`を公開します。スコア判定と最適化はZendIQのホスト型APIに送られ、有料呼び出しはx402クライアントが処理します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @zendiq/mcpZENDIQ_AGENT_NETWORKPayment network: mainnet (default) or devnet. The free screen tool needs no payment.AGENT_STATE_DIRFolder holding payer-mainnet.key.json (any file solana-keygen writes) and the budget ledger. Defaults to ~/.zendiq. Never inside the npm cache.ZENDIQ_AGENT_BUDGET_FILESpend-ceiling ledger every payment is reserved against. Defaults to <state dir>/budget-<network>.json, created by: npx -y @zendiq/mcp budget init 1.00ZENDIQ_AGENT_KEYPAIRシークレットDevnet only: path to a Solana keypair JSON file holding devnet USDC.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
3掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| amount | string | はい | 売却数量。入力 mint の最小単位を 10 進数文字列で指定します。1 SOL(小数点以下 9 桁)の場合は "1000000000" を指定してください。 |
| inputMint | string | はい | 売却するトークンの Base58 mint アドレス。 |
| outputMint | string | はい | 購入するトークンの Base58 mint アドレス。 |
| slippageBps | integer | いいえ | 任意のスリッページ許容値(ベーシスポイント)。省略すると、ルートのデフォルト値が使用されます。 |
詳細
ZendIQ Agent API
ZendIQ は、エージェントが署名する前に、有料かつ機械可読な Solana スワップのトリアージ判定を提供します。公開されている範囲には、MCP クライアント、x402 クライアント、予算管理、レスポンスの契約、実行可能なサンプルが含まれます。
公開されているもの、公開されていないもの
このリポジトリには、エージェント向けの統合機能一式が含まれています。
zendiq_screen_token、zendiq_triage_swap、zendiq_optimize_swapを公開する MCP サーバー- x402 決済クライアント
- 実行クライアント — 最適化された未署名スワップを構築、検証、送信します(
/optimize) - 自律型候補フィードとトリアージループ
- 厳格なローカル支出上限を備えた意思決定台帳
- 公開リクエストおよびレスポンス契約
- ライブ API(
GET /v1/agent)から取得する決済ネットワーク情報(メインネットでは必須の支出上限あり)
スコアリングモデルは意図的に含めていません。各レスポンスには、個々のシグナル、その観測値、ステータス、各要因がスコアに与える点数が表示されます。そのため、エージェントは見出しの判定だけでなく、シリアルデプロイヤーのフラグがあれば拒否するなど、個々のシグナルに基づいて動作できます。ただし、これらのシグナルの導出方法と組み合わせ方、つまりデータソース、しきい値、重み付けモデルは、ホストされた /analyse エンドポイントで実行され、ZendIQ の独自エンジンとして公開されません。契約は公開されているため、統合者は何が送信され、返され、支払われ、実行されるのかを正確に確認できます。
このリポジトリには、拡張機能の分析情報、ユーザーテレメトリー、本番環境のデプロイ設定、データベーススキーマ、ファシリテーターウォレット、本番環境の認証情報は含まれていません。ZendIQ の非公開バックエンドとは独立した、新しい履歴を持つリポジトリです。
要件
- Node.js 22.5 以降
- 有料リクエスト用のメインネット USDC を保有する Solana キーペア(SOL は不要です)
- スコアリングが実行される ZendIQ のホスト API
https://api.zendiq.aiへのネットワークアクセス — 実行前にリクエストの送信先をご確認ください。
クイックスタート
インストール不要で、無料で始められます。 トークンのスクリーニングに、ウォレット、支払い、キー、クローンは必要ありません。実際のリスクスコアが数秒で返されます。
curl -s -X POST https://api.zendiq.ai/v1/agent/analyse-token \
-H "content-type: application/json" \
-d '{"mint":"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"}'
PowerShell:
Invoke-RestMethod -Method Post https://api.zendiq.ai/v1/agent/analyse-token `
-ContentType 'application/json' `
-Body '{"mint":"JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"}' | Select-Object -ExpandProperty tokenRisk
Python(標準ライブラリのみ):
import json, urllib.request
req = urllib.request.Request(
"https://api.zendiq.ai/v1/agent/analyse-token",
data=json.dumps({"mint": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN"}).encode(),
headers={"content-type": "application/json"},
)
with urllib.request.urlopen(req, timeout=30) as resp:
body = json.load(resp)
risk = body["tokenRisk"]
print(risk["symbol"], risk["score"], risk["level"], "signals", body["signals_resolved"])
レスポンスには、tokenRisk(スコアとレベル)、その根拠となる17個のsignalsとそのカバレッジを示すsignals_resolved、および/optimizeで60秒間再利用できるanalysisIdが含まれます。
有料の呼び出し。 以下の手順はお使いのマシン上で実行します。ZendIQへの呼び出しは、ホストされたAPIへのスコアリングリクエストと/optimizeリクエストのみです。これらのリクエストにURLを設定する必要はありません。npmコマンドはbashとPowerShellで共通です。
1. インストールし、ローカルの支出上限を設定します。 budget:initはAPIから支払いネットワークを取得し(GET /v1/agent、無料)、そのネットワーク用の$1.00の台帳をruntime/に書き込みます。支払いは発生しません。メインネットでは、すべての支払いがこの上限に対して予約されます。ここでの手順では、上限なしに支払いが行われることはありません。
npm ci
npm run budget:init
2. 支払いに使うキーを用意して、資金を入れます。 このコードがメインネットキーを生成したり、書き込んだりすることはありません。ご自身で管理するSolanaキーペアをruntime/payer-mainnet.key.jsonに配置します。たとえば、solana-keygen new -o runtime/payer-mainnet.key.jsonで書き込まれるファイルを使います。そのアドレスに、Solanaメインネット上のUSDCを少額入金してください。SOLは不要です。x402ファシリテーターが支払いのネットワーク手数料を負担します。$1で100回呼び出せます(1回あたり$0.01)。この台帳が上限を設定するのはこのコード経由の支払いのみなので、専用ウォレットを使用してください。
3. 有料の呼び出しを1回実行します(メインネットのUSDCで$0.01)。
npm run analyse
4. 同じキーと台帳を使ってMCP サーバーを実行します。
npm run mcp
クローンを省略することもできます。npx -y @zendiq/mcp@latestを実行すると、npmから同じサーバーが起動します。エージェントに接続するをご覧ください。
MCP サーバーは、stdio経由で改行区切りのJSON-RPCを使用します。診断情報はstderrに出力されるため、stdoutは有効なMCPトランスポートのまま保たれます。
5. 任意:/optimizeをビルドのみで試します。 /optimizeは、taker向けにメインネット上のスワップを構築します。takerは公開鍵にすぎず、署名も行われないため、資金のあるメインネットアドレスであれば、プラン、シミュレーション、取引先の判断をすべて確認できます。デフォルトの0.003 SOLのスワップには、0.003 SOLを少し上回る額を保有するアドレスを選んでください。
npm run optimize -- --taker <ANY_FUNDED_MAINNET_ADDRESS>
これはビルドのみです。USDCで$0.02を支払いますが、署名は行いません。また、ご自身が管理していないウォレット用に構築されたトランザクションには署名できません。取引資金が不足しているtakerは、課金されずに422 taker_insufficient_balanceを受け取ります。取引を実行するには、実行をご覧ください。
変数はシェルで設定してください。このリポジトリは.envファイルを読み込みません。.env.exampleには参考用の変数一覧のみが記載されています。
トークンの初回スキャンには通常1~5秒、最長で約12秒かかります。過去60秒以内に誰かがスキャンしたトークンの場合、1秒未満で結果が返されます。詳細:呼び出しにかかる時間。
支払いのオンチェーン決済が確認されるまで、最大90秒間レスポンスが保留される場合もあります。これはファシリテーターが送金自体を確認できない場合に発生します。/analyseと/optimizeには、少なくとも120秒のタイムアウトを設定してください。MCPホストではそれより早くツール呼び出しがタイムアウトすることがよくあります。ホストで設定できる場合は、タイムアウト時間を延長してください。詳細:決済によりレスポンスが保留される場合。
settlement_pendingを伴う402で終了した場合は、支払いヘッダーを保持し、同じヘッダーを使って1回だけ再試行してください。遅れて決済された支払いは、24時間以内であれば、同じルートで新しいレスポンスを1回取得するために利用できます。zendiq-client.jsとMCP サーバーは、この処理を自動で行います。詳細:settlement_pending後に1回再試行する。
呼び出し先
お使いのマシン上で実行されるもの: MCP サーバー(ローカルの stdio アダプター)、x402 の支払い署名、予算台帳、候補フィード、トリアージループ、トランザクションの検証と署名、デモビジュアライザー。
ZendIQ のホスト型 API を呼び出すもの: トークンのスクリーニング、/analyse、/optimize。スコアリングエンジンはこのリポジトリに含まれておらず、ローカルモードもありません。すべてのスコアはホスト型 API から取得されます。
サードパーティを直接呼び出すもの: DexScreener(候補フィード)、Jupiter の /execute と Solana RPC(--execute を渡した場合のみ)、x402 ファシリテーター(支払いの決済)。
デフォルトのエンドポイントは、ZendIQ の本番ホスト型 API です。 このリポジトリをクローンし、URL を設定せずに実行すると、呼び出しは当社の本番サービスに送信され、実際の x402 支払いとして請求されます。
const BASE_URL = process.env.ZENDIQ_API_URL ?? 'https://api.zendiq.ai';
このデフォルト設定は意図的なものです。インフラを用意しなくてもクイックスタートを動作させるためです。サンドボックスではありません。ループを実行する前に理解しておくべき点が 2 つあります。
- 支払いは mainnet USDC で実際に決済されます。
/analyseは$0.01、/optimizeは$0.02です。モックではなく、オンチェーントランザクションです。 npm run watchは自律型ループです。 ローカルの予算上限に達して停止するまで、候補ごとに支払いが発生します。budget:initは慎重に設定してください。支出を制限するのはこれだけです。
エンドポイントは上書きできます。MCP サーバーには ZENDIQ_AGENT_URL、サンプルとデモランナーには ZENDIQ_API_URL を指定します。ただし、ZendIQ Agent API を指している必要があります。これらは別々のコードパスを参照する 2 つの異なる変数であり、一方を設定してももう一方には影響しません。例外はデモランナーです。デモランナーは自身の ZENDIQ_API_URL を起動する MCP サーバーに渡すため、その場合 ZENDIQ_AGENT_URL は無視されます。
決済レール: サンプル、budget:init、デモランナーは、API(GET /v1/agent、フィールド network)から支払いネットワークを読み取ります。AGENT_NETWORK は任意ですが、設定する場合は API の値と一致していなければ、実行を拒否します。例外は budget:init です。ここでは明示的に指定された AGENT_NETWORK がそのまま使用されるため、サーバーを切り替える前に台帳を作成できます。MCP サーバーは ZENDIQ_AGENT_NETWORK を読み取り、デフォルトは mainnet です。mainnet または devnet 以外の値を指定すると、有料ツールは実行を拒否します。ホスト型 API は mainnet USDC で決済し、mainnet を分析します。また、/optimize は実際の mainnet トランザクションを返します。
このリポジトリには ZendIQ の認証情報は含まれていません。支払いに使うキーはお客様自身のもので、お客様の支払いに署名し、お使いのマシンから外に出ることはありません。
エージェントに接続する(MCP)
サーバーは stdio(改行区切りの JSON-RPC)で Model Context Protocol を使用するため、Claude Desktop、Cursor、Cline、独自のハーネスなど、MCP 対応のクライアントから直接呼び出せます。ワークフローの各段階に対応する 3 つのツールを公開しています。これらは独立したエントリーポイントであり、決められた順序で呼び出す必要はありません。実際に知りたいことに合わせて呼び出してください。
zendiq_screen_token — スクリーニング段階。トークンを検討していて、まだ取引がない場合は、最初に呼び出します(新規ミントを多数スキャンするエージェントには、取引がありません)。無料で、レート制限があります。複数の呼び出し元間でキャッシュできます。トークンのリスクスコア、シグナルの内訳、signals_resolved によるカバレッジ、cache ブロック(hit、ageSeconds、observedAt)を返すため、最新の情報を強制的に取得するかどうかを判断できます。
| 入力 | 型 | 必須 | 説明 |
|---|---|---|---|
mint | 文字列 | はい | スクリーニングするトークンの Base58 ミント |
zendiq_triage_swap — 判断段階。スワップに署名する前に呼び出し、そのトークンを取引するかどうか、またどのように取引するかを判断します。有料です。トークンのスコア全体をインラインで返すため、先にスクリーニングする必要はなく、任意です。サンドイッチ攻撃へのエクスポージャー、ルート、推奨される実行方法も返します。トランザクションは構築しません。
| 入力 | 型 | 必須 | 説明 |
|---|---|---|---|
inputMint | string | はい | 売却する Base58 ミント |
outputMint | string | はい | 購入する Base58 ミント |
amount | string | はい | 売却する数量。入力ミントの最小単位で指定します(例:1 SOL の場合は "1000000000") |
slippageBps | integer | いいえ | ベーシスポイント単位のスリッページ許容値。ルートのデフォルト値を使う場合は省略します |
出力(structuredContent):
verdict—Safe(通常のルートを使用)、Protect(Jito バンドル経由でルート設定)、またはRefuse(実行しない)recommendedExecution—{ path, priorityFeeLamports, jitoTipLamports }reasons— 平易な言葉での根拠
トークンリスク要因、サンドイッチ攻撃への露出、プロベナンス・フィンガープリントを含むリスクの詳細な内訳は、これらの確定フィールドとともに変更されずに返されるため、MCP の結果は HTTP の /analyse レスポンスとバイト単位で同一です。各呼び出しの料金は $0.01 で、設定済みのキーペアを使って x402 により USDC で自動決済されます。
zendiq_optimize_swap — 実行段階です。取引を決定し、トランザクションが必要になったら呼び出します。有料です。署名なしのスワップトランザクション(Jupiter ルート、またはすべてのコストを差し引いても取引額の 0.1% を超える差がある場合は、より有利な直接の取引所または Jito バンドル)、照合用の plan、submit の手順、シミュレーション、項目別の netBenefit、および zendiq_triage_swap と同じ verdict を返します。カストディは行わないため、ここで署名されることはありません。
| 入力 | 型 | 必須 | 説明 |
|---|---|---|---|
inputMint | string | はい | 売却する Base58 ミント |
outputMint | string | はい | 購入する Base58 ミント |
amount | string | はい | 売却する数量。入力ミントの最小単位で指定します |
taker | string | はい | スワップの構築対象となる Base58 形式のメインネットウォレット。入力数量と、手数料およびレンタル料を支払うための SOL を保有している必要があります(ガスレスの Jupiter Ultra フィルの場合、SOL は不要です) |
slippageBps | integer | いいえ | ベーシスポイント単位のスリッページ許容値。ルートのデフォルト値を使う場合は省略します |
method | "jito" | いいえ | リスクスコアがバンドルを必要としない場合でも、Jito バンドルの取引所を強制します。この場合、plan.choice は forced となり、構築できるバンドルがない場合でも、バンドルを使わないルートへの置き換えは行われません。署名済みバンドルを POST /v1/agent/bundle に送信します |
このツールも、zendiq_triage_swap と同じ Safe/Protect/Refuse の verdict と reasons を返します。ただし、取引の決定はすでになされているものとして扱うため、Refuse の場合でもトランザクションを構築します。署名する前に verdict を確認してください。各呼び出しの料金は $0.02 です。構築に失敗した場合、料金はかかりません。
支払いは支払い元ウォレットからメインネットの USDC で決済され、スワップは taker 向けにメインネットの流動性を使ってルーティングされます。API では支払い元ウォレットを taker として指定できますが、以下の例では 2 つのキーを分けており、支払い元と同じキーを taker として指定した場合は拒否されます。
MCP クライアントの設定に登録してください。このパッケージはクローンせずに npm から直接実行できます。Claude Code なら、コマンド 1 つで設定できます。
claude mcp add --scope user zendiq -- npx -y @zendiq/mcp@latest
その他のクライアントでは、以下の JSON をユーザー設定(Claude Code の場合は ~/.claude.json、それ以外はクライアント独自の設定ファイル)に貼り付けると、すぐに接続できます。プロジェクトの .mcp.json も使用できますが、その場合は先にサーバーの承認を求められます。
{
"mcpServers": {
"zendiq": {
"command": "npx",
"args": ["-y", "@zendiq/mcp@latest"]
}
}
}
これで、無料でウォレットも不要な zendiq_screen_token を使う準備は完了です。有料ツールを使うには、~/.zendiq(または AGENT_STATE_DIR)に保管する以下の 2 つも必要です。
- 支出上限:
npx -y @zendiq/mcp@latest budget init 1.00を実行すると、budget-mainnet.jsonが書き込まれます。支出は発生しません。支出額を確認するにはnpx -y @zendiq/mcp@latest budgetを実行します。 - メインネットの USDC を保有する支払い用キー:
~/.zendiq/payer-mainnet.key.jsonに配置します。たとえば、solana-keygen new -o ~/.zendiq/payer-mainnet.key.jsonのように、solana-keygenが書き出す任意のファイルを使用できます。このキーが自動生成されることはありません。起動時に、サーバーは支払い元アドレスと、そのキーの取得元ファイルを標準エラー出力に記録します。
npm が予告なく削除するため、サーバーはキーや台帳を node_modules または npx キャッシュ内に保持しません。資金の入ったキーがそこにあると失われるおそれがあるためです。
クローンから実行する場合は、代わりにクライアントからファイルを指定します(パスは絶対パスである必要があります)。
{
"mcpServers": {
"zendiq": {
"command": "node",
"args": ["/absolute/path/to/ZendIQ-Agent-API/src/mcp-server.js"]
}
}
}
この場合、例と同様に、キーと台帳はクローンの隣にある runtime/ がデフォルトになります。
| 環境変数 | デフォルト | 用途 |
|---|---|---|
ZENDIQ_AGENT_URL | https://api.zendiq.ai | API のベース URL。デフォルトでは ZendIQ のライブサービスを使用します — 呼び出し先を参照してください |
ZENDIQ_AGENT_NETWORK | mainnet | 決済ネットワーク:mainnet または devnet。API の決済ネットワークと一致している必要があります。それ以外の値では、有料ツールは拒否します |
AGENT_STATE_DIR | ~/.zendiq(npm)、runtime/(クローン) | 支払い用キーと予算台帳の保存先 |
ZENDIQ_AGENT_BUDGET_FILE | <state dir>/budget-<network>.json | 各支払いの予約先となる予算台帳。mainnet では、これがない場合、有料呼び出しは拒否されます。予算上限が保証する内容を参照してください |
ZENDIQ_AGENT_KEYPAIR | — | devnet 専用。 USDC を保有する Solana キーペアの JSON です。x402 支払いの署名にのみ使用されます。mainnet では拒否されます |
mainnet では、支払い用キーは mainnet 用台帳と同時に読み込まれる場合に限り読み込まれます。
診断情報は stderr に出力されるため、stdout はクリーンな JSON-RPC トランスポートとして保たれます。トランスポートは stdio のみです。これは、すべてのクライアントがサポートする標準のローカル MCP トランスポートです。リモート/HTTP トランスポートは現在提供していません。
クライアントを使わずに接続を確認するには、手動で実行します。initialize、続けて tools/list を実行する際に、キーペアや支払いは不要です。
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | npx -y @zendiq/mcp@latest
PowerShell:
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}',
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | npx -y @zendiq/mcp@latest
自律エージェント
テストエージェントの完全版は examples/ で公開されています。DexScreener の Solana ブーストのライブフィードを監視し、候補ごとに情報を補完して、ZendIQ に支払って判定を取得し、取引を拒否、保護、または通常どおりルーティングするかを記録します。
npm run budget:init
npm run feed
npm run watch
watch は、何でも拒否するのではなくエージェントが候補を判別することを実行結果で確認できるよう、まず USDC を対照として使用します。その後、トリアージ費用、拒否された候補、保護された候補、直接ルーティング可能と判定された候補を含む実行台帳を出力します。
自律エージェントは助言のみを行います。推奨される経路と手数料を報告しますが、資金が移動したとは主張しません。実際の最適化されたスワップを構築して送信する方法については、以下の実行を参照してください。キーと予算台帳は、gitignore 対象の runtime/ ディレクトリに保存されます。
予算上限で保証されること
台帳(examples/budget.js)は、支払い用ウォレットが ZendIQ の呼び出しに使う金額に対する厳格な上限です。次の条件下でのみ、この上限が適用されます。
- 計上対象。
ZendIQClientを通じて行われるすべての x402 支払いです。サンプル、デモランナー、MCP サーバーはすべて、同じ支払い経路を共有しています。各支払いは署名の前に予約され、その後に結果が記録されます。課金された可能性がある処理結果は支出済みとして計上されるため、上限は過少計上ではなく過大計上になります。 - メインネットでは、支払い用キーが制限されています。
- キーは
loadAgentSignerだけが専用ファイルruntime/payer-mainnet.key.jsonから読み込み、メインネット用の台帳が紐付いている場合に限られます。台帳がなければエラーが発生します。 - CI 向けの上級者用オーバーライド:
AGENT_SECRET_SEEDには、支払い用キーを 32 バイトちょうどの JSON 配列(シード)として指定します。キーのファイルも存在し、異なるキーが含まれている場合は起動せず、両方のアドレスを表示します。 - 台帳には、その台帳に対して支払いを行う 1 つのキーが記録され、キーは 1 つの台帳に紐付けられます。
- スワップの対象となるウォレット(
--taker、ZENDIQ_TAKER_KEYPAIR)は別のキーであり、支払い用キーと同じ場合は拒否されます。
- キーは
- 複数のプロセスで 1 つの台帳を共有できます。 変更のたびにロックファイル(
<ledger>.lock、所有者の PID を記録)が取得され、ファイルが再読み込みされます。そのため、2 つのプロセスが同じ残予算を同時に予約することはできません。 - プロセスがクラッシュしても、台帳がロックされたままにはなりません。 ロック保持プロセスが処理中に強制終了された場合、次の支払い処理はその PID が存在しないことを確認し、すぐにロックを引き継ぎます。ロック保持プロセスがまだ動作中の場合、支払い処理は最大 5 秒待機した後、支払いを拒否します。エラーには PID とロックファイルが記載され、処理が永久に停止することはありません。30 秒を超えたロックは、いずれの場合も引き継がれます。手動で復旧する場合: この台帳を使っているすべてのエージェントを停止してから、
<ledger>.lockを削除してください。 - 確認できないもの:
- このコードの外で支払い用キーを使って署名されたもの。たとえば、キーのファイルを直接読み込むスクリプトなどです。
- 支払い用ウォレットへの資金移動と、その後の追加チャージ。
- ネットワーク手数料とトークンアカウントのレンタル料。支払いのネットワーク手数料はファシリテーターが負担するため、通常の利用では支払い用ウォレットから USDC のみが支出されます。
- 別のウォレットから行われるスワップ。スワップはテイカーが署名し、支払います。
「正確な照合」の意味。 1 つの支払い用アドレスについて、2 つの一覧を比較します。オンチェーンでそのアドレスから送金されたすべての USDC と、状態が settled のすべての台帳エントリを、トランザクション署名で照合します(エントリの note には、サーバーからの PAYMENT-RESPONSE に含まれる決済署名が格納されています)。このコードだけで使われたキーであれば、1 対 1 で一致します。唯一想定される例外は、unconfirmed_settlement_may_have_landed と記録された settled エントリです。台帳は除外できない支払いを計上するため、対応する送金がない場合があります。入金(資金の入金や追加チャージ)は台帳エントリではなく、比較対象にも含まれません。対応するエントリがない出金があれば、そのキーは台帳の外で使われています。
新しいキーの照合
- キーを生成して USDC を入金します。入金トランザクションの署名を記録してください。これは唯一想定される入金です。
- そのキー用の新しい台帳を作成します(
AGENT_NETWORK=mainnet node examples/budget.js init <ceilingUsd>)。エントリがすでにある台帳を新しいキーに使わないでください。履歴は別のキーに属しており、照合できなくなります。initは既存ファイルの上書きを拒否するため、古いファイルを先に別の場所へ移動してください。 - 支払いを伴う呼び出しは、このコードを通じてのみ行います。初回の読み込み時に、キーが台帳に紐付けられます(台帳の
payer、runtime/payer-bindings.json)。 - オンチェーンで、支払い用アドレスの USDC トークンアカウント履歴を一覧表示します。入金と追加チャージを除外してください。残った出金の署名は、台帳の
settledエントリに記録されたnoteの署名と一致し、金額は各エントリのatomic(USDC、小数点以下 6 桁)と一致する必要があります。
実行 — 署名可能なスワップを構築する(/optimize)
/analyse は助言を行います。/optimize はさらに一歩進み、未署名のスワップトランザクションを返します。会場、優先手数料、MEV 対策は同じリスクモデルと、会場間の純利益比較に基づいて選択されます。さらに、プラン、オンチェーンシミュレーション、純利益の計算内訳も返します。記載されたプランとバイト列が一致することを確認してから、ご自身のウォレットで署名して送信してください。ZendIQ が秘密鍵を保持することはありません。
npm run budget:init
# Stop at simulation — pays $0.02 USDC, prints the plan + simulation, signs nothing:
npm run optimize -- --taker <YOUR_MAINNET_PUBKEY>
# Real landing — signs the returned tx and submits it as the response's submit block directs:
export ZENDIQ_TAKER_KEYPAIR=/path/to/mainnet-keypair.json
npm run optimize -- --taker <YOUR_MAINNET_PUBKEY> --execute
PowerShell では、export の代わりに $env:ZENDIQ_TAKER_KEYPAIR = 'C:\path\to\mainnet-keypair.json' で鍵のパスを設定してください。
このスワップはメインネットで実行されるため、--taker には入力額と手数料およびレント用の SOL を保有するウォレットを指定する必要があります。x402 の支払いは、支払い元ウォレットから別途 USDC で送金されます。デフォルトでは、この例はシミュレーションで停止し、オンチェーンでは何も消費しません。実際のスワップに署名して確定するには、--execute(および ZENDIQ_TAKER_KEYPAIR)を指定してください。jupiter_ultra の場合、この例は Jupiter の /execute 経由で送信します。jupiter_swap の場合は SOLANA_RPC_URL 経由で送信し、デフォルトでは公開メインネット RPC を使用します。Jito バンドルの会場の場合は、署名済みトランザクションを ZendIQ の /v1/agent/bundle に送信し、確定するまでポーリングします。レスポンスには、未署名の transaction、plan、選択した会場での送信手順を示す submit、simulation の結果、netBenefit の内訳が含まれます。署名前に、トランザクションが記載された意図と一致することを確認するために必要な情報がすべてそろっています。
この例では、判定結果と会場の選択内容も出力されます。会場の選択内容には、すべての候補について、純価値、優先手数料、Jito チップ、モデル化されたサンドイッチ攻撃のコスト、バンドルの着地リスク、上回る必要があったマージン、そして勝者が選ばれた理由が記載されます。これはレスポンスの plan.venueDecision に含まれるため、エージェントは選択を鵜呑みにせず検証できます。--execute を指定した場合、シミュレーションに失敗したトレードに署名しないのと同様に、verdict が Refuse のトレードにも署名しません。これを上書きするには --sign-refused を指定してください。
デモビジュアライザー
1 回の実際のスワップトリアージ呼び出しを、2 つのトランスポート(MCP エージェントツールと直接の x402 HTTP レール)で並べて、ライブアニメーションシーケンスとして表示するローカルの観覧ビューです。その後、両方から返されたトークンリスクの証拠フィンガープリントが一致することを検証します。続いて同じスワップに対して /optimize を実行し、Optimize → Sign → Land の実行シーケンスを表示します。最後はオンチェーンシミュレーションで終了するか、--execute を指定した場合は実際にメインネットで着地します。画面上の値はすべて実際のものです。ライブのリスクスコア、実際の USDC 決済、実際のトランザクションが表示されます。演出によるものはありません。
前提条件
- Node.js 22.5+ がインストールされ、
npm ciがすでに実行されていること。 - クイックスタートの手順 1~2 で用意した、資金をチャージ済みの支払い鍵と予算台帳。ランナーは同じ
runtime/payer-mainnet.key.jsonとruntime/budget-mainnet.jsonを使用します。鍵は USDC の支払い承認への署名のみに使用され、マシンの外に出ることはありません(runtime/は gitignore の対象です)。**SOL は不要です。**ランナーがメインネットの台帳を自ら作成することはありません。 - ビジュアライザーとランナーはローカルで実行されますが、表示される呼び出しはホストされた API に送信されます。ランナーは
ZENDIQ_API_URLを読み込み、同じ URL を MCP レーンに渡すため、ここではZENDIQ_AGENT_URLは影響しません。
実行
1 つ目のターミナルでビジュアライザーを起動します。
npm run demo
http://127.0.0.1:4173 を開き、2 つ目のターミナルで次を実行します。
npm run demo:run -- --mint JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN --taker <YOUR_MAINNET_PUBKEY>
実際にオンチェーンで完了させるには、--execute を追加し、ZENDIQ_TAKER_KEYPAIR に --taker 用のメインネットキーペアを設定します。--execute を指定しない場合、実行レーンはシミュレーションで停止し、オンチェーンで資金を使用することはありません。
両方のレーンで、リクエスト → 402 → 署名済み USDC 承認 → 決済完了 → 分析結果の返却、という処理が進みます。フッターには共通のフィンガープリントとともに、検証済み · 同一のトークンリスク証拠 と表示されます。フィンガープリントは決定論的なトークンスクリーニング(ミント、スコア、レベル、シグナル、入力値)を対象とします。各レーンに表示されるライブのルート経済性(サンドイッチ攻撃への露出、価格インパクト)は呼び出しごとに再取得されるため、2 回の逐次リクエストの間に価格が変動すると、わずかにずれる場合があります。フィンガープリントが一致するとランナーは 0 で終了し、一致しない場合は 0 以外で終了します。イベントストリームには、意図的に支払い承認、シークレット、RPC URL、完全なウォレットアドレスを含めていません。
トラブルシューティング
Preflight failed/fetch failed— ランナーを動作させるには、Agent API とビジュアライザー(npm run demo)の両方を同時に起動しておく必要があります。まずビジュアライザーを起動し、そのまま実行しておいてください。Payment was rejected— 支払いウォレットのメインネット USDC 残高が不足しています。資金を補充し(クイックスタートの手順 2)、再実行してください。拒否された支払いが請求されることはありません。- UI が「エージェントの呼び出しを待機しています…」のまま — ページは受動的に動作し、
demo:runがイベントを出力したときにのみ表示が更新されます。ランナーにDemo completeと出力されたことを確認してください。
コントラクト
機械可読なコントラクトの完全版は openapi.json(OpenAPI 3.1)です。すべてのエンドポイント、リクエストボディ、レスポンス形式、エラーコード、実行例が記載されています。同じファイルは https://zendiq.ai/openapi.json で提供されています。現在の価格、レート制限、フィールドの安定性の区分については、API の GET /v1/agent が正式な情報源です。以下の概要では、多くのインテグレーションに必要な内容を説明します。
POST /v1/agent/analyse-token — 無料、レート制限あり(スクリーニング段階)
{ "mint": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN" }
取引サイズを指定せず、ミントによってトークンをスクリーニングします。トークンのリスクスコア、シグナルの内訳、signals_resolved によるカバレッジ、cache ブロック(hit、ageSeconds、observedAt)を返します。キャッシュされたスコアには、現在のスロットと時刻ではなく、そのスコアが計算されたスロットと時刻が示されます。支払いは不要で、IP ごとにレート制限されます。
POST /v1/agent/analyse — 有料(判断段階)
{
"inputMint": "So11111111111111111111111111111111111111112",
"outputMint": "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
"amount": "500000000",
"slippageBps": 100
}
安定したレスポンスフィールド:
verdict:Safe、Protect、またはRefuserecommendedExecution.pathrecommendedExecution.priorityFeeLamportsrecommendedExecution.jitoTipLamportsreasonsdisclaimer
追加のフィールドは試験的なものであり、v1 内で変更される可能性があります。安定したフィールドは v1 内では追加のみで、後方互換性を損なう変更は新しい API バージョンで提供されます。
POST /v1/agent/optimize
/analyse と同じリクエストボディに、taker の公開鍵を加えます。署名されていないスワップ用の transaction、plan(venue、スリッページ、優先手数料、venue の選択理由となる比較結果 venueDecision)、simulation の結果、netBenefit の内訳、/analyse と同じ verdict、confidence、reasons を返します。カストディは一切行いません。内容を確認し、署名して送信するのはお客様です。呼び出しごとに USDC で課金されます。
venue はリスクに基づいて選択されるため、決めつけずに plan.venue を確認してください。Jupiter Ultra は、低リスクの取引とサンドイッチ攻撃に起因するリスクに使用されます。この場合、上流の MEV 保護がリスクに対処する手段となります。優先手数料は Jupiter Ultra が自動的に設定します。リスクスコアに特定の優先手数料が必要と判断された場合は、Jupiter Swap API(Quote + Build)を使用します。Jupiter Ultra ではその手数料を適用できないためです。この場合、plan.priorityFee にはビルド結果から読み取った、実際に適用された手数料が示されます。また、このルートには上流の MEV 保護はありません。
直接取引所の見積もりはJupiterのルートと並行して取得され、優先手数料、Jitoチップ、予想されるサンドイッチ損失、バンドルの場合は着地リスク(再構築の費用が発生する確率を5%と仮定)を含むすべてのコストを差し引いた後でJupiterを上回る場合に限り、Jupiterのルートに置き換わります。取引額の0.1%(上限1ドル)の差が必要です。これにより、見積もりの誤差で取引所が入れ替わることを防ぎつつ、実際の節約があればそちらが選ばれます。保護なしのRaydiumが競合するのはSafe判定の場合のみです。Jitoバンドルの取引所(Raydium + Jito、Jupiter Swap + Jito)は、すべての判定で競合します。Safeの場合は、ZendIQが共有するJito送信枠が使用中であれば、保護された取引をそちらに回すため、候補から外れます。plan.venueDecisionには各候補の計算内容が表示されます。多くの場合、選ばれるのはJupiterです。
送信方法は取引所によって異なります。パスを固定せず、返されたsubmitオブジェクトに従ってください。jupiter_ultraの場合は、transactionに署名し、submit.urlに記載されたURL(現在はhttps://lite-api.jup.ag/ultra/v1/execute)に{ signedTransaction, requestId }をPOSTします。URLはレスポンスごとに取得してください。Ultraの注文は、それを発行したJupiterゲートウェイでのみ実行でき、ホストはapi.jup.ag/swap/v2に移行する予定です。サンプルクライアントはsubmit.urlに従い、既知のJupiter /executeエンドポイント以外のURLは拒否します。独自のRPC経由で送信すると、UltraのMEV保護が失われ、netBenefitの数値も無効になります。jupiter_swapとraydiumではrequestIdはなく(nullです)、/executeの手順もありません。署名して、優先手数料がすでに含まれているトランザクションを独自のRPCに送信します。raydiumのトランザクションは速やかに送信してください。Raydiumは独自のブロックハッシュを埋め込むため、submit.lastValidBlockHeightはnullです。Jitoバンドルの取引所(submit.method: "jito_bundle")では、署名したうえで{ "signedTransaction": "<base64>" }をこのAPIの/v1/agent/bundleにPOSTしてください(無料)。ZendIQがそのバイト列をそのままJitoに転送し、着地状況を報告します。バンドルのトランザクションをRPCに直接送信してはいけません。公開メンプールに入り、チップも支払うことになります。
netBenefit.netUsd = expectedMevLossUsd − zendiqFeeUsd − jitoTipUsd − jupiterPlatformFeeUsd − priorityFeeUsd:このルートによって回避できるサンドイッチ損失から、実行にかかるすべての手数料を差し引いた額です。MEV保護をうたうルート(Jupiter Ultraとバンドルの各取引所)でのみ表示されます。jupiterPlatformFeeUsdはUltraの取引にかかるJupiter独自の手数料(ペアにより0~50 bps、SOL–USDCでは2 bps)で、見積もり額にすでに含まれています。それ以外では0です。priorityFeeUsdはトランザクションからデコードした、テイカーが支払う額です。バンドルまたはガスレスの約定では0です。5,000ラムポートの基本署名手数料はすべてのルートで同じため、含まれていません。コストを価格換算できない場合、netUsdはnullとなり、その理由はnetUsdBasisに記載されます。
/optimizeは/analyseと同じverdict(Safe/Protect/Refuse)を返しますが、構築を拒否しません。Refuse判定でも、CRITICALのスコアが付いたトークンであっても、トランザクションが返されます。署名する前にverdictとtokenRiskを確認し、意図的に取引するのでない限り、Refuseには署名しないでください。
トークンスクリーニングが完了しない場合
すべてのエンドポイントに共通するルールがあります。ソースの応答が遅い場合や失敗した場合でも、呼び出し自体は失敗しません。そのチェックだけが、スコアリング済みの 200 レスポンス内で unknown となり、unknown は合格として扱われるのではなく、注意ポイントとして加算されます。正直な回答ができない場合に限り、呼び出しは 502 analysis_unavailable を返し、課金されません。これは、mintを確認できない場合の3つのエンドポイントすべて、スコアをまったく生成できない場合の /analyse-token、およびルートもスクリーニング結果も取得できない場合の /analyse で発生します。トランザクションを構築できない場合、/optimize は 502 optimize_unavailable を返し、同様に課金されません。
/analyse または /optimize でスクリーニング全体が完了しなくても、ルートを取得できていれば、呼び出しは引き続き 200 を返します。その場合、欠落は明示され、問題がないように見えるスコアが返ることはありません。
tokenRiskは{ mint, available: false, error, assumedScore: 50, assumedLevel: "HIGH", note }となり、scoreやlevelは含まれません。- 手数料と全体的なリスクは、トークンのスコアを0ではなく
HIGHとして計算されます。 /analyseはフェイルクローズ方式です。verdictはProtect、confidenceは"low"となり、degradedにtoken_screening:<reason>が含まれ、reasonsにはスクリーニングが完了しなかったことが記載されます。このようにしてProtectに達した場合、トークンはリスクがあると判明したのではなく、チェックされていないことを意味します。/optimizeは引き続きトランザクションを返します。例ではtoken risk UNAVAILABLEと表示され、署名する前に警告が出ますが、拒否はされません。エージェント側で拒否する必要がある場合は、tokenRisk.availableを自分で確認してください。
セキュリティ
キーペア、シード、.env、予算台帳、または認証情報を含むRPC URLは、決してコミットしないでください。このリポジトリでは、.githooks/pre-push による必須のプッシュ前シークレットスキャンを設定しています。プッシュする前に、gitleaks または trufflehog をインストールしてください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。