suprafx-agent-sdk 0.3.1

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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +452 -0
  3. package/dist/bin/suprafx-mcp.d.ts +15 -0
  4. package/dist/bin/suprafx-mcp.js +238 -0
  5. package/dist/bin/suprafx-mcp.js.map +1 -0
  6. package/dist/src/asset-registry.d.ts +61 -0
  7. package/dist/src/asset-registry.js +118 -0
  8. package/dist/src/asset-registry.js.map +1 -0
  9. package/dist/src/client.d.ts +227 -0
  10. package/dist/src/client.js +282 -0
  11. package/dist/src/client.js.map +1 -0
  12. package/dist/src/derive-ids.d.ts +112 -0
  13. package/dist/src/derive-ids.js +361 -0
  14. package/dist/src/derive-ids.js.map +1 -0
  15. package/dist/src/event-bcs.d.ts +341 -0
  16. package/dist/src/event-bcs.js +767 -0
  17. package/dist/src/event-bcs.js.map +1 -0
  18. package/dist/src/index.d.ts +26 -0
  19. package/dist/src/index.js +26 -0
  20. package/dist/src/index.js.map +1 -0
  21. package/dist/src/mcp/config.d.ts +32 -0
  22. package/dist/src/mcp/config.js +101 -0
  23. package/dist/src/mcp/config.js.map +1 -0
  24. package/dist/src/mcp/lifecycle.d.ts +109 -0
  25. package/dist/src/mcp/lifecycle.js +170 -0
  26. package/dist/src/mcp/lifecycle.js.map +1 -0
  27. package/dist/src/mcp/preflight.d.ts +36 -0
  28. package/dist/src/mcp/preflight.js +291 -0
  29. package/dist/src/mcp/preflight.js.map +1 -0
  30. package/dist/src/mcp/server.d.ts +20 -0
  31. package/dist/src/mcp/server.js +235 -0
  32. package/dist/src/mcp/server.js.map +1 -0
  33. package/dist/src/mcp/tools.d.ts +51 -0
  34. package/dist/src/mcp/tools.js +1022 -0
  35. package/dist/src/mcp/tools.js.map +1 -0
  36. package/dist/src/sign-event.d.ts +185 -0
  37. package/dist/src/sign-event.js +331 -0
  38. package/dist/src/sign-event.js.map +1 -0
  39. package/dist/src/signer.d.ts +89 -0
  40. package/dist/src/signer.js +226 -0
  41. package/dist/src/signer.js.map +1 -0
  42. package/package.json +65 -0
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `suprafx-mcp` CLI entry point.
4
+ *
5
+ * Two modes:
6
+ * - `suprafx-mcp init` — interactive setup wizard. Writes
7
+ * `~/.suprafx/config.json` with the user's delegate priv key
8
+ * after they paste it in or point to a JSON file the dApp
9
+ * downloaded.
10
+ * - `suprafx-mcp` (no args) — runs the MCP server over stdio.
11
+ * Designed to be invoked by Claude Desktop / Cursor / Continue
12
+ * as a subprocess. Reads stdin for JSON-RPC, writes stdout for
13
+ * responses, stderr for log lines.
14
+ */
15
+ import { mkdirSync, writeFileSync, existsSync, readFileSync, chmodSync, renameSync } from "node:fs";
16
+ import { homedir } from "node:os";
17
+ import { join } from "node:path";
18
+ import { createInterface } from "node:readline";
19
+ import { runMCPServer } from "../src/mcp/server.js";
20
+ import { loadConfig, resolveMode, resolveToolGroups } from "../src/mcp/config.js";
21
+ /** Read the real version from the installed package.json.
22
+ * A hard-coded string silently goes stale and then LIES about which
23
+ * build is running — exactly the thing `--version` exists to answer. */
24
+ function packageVersion() {
25
+ try {
26
+ const here = new URL("../package.json", import.meta.url);
27
+ const pkg = JSON.parse(readFileSync(here, "utf-8"));
28
+ if (pkg.version)
29
+ return pkg.version;
30
+ }
31
+ catch {
32
+ /* fall through */
33
+ }
34
+ try {
35
+ const here = new URL("../../package.json", import.meta.url);
36
+ const pkg = JSON.parse(readFileSync(here, "utf-8"));
37
+ if (pkg.version)
38
+ return pkg.version;
39
+ }
40
+ catch {
41
+ /* fall through */
42
+ }
43
+ return "unknown";
44
+ }
45
+ async function main() {
46
+ const cmd = process.argv[2];
47
+ if (cmd === "init") {
48
+ await initWizard();
49
+ return;
50
+ }
51
+ if (cmd === "--help" || cmd === "-h" || cmd === "help") {
52
+ printHelp();
53
+ return;
54
+ }
55
+ if (cmd === "--version" || cmd === "-v") {
56
+ console.log(`suprafx-agent-sdk ${packageVersion()}`);
57
+ return;
58
+ }
59
+ const cfg = loadConfig();
60
+ const mode = resolveMode();
61
+ const groups = resolveToolGroups();
62
+ if (!cfg.delegatePrivKeyHex) {
63
+ process.stderr.write("[suprafx-mcp] no delegate key configured. Running in READ-ONLY mode.\n" +
64
+ "[suprafx-mcp] To enable trading tools, run: `suprafx-mcp init`\n");
65
+ }
66
+ else if (mode === "autonomous") {
67
+ process.stderr.write("[suprafx-mcp] AUTONOMOUS mode: money tools will NOT ask for per-call\n" +
68
+ "[suprafx-mcp] acknowledgement. Every write is real money.\n");
69
+ }
70
+ if (!cfg.masterAddress) {
71
+ process.stderr.write("[suprafx-mcp] no master address set — balance, lock and open-order reads\n" +
72
+ "[suprafx-mcp] need it. Set SUPRAFX_MASTER_ADDRESS or re-run `suprafx-mcp init`.\n");
73
+ }
74
+ await runMCPServer({
75
+ baseUrl: cfg.baseUrl,
76
+ delegatePrivKeyHex: cfg.delegatePrivKeyHex,
77
+ masterAddress: cfg.masterAddress,
78
+ mode,
79
+ groups,
80
+ });
81
+ }
82
+ function printHelp() {
83
+ console.log(`
84
+ suprafx-mcp — Model Context Protocol server for SupraFX
85
+
86
+ Usage:
87
+ suprafx-mcp Run the MCP server over stdio (default for Claude Desktop)
88
+ suprafx-mcp init Interactive setup wizard — writes ~/.suprafx/config.json
89
+ suprafx-mcp --help Show this help
90
+ suprafx-mcp --version Print the installed package version
91
+
92
+ Flags:
93
+ --tools=read Expose ONLY read tools, even with a key loaded
94
+ (a keyed monitor agent that cannot trade).
95
+ Also: --tools=read,cancel (cancel-only)
96
+ --tools=read,trade (no cancel class)
97
+ Default: every class the key entitles you to.
98
+ --allow-dangerous AUTONOMOUS mode: money tools stop requiring a
99
+ per-call 'acknowledged:true'. Without this the
100
+ server is GUARDED — every write asks once.
101
+
102
+ Environment overrides:
103
+ SUPRAFX_DELEGATE_PRIV_HEX Hex of delegate ed25519 private key (32 bytes)
104
+ SUPRAFX_MASTER_ADDRESS Your MASTER StarKey address — balances, locks and
105
+ open orders all live there, not on the delegate
106
+ SUPRAFX_BASE_URL Override the dApp base URL (default https://suprafx.ai)
107
+ SUPRAFX_ALLOW_DANGEROUS=1 Same as --allow-dangerous
108
+ SUPRAFX_TOOLS=read,cancel Same as --tools=
109
+
110
+ One-line install (Claude Code):
111
+
112
+ npm install -g suprafx-agent-sdk
113
+ claude mcp add --scope user suprafx -- suprafx-mcp
114
+
115
+ Configure Claude Desktop by adding this to your claude_desktop_config.json:
116
+
117
+ {
118
+ "mcpServers": {
119
+ "suprafx": {
120
+ "command": "suprafx-mcp"
121
+ }
122
+ }
123
+ }
124
+
125
+ Then restart Claude Desktop. Tools will appear in the model's tool palette.
126
+
127
+ Documentation: https://github.com/jtobkin/suprafx-agent-sdk
128
+ `);
129
+ }
130
+ async function initWizard() {
131
+ console.log("\nSupraFX MCP setup wizard\n========================\n");
132
+ console.log("Before you start, you need a delegate keypair authorized");
133
+ console.log("on chain by your master StarKey wallet.");
134
+ console.log("");
135
+ console.log("If you haven't done that yet:");
136
+ console.log(" 1. Go to https://suprafx.ai");
137
+ console.log(" 2. Connect StarKey, open Profile → Delegates");
138
+ console.log(" 3. Click 'Create Delegate'");
139
+ console.log(" 4. Click 'Generate' — a JSON file downloads to your machine.");
140
+ console.log(" KEEP THIS FILE SAFE. The private key inside controls trading.");
141
+ console.log(" 5. Set per-asset caps, sign the policy with StarKey.");
142
+ console.log("");
143
+ console.log("Now paste the 32-byte hex private key (or a path to the");
144
+ console.log("downloaded JSON file). Press enter when done.");
145
+ console.log("");
146
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
147
+ const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
148
+ const input = await ask("Delegate private key (hex or path to JSON): ");
149
+ let privHex;
150
+ if (input.startsWith("/") || input.startsWith("~") || input.startsWith("./")) {
151
+ const path = input.startsWith("~") ? join(homedir(), input.slice(1)) : input;
152
+ if (!existsSync(path)) {
153
+ throw new Error(`File not found: ${path}`);
154
+ }
155
+ const j = JSON.parse(readFileSync(path, "utf-8"));
156
+ const key = j.delegatePrivKeyHex ?? j.privateKeyHex ?? j.privateKey ?? j.priv;
157
+ if (!key) {
158
+ throw new Error(`JSON at ${path} did not contain a recognized private-key field`);
159
+ }
160
+ privHex = String(key);
161
+ }
162
+ else {
163
+ privHex = input;
164
+ }
165
+ privHex = privHex.replace(/^0x/i, "").toLowerCase();
166
+ if (!/^[0-9a-f]{64}$/.test(privHex)) {
167
+ throw new Error(`Expected a 32-byte hex private key (64 hex chars). Got ${privHex.length} chars.`);
168
+ }
169
+ console.log("");
170
+ console.log("Now your MASTER StarKey address — the wallet you connected to");
171
+ console.log("suprafx.ai with, that holds the funds. Your agent needs it to read");
172
+ console.log("balances and locks; the delegate has no balances of its own.");
173
+ console.log("Saving it here means the agent never has to be told it again.");
174
+ console.log("");
175
+ let masterAddress = await ask("Master StarKey address (0x…, or enter to skip): ");
176
+ masterAddress = masterAddress.trim().toLowerCase();
177
+ if (masterAddress.length > 0) {
178
+ const m = masterAddress.startsWith("0x") ? masterAddress.slice(2) : masterAddress;
179
+ if (!/^[0-9a-f]{64}$/.test(m)) {
180
+ rl.close();
181
+ throw new Error(`Expected a 32-byte hex address (64 hex chars, 0x-prefixed). Got ${m.length} chars.`);
182
+ }
183
+ masterAddress = "0x" + m;
184
+ }
185
+ const baseUrl = await ask("SupraFX base URL (press enter for https://suprafx.ai): ");
186
+ rl.close();
187
+ const cfg = { delegatePrivKeyHex: privHex };
188
+ if (masterAddress.length > 0)
189
+ cfg.masterAddress = masterAddress;
190
+ if (baseUrl.length > 0)
191
+ cfg.baseUrl = baseUrl;
192
+ const cfgDir = join(homedir(), ".suprafx");
193
+ mkdirSync(cfgDir, { recursive: true });
194
+ const cfgPath = join(cfgDir, "config.json");
195
+ // Atomic write (temp + rename): a running suprafx-mcp hot-reloads this
196
+ // file, so a truncate-then-write could be read mid-rotation as a partial
197
+ // (invalid JSON) and flip the server to read-only. Write to a temp file
198
+ // with 0600 first, then rename into place (atomic on the same filesystem).
199
+ const tmpPath = `${cfgPath}.tmp`;
200
+ writeFileSync(tmpPath, JSON.stringify(cfg, null, 2), { mode: 0o600 });
201
+ chmodSync(tmpPath, 0o600);
202
+ renameSync(tmpPath, cfgPath);
203
+ console.log(`\n✓ Saved to ${cfgPath} (mode 600 — owner read/write only)`);
204
+ console.log("");
205
+ if (!cfg.masterAddress) {
206
+ console.log("⚠ No master address saved. Balance and open-order reads will need");
207
+ console.log(" one passed by hand every session. Re-run `suprafx-mcp init` to add it.");
208
+ console.log("");
209
+ }
210
+ console.log("Next — Claude Code, one line:");
211
+ console.log("");
212
+ console.log(" claude mcp add --scope user suprafx -- suprafx-mcp");
213
+ console.log("");
214
+ console.log("Or add this to your Claude Desktop config:");
215
+ console.log("");
216
+ console.log(" ~/Library/Application Support/Claude/claude_desktop_config.json");
217
+ console.log("");
218
+ console.log(` {
219
+ "mcpServers": {
220
+ "suprafx": {
221
+ "command": "suprafx-mcp"
222
+ }
223
+ }
224
+ }`);
225
+ console.log("");
226
+ console.log("Restart / reconnect. SupraFX tools will appear in the tool palette —");
227
+ console.log("the key is read at STARTUP, so a running server will not see it until then.");
228
+ console.log("");
229
+ console.log("The server starts GUARDED: every money tool asks for an explicit");
230
+ console.log("acknowledgement per call. For an unattended loop, launch it with");
231
+ console.log("--allow-dangerous. For a monitor that must never trade: --tools=read.");
232
+ console.log("");
233
+ }
234
+ main().catch((e) => {
235
+ process.stderr.write(`[suprafx-mcp] fatal: ${e instanceof Error ? e.message : String(e)}\n`);
236
+ process.exit(1);
237
+ });
238
+ //# sourceMappingURL=suprafx-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suprafx-mcp.js","sourceRoot":"","sources":["../../bin/suprafx-mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * BFT `Amount` encoding math.
3
+ *
4
+ * The council-rust protocol denominates token amounts in `Amount`
5
+ * (u128) using **native per-asset decimals** — an asset with `D`
6
+ * on-chain decimals is carried at the `10^D` scale, exactly as the
7
+ * token contract reports it. See the `council-amount-decimals`
8
+ * decision and council-rust `chain::eth::u256_to_native_amount`.
9
+ * Rates are scaled by `PRICE_SCALE = 10^18` (council-rust `fees.rs`).
10
+ *
11
+ * ## This module is pure math — it embeds NO asset table
12
+ *
13
+ * Every function takes explicit `decimals` values. Per-(chain, asset)
14
+ * decimals are the single responsibility of the `supported_assets`
15
+ * registry, verified against each token's on-chain `decimals()` by
16
+ * `scripts/verify-asset-decimals.ts`. There is deliberately no symbol
17
+ * table here to drift as assets land on new chains — e.g. USDT is 6
18
+ * decimals on Ethereum but 18 on BNB Smart Chain.
19
+ *
20
+ * Sourcing decimals:
21
+ * - server: `getAssetDecimals(chain, symbol)` — `lib/council/asset-decimals.ts`
22
+ * - client: `clientAssetDecimals(chain, symbol)` — `lib/council/client-asset-decimals.ts`
23
+ * (both read the `supported_assets` registry; client via `GET /api/assets`)
24
+ */
25
+ /**
26
+ * Convert a display-unit amount to a BFT `Amount` (u128) at the asset's
27
+ * native scale: `displayAmount × 10^decimals`.
28
+ *
29
+ * `decimals` is the asset's on-chain decimal precision on its chain
30
+ * (from `supported_assets`). High-decimal assets split through 10^9 to
31
+ * stay within IEEE-754 safe-integer range.
32
+ */
33
+ export declare function toMicroUnits(amountDisplay: number, decimals: number): bigint;
34
+ /**
35
+ * Convert a display exchange rate (quote per base) to the BFT-scaled
36
+ * `rate` (u128).
37
+ *
38
+ * Protocol definition (council-rust `fees.rs`):
39
+ * `rate / PRICE_SCALE = quote-micro-units per base-micro-unit`
40
+ *
41
+ * With native per-asset decimals on both legs:
42
+ * `rate_BFT = rateDisplay × 10^(18 + quoteDecimals − baseDecimals)`
43
+ */
44
+ export declare function toRateBFT(rateDisplay: number, baseDecimals: number, quoteDecimals: number): bigint;
45
+ /**
46
+ * Parse a `"BASE/QUOTE"` pair string into its two uppercase symbols.
47
+ * @throws if the format is invalid.
48
+ */
49
+ export declare function parsePair(pair: string): {
50
+ base: string;
51
+ quote: string;
52
+ };
53
+ /**
54
+ * Encode `PlaceQuote` amounts: `fill_size` in base-asset native
55
+ * micro-units, `rate` BFT-scaled. Caller supplies the base/quote
56
+ * decimals (from the `supported_assets` registry).
57
+ */
58
+ export declare function encodePlaceQuoteAmounts(sizeDisplay: number, rateDisplay: number, baseDecimals: number, quoteDecimals: number): {
59
+ fillSizeMicro: bigint;
60
+ rateBFT: bigint;
61
+ };
@@ -0,0 +1,118 @@
1
+ /**
2
+ * BFT `Amount` encoding math.
3
+ *
4
+ * The council-rust protocol denominates token amounts in `Amount`
5
+ * (u128) using **native per-asset decimals** — an asset with `D`
6
+ * on-chain decimals is carried at the `10^D` scale, exactly as the
7
+ * token contract reports it. See the `council-amount-decimals`
8
+ * decision and council-rust `chain::eth::u256_to_native_amount`.
9
+ * Rates are scaled by `PRICE_SCALE = 10^18` (council-rust `fees.rs`).
10
+ *
11
+ * ## This module is pure math — it embeds NO asset table
12
+ *
13
+ * Every function takes explicit `decimals` values. Per-(chain, asset)
14
+ * decimals are the single responsibility of the `supported_assets`
15
+ * registry, verified against each token's on-chain `decimals()` by
16
+ * `scripts/verify-asset-decimals.ts`. There is deliberately no symbol
17
+ * table here to drift as assets land on new chains — e.g. USDT is 6
18
+ * decimals on Ethereum but 18 on BNB Smart Chain.
19
+ *
20
+ * Sourcing decimals:
21
+ * - server: `getAssetDecimals(chain, symbol)` — `lib/council/asset-decimals.ts`
22
+ * - client: `clientAssetDecimals(chain, symbol)` — `lib/council/client-asset-decimals.ts`
23
+ * (both read the `supported_assets` registry; client via `GET /api/assets`)
24
+ */
25
+ /** `rate` fixed-point exponent. council-rust `fees.rs` PRICE_SCALE = 10^18. */
26
+ const PRICE_SCALE_EXP = 18;
27
+ /** Upper bound on plausible token decimals — guards against bad registry data. */
28
+ const MAX_DECIMALS = 36;
29
+ /** bigint exponentiation (avoids `**` for older TS lib targets). */
30
+ function bigintPow(base, exp) {
31
+ if (exp < 0)
32
+ throw new Error(`bigintPow: negative exponent ${exp}`);
33
+ let result = BigInt(1);
34
+ for (let i = 0; i < exp; i++)
35
+ result *= base;
36
+ return result;
37
+ }
38
+ function assertValidDecimals(decimals, label) {
39
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > MAX_DECIMALS) {
40
+ throw new Error(`${label}: invalid decimals ${decimals} (expected integer 0..${MAX_DECIMALS})`);
41
+ }
42
+ }
43
+ /**
44
+ * Convert a display-unit amount to a BFT `Amount` (u128) at the asset's
45
+ * native scale: `displayAmount × 10^decimals`.
46
+ *
47
+ * `decimals` is the asset's on-chain decimal precision on its chain
48
+ * (from `supported_assets`). High-decimal assets split through 10^9 to
49
+ * stay within IEEE-754 safe-integer range.
50
+ */
51
+ export function toMicroUnits(amountDisplay, decimals) {
52
+ assertValidDecimals(decimals, "toMicroUnits");
53
+ if (!Number.isFinite(amountDisplay) || amountDisplay < 0) {
54
+ throw new Error(`toMicroUnits: invalid amount ${amountDisplay}`);
55
+ }
56
+ if (decimals <= 15) {
57
+ // 10^15 < 2^53 — exact in float.
58
+ return BigInt(Math.round(amountDisplay * 10 ** decimals));
59
+ }
60
+ // Split at 9 to stay within safe float range (2^53 ≈ 9×10^15).
61
+ const lower = BigInt(Math.round(amountDisplay * 1e9));
62
+ return lower * bigintPow(BigInt(10), decimals - 9);
63
+ }
64
+ /**
65
+ * Convert a display exchange rate (quote per base) to the BFT-scaled
66
+ * `rate` (u128).
67
+ *
68
+ * Protocol definition (council-rust `fees.rs`):
69
+ * `rate / PRICE_SCALE = quote-micro-units per base-micro-unit`
70
+ *
71
+ * With native per-asset decimals on both legs:
72
+ * `rate_BFT = rateDisplay × 10^(18 + quoteDecimals − baseDecimals)`
73
+ */
74
+ export function toRateBFT(rateDisplay, baseDecimals, quoteDecimals) {
75
+ assertValidDecimals(baseDecimals, "toRateBFT base");
76
+ assertValidDecimals(quoteDecimals, "toRateBFT quote");
77
+ if (!Number.isFinite(rateDisplay) || rateDisplay < 0) {
78
+ throw new Error(`toRateBFT: invalid rate ${rateDisplay}`);
79
+ }
80
+ const totalExp = PRICE_SCALE_EXP + quoteDecimals - baseDecimals;
81
+ if (totalExp < 0) {
82
+ // Quote asset has far fewer decimals than base — encoding here
83
+ // would truncate sub-unit precision. Refuse rather than silently
84
+ // lose money-precision; this is unreachable for realistic pairs.
85
+ throw new Error(`toRateBFT: negative scale exponent ${totalExp} (baseDec ${baseDecimals}, quoteDec ${quoteDecimals})`);
86
+ }
87
+ if (totalExp >= 9) {
88
+ const lower = BigInt(Math.round(rateDisplay * 1e9));
89
+ return lower * bigintPow(BigInt(10), totalExp - 9);
90
+ }
91
+ return BigInt(Math.round(rateDisplay * 10 ** totalExp));
92
+ }
93
+ /**
94
+ * Parse a `"BASE/QUOTE"` pair string into its two uppercase symbols.
95
+ * @throws if the format is invalid.
96
+ */
97
+ export function parsePair(pair) {
98
+ const parts = pair.split("/");
99
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
100
+ throw new Error(`parsePair: expected "BASE/QUOTE", got "${pair}"`);
101
+ }
102
+ return {
103
+ base: parts[0].trim().toUpperCase(),
104
+ quote: parts[1].trim().toUpperCase(),
105
+ };
106
+ }
107
+ /**
108
+ * Encode `PlaceQuote` amounts: `fill_size` in base-asset native
109
+ * micro-units, `rate` BFT-scaled. Caller supplies the base/quote
110
+ * decimals (from the `supported_assets` registry).
111
+ */
112
+ export function encodePlaceQuoteAmounts(sizeDisplay, rateDisplay, baseDecimals, quoteDecimals) {
113
+ return {
114
+ fillSizeMicro: toMicroUnits(sizeDisplay, baseDecimals),
115
+ rateBFT: toRateBFT(rateDisplay, baseDecimals, quoteDecimals),
116
+ };
117
+ }
118
+ //# sourceMappingURL=asset-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-registry.js","sourceRoot":"","sources":["../../src/asset-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Thin HTTP client over the SupraFX dApp's public endpoints.
3
+ *
4
+ * Wraps the read + write surfaces documented in
5
+ * `docs/INTEGRATING-AGENTS.md`. No auth required for reads; writes
6
+ * carry their own ed25519 signature inside the BCS envelope (see
7
+ * `./signer.ts`).
8
+ *
9
+ * Pure fetch — no global state, no caching beyond the chain-info
10
+ * lookup. Safe to use from the MCP server, from a cookbook script,
11
+ * or as a library inside a larger agent codebase.
12
+ */
13
+ export interface SupraFxClientOptions {
14
+ /**
15
+ * Base URL of the SupraFX dApp. Defaults to `https://suprafx.ai`.
16
+ * Override for staging or for direct validator HTTP submit.
17
+ */
18
+ baseUrl?: string;
19
+ /** Per-request timeout in ms. Defaults to 15000. */
20
+ timeoutMs?: number;
21
+ }
22
+ export interface ChainInfo {
23
+ chainId: string;
24
+ chainIdHashHex: string;
25
+ threshold: number;
26
+ /** Live venue also returns these; optional so older deployments parse. */
27
+ validatorCount?: number;
28
+ stateMachineVersion?: number;
29
+ }
30
+ export interface AssetInfo {
31
+ chain_id: string;
32
+ asset_symbol: string;
33
+ contract_address: string | null;
34
+ decimals: number;
35
+ }
36
+ export interface PlatformBalance {
37
+ asset: string;
38
+ available: number;
39
+ locked_in_orders: number;
40
+ locked_in_rfq: number;
41
+ total: number;
42
+ }
43
+ /** One deposit claim as `GET /api/platform/deposit` summarises it. */
44
+ export interface DepositClaimSummary {
45
+ claim_id: string;
46
+ claimer_address: string;
47
+ chain: string;
48
+ tx_hash: string;
49
+ asset: string;
50
+ /** Decimal string, never a float. */
51
+ amount: string;
52
+ /** Raw venue status, e.g. `awaiting_council`, `rejected_wrong_vault`. */
53
+ status: string;
54
+ state: "pending" | "credited" | "rejected" | "expired";
55
+ created_at: string;
56
+ credited_at: string | null;
57
+ credited_batch_number: number | null;
58
+ rejection_reason: string | null;
59
+ age_seconds: number;
60
+ /** Pending for longer than the venue's fresh-wallet threshold. NOT a failure. */
61
+ stale: boolean;
62
+ next_step: string;
63
+ /**
64
+ * True when `state` came from the venue's ledger rather than the claim
65
+ * record — the money provably arrived while the record still says
66
+ * otherwise. `status` keeps the raw record value, so the two can disagree
67
+ * in one response; `state` is the one to act on.
68
+ */
69
+ reconciled_from_ledger?: boolean;
70
+ /**
71
+ * What the chain actually credited, when the venue matched a ledger entry.
72
+ * May differ from `amount`, which is what the depositor claimed to send.
73
+ */
74
+ credited_amount?: string | null;
75
+ }
76
+ /** Single-claim lookup. `found:false` is a normal answer, not an error. */
77
+ export type DepositStatusLookup = {
78
+ found: true;
79
+ claim: DepositClaimSummary;
80
+ } | {
81
+ found: false;
82
+ chain: string;
83
+ tx_hash: string;
84
+ state: "unclaimed";
85
+ next_step: string;
86
+ };
87
+ export interface DepositClaimList {
88
+ address: string;
89
+ claims: DepositClaimSummary[];
90
+ counts: {
91
+ pending: number;
92
+ stale: number;
93
+ credited: number;
94
+ rejected: number;
95
+ expired: number;
96
+ /** How many of these were only known credited via the ledger. */
97
+ reconciled_from_ledger?: number;
98
+ };
99
+ truncated: boolean;
100
+ }
101
+ /** Public delegate-policy response. Additional venue fields are preserved. */
102
+ export interface DelegatePolicy {
103
+ active?: boolean;
104
+ master?: string;
105
+ master_address?: string;
106
+ [key: string]: unknown;
107
+ }
108
+ export interface OrderbookRfq {
109
+ id: string;
110
+ taker_address: string;
111
+ pair: string;
112
+ size: number;
113
+ remaining_size: number;
114
+ source_chain: string;
115
+ dest_chain: string;
116
+ reference_price: number;
117
+ status: string;
118
+ settlement_mode: string;
119
+ allow_partial_fills: boolean;
120
+ min_fill_size: number;
121
+ expires_at: string;
122
+ created_at: string;
123
+ }
124
+ export interface SubmitResult {
125
+ ok: boolean;
126
+ batch?: number;
127
+ event_hash_hex?: string;
128
+ code?: string;
129
+ detail?: string;
130
+ per_validator?: unknown[];
131
+ }
132
+ /**
133
+ * Stable, machine-readable error categories. An agent can branch on
134
+ * `code` without parsing prose, and `action` names the one thing that
135
+ * clears it. Mirrors the envelope Kraken ships on every command.
136
+ */
137
+ export type SupraFxErrorCode = "auth" | "rate_limit" | "validation" | "not_found" | "api" | "network" | "timeout" | "seq_desync" | "needs_acknowledgement" | "read_only";
138
+ export type SupraFxErrorAction = "authenticate" | "backoff" | "fix_input" | "reconnect" | "configure_key" | "acknowledge" | "retry" | "report";
139
+ /** An error carrying a stable category and the action that clears it. */
140
+ export declare class SupraFxError extends Error {
141
+ readonly code: SupraFxErrorCode;
142
+ readonly action: SupraFxErrorAction;
143
+ readonly status?: number;
144
+ readonly detail?: unknown;
145
+ constructor(code: SupraFxErrorCode, action: SupraFxErrorAction, message: string, opts?: {
146
+ status?: number;
147
+ detail?: unknown;
148
+ });
149
+ /** The JSON body an MCP handler returns on failure. */
150
+ toEnvelope(): {
151
+ error: SupraFxErrorCode;
152
+ action: SupraFxErrorAction;
153
+ message: string;
154
+ status?: number;
155
+ detail?: unknown;
156
+ };
157
+ }
158
+ export interface OracleQuote {
159
+ pair: string;
160
+ conversionRate: number | null;
161
+ updatedAt: number | null;
162
+ /** Age of the quote in ms at read time. */
163
+ ageMs: number | null;
164
+ }
165
+ export declare class SupraFxClient {
166
+ private readonly baseUrl;
167
+ private readonly timeoutMs;
168
+ private cachedChainInfo;
169
+ private cachedClockOffset;
170
+ constructor(opts?: SupraFxClientOptions);
171
+ /**
172
+ * Fetch the canonical chain-id hash and validator threshold.
173
+ * Cached for the lifetime of the client — these values are
174
+ * constant per chain genesis.
175
+ */
176
+ getChainInfo(): Promise<ChainInfo>;
177
+ /**
178
+ * Difference between the venue's HTTP clock and the local clock.
179
+ * Best-effort only: expiry calculation must remain available when the
180
+ * header or endpoint is unavailable.
181
+ */
182
+ getVenueClockOffsetMs(): Promise<number>;
183
+ /** Current committed batch height. Useful for `expires_at_batch` math. */
184
+ getCurrentBatch(): Promise<number>;
185
+ /**
186
+ * Next strictly-monotonic sequence number this address must use
187
+ * for its next signed event. `0` for a brand-new account.
188
+ */
189
+ getSequenceNumber(address: string): Promise<number>;
190
+ /** All supported assets with canonical chain id + decimals. */
191
+ listAssets(): Promise<AssetInfo[]>;
192
+ /**
193
+ * Available + locked balances for `address` (a master Supra account).
194
+ * Returns an empty array if the address has no balance rows.
195
+ */
196
+ getBalances(address: string): Promise<PlatformBalance[]>;
197
+ /**
198
+ * Status of one deposit claim, keyed on the chain and the L1 transaction
199
+ * hash. Answers "still crediting, or failed?" — see `state`, `stale` and
200
+ * `next_step`. An unknown transaction is `found:false`, not an error: a
201
+ * deposit made without recording a claim still credits through the
202
+ * validator bridge, it is just not visible here.
203
+ */
204
+ getDepositStatus(chain: string, txHash: string): Promise<DepositStatusLookup>;
205
+ /** Every deposit claim recorded by `address` (a master account), newest first. */
206
+ listDepositClaims(address: string, limit?: number): Promise<DepositClaimList>;
207
+ /** On-chain policy currently associated with a delegate address. */
208
+ getDelegatePolicy(address: string): Promise<DelegatePolicy | null>;
209
+ /**
210
+ * Public orderbook: open RFQs. Filters as documented in
211
+ * `INTEGRATING-AGENTS.md` §2.
212
+ */
213
+ getOrderbook(filters?: {
214
+ pair?: string;
215
+ status?: string;
216
+ limit?: number;
217
+ }): Promise<OrderbookRfq[]>;
218
+ /**
219
+ * Venue oracle quote for `pair` (e.g. `"ETH/USDC"`), with the quote's
220
+ * age computed at read time. Quote against THIS, never an external
221
+ * price — and never against a stale one (see `ORACLE_STALE_MS`).
222
+ */
223
+ getOracle(pair: string): Promise<OracleQuote>;
224
+ submitEnvelope(endpoint: "submit-rfq" | "place-quote" | "accept-quote" | "withdraw-quote" | "cancel-rfq", bodyFieldName: string, envelopeBcsHex: string): Promise<SubmitResult>;
225
+ private get;
226
+ private post;
227
+ }