perp-cli 0.14.2 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/README.md +152 -13
  2. package/dist/agent-wallet/store.d.ts +3 -2
  3. package/dist/agent-wallet/store.js +2 -2
  4. package/dist/api/public/hyperliquid.js +4 -0
  5. package/dist/api/public/pacifica.js +83 -13
  6. package/dist/api/public/urls.d.ts +2 -0
  7. package/dist/api/public/urls.js +3 -0
  8. package/dist/arb/utils.d.ts +1 -2
  9. package/dist/arb/utils.js +1 -2
  10. package/dist/bot/apex/pulse.js +3 -0
  11. package/dist/bot/apex/radar.js +2 -1
  12. package/dist/bot/engine.d.ts +10 -1
  13. package/dist/bot/engine.js +14 -6
  14. package/dist/bot/indicators.d.ts +7 -0
  15. package/dist/bot/indicators.js +16 -0
  16. package/dist/bot/perp-order.d.ts +4 -4
  17. package/dist/bot/perp-order.js +5 -5
  18. package/dist/bot/quarantine.d.ts +1 -1
  19. package/dist/bot/quarantine.js +1 -1
  20. package/dist/bot/strategies/apex-strategy.js +3 -2
  21. package/dist/bot/strategies/engine-mm.js +6 -5
  22. package/dist/bot/strategies/funding-arb-strategy.js +9 -9
  23. package/dist/bot/strategies/funding-arb-utils.d.ts +15 -2
  24. package/dist/bot/strategies/funding-arb-utils.js +43 -24
  25. package/dist/bot/strategies/funding-auto.js +2 -2
  26. package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
  27. package/dist/bot/strategies/liquidation-mm.js +8 -2
  28. package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
  29. package/dist/bot/strategies/momentum-breakout.js +11 -3
  30. package/dist/bot/strategies/spot-perp-arb-strategy.js +23 -12
  31. package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
  32. package/dist/bot/strategies/spot-perp-executor.js +1 -1
  33. package/dist/bot/strategy-types.d.ts +2 -1
  34. package/dist/bot/tui/BotDashboard.d.ts +1 -1
  35. package/dist/bot/tui/BotDashboard.js +1 -1
  36. package/dist/cache.js +12 -6
  37. package/dist/cli-program.d.ts +15 -0
  38. package/dist/cli-program.js +125 -5
  39. package/dist/commands/agent-import.d.ts +7 -0
  40. package/dist/commands/agent-import.js +30 -1
  41. package/dist/commands/agent.d.ts +6 -3
  42. package/dist/commands/agent.js +160 -12
  43. package/dist/commands/arb/index.js +4 -4
  44. package/dist/commands/arb-auto.js +21 -17
  45. package/dist/commands/arb.d.ts +12 -0
  46. package/dist/commands/arb.js +61 -143
  47. package/dist/commands/bot.js +1 -1
  48. package/dist/commands/builder.js +1 -1
  49. package/dist/commands/funds.js +113 -3
  50. package/dist/commands/init.d.ts +1 -1
  51. package/dist/commands/init.js +27 -7
  52. package/dist/commands/manage.js +23 -21
  53. package/dist/commands/market.js +168 -36
  54. package/dist/commands/options.d.ts +9 -0
  55. package/dist/commands/options.js +134 -0
  56. package/dist/commands/pacifica-earn.d.ts +5 -0
  57. package/dist/commands/pacifica-earn.js +468 -0
  58. package/dist/commands/pacifica-orders.d.ts +14 -0
  59. package/dist/commands/pacifica-orders.js +142 -0
  60. package/dist/commands/portfolio.js +32 -47
  61. package/dist/commands/rebalance.d.ts +1 -0
  62. package/dist/commands/rebalance.js +15 -0
  63. package/dist/commands/risk.d.ts +11 -2
  64. package/dist/commands/risk.js +39 -44
  65. package/dist/commands/trade.d.ts +1 -0
  66. package/dist/commands/trade.js +63 -58
  67. package/dist/commands/wallet.js +1 -1
  68. package/dist/config.d.ts +2 -2
  69. package/dist/config.js +15 -4
  70. package/dist/constants.js +6 -0
  71. package/dist/dashboard/server.js +1 -1
  72. package/dist/dashboard/ui.js +1 -1
  73. package/dist/errors.d.ts +24 -1
  74. package/dist/errors.js +25 -3
  75. package/dist/exchanges/arcus/adapter.d.ts +7 -7
  76. package/dist/exchanges/arcus/adapter.js +12 -12
  77. package/dist/exchanges/arcus/agent.d.ts +1 -1
  78. package/dist/exchanges/arcus/agent.js +1 -1
  79. package/dist/exchanges/arcus/client.js +1 -1
  80. package/dist/exchanges/arcus/signing.d.ts +2 -3
  81. package/dist/exchanges/arcus/signing.js +1 -1
  82. package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
  83. package/dist/exchanges/arcus/spot-chain.js +1 -1
  84. package/dist/exchanges/arcus/spot-router.d.ts +1 -1
  85. package/dist/exchanges/arcus/spot-router.js +2 -2
  86. package/dist/exchanges/arcus/spot.d.ts +2 -3
  87. package/dist/exchanges/arcus/spot.js +2 -3
  88. package/dist/exchanges/aster-spot.d.ts +3 -3
  89. package/dist/exchanges/aster-spot.js +6 -9
  90. package/dist/exchanges/aster-typed-data.d.ts +1 -1
  91. package/dist/exchanges/aster-typed-data.js +1 -1
  92. package/dist/exchanges/aster.d.ts +9 -4
  93. package/dist/exchanges/aster.js +125 -55
  94. package/dist/exchanges/builder-fee.d.ts +1 -1
  95. package/dist/exchanges/builder-fee.js +13 -2
  96. package/dist/exchanges/canonical-symbols.d.ts +1 -2
  97. package/dist/exchanges/canonical-symbols.js +26 -2
  98. package/dist/exchanges/derive/client.d.ts +37 -0
  99. package/dist/exchanges/derive/client.js +135 -0
  100. package/dist/exchanges/derive/options.d.ts +68 -0
  101. package/dist/exchanges/derive/options.js +360 -0
  102. package/dist/exchanges/extended/adapter.d.ts +82 -0
  103. package/dist/exchanges/extended/adapter.js +179 -0
  104. package/dist/exchanges/extended/client.d.ts +38 -0
  105. package/dist/exchanges/extended/client.js +88 -0
  106. package/dist/exchanges/extended/public.d.ts +130 -0
  107. package/dist/exchanges/extended/public.js +429 -0
  108. package/dist/exchanges/grvt/adapter.d.ts +86 -0
  109. package/dist/exchanges/grvt/adapter.js +206 -0
  110. package/dist/exchanges/grvt/client.d.ts +25 -0
  111. package/dist/exchanges/grvt/client.js +86 -0
  112. package/dist/exchanges/grvt/public.d.ts +151 -0
  113. package/dist/exchanges/grvt/public.js +438 -0
  114. package/dist/exchanges/hyperliquid-spot.d.ts +1 -1
  115. package/dist/exchanges/hyperliquid-spot.js +5 -5
  116. package/dist/exchanges/hyperliquid.d.ts +22 -16
  117. package/dist/exchanges/hyperliquid.js +80 -55
  118. package/dist/exchanges/index.d.ts +1 -1
  119. package/dist/exchanges/index.js +1 -1
  120. package/dist/exchanges/interface.d.ts +97 -8
  121. package/dist/exchanges/interface.js +19 -2
  122. package/dist/exchanges/ioc-outcome.d.ts +1 -1
  123. package/dist/exchanges/ioc-outcome.js +1 -1
  124. package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
  125. package/dist/exchanges/legacy-trading-v2.js +7 -2
  126. package/dist/exchanges/lighter-public.d.ts +2 -2
  127. package/dist/exchanges/lighter-public.js +2 -2
  128. package/dist/exchanges/lighter-signer.d.ts +1 -1
  129. package/dist/exchanges/lighter-signer.js +1 -1
  130. package/dist/exchanges/lighter-spot.d.ts +3 -4
  131. package/dist/exchanges/lighter-spot.js +6 -7
  132. package/dist/exchanges/lighter.d.ts +11 -11
  133. package/dist/exchanges/lighter.js +28 -14
  134. package/dist/exchanges/ondo/adapter.d.ts +5 -6
  135. package/dist/exchanges/ondo/adapter.js +16 -14
  136. package/dist/exchanges/ondo/agent.d.ts +1 -1
  137. package/dist/exchanges/ondo/agent.js +1 -1
  138. package/dist/exchanges/ondo/client.d.ts +1 -1
  139. package/dist/exchanges/ondo/client.js +2 -2
  140. package/dist/exchanges/ondo/public.d.ts +8 -1
  141. package/dist/exchanges/ondo/public.js +13 -2
  142. package/dist/exchanges/ondo/spot.d.ts +2 -2
  143. package/dist/exchanges/ondo/spot.js +3 -3
  144. package/dist/exchanges/options-interface.d.ts +158 -0
  145. package/dist/exchanges/options-interface.js +17 -0
  146. package/dist/exchanges/options-venues.d.ts +12 -0
  147. package/dist/exchanges/options-venues.js +35 -0
  148. package/dist/exchanges/pacifica-atomic.d.ts +211 -0
  149. package/dist/exchanges/pacifica-atomic.js +440 -0
  150. package/dist/exchanges/pacifica-decimal.d.ts +10 -0
  151. package/dist/exchanges/pacifica-decimal.js +51 -0
  152. package/dist/exchanges/pacifica-presigned.d.ts +53 -0
  153. package/dist/exchanges/pacifica-presigned.js +141 -0
  154. package/dist/exchanges/pacifica-print.d.ts +200 -0
  155. package/dist/exchanges/pacifica-print.js +417 -0
  156. package/dist/exchanges/pacifica-spot.d.ts +2 -2
  157. package/dist/exchanges/pacifica-spot.js +3 -3
  158. package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
  159. package/dist/exchanges/pacifica-typed-data.js +1 -1
  160. package/dist/exchanges/pacifica-vaults.d.ts +121 -0
  161. package/dist/exchanges/pacifica-vaults.js +264 -0
  162. package/dist/exchanges/pacifica.d.ts +32 -5
  163. package/dist/exchanges/pacifica.js +114 -48
  164. package/dist/exchanges/precision.d.ts +3 -1
  165. package/dist/exchanges/precision.js +9 -2
  166. package/dist/exchanges/qfex/adapter.d.ts +18 -5
  167. package/dist/exchanges/qfex/adapter.js +32 -12
  168. package/dist/exchanges/qfex/agent.d.ts +1 -1
  169. package/dist/exchanges/qfex/agent.js +1 -1
  170. package/dist/exchanges/qfex/client.d.ts +1 -1
  171. package/dist/exchanges/qfex/client.js +1 -1
  172. package/dist/exchanges/qfex/errors.d.ts +1 -1
  173. package/dist/exchanges/qfex/errors.js +2 -2
  174. package/dist/exchanges/qfex/public.d.ts +3 -3
  175. package/dist/exchanges/qfex/public.js +3 -3
  176. package/dist/exchanges/qfex/signing.d.ts +2 -2
  177. package/dist/exchanges/qfex/signing.js +4 -5
  178. package/dist/exchanges/qfex/ws-transport.d.ts +2 -2
  179. package/dist/exchanges/qfex/ws-transport.js +3 -3
  180. package/dist/exchanges/rate-limiter.d.ts +1 -1
  181. package/dist/exchanges/rate-limiter.js +5 -2
  182. package/dist/exchanges/registry.d.ts +1 -1
  183. package/dist/exchanges/registry.js +1 -1
  184. package/dist/exchanges/risex/adapter.d.ts +148 -0
  185. package/dist/exchanges/risex/adapter.js +796 -0
  186. package/dist/exchanges/risex/agent.d.ts +154 -0
  187. package/dist/exchanges/risex/agent.js +384 -0
  188. package/dist/exchanges/risex/client.d.ts +47 -0
  189. package/dist/exchanges/risex/client.js +174 -0
  190. package/dist/exchanges/risex/nonce.d.ts +43 -0
  191. package/dist/exchanges/risex/nonce.js +212 -0
  192. package/dist/exchanges/risex/public.d.ts +64 -0
  193. package/dist/exchanges/risex/public.js +150 -0
  194. package/dist/exchanges/risex/session.d.ts +71 -0
  195. package/dist/exchanges/risex/session.js +171 -0
  196. package/dist/exchanges/risex/typed-data.d.ts +173 -0
  197. package/dist/exchanges/risex/typed-data.js +240 -0
  198. package/dist/exchanges/risex/units.d.ts +29 -0
  199. package/dist/exchanges/risex/units.js +104 -0
  200. package/dist/exchanges/slippage.d.ts +1 -1
  201. package/dist/exchanges/slippage.js +1 -1
  202. package/dist/exchanges/spot-factory.d.ts +3 -3
  203. package/dist/exchanges/spot-factory.js +7 -7
  204. package/dist/exchanges/spot-interface.d.ts +5 -5
  205. package/dist/exchanges/spot-interface.js +2 -2
  206. package/dist/exchanges/spot-result.d.ts +3 -3
  207. package/dist/exchanges/spot-result.js +3 -3
  208. package/dist/exchanges/trading-v2.d.ts +3 -3
  209. package/dist/exchanges/trading-v2.js +9 -6
  210. package/dist/exchanges/txflow/adapter.d.ts +54 -0
  211. package/dist/exchanges/txflow/adapter.js +118 -0
  212. package/dist/exchanges/txflow/client.d.ts +47 -0
  213. package/dist/exchanges/txflow/client.js +153 -0
  214. package/dist/exchanges/txflow/public.d.ts +76 -0
  215. package/dist/exchanges/txflow/public.js +284 -0
  216. package/dist/exchanges/unknown-symbol.d.ts +29 -0
  217. package/dist/exchanges/unknown-symbol.js +51 -0
  218. package/dist/exchanges/variational/adapter.d.ts +71 -0
  219. package/dist/exchanges/variational/adapter.js +137 -0
  220. package/dist/exchanges/variational/client.d.ts +21 -0
  221. package/dist/exchanges/variational/client.js +66 -0
  222. package/dist/exchanges/variational/public.d.ts +126 -0
  223. package/dist/exchanges/variational/public.js +430 -0
  224. package/dist/exchanges/venue-types.d.ts +6 -7
  225. package/dist/exchanges/venue-types.js +2 -2
  226. package/dist/exchanges/venue.d.ts +51 -8
  227. package/dist/exchanges/venue.js +54 -4
  228. package/dist/exchanges/venues/arcus.d.ts +1 -2
  229. package/dist/exchanges/venues/arcus.js +5 -4
  230. package/dist/exchanges/venues/aster.d.ts +2 -2
  231. package/dist/exchanges/venues/aster.js +6 -4
  232. package/dist/exchanges/venues/create-helpers.d.ts +1 -1
  233. package/dist/exchanges/venues/create-helpers.js +3 -3
  234. package/dist/exchanges/venues/extended.d.ts +21 -0
  235. package/dist/exchanges/venues/extended.js +96 -0
  236. package/dist/exchanges/venues/grvt.d.ts +30 -0
  237. package/dist/exchanges/venues/grvt.js +98 -0
  238. package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
  239. package/dist/exchanges/venues/hyperliquid.js +10 -8
  240. package/dist/exchanges/venues/index.d.ts +7 -2
  241. package/dist/exchanges/venues/index.js +8 -2
  242. package/dist/exchanges/venues/lighter-family.d.ts +7 -9
  243. package/dist/exchanges/venues/lighter-family.js +9 -11
  244. package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
  245. package/dist/exchanges/venues/lighter-rh.js +7 -5
  246. package/dist/exchanges/venues/lighter.d.ts +1 -1
  247. package/dist/exchanges/venues/lighter.js +5 -3
  248. package/dist/exchanges/venues/ondo.d.ts +1 -1
  249. package/dist/exchanges/venues/ondo.js +5 -3
  250. package/dist/exchanges/venues/pacifica.d.ts +2 -2
  251. package/dist/exchanges/venues/pacifica.js +6 -4
  252. package/dist/exchanges/venues/qfex.d.ts +1 -1
  253. package/dist/exchanges/venues/qfex.js +4 -2
  254. package/dist/exchanges/venues/risex-release.d.ts +14 -0
  255. package/dist/exchanges/venues/risex-release.js +14 -0
  256. package/dist/exchanges/venues/risex.d.ts +31 -0
  257. package/dist/exchanges/venues/risex.js +116 -0
  258. package/dist/exchanges/venues/txflow.d.ts +18 -0
  259. package/dist/exchanges/venues/txflow.js +77 -0
  260. package/dist/exchanges/venues/variational.d.ts +21 -0
  261. package/dist/exchanges/venues/variational.js +85 -0
  262. package/dist/execution-log.d.ts +1 -1
  263. package/dist/funding/legacy-public.d.ts +1 -1
  264. package/dist/funding/legacy-public.js +9 -4
  265. package/dist/funding/normalize.d.ts +1 -1
  266. package/dist/funding/normalize.js +1 -1
  267. package/dist/funding/rates.d.ts +44 -4
  268. package/dist/funding/rates.js +56 -12
  269. package/dist/index.js +7 -6
  270. package/dist/jobs.d.ts +1 -0
  271. package/dist/jobs.js +25 -1
  272. package/dist/landing.d.ts +2 -0
  273. package/dist/landing.js +1 -1
  274. package/dist/mcp-pacifica-earn.d.ts +9 -0
  275. package/dist/mcp-pacifica-earn.js +58 -0
  276. package/dist/mcp-server.js +113 -59
  277. package/dist/pacifica/client.d.ts +67 -4
  278. package/dist/pacifica/client.js +170 -8
  279. package/dist/pacifica/rate-limit.d.ts +144 -0
  280. package/dist/pacifica/rate-limit.js +267 -0
  281. package/dist/pacifica/types/order.d.ts +2 -1
  282. package/dist/plan-executor.js +7 -2
  283. package/dist/rebalance.js +1 -1
  284. package/dist/risk.d.ts +2 -1
  285. package/dist/risk.js +2 -4
  286. package/dist/settings.d.ts +32 -3
  287. package/dist/signer/ows-evm.d.ts +1 -1
  288. package/dist/signer/ows-evm.js +1 -1
  289. package/dist/smart-order.d.ts +1 -1
  290. package/dist/smart-order.js +1 -1
  291. package/dist/strategies/funding-arb.d.ts +1 -1
  292. package/dist/strategies/funding-arb.js +1 -1
  293. package/dist/trade-validator.d.ts +1 -1
  294. package/dist/trade-validator.js +9 -4
  295. package/dist/utils.d.ts +12 -3
  296. package/dist/utils.js +11 -3
  297. package/dist/venue-health.d.ts +40 -0
  298. package/dist/venue-health.js +75 -0
  299. package/dist/withdraw-gate.d.ts +1 -1
  300. package/dist/withdraw-gate.js +1 -1
  301. package/dist/ws/index.d.ts +959 -0
  302. package/dist/ws/index.js +4295 -0
  303. package/dist/ws/node.d.ts +975 -0
  304. package/dist/ws/node.js +4366 -0
  305. package/dist/ws/pacifica-instrument.d.ts +8 -0
  306. package/dist/ws/pacifica-instrument.js +8 -0
  307. package/dist/ws-cli/credentials.d.ts +62 -0
  308. package/dist/ws-cli/credentials.js +126 -0
  309. package/package.json +58 -10
  310. package/skills/perp-cli/SKILL.md +62 -9
  311. package/skills/perp-cli/references/agent-operations.md +7 -0
  312. package/skills/perp-cli/references/commands.md +76 -5
  313. package/skills/perp-cli/references/ws-library.md +492 -0
