Bankr stock-token lane
developerDeveloper reference for the Bankr trading lane: intent schema, canonical registry, command packs, the gated submit path, and receipt reconciliation.
Module + API surface
@hiss/core ships the lane under bankr-stock-tokens/: intent types and validation, a canonical-registry loader (15 tokenized stocks/ETFs plus USDG/WETH, all derived from the source-verified registry), three-surface command packs, and proof-only receipts. The web API mirrors it under /api/stocks/*:
GET /api/stocks/registry— the canonical table, public-safe.GET /api/stocks/bankr-status— honest lane status; submit availability is env-dependent and reported as booleans.POST /api/stocks/prepare-bankr-command— intent in, validated plan + command pack out. Never contacts Bankr.POST /api/stocks/submit-bankr-intent— the gated Agent API relay (below).GET /api/stocks/bankr-job/[jobId]— poll a Bankr job, mapped to honest receipt states.POST /api/stocks/reconcile-receipt— proof-derived receipts from a txHash (chain 4663 RPC) and/or a jobId.
Intent schema
POST /api/stocks/prepare-bankr-command
{
"intent": {
"mode": "personal_bankr_trade",
"side": "buy",
"targetSymbol": "NVDA",
"targetTokenAddress": "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
"inputAsset": "USDG",
"inputAmount": "100",
"maxSlippageBps": 100,
"maxNotionalUsd": 500,
"userAcknowledgedTokenizedExposureNotDirectStockOwnership": true,
"userAcknowledgedBankrExecutesTrade": true
}
}Validation rejects (never clamps): non-canonical addresses, ticker-only intents, commands without on robinhood, missing explicit venue on vault_operator_rebalance intents, slippage above 500 bps, notional above the cap, wrong chain, and missing acknowledgments. hissExecutesTrade and hissCollectsLocation are hard-typed false; requiresBankrLocationVerification is hard-typed true.
Command pack
{
"social": "@bankrbot buy $100 of NVDA on robinhood",
"cli": "bankr --ni \"buy $100 of NVDA on robinhood\"",
"agentApi": {
"method": "POST",
"url": "https://api.bankr.bot/agent/prompt",
"authHeaderName": "X-API-Key",
"apiKeyEnvVar": "BANKR_API_KEY",
"body": { "prompt": "buy $100 of NVDA on robinhood" },
"pollUrlTemplate": "https://api.bankr.bot/agent/job/{jobId}"
},
"chainId": 4663,
"canonical": {
"targetSymbol": "NVDA",
"targetTokenAddress": "0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC",
"usdgAddress": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168"
}
}The gated submit path
POST /api/stocks/submit-bankr-intent is the only route that hands a trade to Bankr, and it opens only when every gate passes:
BANKR_AGENT_API_ENABLED=trueandBANKR_API_KEYpresent — otherwise an honest503 LANE_NOT_ENABLED, never a fake acceptance;userConfirmedPlanHashmust equal the plan hash recomputed from the intent (pass prepare’sgeneratedAtback asnowIso) — mismatch is a 409;- notional revalidates against
BANKR_STOCK_TRADE_MAX_NOTIONAL_USD(default $500); vault_operator_rebalanceis refused outright (403) — vault rebalancing has its own separately gated flow.
Success returns a jobId and receiptStatus: "job_pending". A jobId is not a fill. Bankr errors that indicate its console verification surface as BANKR_EXTERNAL_VERIFICATION_REQUIRED — Bankr’s requirement, not a HISS gate.
Receipt reconciliation
POST /api/stocks/reconcile-receipt
{ "txHash": "0x…", "jobId": "job-…", "planHash": "…" }
# → receipt.status from proof only:
# onchain_confirmed — tx receipt on chain 4663, status 0x1
# onchain_reverted — tx receipt on chain 4663, status 0x0
# job_* — Bankr job status (completed → job_completed_unconfirmed)
# prepared — no proof obtainedThe reconciler verifies the RPC endpoint serves chain 4663 (eth_chainId) before trusting eth_getTransactionReceipt. RPC resolution is server-only and env-named (ROBINHOOD_CHAIN_RPC_URL); URLs never appear in responses.
User-facing walkthrough: stock-token trading via Bankr. The asset universe: tokenized assets.