Reins について
Reinsは、Hyperliquidで取引するAIエージェント向けのMCPサーバーです。モデルの外部でリスク制限を適用し、取引判断を記録します。実価格を使ったペーパートレードで、実取引の前にテストできます。
主な機能
- 01モデル外でポジションとレバレッジを制限
- 02取引市場と日次損失を制限
- 03判断、拒否、取引所の約定を記録
- 04実価格を使ったペーパートレード
- 05Hyperliquidの実取引に対応
活用シーン
- 01ペーパーモードで取引エージェントをテスト
- 02上限超過の注文が取引所に届くのを防止
- 03エージェントの判断と取引結果を確認
MCP 対応
MCPクライアントに、リスク検査と記録を伴うHyperliquid取引ツールを提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @r2rlabs/reinsREINS_SYMBOLSMarkets the agent may trade, comma separated, e.g. BTC,ETH. Every other market is refused.REINS_MAX_POSITION_USDLargest position per market, in USD.REINS_DAILY_LOSS_USDRealised loss in a UTC day after which new risk is refused.REINS_MAX_LEVERAGELargest total exposure as a multiple of account value.REINS_MODEpaper (live prices, simulated fills, nothing signed) or live.REINS_NETWORKHyperliquid network for prices and, in live mode, orders. Mainnet spends real money.REINS_REQUIRE_STOP_LOSStrue to refuse any order that adds risk without a stop-loss.REINS_LOG_FILEDecision log, one JSON line per action with the agent's stated reason. In memory if unset.REINS_PAPER_FILEWhere the paper account is kept between runs. In memory if unset.REINS_ACCOUNT_ADDRESSLive mode: the Hyperliquid account traded. Approve Reins' 2 bp builder fee from it first: npx @r2rlabs/reins approve-builderREINS_PRIVATE_KEYシークレットLive mode: an API wallet's key, which can trade but not withdraw. Never the account's own key.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Reins
AI エージェントに、すべてを失う力を与えずに取引させましょう。
npx @r2rlabs/reins init # adds a paper-trading Reins server to .mcp.json
実際の動作はこちらをご覧ください:Hyperliquid でペーパートレードを行う AI エージェント、実行 2。
ソースは GitHub にあります:R2Rlabs/reins。この README に記載されているすべての上限は、 コードを読んで確認できます。
Reins とは
- エージェントが言い逃れできない制限。 すべての注文は、モデルの外部にあるチェックを通過します。ポジションサイズ、レバレッジ、1 日あたりの損失、取引可能な市場、すべてのポジションに対するストップロスが対象です。プロンプトや巧みな推論、ミスでこれらを回避することはできません。
- 確認できる記録。 エージェントが示した理由とともに、すべての判断が記録されます。拒否された注文や、待つことを選んだ時点、エージェント不在時に取引所が行ったことも含まれます。エージェントが 述べた ことと、実際に 起きた ことを比較できます。
- 練習できる場所。 ライブの Hyperliquid 価格を使ったペーパートレードで、現実的な約定と手数料を適用し、ライブ取引と同じツールと制限を利用できます。
- ノンカストディアル。 資金はご自身の Hyperliquid アカウントに保管されます。Reins は注文を出せますが出金はできない API ウォレットを通じて取引します。
- 料金は明示されています。 ライブ注文には少額のビルダー手数料(2 bp)がかかり、事前に表示されます。
Reins ではないもの
- 取引ボットでも、戦略でもありません。 Reins は何を取引するかを決めず、エージェントの利益を保証するものでもありません。デモ用エージェントは試運転用であり、製品ではありません。
- 取引所、ブローカー、カストディアンではありません。 資金を預からず、注文をマッチングしません。それを行うのは Hyperliquid です。
- 損失を防ぐ保証ではありません。 制限によって、問題が起きた場合の損失額を抑えます。悪い取引が良い取引になるわけではなく、相場の変動が激しいときはストップ価格を超えて約定することがあります。
- 金融アドバイスではありません。
- 信頼を前提とするものではありません。 エージェントの言葉も、私たちの言葉も信じる必要はありません。すべての動作が記録されています。
原則
- 制限はモデルの外部に置く。
- 記録は推論より優先される。
- 実資金を使う前にペーパートレードを行う。
- 自分の鍵、自分の資金。
これが存在する理由
オープンソースの Hyperliquid MCP サーバーはすでにいくつか存在します。これらは薄い API ラッパーで、秘密鍵を渡し、モデルが適切に動作することを願うだけです。欠けているのは、その周辺にあるすべてのもの、つまり制限、サンドボックス、監査証跡です。このリポジトリは、そのためのものです。
ステータス
まだ初期段階ですが、実際に動作します。テストは391件あり、いずれもネットワーク呼び出しはありません。
| モジュール | 説明 |
|---|---|
src/risk.ts | リスクエンジン — ポジション上限、取引ごとのリスク、レバレッジ上限、日次損失による停止、許可リスト、レート制限 |
src/client.ts | Hyperliquid REST クライアント — 注文、キャンセル、板、ローソク足、約定、アカウント状態、ビルダーコード |
src/mcp-server.ts | エージェント向けのツール。何かを送信する前に、それぞれリスクチェックを行い、ログに記録します |
src/paper.ts | ペーパートレード — ライブ価格とシミュレートされた約定。以下を参照 |
src/paper-store.ts | 再起動後もペーパートレードの実行状態を保持します |
src/trading-client.ts | ライブとペーパーの両方が実装するインターフェース |
src/decision-log.ts | すべての試行と、その理由として示された内容を記録する追記専用の記録 |
src/decision-log-file.ts | ディスク上の JSON Lines ログ |
src/bin/cli.ts | reins コマンド:serve(デフォルト)、init、approve-builder、live-check、http、stats |
src/bin/serve.ts | stdio エントリーポイント |
src/bin/http.ts | reins http — HTTP サーバー:トークン、バインド、JSON |
src/http-api.ts | MCP を話さないボット向けに、同じ9つのツールを HTTP ルートとして提供します |
src/runtime.ts | 2つのエントリーポイントで共有する制限、クライアント、ログ、バナー |
src/init.ts | reins init — .mcp.json にペーパーモードのサーバーエントリーを書き込みます |
src/builder-fee.ts | Reins のビルダー手数料と、ライブ取引の開始前に必要な承認 |
src/approve-builder.ts | reins approve-builder — ユーザーが自身のウォレットでビルダー手数料を承認します |
src/live-check.ts | reins live-check — Reins が送信する内容をライブ取引所が受け付けることを確認します |
src/platform-stats.ts | reins stats — Reins のビルダーコードを通じたアカウント、取引、取引高、手数料 |
src/lz4.ts | Hyperliquid の LZ4 圧縮データファイルを、依存関係なしで読み込みます |
src/builder-approval.ts | ApproveBuilderFee アクション:EIP-712 型付きデータ、署名チェック |
src/format.ts | Hyperliquid のティックとロットのルールに合わせた価格と数量のフォーマット |
src/signing.ts | L1 アクションの署名。Python SDK のベクトルと照合済み |
src/private-key-signer.ts | 秘密鍵を使用する Signer |
src/signer.ts | Signer インターフェースとスタブ。「署名について」を参照 |
src/mock-transport.ts | ネットワークなしでエージェントをテストできる、メモリ内の API 代替実装 |
examples/demo-agent/ | Reins 経由でペーパートレードを行う Claude。公開可能な意思決定ログを生成します |
すべてエンドツーエンドで動作します。ライブ取引を開始するには、アカウントに資金を入金し、キーを設定して REINS_MODE=live にするだけです。
ライブ運用を開始する
REINS_MODE=live
REINS_NETWORK=testnet # mainnet spends real money
REINS_ACCOUNT_ADDRESS=0x... # your Hyperliquid account
REINS_PRIVATE_KEY=0x... # an API wallet's key, not your account's; omit to stay read-only
メインネットでは、最初のライブセッションを開始する前に、アカウント自身のウォレットからReinsの2 bpのビルダーフィーを一度だけ承認してください:npx @r2rlabs/reins approve-builder。承認されていない場合、ライブモードは起動を拒否し、その理由を表示します。
アカウント自身のキーではなく、APIウォレットを使用してください。 Hyperliquidでは、アカウントに代わって取引できますが、アカウントから出金することはできないAPIウォレットを承認できます。HyperliquidのAPIページで作成し、メインウォレットで承認に署名してください。そのキーをREINS_PRIVATE_KEYに、アカウントのアドレスをREINS_ACCOUNT_ADDRESSに設定します。注文はAPIウォレットで署名されますが、ポジション、約定、ストップはアカウントから読み取られます。APIウォレット自身のアドレスから見ると、アカウントには何もないように見えるためです。起動時のバナーには両方のアドレスが表示されます。Hyperliquidは期限切れまたは置き換えられたAPIウォレットを削除するため、古いアドレスを再利用せず、新しいウォレットを作成してください。
どのアカウントモードでも動作します。Hyperliquidでは、新しいアカウントはUnifiedで始まります。このモードではUSDCはスポット残高にあり、パーペチュアルアカウントは0ドルと表示されます。Reinsはアカウントにモードを問い合わせ、Unifiedおよびポートフォリオマージンでは、USDC残高とポジションの未実現損益からエクイティを取得します。Manualアカウントでは、これまでどおりパーペチュアルから読み取ります。(ビルダーアドレスは別で、手数料を得るにはManual(standard)である必要があります。)
デフォルトは意図的に安全に設定されています。REINS_MODEはpaper、REINS_NETWORKはtestnetであるため、実資金を取引するには、変更し忘れた変数が原因で誤って開始するのではなく、明示的に2つの変更が必要です。キーを設定せずにライブモードを使った場合、最初の注文で失敗するのではなく、読み取り専用のまま動作します。また、メインネットでは起動時に目立つバナーが表示されます。
秘密鍵はライブモードでのみ読み込まれます。paperモードでは署名を一切行わないため、署名に必要な手段が渡されることはありません。
実行の様子を見る
npm run build
npm run demo -- --scripted # free: no API key, live prices, paper fills
Anthropic APIキーがあれば、npm run demoでClaudeをエージェントとして実行し、厳格な支出上限を適用できます。費用、制限、および結果を誠実に公開する方法については、examples/demo-agentを参照してください。
判断ログ
エージェントが示した理由とともに、試みたすべてのアクションがログに追記されます。**リスク制限に拒否されたアクションも含まれます。**これが重要な点です。「エージェントは午前3時にポジション上限の6倍の注文を試み、その理由としてこう説明した」という情報は、このシステムが伝えられる中で最も役立つものです。そして、拒否が記録されていなければ、その情報は存在しません。
place_order、close_position、set_stop_lossには、必須のreasonが必要です。任意のフィールドは省略されますが、必須のフィールドには値が入力されます。
記録はJSON Lines形式です。1行につき自己完結したオブジェクトが1つ追加され、書き換えられることはありません。ファイルが大きくなっても追記のコストは低く、書き込みが途中で切れてもファイル全体ではなく1行だけが損傷します。また、通常のツールで照会できます:
jq -r 'select(.risk.allowed == false) | [.time, .risk.code, .reason] | @tsv' decisions.jsonl
各記録には、提示された理由、リクエスト、実行時のアカウントコンテキスト、リスク判定、結果が含まれます。REINS_LOG_FILEを設定すると、ログが保存されます。設定しない場合、ログはメモリ上に保持され、プロセスの終了とともに失われます。
取引所も独自に動作します。ストップロスが発動したり、発注から数時間後に指値注文が約定したりします。すべてのツール呼び出しの前に、Reinsはアカウントの約定とログを照合し、まだ記録されていない約定をそれぞれexchange_fillレコードとして追記します。その理由は「Not an agent decision:」で始まり、それがストップ、指値注文、またはReinsが発注していない約定のいずれかを示します。これらがなければ、最も重要な取引、つまりそれを終了させたストップが記録から抜け落ちてしまいます。エージェントは、他の記録と同じようにget_recent_decisionsを通じてそれらを読み取ります。
明確にしておくべき2つのこと
reasonは証言であり、確かな事実ではありません。 これはモデル自身が、なぜそのように行動したかを説明したもので、求めなければ後から取得できない推論を記録しています。モデルは事後に理屈をつけることがあり、自信に満ちた説明だからといって、その説明が実際に判断を左右した証拠にはなりません。デバッグや監査には非常に役立ちますが、証明にはなりません。
ログの書き込みに失敗しても、約定済みの注文が失敗扱いになることはありません。 ログを書き込めない場合でも、ツールは成功を報告し、警告を付けます。注文が失敗したと伝えられたエージェントは再度注文を出します。そのため、ログの1行が失われるとポジションが二重になり、ログの欠落よりはるかに深刻な事態になります。安全機構はリスクエンジンであり、ログは可観測性のためのものです。
ペーパートレード
REINS_MODE=paper(デフォルト)では、実際の価格を使い、約定をシミュレートして、同じツール、同じリスクエンジン、同じエージェントを実行します。署名は行われず、取引所にも何も送信されません。
ペーパーとライブは単一のインターフェースの背後で切り替わるため、エージェントはどちらと通信しているかを判別できません。これが狙いです。ペーパーで動作する戦略は、ライブでも変更なしで動作します。
シミュレーションでモデル化するもの
- 実際の板の厚み。 大きな注文は複数の価格水準を順に消化し、最良気配値ですべて約定するのではなく、実際のスリッページが発生します。
- 指値価格の範囲内で板が薄すぎる場合の部分約定。
- Hyperliquidの基本手数料階層でのテイカー手数料とメイカー手数料(0.045% / 0.015%)に加え、ビルダー手数料があればそれも反映し、実際の取引コストを差し引いた資産曲線を表示します。
- 市場価格が注文価格を明確に通過した場合にのみ約定する、板に残った注文。注文価格と同じ価格では、シミュレーションでは把握できないキューの後ろに並びます。そこで約定すると仮定するのは、ペーパーの資産曲線が実態と異なる最も一般的な原因です。
- ポーリング間の約定。 呼び出しごとに、板のその時点での状態だけでなく、注文を出してから形成された1分足を使って、板に残った注文を確認し、市場価格が初めて注文価格を通過した分足で約定させます。すでに約定した注文のキャンセルは、取引所と同様に拒否されます。この変更以前は、デモエージェントのブレイクアウト買い指値注文が2分間続いた下落中に約定せず、その後、Hyperliquidならすでに約定していた注文をキャンセルしていました。
シミュレーションでモデル化しないもの
最初の5項目は結果を良く見せ、最後の2項目は約定を見逃す場合があります。すべてを埋もれさせずに記載しています。
- レイテンシ — 約定価格はツール呼び出し時点の板に基づきます
- マーケットインパクト — 注文によって価格が動いたり、流動性がなくなったりすることはありません
- 無期限先物のファンディング支払い
- すでに過ぎた1分足の中でのストップ価格超過によるスリッページ — 過去のローソク足で発動が判明したストップは、トリガー価格、または市場価格が窓を開けて通過した場合はそのローソク足の始値で約定します。現在発動したストップは、実際の板を順に消化します。
- マーク価格 — Hyperliquidはマーク価格でストップを発動しますが、ペーパーでは取引価格を使うため、一時的に異なる場合があります
- 注文を出した分足 — ローソク足は、注文後に始まった最初の分からのみカウントされるため、同じ分の下落は見逃されます
- 約3日を超えて板に残る注文 — 利用できる1分足は最新の5000本のみのため、それより古い期間は確認されません
ペーパーの資産曲線は、ライブの成績予測ではなく、ライブ成績の上限として扱ってください。
ペーパー口座の実行
{
"env": {
"REINS_MODE": "paper",
"REINS_PAPER_BALANCE": "10000",
"REINS_PAPER_FILE": "./paper-run.json"
}
}
REINS_PAPER_FILEを設定しない場合、口座はメモリ上に保持され、再起動時に失われます。1セッションを超えて実行する場合は設定してください。書き込みは一時ファイルに対して行われ、その後、所定の場所に名前を変更して配置されるため、クラッシュしても実行データが中途半端な状態で残ることはありません。
MCP サーバー
9 つのツールがあります。資金を動かせるすべてのツールは、まずリスクエンジンを通過し、すべての試行が判断ログに記録されます。
| ツール | 説明 |
|---|---|
get_limits | 制限、シンボルごとの余力、残り損失予算、停止状態 |
get_positions | シンボルごとの符号付き想定元本、口座価値、本日の実現損益、ストップロス、およびストップロスが設定されていないポジション |
get_book | 最良買い気配値/売り気配値、スプレッド、直近の価格水準 |
get_candles | 1 分足から 1 日足までの価格履歴、1 本あたりの平均値幅、最新のローソク足がまだ形成中かどうか |
place_order | 資産単位ではなく USD 建てです。制限と同じ単位です。すぐに約定する注文には任意で stopLoss を設定できます |
set_stop_loss | ポジション全体にストップを設定するか、ストップを変更します。取引所が保持します |
cancel_order | 取引所の注文 ID で指定します。ストップ注文も対象です |
close_position | リデュースオンリーでスプレッドをまたぎます。停止中でも機能します |
get_recent_decisions | 再起動後に、エージェント自身の直近の操作と理由を取得します |
ブロックされた注文は、具体的な理由を示すツールの エラー として返されます(BLOCKED (POSITION_TOO_LARGE): Would put BTC at $61,400, over the $25,000 cap)。これにより、エージェントは同じ拒否された注文を再試行せずに修正できます。制限を変更するツールは意図的に用意していません。
注文が真の成行注文になることはありません。価格を指定せずに place_order を実行すると、少量のバッファを加えてスプレッドをまたぐ、成行性のある指値注文になります。そのため、板が薄くても、エージェントが上限のない価格で約定することはありません。
ストップロス
「2,630 を下回ったら手仕舞います」と言うエージェントの有効性は、次に起動するまでに限られます。ストップロスを設定すると、その注文を 取引所が保持し、執行する ため、エージェントが休止中でも、価格が設定値に達した時点でポジション全体を決済するリデュースオンリーのストップ成行注文になります。
set_stop_lossは、現在のポジション全体を対象とするストップを設定し、そのシンボルに設定済みのストップを置き換えます。新しいストップを設定してから古いストップを解除するため、その間にポジションが無防備になることはありません。相場の反対側にあるトリガーは即座に発動してしまうため、設定を拒否します。place_orderのstopLossを使うと、同じ呼び出しでエントリーを保護できます。注文がすぐに約定した場合は、その直後にポジション全体を対象とするストップが設定されます。ストップの設定に失敗しても約定は有効のままで、ポジションが保護されていないことをエージェントに明確に伝えます。未約定の注文にはストップが付随し、約定するたびに取引所がその注文分のストップを設定します。そのため、安いメイカー手数料で板に置いておいたエントリー注文も、約定後に無防備になることはありません。close_positionはポジションとともにストップも解除します。REINS_REQUIRE_STOP_LOSS=trueにすると、単なる推奨ではなく必須になります。リスクエンジンは、専用のstopLossなしにリスクを増やす注文と、ポジション全体をカバーするストップがない状態でリスクを増やす注文(NO_STOP_LOSS)を拒否します。リスクを減らす注文がブロックされることはありません。
通信上、単独のストップ注文は、Hyperliquid の Python SDK が tpsl テストベクターで署名するトリガー注文です。signing.test.ts は、両方のネットワークでそのテストベクターをバイト単位で再現します。未約定注文とそのストップは、SDK の basic_tpsl の例と同様に、normalTpsl グループにまとめて送信されます。ストップの最悪約定価格はトリガー価格を 5% 超える値です。これは SDK 独自のデフォルトスリッページです。約定を拒むストップでは何も保護できないためです。ペーパーモードでは、未約定注文と同じ 1 分足のローソク足からストップが発動し、市場が到達した順に処理されます。過去のローソク足内で約定した注文に付随するストップも、同じ分の値動きを対象にします。ローソク足だけではどちらが先だったか判断できないためです。両方の種類の注文とストップの変更は、2026-09-21 に、資金を入金したアカウントから live-check --trade を実行し、メインネットで受け付けられました。
実行方法
npx @r2rlabs/reins init # from a clone: npm run build && node dist/bin/cli.js init
init は、以下の制限を設定した paper-mode の reins サーバーを ./.mcp.json に追加します(既存の他のサーバーは保持されます)。最大ポジションは $5,000、1日の損失上限は $500、対象は BTC と ETH で、判断ログとペーパー口座には絶対パスを指定します。フラグ(--symbols SOL,BTC --max-position 2500)で変更したり、--file で別の場所に書き込んだり、代わりに --print でエントリーを表示したりできます。ライブモードやキーを書き込むことはなく、--force を指定しない限り、既存の reins エントリーの置き換えを拒否します。すべてのオプションは reins init --help に記載されています。
Reins は ライブのメインネット注文に 2 bp のビルダーフィーを課金します。料金は src/builder-fee.ts の REINS_BUILDER_ADDRESS に支払われます。init の実行時にその旨が表示され、ペーパーモードの結果にも手数料が含まれるため、ライブ取引時のコストと一致します。ライブ取引を開始する前に、口座から一度だけ自身のウォレットで手数料を承認してください(npx @r2rlabs/reins approve-builder)。承認が済むまで、サーバーはライブモードでの起動を拒否し、承認方法を案内します。テストネットの注文には手数料がかかりません。
ボットを接続する(HTTP)
MCP に対応していないボットでも、HTTP リクエストを送信できるものであれば、Python、Go、Rust など、同じ制限と同じ判断ログを利用できます。
npx @r2rlabs/reins http --port 8787 # prints a token; paper by default
curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8787/limits
curl -H "Authorization: Bearer $TOKEN" -H "content-type: application/json" \
-d '{"symbol":"ETH","side":"buy","sizeUsd":1000,"stopLoss":2620,"reason":"Breakout retest"}' \
http://127.0.0.1:8787/orders
| ルート | 内容 |
|---|---|
GET /health | ペーパーかライブか、および各ルートを表示します。トークンが不要なのはこのルートだけです |
GET /limits | 制限、余力、および1日の損失により取引が停止されているかを表示します |
GET /positions | エクスポージャー、口座価値、ストップ、保護されていないポジションを表示します |
GET /book?symbol=ETH&depth=5 | 板の最良気配 |
GET /candles?symbol=ETH&interval=1h&count=24 | 平均レンジを含む価格履歴 |
GET /decisions?limit=10 | ログを新しい順に取得します |
POST /orders | 注文を出します。エージェントの場合と同様、reason が必須です |
POST /stops | ストップを設定または変更します |
POST /cancel | ID を指定して未約定注文をキャンセルします |
POST /close | ポジションを決済します |
すべてのルートで MCP ツールと同じリスクエンジンが動作し、同じ記録が書き込まれます。そのため、拒否された注文は、拒否の原因となった制限とともに 400 で返されます。
BLOCKED (TRADE_RISK_TOO_LARGE): Stopping out would lose $50.99, over the $30 allowed on one trade.
これは取引エンドポイントです。 --host で別途指定しない限り 127.0.0.1 にバインドされ、/health 以外のすべてのルートでベアラートークンが必要です。自分のマシンの外部に公開する場合は、自分でトークンを選び、TLS を前段に配置してください。
Python から利用する
Hyperliquid のボットの大半は Python で作られているため、コード例ではなくクライアントを用意しています。
pip install reins-client
from reins import Reins, Refused
reins = Reins.from_env() # REINS_URL, REINS_HTTP_TOKEN
book = reins.book("BTC")
entry, stop = book["bestAsk"], book["bestBid"] * 0.99
try:
reins.place_order(
symbol="BTC",
side="buy",
size_usd=Reins.size_for_risk(entry, stop, risk_usd=25),
price=entry,
stop_loss=stop,
reason="range low held on the hourly",
)
except Refused as refusal:
print(refusal.code, refusal.reason) # e.g. TRADE_RISK_TOO_LARGE
拒否はコードのエラーではなく、Reins が正常に機能している証拠です。そのため、コードとともに Refused として返され、ボットはそれに応じた分岐処理を行えます。
size_for_risk() はリスクエンジンが確認する計算と同じなので、注文が拒否されないよう、1取引あたりの制限内に収まるサイズを算出できます。依存関係はありません。clients/python は標準ライブラリだけを使う単一ファイルで、パッケージを追加したくない場合はベンダーとして取り込めます。
クライアントを使わずに実行する場合は、通常の Python だけで書かれた40行の例をご覧ください。
examples/bot.py。
実際の取引所での確認
ユニットテストでは、Reins が Hyperliquid 独自の SDK と同じ署名を行うことを確認できます。しかし、Hyperliquid がその署名を受け入れることまでは確認できません。reins live-check は実際のアカウントで確認します。
REINS_ACCOUNT_ADDRESS=0x… npx @r2rlabs/reins live-check # reads only, free
REINS_ACCOUNT_ADDRESS=0x… REINS_PRIVATE_KEY=0x… \
npx @r2rlabs/reins live-check --trade --size-usd 12 # a few cents in fees
読み取りでは、アカウント、市場、未決済注文、そしてアカウントが Reins のビルダーフィーを承認済みかどうかを確認します。--trade を指定すると、取引所で許可される最小ポジションを使って注文の全手順を実行します。ストップ注文を付けたポストオンリー注文、キャンセル、成行エントリー、ストップ注文の発注と変更、ポジションの決済、未決済の注文が残っていないかの確認を行います。Reins の想定と異なる応答があった時点で停止し、実際の応答を表示するため、何が起きたのか推測せずに失敗した手順を特定できます。テストサイズは最大 $100 に制限され、注文はチェックの実行中に約定しないよう、現在価格から 3% 離れた位置に置かれます。ポジションが開いている間にアカウント価値も再読み取りするため、アカウントのモードに応じたエクイティの読み取りミスも検出できます。Manual アカウントと Unified アカウントの両方で、メインネット上の全 12 ステップに合格しています。
使い方
npx @r2rlabs/reins stats # the last 30 days
npx @r2rlabs/reins stats --days 365 --json
Hyperliquid は、ビルダーコードを付けて行われたすべての約定を、UTC の日付が変わった後に日次ファイルで公開します。stats は Reins のビルダーアドレスのファイルを読み取り、アカウント数(および日ごとの新規アカウント数)、取引数、取引高、獲得手数料、メイカー約定、発動したストップ、最も取引が活発な市場を報告します。また、Hyperliquid がビルダーに付与した手数料の合計も表示します。この値はファイルではなく API から取得するため、遅れることはありません。日次ファイルは、その日の終了から 1 日以上経ってから届く場合があります。Reins 自体は外部に何も送信しないため、これはメインネットでの実取引のみを対象とします。ペーパートレードの記録は残りません。
手数料の承認
npx @r2rlabs/reins approve-builder # from a clone: node dist/bin/cli.js approve-builder
npx @r2rlabs/reins approve-builder --check 0x… # what a wallet has approved
承認にはユーザーのメインウォレットによる署名が必要なため、Reins がそのキーを求めることはありません。approve-builder はランダムなパスの下で 127.0.0.1 にページを表示し、ユーザーはブラウザーウォレット(MetaMask など)でそこで EIP-712 承認に署名します。Reins に返されるのは署名だけです。Reins は、署名に Reins のビルダー、要求されたレートとネットワーク、新しい nonce が含まれていること、さらに署名者として示されたウォレットに署名が復元されることを確認します。その後、Hyperliquid に送信し、maxBuilderFee で承認内容を読み取って確認します。署名にガス代はかかりません。--max-fee はデフォルトの 2 bp より高い上限を承認します。--network testnet は testnet で承認します。
署名は Hyperliquid 自体で確認済みです。使い捨てキーの承認を testnet に送信したところ、入金がなかったことだけを理由に拒否され、エラーには使い捨てアドレスが正確に示されました。これは、ブラウザーウォレットと同様に Arbitrum のチェーン ID で署名した場合も含め、署名が正しく復元されたことを示しています。
または、MCP クライアントから手動で接続します。
{
"mcpServers": {
"reins": {
"command": "node",
"args": ["/absolute/path/to/hyperliquid-agent/dist/bin/serve.js"],
"env": {
"REINS_NETWORK": "testnet",
"REINS_SYMBOLS": "BTC,ETH",
"REINS_MAX_POSITION_USD": "5000",
"REINS_DAILY_LOSS_USD": "500",
"REINS_MAX_LEVERAGE": "3",
"REINS_MAX_ORDERS_PER_MIN": "12",
"REINS_LOG_FILE": "./decisions.jsonl"
}
}
}
}
REINS_SYMBOLS、REINS_MAX_POSITION_USD、REINS_DAILY_LOSS_USD は必須です。「資金をどれだけ失ってもよいか」にデフォルト値はありません。
署名者を接続するまでは、サーバーは読み取り専用で動作します。読み取りはできますが、取引を行うとエラーになります。起動時に stderr にその旨が表示されます。
署名について
L1 アクションは msgpack でハッシュ化され、「phantom agent」に格納された後、EIP-712 で署名されます。 Hyperliquid のドキュメントでは、これを手作業で実装しないよう警告していますが、その警告はもっともです。msgpack はマップキーの順序を保持するため、キーの順序もハッシュの一部です。 アクション内の 2 つのフィールドの順序を入れ替えると、署名は黙って無効になり、拒否理由にも順序が原因だとは示されません。
src/signing.ts は、鍵の情報を一切保持しない純粋関数の集合としてこの方式を実装しており、そのため検証が可能です。src/signing.test.ts では、Python SDK 自身の signing_test.py で公開されているテストベクトルを使って検証しています。メインネットとテストネットの両方で、鍵、アクション、nonce が同一であり、r、s、v もバイト単位で一致します。これは「ある順序で一度成功した」よりも強い保証です。
間違いやすい点はすべてテストでカバーされています。
- msgpack のキーの順序はハッシュの一部です。2 つのキーを入れ替えるとハッシュが変わることを確認するテストがあります
- nonce は、パックされたアクションの末尾に追加される 8 バイトのビッグエンディアン値です
- ボールトアドレスがある場合は
0x01マーカーと 20 バイトが追加され、ない場合は0x00が追加されます - メインネットでは
sourceは"a"、テストネットでは"b"です。誤った値でも問題なく署名できますが、もう一方のネットワークでは拒否されます - EIP-712 ドメインは、取引対象にかかわらず、chainId 1337 とゼロの検証コントラクトで固定されています
r と s は、先頭のゼロを除いた最小限の 16 進数として出力され、Python SDK と完全に一致します。これはエンドツーエンドで確認済みです。署名済み注文をテストネットに送信したところ、価格帯ルールに基づいて拒否されました。これは注文の検証であり、認証がすでに通過した後にのみ実行されます。
PrivateKeySigner はインスタンスに鍵を保存せず、toJSON をオーバーライドするため、署名権限がログ行や意思決定記録に漏れることはありません。
使用方法
import { HyperliquidClient, RiskEngine } from "./src/index.js";
const client = new HyperliquidClient({
network: "testnet",
signer,
builder: { address: "0xYOUR_BUILDER_ADDRESS", feeTenthsBps: 10 }, // 1 bp
});
const engine = new RiskEngine({
maxPositionUsd: 25_000,
maxLeverage: 5,
dailyLossLimitUsd: 2_500,
symbolAllowlist: ["BTC", "ETH"],
maxOrdersPerMinute: 12,
});
const snapshot = await client.positionSnapshot();
const state = { ...snapshot, realizedPnlTodayUsd: todaysPnl };
const decision = engine.check({ symbol: "BTC", side: "buy", sizeUsd: 18_400 }, state);
if (!decision.allowed) throw new Error(decision.reason);
const outcome = await client.placeOrder({
symbol: "BTC",
side: "buy",
size: 0.18,
price: 102_000,
});
engine.recordOrder();
signer を指定せずに構築すると、クライアントは読み取り専用になります。マーケットデータは利用できますが、placeOrder は例外をスローします。
開発
npm install
npm test
設計
製品画面は design/ にあり、プロジェクトのノートにリンクされている Artifact 上でキャンバスとして表示されます。
Hyperliquid のドキュメントで確認済みのビルダーコードに関する事実
| 手数料上限、無期限先物 | 約定額の 0.1% |
| 手数料上限、現物 | 約定額の 1% |
| 手数料単位 | ベーシスポイントの 10 分の 1 — f: 10 は 1 bp |
| ビルダーの要件 | 無期限先物口座の価値が 100 USDC 以上、standard アカウント抽象化 |
| ユーザーの承認 | ApproveBuilderFee。API ウォレットではなく、ユーザーのメインウォレットで署名します |
| ユーザーごとの承認数 | 一度に有効にできるのは 10 件 |
| 適用範囲 | 無期限先物は買い側と売り側の両方、現物は売り側のみ |
| 報酬の受け取り | 通常の紹介報酬プロセスを通じて請求します |
安全に関する注意事項
- エージェントには、制約を確認できる
get_limitsツールが提供されます。制約を変更できるツールは提供されません。 - 取引停止中も、reduce-only 注文は有効です。リスクを閉じることは常に許可されますが、リスクを開くことは許可されません。
- 秘密鍵がない場合、サーバーは読み取り専用で動作します。マーケットデータは利用できますが、取引はできません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。