@@ -2,7 +2,7 @@
2
2
  * Venue definitions — the single source of truth for "which venue, on which
3
3
  * network, signed how, funded how, supporting what".
4
4
  *
5
- * See docs/DESIGN-venue-abstraction.md §10. One adapter class may serve several
5
+ * One adapter class may serve several
6
6
  * venues (LighterAdapter serves `lighter` and `lighter-rh`).
7
7
  *
8
8
  * Venue definition modules must load adapter code lazily (`import()` inside
@@ -10,9 +10,21 @@
10
10
  */
11
11
  import { PerpError } from "../errors.js";
12
12
  import { isVenueId } from "./venue-types.js";
13
+ import { optionsVenueWords } from "./options-venues.js";
13
14
  export const READ_ONLY_CREDENTIALS = {
14
15
  pk: null, owsWallet: null, owsPassphrase: null, owsKeyToken: null, agent: null,
15
16
  };
17
+ export const OFFICIAL_API = { kind: "official" };
18
+ /** "official" | "unofficial" — the per-row label for mixed-venue tables and JSON. */
19
+ export function apiStatusOf(venue) {
20
+ return getVenue(venue).apiStatus.kind;
21
+ }
22
+ /** Human footnote for an unofficial-API venue; null for an official one. */
23
+ export function unofficialApiNote(def) {
24
+ return def.apiStatus.kind === "unofficial"
25
+ ? `${def.displayName}: UNOFFICIAL API — ${def.apiStatus.note}`
26
+ : null;
27
+ }
16
28
  // ── Registry ──
17
29
  const _venues = new Map();
18
30
  const _aliases = new Map();
@@ -29,8 +41,12 @@ export function registerVenue(def) {
29
41
  }
30
42
  }
31
43
  function unknownVenue(input) {
44
+ // An options venue (e.g. derive) is not a perp venue: say where it works instead.
45
+ const optionsOnly = optionsVenueWords().includes(input.toLowerCase())
46
+ ? ` — ${input} is options-only: perp -e ${input} options …`
47
+ : "";
32
48
  return new PerpError("UNKNOWN_VENUE", `Unknown venue: "${input}"`, {
33
- remediation: `Use one of: ${[..._venues.keys()].join(", ")}`,
49
+ remediation: `Use one of: ${[..._venues.keys()].join(", ")}${optionsOnly}`,
34
50
  });
35
51
  }
36
52
  /** Resolve a venue id or alias. Throws UNKNOWN_VENUE. */
@@ -65,7 +81,41 @@ export function networkConfig(def, net) {
65
81
  }
66
82
  return cfg;
67
83
  }
84
+ /**
85
+ * The uniform refusal for any account / trading / funds / agent / builder / bot action on a venue
86
+ * whose roles do not include `role` (a market-data-only venue such as TxFlow). Raised before any
87
+ * credential is resolved or any request is sent.
88
+ */
89
+ export function roleUnsupported(def, feature, role = "trading") {
90
+ if (def.gatedRoles !== null && def.gatedRoles.roles.includes(role)) {
91
+ const { reason, remediation } = def.gatedRoles;
92
+ return new PerpError("CAPABILITY_UNSUPPORTED", `${def.id} does not support ${feature} — ${reason}`, {
93
+ venue: def.id, feature, reason, remediation,
94
+ });
95
+ }
96
+ const reason = def.apiStatus.kind === "unofficial"
97
+ ? `${def.displayName} is integrated through an unofficial read-only API (market data only)`
98
+ : `${def.displayName} is available for market data only (no ${role} role)`;
99
+ // Precedence: gatedRoles (above: a role switched off this release, e.g. RISEx) → the venue's own
100
+ // readOnlyRemediation (official read-only venues, e.g. Variational) → the generic text (TxFlow).
101
+ const remediation = def.readOnlyRemediation !== undefined
102
+ ? def.readOnlyRemediation
103
+ : def.apiStatus.kind === "unofficial"
104
+ ? `Trade on the ${def.displayName} website; perp-cli shows ${def.displayName} market data only (perp -e ${def.id} market list|info|funding|book|trades|kline)`
105
+ : `Use the market-data commands for ${def.id} (perp -e ${def.id} market list|funding)`;
106
+ return new PerpError("CAPABILITY_UNSUPPORTED", `${def.id} does not support ${feature} — ${reason}`, {
107
+ venue: def.id, feature, reason, remediation,
108
+ });
109
+ }
110
+ /** Throws roleUnsupported() unless the venue has `role`. */
111
+ export function requireRole(def, role, feature) {
112
+ if (!def.roles.includes(role))
113
+ throw roleUnsupported(def, feature, role);
114
+ }
68
115
  export function requireCapabilities(def) {
116
+ // A venue without the trading role is a definite capability refusal, not "not implemented yet".
117
+ if (!def.roles.includes("trading"))
118
+ throw roleUnsupported(def, "trading");
69
119
  if (!def.capabilities) {
70
120
  throw new PerpError("NOT_IMPLEMENTED", `${def.displayName} does not support trading via API`, {
71
121
  remediation: `${def.id} is available for market data only (funding/market commands)`,
@@ -88,7 +138,7 @@ export function parseVenueRef(ref) {
88
138
  }
89
139
  /**
90
140
  * Funding basis for a venue ref. HIP-3 dexes use the Hyperliquid core basis
91
- * (current behavior preserved; see design §10.1 — verify against live data).
141
+ * (current behavior preserved; verify against live data).
92
142
  * Throws for venues whose basis is per-market; callers must use the market's value.
93
143
  */
94
144
  export function fundingBasisOf(ref) {
@@ -114,7 +164,7 @@ export function settlementIntervalOf(ref) {
114
164
  /**
115
165
  * Refuse a venue whose funding rate is unverified (VenueDefinition.fundingVerified false) as a
116
166
  * leg of a funding strategy (arb scan ranking, arb exec / auto, funding bots). Uniform
117
- * CAPABILITY_UNSUPPORTED (design §13.6, §14.12 #6). Unknown venue refs throw UNKNOWN_VENUE.
167
+ * CAPABILITY_UNSUPPORTED. Unknown venue refs throw UNKNOWN_VENUE.
118
168
  */
119
169
  export function assertFundingArbVenue(ref) {
120
170
  const def = getVenue(parseVenueRef(ref).venue);
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Arcus — perps on the Robinhood chain rootchain, USDG collateral
3
- * (design §4 Arcus column, §10.4, §10.10).
4
3
  * Not registered here; the registry module owns registerVenue().
5
- * Adapter and public-data code are loaded lazily (§10.10).
4
+ * Adapter and public-data code are loaded lazily.
6
5
  */
7
6
  import type { VenueDefinition } from "../venue.js";
8
7
  export declare const arcusVenue: VenueDefinition;
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * Arcus — perps on the Robinhood chain rootchain, USDG collateral
3
- * (design §4 Arcus column, §10.4, §10.10).
4
3
  * Not registered here; the registry module owns registerVenue().
5
- * Adapter and public-data code are loaded lazily (§10.10).
4
+ * Adapter and public-data code are loaded lazily.
6
5
  */
7
6
  import { BUILDER_FEE_CAPABILITIES } from "../builder-fee.js";
8
7
  const publicData = {
@@ -50,6 +49,7 @@ export const arcusVenue = {
50
49
  settlementIntervalHours: 1,
51
50
  fundingVerified: true,
52
51
  roles: ["marketData", "account", "trading"],
52
+ gatedRoles: null,
53
53
  capabilities: {
54
54
  marketOrder: "slippageBounded",
55
55
  // GTC = GTT at goodTil now + 40 days (ARCUS_GOOD_TIL_HORIZON_MS); GTT kept as the venue alias.
@@ -83,7 +83,7 @@ export const arcusVenue = {
83
83
  restrictedRegions: ["US", "CA", "GB"],
84
84
  symbolIdentity: "baseTicker",
85
85
  publicData,
86
- // §12: market swaps via router.spot.arcus.xyz, settled on-chain from the master EVM wallet.
86
+ // market swaps via router.spot.arcus.xyz, settled on-chain from the master EVM wallet.
87
87
  spot: {
88
88
  accountModel: "wallet",
89
89
  quoteAssets: { mainnet: ["USDG"], testnet: ["USDG"] },
@@ -99,9 +99,10 @@ export const arcusVenue = {
99
99
  return spot;
100
100
  },
101
101
  },
102
- // Arcus venue limit per design §13.10 #1.
102
+ // Arcus venue slippage limit.
103
103
  maxSlippageBps: 1000,
104
104
  builderFee: BUILDER_FEE_CAPABILITIES["arcus"],
105
+ apiStatus: { kind: "official" },
105
106
  async create(ctx) {
106
107
  const { ArcusAdapter } = await import("../arcus/adapter.js");
107
108
  return new ArcusAdapter(arcusVenue, ctx);
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Aster venue definition (design §10.1, §10.8, §10.13 #4).
3
- * Adapter + public-data code are loaded lazily (§10.10).
2
+ * Aster venue definition.
3
+ * Adapter + public-data code are loaded lazily.
4
4
  */
5
5
  import type { VenueDefinition } from "../venue.js";
6
6
  /** Aster client order id (V3 futures "New Order" `newClientOrderId` rule). */
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Aster venue definition (design §10.1, §10.8, §10.13 #4).
3
- * Adapter + public-data code are loaded lazily (§10.10).
2
+ * Aster venue definition.
3
+ * Adapter + public-data code are loaded lazily.
4
4
  */
5
5
  import { BUILDER_FEE_CAPABILITIES } from "../builder-fee.js";
6
6
  /** Aster client order id (V3 futures "New Order" `newClientOrderId` rule). */
@@ -122,6 +122,7 @@ export const asterVenue = {
122
122
  settlementIntervalHours: "perMarket",
123
123
  fundingVerified: true,
124
124
  roles: ["marketData", "account", "trading"],
125
+ gatedRoles: null,
125
126
  capabilities: {
126
127
  // Market = IOC LIMIT at mark ± slippage (adapter marketOrder), never native MARKET.
127
128
  marketOrder: "slippageBounded",
@@ -146,12 +147,12 @@ export const asterVenue = {
146
147
  },
147
148
  // GET /fapi/v1/exchangeInfo rateLimits: REQUEST_WEIGHT 2400/min
148
149
  // (ORDERS 1200/min and 300/10s are separate order-count limits, not modeled).
149
- // Declared only — per §10.9 the limiter is applied to new venues + lighter-rh.
150
+ // Declared only — per the limiter is applied to new venues + lighter-rh.
150
151
  rateLimit: { capacity: 2400, refillPerSec: 40, weights: null },
151
152
  restrictedRegions: [],
152
153
  symbolIdentity: "baseTicker",
153
154
  publicData,
154
- // §12: separate spot account (sapi /api/v3) + /asset/wallet/transfer. Agent signer needs canSpotTrade.
155
+ // separate spot account (sapi /api/v3) + /asset/wallet/transfer. Agent signer needs canSpotTrade.
155
156
  spot: {
156
157
  accountModel: "separate",
157
158
  quoteAssets: { mainnet: ["USDT", "USD1"], testnet: ["USDT", "USD1"] },
@@ -172,5 +173,6 @@ export const asterVenue = {
172
173
  // (INVALID_PARAMS) at order time; this is only the outer venue-wide bound.
173
174
  maxSlippageBps: 5000,
174
175
  builderFee: BUILDER_FEE_CAPABILITIES["aster"],
176
+ apiStatus: { kind: "official" },
175
177
  create: async (ctx) => (await import("./create-helpers.js")).createAster(ctx),
176
178
  };
@@ -2,7 +2,7 @@
2
2
  * Adapter construction for the pre-existing venues (pacifica / hyperliquid /
3
3
  * lighter / lighter-rh / aster) — the single creation path that replaced the
4
4
  * three copies in src/index.ts (getAdapter / _initWithOws / getAdapterForExchange)
5
- * and the MCP server's getOrCreateAdapter (design §10.2).
5
+ * and the MCP server's getOrCreateAdapter.
6
6
  *
7
7
  * Signer tiers, as before: agent (Tier 1) → OWS master (Tier 2) → raw PK (Tier 3).
8
8
  * Which tier signs a given request is still decided inside each adapter.
@@ -2,7 +2,7 @@
2
2
  * Adapter construction for the pre-existing venues (pacifica / hyperliquid /
3
3
  * lighter / lighter-rh / aster) — the single creation path that replaced the
4
4
  * three copies in src/index.ts (getAdapter / _initWithOws / getAdapterForExchange)
5
- * and the MCP server's getOrCreateAdapter (design §10.2).
5
+ * and the MCP server's getOrCreateAdapter.
6
6
  *
7
7
  * Signer tiers, as before: agent (Tier 1) → OWS master (Tier 2) → raw PK (Tier 3).
8
8
  * Which tier signs a given request is still decided inside each adapter.
@@ -84,7 +84,7 @@ export async function createPacifica(ctx) {
84
84
  adapter = new PacificaAdapter(parseSolanaKeypair(creds.pk), ctx.network, true);
85
85
  }
86
86
  else {
87
- // Read-only: no key material. index.ts:143 Keypair.generate() recorded as out of scope (§10.11).
87
+ // Read-only: no key material. index.ts:143 Keypair.generate() recorded as out of scope.
88
88
  adapter = new PacificaAdapter(Keypair.generate(), ctx.network, false);
89
89
  }
90
90
  const agent = await legacyAgentOf(ctx, creds, "pacifica");
@@ -138,7 +138,7 @@ export async function createHyperliquid(ctx) {
138
138
  export async function createLighterFamily(venue, ctx) {
139
139
  const creds = effectiveCredentials(ctx);
140
140
  if (venue === "lighter-rh" && creds.pk !== null) {
141
- // Design §10.3: the Lighter RH master key is an OWS wallet only — no env / raw-PK tier.
141
+ // The Lighter RH master key is an OWS wallet only — no env / raw-PK tier.
142
142
  throw new PerpError("NO_ENV_TIER", "Lighter RH does not accept a raw private key (env / --private-key / local wallet)", {
143
143
  remediation: "Import the key into OWS (perp wallet import, key via hidden prompt / stdin) and run with --ows <wallet>, or register an agent: perp wallet agent approve lighter-rh",
144
144
  });
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Extended (formerly X10) — perps order book on Starknet, USD collateral. MARKET DATA ONLY in this
3
+ * version, through the OFFICIAL public REST API (https://api.docs.extended.exchange/).
4
+ *
5
+ * - roles are ["marketData"]: every account / trading / funds / agent / builder / bot path
6
+ * refuses with CAPABILITY_UNSUPPORTED before any request (venue.ts roleUnsupported(), with the
7
+ * readOnlyRemediation below). There is no Extended order, signing (Stark), transfer or account
8
+ * code at all; trading is planned for a later release.
9
+ * - Hosts (docs "Mainnet" / "Testnet"): mainnet api.starknet.extended.exchange, testnet (Sepolia)
10
+ * api.starknet.sepolia.extended.exchange. The old api.extended.exchange answers 404.
11
+ * - Every request must carry a User-Agent header (docs "Mandatory headers"; none → HTTP 403).
12
+ * - Funding (docs "Get funding rates history", docs.extended.exchange funding-payments): applied
13
+ * once per hour; marketStats.fundingRate is the current hour's ACCRUING rate (recomputed every
14
+ * minute) as a FRACTION per hour — see extended/public.ts.
15
+ * Not registered here; the registry module owns registerVenue().
16
+ */
17
+ import type { VenueDefinition } from "../venue.js";
18
+ export declare const EXTENDED_DOCS_URL = "https://api.docs.extended.exchange/";
19
+ /** The remediation of every role refusal (owner decision: phase 1 is read-only). */
20
+ export declare const EXTENDED_READ_ONLY_REMEDIATION = "Extended is read-only (market data) in this version; trading is planned for a later release. Market data: perp -e extended market list|prices|info|book|trades|funding|kline";
21
+ export declare const extendedVenue: VenueDefinition;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Extended (formerly X10) — perps order book on Starknet, USD collateral. MARKET DATA ONLY in this
3
+ * version, through the OFFICIAL public REST API (https://api.docs.extended.exchange/).
4
+ *
5
+ * - roles are ["marketData"]: every account / trading / funds / agent / builder / bot path
6
+ * refuses with CAPABILITY_UNSUPPORTED before any request (venue.ts roleUnsupported(), with the
7
+ * readOnlyRemediation below). There is no Extended order, signing (Stark), transfer or account
8
+ * code at all; trading is planned for a later release.
9
+ * - Hosts (docs "Mainnet" / "Testnet"): mainnet api.starknet.extended.exchange, testnet (Sepolia)
10
+ * api.starknet.sepolia.extended.exchange. The old api.extended.exchange answers 404.
11
+ * - Every request must carry a User-Agent header (docs "Mandatory headers"; none → HTTP 403).
12
+ * - Funding (docs "Get funding rates history", docs.extended.exchange funding-payments): applied
13
+ * once per hour; marketStats.fundingRate is the current hour's ACCRUING rate (recomputed every
14
+ * minute) as a FRACTION per hour — see extended/public.ts.
15
+ * Not registered here; the registry module owns registerVenue().
16
+ */
17
+ export const EXTENDED_DOCS_URL = "https://api.docs.extended.exchange/";
18
+ /** The remediation of every role refusal (owner decision: phase 1 is read-only). */
19
+ export const EXTENDED_READ_ONLY_REMEDIATION = "Extended is read-only (market data) in this version; trading is planned for a later release. Market data: perp -e extended market list|prices|info|book|trades|funding|kline";
20
+ /** Lazy: public.ts is only loaded when market data is actually requested. */
21
+ const publicData = {
22
+ async fetchFundingRates(net) {
23
+ return (await import("../extended/public.js")).extendedPublicData.fetchFundingRates(net);
24
+ },
25
+ async fetchMarkets(net) {
26
+ return (await import("../extended/public.js")).extendedPublicData.fetchMarkets(net);
27
+ },
28
+ };
29
+ export const extendedVenue = {
30
+ id: "extended",
31
+ aliases: ["ext", "x10"],
32
+ displayName: "Extended",
33
+ family: "extended",
34
+ masterKeyKind: "none",
35
+ agentKeyKind: "none",
36
+ secretStorage: { kind: "none", dir: null },
37
+ networks: {
38
+ mainnet: {
39
+ restUrl: "https://api.starknet.extended.exchange/api/v1",
40
+ wsUrl: "wss://api.starknet.extended.exchange/stream.extended.exchange/v1",
41
+ explorerUrl: null,
42
+ signingChainId: null,
43
+ settlementChain: "starknet",
44
+ collateral: ["USD"],
45
+ collateralAssetIndex: null,
46
+ rpcUrl: null,
47
+ depositPins: null,
48
+ },
49
+ testnet: {
50
+ restUrl: "https://api.starknet.sepolia.extended.exchange/api/v1",
51
+ // The docs' SDK config (TESTNET_CONFIG stream_url). Unused (no ws codec); live 2026-10-19 it
52
+ // answered HTTP 403 to a public stream (api.starknet.sepolia… answered 503) — unverified.
53
+ wsUrl: "wss://starknet.sepolia.extended.exchange/stream.extended.exchange/v1",
54
+ explorerUrl: null,
55
+ signingChainId: null,
56
+ settlementChain: "starknet",
57
+ collateral: ["USD"],
58
+ collateralAssetIndex: null,
59
+ rpcUrl: null,
60
+ depositPins: null,
61
+ },
62
+ },
63
+ // Funding is applied once per hour on every perpetual market; the published rate is per hour.
64
+ fundingRateBasis: { kind: "perHours", hours: 1 },
65
+ settlementIntervalHours: 1,
66
+ // Not verified: the unit / sign of marketStats.fundingRate is not checked against a settled account
67
+ // funding payment (needs an account; RISEx's bar). Partial evidence only: docs + one recorded
68
+ // settlement (src/__tests__/fixtures/extended/funding-settlement-evidence.json — last accruing value
69
+ // == applied print on 8 markets, 5 of them at the baseline). And `_24_5` equities print 0 while
70
+ // their underlying is closed (TSLA_24_5: 34 of 43 weekend prints were 0), so hourly × 8760
71
+ // overstates them. Until settled against payments Extended is not a funding-arb venue.
72
+ fundingVerified: false,
73
+ roles: ["marketData"],
74
+ capabilities: null,
75
+ // Docs "Rate Limits": default tier 1,000 requests/minute per IP, all endpoints throttled by IP.
76
+ // 15/s sustained (900/min) leaves headroom for other processes on the same IP.
77
+ rateLimit: { capacity: 50, refillPerSec: 15, weights: null },
78
+ // docs.extended.exchange/extended-resources/legal/restricted-countries (2026-10-19), Category A;
79
+ // Ukraine is restricted only for Crimea / Donetsk / Kherson / Luhansk / Zaporizhzhia (no alpha-2).
80
+ // Warning-only and shown with credentials — unused while the venue is market data only.
81
+ restrictedRegions: ["AF", "CA", "HK", "CU", "IR", "IQ", "YE", "KP", "RU", "SY", "SC", "GB", "US"],
82
+ symbolIdentity: "baseTicker",
83
+ publicData,
84
+ spot: null,
85
+ // Unused (no trading role); the field is required by the definition shape.
86
+ maxSlippageBps: 1,
87
+ builderFee: null,
88
+ apiStatus: { kind: "official" },
89
+ gatedRoles: null,
90
+ readOnlyRemediation: EXTENDED_READ_ONLY_REMEDIATION,
91
+ // A public-only adapter: market data works, every account / trading method refuses.
92
+ async create(ctx) {
93
+ const { ExtendedPublicAdapter } = await import("../extended/adapter.js");
94
+ return new ExtendedPublicAdapter(extendedVenue, ctx.network);
95
+ },
96
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * GRVT venue definition — MARKET DATA ONLY in this version (official, documented API).
3
+ *
4
+ * GRVT (api-docs.grvt.io) is a hybrid perps exchange (off-chain matching, ZK-validium settlement on
5
+ * GRVT chain 325), USDT collateral. perp-cli reads its public Market Data REST API
6
+ * (`POST https://market-data.grvt.io/full/v1/<endpoint>`, no key) and nothing else:
7
+ * - roles are ["marketData"]: every account / trading / funds / agent / builder / bot path refuses
8
+ * with CAPABILITY_UNSUPPORTED before any request (venue.ts roleUnsupported(), with the
9
+ * readOnlyRemediation below). There is no GRVT order, signing, transfer or account code at all.
10
+ * - funding is unverified (fundingVerified false): the ticker's `funding_rate` is the venue's
11
+ * indicative rate for the active interval (a moving estimate of the next payment, "predicted"),
12
+ * quoted in percent per the market's own funding interval (4 h or 8 h, per instrument). The
13
+ * percent unit is documented for settled history (/full/v1/funding "percentage points") and
14
+ * observed identical in magnitude on the ticker (whose schema says "centibeeps"); it is not yet
15
+ * checked against settled funding payments (an authenticated read) — kept out of arb ranking
16
+ * unless --include-unverified.
17
+ * Not registered here; the registry module owns registerVenue().
18
+ */
19
+ import type { RateLimitPolicy, VenueDefinition } from "../venue.js";
20
+ export declare const GRVT_DOCS_URL = "https://api-docs.grvt.io";
21
+ /** Uniform refusal text for every write / signer / setup-trading path on GRVT. */
22
+ export declare const GRVT_READ_ONLY_REMEDIATION = "GRVT is read-only (market data) in this version; trading is planned for a later release";
23
+ /**
24
+ * help.grvt.io "What are the rate limitations on Grvt?" — REST Market Data, every tier, per minute:
25
+ * GetInstrument / MiniTicker / Ticker 1500, all others 500 (WS JSON-RPC calls count too). Two token
26
+ * buckets sized so that no 60 s window can exceed the limit (capacity + 60 s × refill ≤ limit).
27
+ */
28
+ export declare const GRVT_TICKER_RATE_LIMIT: RateLimitPolicy;
29
+ export declare const GRVT_OTHER_RATE_LIMIT: RateLimitPolicy;
30
+ export declare const grvtVenue: VenueDefinition;
@@ -0,0 +1,98 @@
1
+ /**
2
+ * GRVT venue definition — MARKET DATA ONLY in this version (official, documented API).
3
+ *
4
+ * GRVT (api-docs.grvt.io) is a hybrid perps exchange (off-chain matching, ZK-validium settlement on
5
+ * GRVT chain 325), USDT collateral. perp-cli reads its public Market Data REST API
6
+ * (`POST https://market-data.grvt.io/full/v1/<endpoint>`, no key) and nothing else:
7
+ * - roles are ["marketData"]: every account / trading / funds / agent / builder / bot path refuses
8
+ * with CAPABILITY_UNSUPPORTED before any request (venue.ts roleUnsupported(), with the
9
+ * readOnlyRemediation below). There is no GRVT order, signing, transfer or account code at all.
10
+ * - funding is unverified (fundingVerified false): the ticker's `funding_rate` is the venue's
11
+ * indicative rate for the active interval (a moving estimate of the next payment, "predicted"),
12
+ * quoted in percent per the market's own funding interval (4 h or 8 h, per instrument). The
13
+ * percent unit is documented for settled history (/full/v1/funding "percentage points") and
14
+ * observed identical in magnitude on the ticker (whose schema says "centibeeps"); it is not yet
15
+ * checked against settled funding payments (an authenticated read) — kept out of arb ranking
16
+ * unless --include-unverified.
17
+ * Not registered here; the registry module owns registerVenue().
18
+ */
19
+ export const GRVT_DOCS_URL = "https://api-docs.grvt.io";
20
+ /** Uniform refusal text for every write / signer / setup-trading path on GRVT. */
21
+ export const GRVT_READ_ONLY_REMEDIATION = "GRVT is read-only (market data) in this version; trading is planned for a later release";
22
+ /**
23
+ * help.grvt.io "What are the rate limitations on Grvt?" — REST Market Data, every tier, per minute:
24
+ * GetInstrument / MiniTicker / Ticker 1500, all others 500 (WS JSON-RPC calls count too). Two token
25
+ * buckets sized so that no 60 s window can exceed the limit (capacity + 60 s × refill ≤ limit).
26
+ */
27
+ export const GRVT_TICKER_RATE_LIMIT = { capacity: 750, refillPerSec: 12, weights: null };
28
+ export const GRVT_OTHER_RATE_LIMIT = { capacity: 250, refillPerSec: 4, weights: null };
29
+ /** Lazy: public.ts is only loaded when market data is actually requested. */
30
+ const publicData = {
31
+ async fetchFundingRates(net) {
32
+ return (await import("../grvt/public.js")).grvtPublicData.fetchFundingRates(net);
33
+ },
34
+ async fetchMarkets(net) {
35
+ return (await import("../grvt/public.js")).grvtPublicData.fetchMarkets(net);
36
+ },
37
+ };
38
+ export const grvtVenue = {
39
+ id: "grvt",
40
+ aliases: ["grv"],
41
+ displayName: "GRVT",
42
+ family: "grvt",
43
+ masterKeyKind: "none",
44
+ agentKeyKind: "none",
45
+ secretStorage: { kind: "none", dir: null },
46
+ networks: {
47
+ // grvt-pysdk grvt_raw_env.py (PROD / TESTNET); the docs' "Try it out" uses the same hosts.
48
+ mainnet: {
49
+ restUrl: "https://market-data.grvt.io",
50
+ wsUrl: "wss://market-data.grvt.io/ws/full",
51
+ explorerUrl: null,
52
+ signingChainId: null,
53
+ settlementChain: "offchain",
54
+ collateral: ["USDT"],
55
+ collateralAssetIndex: null,
56
+ rpcUrl: null,
57
+ depositPins: null,
58
+ },
59
+ testnet: {
60
+ restUrl: "https://market-data.testnet.grvt.io",
61
+ wsUrl: "wss://market-data.testnet.grvt.io/ws/full",
62
+ explorerUrl: null,
63
+ signingChainId: null,
64
+ settlementChain: "offchain",
65
+ collateral: ["USDT"],
66
+ collateralAssetIndex: null,
67
+ rpcUrl: null,
68
+ depositPins: null,
69
+ },
70
+ },
71
+ // Per instrument: funding_interval_hours is 8 or 4 (live 2026-10-19: 124 × 8 h, 60 × 4 h).
72
+ fundingRateBasis: "perMarket",
73
+ settlementIntervalHours: "perMarket",
74
+ fundingVerified: false,
75
+ roles: ["marketData"],
76
+ // Not a release gate (nothing is implemented and switched off): the venue has no trading code yet.
77
+ gatedRoles: null,
78
+ capabilities: null,
79
+ // "All others" bucket (instruments, book, trade, funding, kline, margin_rules); the ticker bucket
80
+ // is GRVT_TICKER_RATE_LIMIT (grvt/client.ts picks per endpoint).
81
+ rateLimit: GRVT_OTHER_RATE_LIMIT,
82
+ // help.grvt.io/en/articles/9711621-restricted-jurisdictions (also Crimea / Donetsk / Luhansk /
83
+ // Kherson / Zaporizhzhya / Sevastopol regions). Trading needs KYC — relevant once trading lands.
84
+ restrictedRegions: ["US", "PR", "AS", "GU", "MP", "VI", "SG", "HK", "KP", "IR", "MM", "BY", "CU", "AF", "CA", "LY", "RU", "SO", "SS", "SD", "SY"],
85
+ symbolIdentity: "baseTicker",
86
+ publicData,
87
+ spot: null,
88
+ // Unused (no trading role); the field is required by the definition shape.
89
+ maxSlippageBps: 1,
90
+ builderFee: null,
91
+ apiStatus: { kind: "official" },
92
+ readOnlyRemediation: GRVT_READ_ONLY_REMEDIATION,
93
+ // A public-only adapter: market data works, every account / trading method refuses.
94
+ async create(ctx) {
95
+ const { GrvtPublicAdapter } = await import("../grvt/adapter.js");
96
+ return new GrvtPublicAdapter(grvtVenue, ctx.network);
97
+ },
98
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Hyperliquid venue definition (design §10.1, §10.8, §10.13 #4).
2
+ * Hyperliquid venue definition.
3
3
  * HIP-3 dexes are not venues: they are selected via VenueCreateContext.hlDex.
4
- * Adapter + public-data code are loaded lazily (§10.10).
4
+ * Adapter + public-data code are loaded lazily.
5
5
  */
6
6
  import type { Network, VenueDefinition } from "../venue.js";
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Hyperliquid venue definition (design §10.1, §10.8, §10.13 #4).
2
+ * Hyperliquid venue definition.
3
3
  * HIP-3 dexes are not venues: they are selected via VenueCreateContext.hlDex.
4
- * Adapter + public-data code are loaded lazily (§10.10).
4
+ * Adapter + public-data code are loaded lazily.
5
5
  */
6
6
  import { BUILDER_FEE_CAPABILITIES } from "../builder-fee.js";
7
7
  /**
@@ -36,7 +36,7 @@ export const hyperliquidVenue = {
36
36
  agentKeyKind: "evm",
37
37
  secretStorage: { kind: "ows-wallet", dir: null },
38
38
  // REST: src/exchanges/hyperliquid.ts; mainnet WS: src/dashboard/ws-feeds.ts.
39
- // Testnet WS is not in code → null. signingChainId: L1 action phantom-agent domain (hyperliquid.ts).
39
+ // Testnet WS per the HL websocket docs (opened in the 2026-10-13 ws probe). signingChainId: L1 action phantom-agent domain (hyperliquid.ts).
40
40
  networks: {
41
41
  mainnet: {
42
42
  restUrl: "https://api.hyperliquid.xyz",
@@ -51,7 +51,7 @@ export const hyperliquidVenue = {
51
51
  },
52
52
  testnet: {
53
53
  restUrl: "https://api.hyperliquid-testnet.xyz",
54
- wsUrl: null,
54
+ wsUrl: "wss://api.hyperliquid-testnet.xyz/ws",
55
55
  explorerUrl: null,
56
56
  signingChainId: 1337,
57
57
  settlementChain: "hyperliquid",
@@ -65,11 +65,12 @@ export const hyperliquidVenue = {
65
65
  settlementIntervalHours: 1,
66
66
  fundingVerified: true,
67
67
  roles: ["marketData", "account", "trading"],
68
- // marketOrder: IOC limit at a protection price (§13.2/§13.10 #5). Declared reference
68
+ gatedRoles: null,
69
+ // marketOrder: IOC limit at a protection price. Declared reference
69
70
  // price = l2Book mid ((best bid + best ask) / 2) for native perps, HIP-3 and spot —
70
71
  // no runtime substitute; a one-sided/empty book → PRICE_STALE. Rounding: 5 significant
71
72
  // figures, max 6 − szDecimals (perp) / 8 − szDecimals (spot) decimals, toward crossing.
72
- // tpsl stays "separateOrders": HL `normalTpsl` grouping was evaluated (§13.10 #12) and not
73
+ // tpsl stays "separateOrders": HL `normalTpsl` grouping was evaluated and not
73
74
  // used — its children have a fixed size equal to the parent and are fully cancelled when
74
75
  // a partially filled parent is cancelled (HL docs, TP/SL orders), so a partially filled
75
76
  // IOC entry would be left unprotected; separateOrders sizes TP/SL to the verified fill.
@@ -92,7 +93,7 @@ export const hyperliquidVenue = {
92
93
  // HL docs "Rate limits and user limits": REST requests share an aggregated
93
94
  // weight of 1200/min per IP. Exchange actions weigh 1 (unbatched); light info
94
95
  // requests 2; most info requests 20; userRole 60.
95
- // Declared only — per §10.9 the limiter is applied to new venues + lighter-rh.
96
+ // Declared only — per the limiter is applied to new venues + lighter-rh.
96
97
  rateLimit: {
97
98
  capacity: 1200,
98
99
  refillPerSec: 20,
@@ -104,7 +105,7 @@ export const hyperliquidVenue = {
104
105
  restrictedRegions: [],
105
106
  symbolIdentity: "baseTicker",
106
107
  publicData,
107
- // §12: spot USDC is shared with perp margin when the account is unified (isUnifiedAccount, read at init).
108
+ // spot USDC is shared with perp margin when the account is unified (isUnifiedAccount, read at init).
108
109
  spot: {
109
110
  accountModel: "runtime",
110
111
  quoteAssets: { mainnet: ["USDC"], testnet: ["USDC"] },
@@ -122,5 +123,6 @@ export const hyperliquidVenue = {
122
123
  },
123
124
  maxSlippageBps: 5000,
124
125
  builderFee: BUILDER_FEE_CAPABILITIES["hyperliquid"],
126
+ apiStatus: { kind: "official" },
125
127
  create: async (ctx) => (await import("./create-helpers.js")).createHyperliquid(ctx),
126
128
  };
@@ -10,7 +10,12 @@ import { lighterVenue } from "./lighter.js";
10
10
  import { ondoVenue } from "./ondo.js";
11
11
  import { pacificaVenue } from "./pacifica.js";
12
12
  import { qfexVenue } from "./qfex.js";
13
- export declare const ALL_VENUES: readonly [import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition];
13
+ import { risexVenue } from "./risex.js";
14
+ import { txflowVenue } from "./txflow.js";
15
+ import { variationalVenue } from "./variational.js";
16
+ import { grvtVenue } from "./grvt.js";
17
+ import { extendedVenue } from "./extended.js";
18
+ export declare const ALL_VENUES: readonly [import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition, import("../venue.js").VenueDefinition];
14
19
  /** Idempotent: registers all venues on first call, no-op afterwards. */
15
20
  export declare function ensureVenuesRegistered(): void;
16
- export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, };
21
+ export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, risexVenue, txflowVenue, variationalVenue, grvtVenue, extendedVenue, };
@@ -11,9 +11,15 @@ import { lighterVenue } from "./lighter.js";
11
11
  import { ondoVenue } from "./ondo.js";
12
12
  import { pacificaVenue } from "./pacifica.js";
13
13
  import { qfexVenue } from "./qfex.js";
14
+ import { risexVenue } from "./risex.js";
15
+ import { txflowVenue } from "./txflow.js";
16
+ import { variationalVenue } from "./variational.js";
17
+ import { grvtVenue } from "./grvt.js";
18
+ import { extendedVenue } from "./extended.js";
14
19
  export const ALL_VENUES = [
15
20
  pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue,
16
- lighterRhVenue, ondoVenue, arcusVenue, qfexVenue,
21
+ lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, risexVenue, txflowVenue, variationalVenue, grvtVenue,
22
+ extendedVenue,
17
23
  ];
18
24
  /** Idempotent: registers all venues on first call, no-op afterwards. */
19
25
  export function ensureVenuesRegistered() {
@@ -23,4 +29,4 @@ export function ensureVenuesRegistered() {
23
29
  }
24
30
  }
25
31
  ensureVenuesRegistered();
26
- export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, };
32
+ export { pacificaVenue, hyperliquidVenue, lighterVenue, asterVenue, lighterRhVenue, ondoVenue, arcusVenue, qfexVenue, risexVenue, txflowVenue, variationalVenue, grvtVenue, extendedVenue, };