@blazephoenix/sdk 0.4.0 → 0.5.2

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.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @blazephoenix/sdk
2
2
 
3
3
  Official TypeScript SDK for **[BlazePhoenix](https://blazephoenix.xyz)** — the on-chain
4
- DEX aggregator on **Base · Ethereum · Optimism · Arbitrum**.
4
+ DEX aggregator on **Base · Ethereum · Optimism · Arbitrum · Robinhood Chain**.
5
5
 
6
6
  Every number the API serves is computed **on-chain** by the Quoter contract
7
7
  (`previewPlan`) — your bot, your frontend and the site itself all read the same truth.
@@ -120,6 +120,27 @@ npm i grammy viem
120
120
  BOT_TOKEN=... RPC_URL=https://your-base-rpc npx tsx examples/phoenix-bot.ts
121
121
  ```
122
122
 
123
+ ## Bring your own RPC (optional, v0.5.0)
124
+
125
+ Set `rpc` once on the client and every read goes through **your** node instead
126
+ of the shared pool:
127
+
128
+ ```ts
129
+ const blaze = new BlazePhoenix({ rpc: process.env.MY_RPC });
130
+ // or per call:
131
+ await blaze.quote({ chain: 'base', tokenIn: 'WETH', tokenOut: 'USDC', amountIn: 10n ** 18n, rpc });
132
+ ```
133
+
134
+ The service stays **free and keyless either way** — this exists so sustained
135
+ automation carries its own read volume, which is what keeps the free path
136
+ viable for callers who cannot bring a node. Your node is tried first and the
137
+ public pool remains the fallback, so supplying one can only make calls more
138
+ reliable, never less. `meta.rpc` in the response reads `byo` or `shared`.
139
+
140
+ Any free tier is enough. Lock the key to your domain or IP in the provider
141
+ dashboard if it will run in a browser. Full guide:
142
+ <https://blazephoenix.xyz/learn/bring-your-own-rpc>
143
+
123
144
  ## Errors
124
145
 
125
146
  HTTP-level failures throw `BlazeApiError` with a stable `code`:
package/dist/index.cjs CHANGED
@@ -55,6 +55,23 @@ var CHAINS = {
55
55
  router: "0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A",
56
56
  quoter: "0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2"
57
57
  }
58
+ },
59
+ // Robinhood Chain — the same bytecode as every other deployment, so every
60
+ // property proven elsewhere holds here. Note the USD asset is USDG, not
61
+ // USDC: the `usdc` field carries the chain's canonical dollar token, which
62
+ // on this chain is USDG. Explorer is Blockscout rather than an Etherscan.
63
+ 4663: {
64
+ chainId: 4663,
65
+ name: "Robinhood",
66
+ explorer: "https://robinhoodchain.blockscout.com",
67
+ weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
68
+ usdc: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
69
+ contracts: {
70
+ hub: "0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483",
71
+ solver: "0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f",
72
+ router: "0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A",
73
+ quoter: "0xE1aE5f49013920CF71De8CED4043e14C4d63416b"
74
+ }
58
75
  }
59
76
  };
60
77
  function resolveChain(chain) {
@@ -71,12 +88,16 @@ function resolveChain(chain) {
71
88
  "42161": 42161,
72
89
  arb: 42161,
73
90
  arbitrum: 42161,
74
- "arbitrum-one": 42161
91
+ "arbitrum-one": 42161,
92
+ "4663": 4663,
93
+ rh: 4663,
94
+ robinhood: 4663,
95
+ "robinhood-chain": 4663
75
96
  };
76
97
  const id = aliases[String(chain).trim().toLowerCase()];
77
98
  if (!id) {
78
99
  throw new Error(
79
- `Unsupported chain "${chain}" \u2014 use 8453/base, 1/eth, 10/optimism or 42161/arbitrum`
100
+ `Unsupported chain "${chain}" \u2014 use 8453/base, 1/eth, 10/optimism, 42161/arbitrum or 4663/robinhood`
80
101
  );
81
102
  }
82
103
  return id;
@@ -101,6 +122,9 @@ var PUBLIC_RPCS = {
101
122
  "https://arbitrum-one-rpc.publicnode.com",
102
123
  "https://arb1.arbitrum.io/rpc",
103
124
  "https://1rpc.io/arb"
125
+ ],
126
+ 4663: [
127
+ "https://rpc.mainnet.chain.robinhood.com"
104
128
  ]
105
129
  };
106
130
  var FEE_BPS = 28;
@@ -181,6 +205,7 @@ function toSearch(req) {
181
205
  if (req.slippageBps !== void 0) sp.set("slippageBps", String(req.slippageBps));
182
206
  if (req.deadlineSec !== void 0) sp.set("deadlineSec", String(req.deadlineSec));
183
207
  if (req.exact) sp.set("exact", "1");
208
+ if (req.rpc) sp.set("rpc", req.rpc.trim());
184
209
  return sp;
185
210
  }
186
211
  var BlazePhoenix = class {
@@ -189,17 +214,24 @@ var BlazePhoenix = class {
189
214
  timeoutMs;
190
215
  retries;
191
216
  cacheTtlMs;
217
+ /** Default BYO-RPC endpoint applied to every request that does not set one. */
218
+ rpc;
192
219
  constructor(opts = {}) {
193
220
  this.base = (opts.baseUrl ?? API_BASE).replace(/\/+$/, "");
194
221
  this.fetchFn = opts.fetchFn ?? globalThis.fetch;
195
222
  this.timeoutMs = opts.timeoutMs ?? 15e3;
196
223
  this.retries = opts.retries ?? 2;
197
224
  this.cacheTtlMs = opts.cacheTtlMs ?? 1e3;
225
+ this.rpc = opts.rpc;
198
226
  if (!this.fetchFn) throw new Error("No fetch available \u2014 Node >= 18 required (or pass fetchFn)");
199
227
  }
228
+ /** Fold the client-wide BYO-RPC default into a request that omits one. */
229
+ withRpc(req) {
230
+ return this.rpc && !req.rpc ? { ...req, rpc: this.rpc } : req;
231
+ }
200
232
  /** Build the GET /api/quote URL for a request (useful for logging/debugging). */
201
233
  quoteUrl(req) {
202
- return `${this.base}/api/quote?${toSearch(req).toString()}`;
234
+ return `${this.base}/api/quote?${toSearch(this.withRpc(req)).toString()}`;
203
235
  }
204
236
  async call(path, init) {
205
237
  const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {
@@ -218,7 +250,8 @@ var BlazePhoenix = class {
218
250
  /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.
219
251
  * Identical concurrent calls share one request; preview quotes ride a tiny
220
252
  * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */
221
- async quote(req) {
253
+ async quote(reqIn) {
254
+ const req = this.withRpc(reqIn);
222
255
  const qs = toSearch(req).toString();
223
256
  const key = `Q ${this.base}?${qs}`;
224
257
  const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/resilience.ts","../src/client.ts","../src/abis.ts","../src/erc20.ts","../src/onchain.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// =============================================================================\n// Protocol constants — BlazePhoenix v1.0.0 deployments.\n// Source of truth at runtime: GET https://blazephoenix.xyz/api/manifest\n// (these statics let the SDK work fully offline / on-chain-only).\n// =============================================================================\n\nexport const API_BASE = 'https://blazephoenix.xyz';\n\nexport type SupportedChainId = 1 | 8453 | 10 | 42161;\n\nexport interface ChainInfo {\n chainId: SupportedChainId;\n name: string;\n explorer: string;\n weth: `0x${string}`;\n usdc: `0x${string}`;\n bzpx?: `0x${string}`;\n contracts: {\n hub: `0x${string}`;\n solver: `0x${string}`;\n router: `0x${string}`;\n quoter: `0x${string}`;\n };\n}\n\nexport const CHAINS: Record<SupportedChainId, ChainInfo> = {\n 1: {\n chainId: 1,\n name: 'Ethereum',\n explorer: 'https://etherscan.io',\n weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n contracts: {\n hub: '0xc4FA9a5720fe3294D3AA9fc427E2a760591E57ae',\n solver: '0xc124d91258db0C14bf13b826CF64E16bfEA8a73e',\n router: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n quoter: '0x4a20AA0912388ff7A9221Ab6BFC224cc20Baa0c3',\n },\n },\n 8453: {\n chainId: 8453,\n name: 'Base',\n explorer: 'https://basescan.org',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n bzpx: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n contracts: {\n hub: '0x428554DEe93A1B8B5Bc6Fd19adDAfe55106fc04C',\n solver: '0xB1902990260975dD4C89ad74B1f317bc100CB830',\n router: '0x2a779f9Be49aac57495A8B6467Cc325a8a47Eb9f',\n quoter: '0x4cEF0615614B212895F45Aa1D4833B16666E18d3',\n },\n },\n 10: {\n chainId: 10,\n name: 'Optimism',\n explorer: 'https://optimistic.etherscan.io',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n 42161: {\n chainId: 42161,\n name: 'Arbitrum',\n explorer: 'https://arbiscan.io',\n weth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n};\n\n/** Accepts a chain id (number or numeric string) or a human alias. */\nexport function resolveChain(chain: number | string): SupportedChainId {\n const aliases: Record<string, SupportedChainId> = {\n '1': 1, eth: 1, ethereum: 1, mainnet: 1,\n '8453': 8453, base: 8453,\n '10': 10, op: 10, optimism: 10,\n '42161': 42161, arb: 42161, arbitrum: 42161, 'arbitrum-one': 42161,\n };\n const id = aliases[String(chain).trim().toLowerCase()];\n if (!id) {\n throw new Error(\n `Unsupported chain \"${chain}\" — use 8453/base, 1/eth, 10/optimism or 42161/arbitrum`,\n );\n }\n return id;\n}\n\n/** Public, KEYLESS RPC endpoints per chain — community infrastructure, no\n * providers, no keys (enforced by tests). They make the on-chain module work\n * with ZERO configuration; production integrations should still bring their\n * own `rpcUrl` for guaranteed throughput. */\nexport const PUBLIC_RPCS: Record<SupportedChainId, string[]> = {\n 1: [\n 'https://ethereum-rpc.publicnode.com',\n 'https://cloudflare-eth.com',\n 'https://1rpc.io/eth',\n ],\n 8453: [\n 'https://mainnet.base.org',\n 'https://base-rpc.publicnode.com',\n 'https://1rpc.io/base',\n ],\n 10: [\n 'https://optimism-rpc.publicnode.com',\n 'https://mainnet.optimism.io',\n 'https://1rpc.io/op',\n ],\n 42161: [\n 'https://arbitrum-one-rpc.publicnode.com',\n 'https://arb1.arbitrum.io/rpc',\n 'https://1rpc.io/arb',\n ],\n};\n\n/** Protocol fee (bps) applied to quoted output; execution surplus is fee-exempt. */\nexport const FEE_BPS = 28;\n\n/** Router event topic0 hashes (one `Swap` per fill — index everything with them).\n * Verified against the ABIs by `npm test` (viem toEventSelector). */\nexport const SWAP_TOPIC0 =\n '0xd6d34547c69c5ee3d2667625c188acf1006abb93e0ee7cf03925c67cf7760413' as const;\nexport const SURPLUS_TOPIC0 =\n '0x1a3afef0f067eb51a6bfec6ab3625a4408dd8c3571b72836483e68feb70d1026' as const;\n","// =============================================================================\n// Resilience core — the SDK ships the same meta-patterns the BlazePhoenix\n// edge runs, so every integration is polite and outage-proof by default:\n//\n// • singleflight — identical concurrent calls share ONE request\n// • micro-TTL — a tiny preview cache (default 1s ≈ intra-block) absorbs\n// hot loops without ever serving stale execution data\n// • retry — transient failures (network, 429, 502/503) retry with\n// backoff and RESPECT the server's retry-after header\n//\n// Execution-grade requests (recipient / exact=1) are never TTL-cached here,\n// mirroring the server's own red line.\n// =============================================================================\n\nconst INFLIGHT = new Map<string, Promise<unknown>>();\nconst MEM = new Map<string, { at: number; data: unknown }>();\n\n/** Coalesce concurrent identical work — leader runs, followers share. */\nexport async function singleflight<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const existing = INFLIGHT.get(key) as Promise<T> | undefined;\n if (existing) return existing;\n const flight = fn();\n INFLIGHT.set(key, flight as Promise<unknown>);\n try {\n return await flight;\n } finally {\n INFLIGHT.delete(key);\n }\n}\n\nexport function memGet(key: string, ttlMs: number, now = Date.now()): unknown | undefined {\n if (ttlMs <= 0) return undefined;\n const hit = MEM.get(key);\n return hit && now - hit.at < ttlMs ? hit.data : undefined;\n}\n\nexport function memPut(key: string, data: unknown, now = Date.now()): void {\n MEM.set(key, { at: now, data });\n // Bound the cache — a long-running bot must never leak memory here.\n if (MEM.size > 500) {\n const oldest = MEM.keys().next().value;\n if (oldest !== undefined) MEM.delete(oldest);\n }\n}\n\nexport interface RetryOptions {\n /** Extra attempts after the first (default 2). */\n retries?: number;\n /** Base backoff in ms; grows ×3 per attempt with jitter (default 250). */\n backoffMs?: number;\n timeoutMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction retryDelayMs(res: Response | undefined, attempt: number, base: number): number {\n const ra = Number(res?.headers.get('retry-after'));\n if (Number.isFinite(ra) && ra > 0) return Math.min(10_000, ra * 1000);\n return base * 3 ** attempt + Math.floor(Math.random() * base);\n}\n\n/** Quote reads are idempotent — transient failures deserve another shot. */\nfunction isTransient(res: Response | undefined): boolean {\n return !res || res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504;\n}\n\n/** fetch with timeout + polite retries. Returns the final Response (which may\n * still be an error status — non-transient statuses are never retried). */\nexport async function resilientFetch(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit | undefined,\n opts: RetryOptions = {},\n): Promise<Response> {\n const { retries = 2, backoffMs = 250, timeoutMs = 15_000 } = opts;\n let lastErr: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n let res: Response | undefined;\n try {\n res = await fetchFn(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n if (!isTransient(res)) return res;\n if (attempt === retries) return res;\n } catch (e) {\n lastErr = e;\n if (attempt === retries) throw e;\n }\n await sleep(retryDelayMs(res, attempt, backoffMs));\n }\n /* istanbul ignore next -- loop always returns or throws */\n throw lastErr instanceof Error ? lastErr : new Error('request failed');\n}\n\n/** Test hook. */\nexport function __resetResilience(): void {\n INFLIGHT.clear();\n MEM.clear();\n}\n","// =============================================================================\n// HTTP client — zero dependencies (native fetch). Every quote is computed\n// on-chain by the BlazePhoenix Quoter; the API is a thin mirror of the chain.\n// No API key. Open CORS. https://blazephoenix.xyz/?tab=api\n// =============================================================================\n\nimport { API_BASE, resolveChain } from './constants.js';\nimport { memGet, memPut, resilientFetch, singleflight } from './resilience.js';\nimport type {\n BatchResponse, HealthResponse, ManifestResponse, QuoteRequest, QuoteResponse, QuoteTx,\n} from './types.js';\n\nexport class BlazeApiError extends Error {\n readonly code: string;\n readonly status: number;\n constructor(code: string, message: string, status: number) {\n super(message);\n this.name = 'BlazeApiError';\n this.code = code;\n this.status = status;\n }\n}\n\nexport interface ClientOptions {\n /** Override the API origin (e.g. a mirror). Default: https://blazephoenix.xyz */\n baseUrl?: string;\n /** Custom fetch (tests, proxies). Default: globalThis.fetch. */\n fetchFn?: typeof fetch;\n /** Per-request timeout in ms. Default 15000. */\n timeoutMs?: number;\n /** Extra attempts on transient failures (network, 429, 502-504), honouring\n * the server's retry-after. Default 2. Set 0 to disable. */\n retries?: number;\n /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot\n * loops without serving stale execution data. Default 1000ms; 0 disables. */\n cacheTtlMs?: number;\n}\n\nfunction toSearch(req: QuoteRequest): URLSearchParams {\n const sp = new URLSearchParams();\n sp.set('chain', String(resolveChain(req.chain)));\n sp.set('in', req.tokenIn.trim());\n sp.set('out', req.tokenOut.trim());\n sp.set('amountIn', typeof req.amountIn === 'bigint' ? req.amountIn.toString() : String(req.amountIn).trim());\n if (req.recipient) sp.set('recipient', req.recipient);\n if (req.slippageBps !== undefined) sp.set('slippageBps', String(req.slippageBps));\n if (req.deadlineSec !== undefined) sp.set('deadlineSec', String(req.deadlineSec));\n if (req.exact) sp.set('exact', '1');\n return sp;\n}\n\nexport class BlazePhoenix {\n private readonly base: string;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly cacheTtlMs: number;\n\n constructor(opts: ClientOptions = {}) {\n this.base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n this.fetchFn = opts.fetchFn ?? globalThis.fetch;\n this.timeoutMs = opts.timeoutMs ?? 15_000;\n this.retries = opts.retries ?? 2;\n this.cacheTtlMs = opts.cacheTtlMs ?? 1_000;\n if (!this.fetchFn) throw new Error('No fetch available — Node >= 18 required (or pass fetchFn)');\n }\n\n /** Build the GET /api/quote URL for a request (useful for logging/debugging). */\n quoteUrl(req: QuoteRequest): string {\n return `${this.base}/api/quote?${toSearch(req).toString()}`;\n }\n\n private async call<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {\n retries: this.retries,\n timeoutMs: this.timeoutMs,\n });\n const body = (await res.json().catch(() => null)) as\n | (T & { ok: true })\n | { ok: false; code?: string; error?: string }\n | null;\n if (!body || typeof body !== 'object') {\n throw new BlazeApiError('bad_response', `non-JSON response (HTTP ${res.status})`, res.status);\n }\n if ('ok' in body && body.ok === false) {\n throw new BlazeApiError(body.code ?? 'error', body.error ?? 'request failed', res.status);\n }\n return body as T;\n }\n\n /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.\n * Identical concurrent calls share one request; preview quotes ride a tiny\n * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */\n async quote(req: QuoteRequest): Promise<QuoteResponse> {\n const qs = toSearch(req).toString();\n const key = `Q ${this.base}?${qs}`;\n const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;\n if (cacheable) {\n const hit = memGet(key, this.cacheTtlMs);\n if (hit) return hit as QuoteResponse;\n }\n const q = await singleflight(key, () => this.call<QuoteResponse>(`/api/quote?${qs}`));\n if (cacheable) memPut(key, q);\n return q;\n }\n\n /** Up to 10 quotes in one round-trip (screeners / arb loops).\n * Per-item failures come back inline — the batch itself only throws on\n * transport/validation errors. Identical concurrent batches coalesce. */\n quoteBatch(reqs: QuoteRequest[]): Promise<BatchResponse> {\n const body = JSON.stringify({\n requests: reqs.map((r) => Object.fromEntries(toSearch(r).entries())),\n });\n return singleflight(`B ${this.base} ${body}`, () =>\n this.call<BatchResponse>('/api/quote/batch', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body,\n }));\n }\n\n /** Service health + per-chain live flags. Zero upstream cost server-side —\n * poll it from your monitor as often as you like. */\n health(): Promise<HealthResponse> {\n return this.call<HealthResponse>('/api/health');\n }\n\n /** Machine-readable protocol manifest — near-static, cached for 1h. */\n async manifest(): Promise<ManifestResponse> {\n const key = `M ${this.base}`;\n const hit = memGet(key, 3_600_000);\n if (hit) return hit as ManifestResponse;\n const m = await singleflight(key, () => this.call<ManifestResponse>('/api/manifest'));\n memPut(key, m);\n return m;\n }\n}\n\nexport interface PollOptions {\n /** Tick interval in ms (min 500, default 4000). */\n intervalMs?: number;\n onError?: (e: unknown) => void;\n}\n\n/** Poll a pair and get called back with each fresh quote — the heartbeat of a\n * price bot in one line. Overlap-safe (a slow tick is skipped, not stacked).\n * Returns a stop function. */\nexport function pollQuote(\n client: BlazePhoenix,\n req: QuoteRequest,\n onQuote: (q: QuoteResponse) => void,\n opts: PollOptions = {},\n): () => void {\n const interval = Math.max(500, opts.intervalMs ?? 4_000);\n let stopped = false;\n let busy = false;\n const tick = async () => {\n if (stopped || busy) return;\n busy = true;\n try {\n const q = await client.quote(req);\n if (!stopped) onQuote(q);\n } catch (e) {\n if (!stopped) opts.onError?.(e);\n } finally {\n busy = false;\n }\n };\n void tick();\n const timer = setInterval(() => { void tick(); }, interval);\n return () => { stopped = true; clearInterval(timer); };\n}\n\n/** The ready-to-broadcast transaction from a quote (requires `recipient` in the\n * request and an ERC-20 input). Throws with a precise reason otherwise. */\nexport function buildSwapTx(q: QuoteResponse): QuoteTx {\n if (q.tx) return q.tx;\n if (q.wrapRequired) {\n throw new Error('native ETH input: wrap to WETH first (WETH.deposit), then re-quote with in=WETH');\n }\n throw new Error('no tx in quote — pass `recipient` in the request (and check quote.canExecute)');\n}\n\nexport interface DeepLinkOptions {\n chain?: number | string;\n tokenIn?: string;\n tokenOut?: string;\n /** Human units for the pay field (e.g. \"0.5\"). */\n amount?: string;\n tab?: 'home' | 'swap' | 'staking' | 'airdrop' | 'api';\n baseUrl?: string;\n}\n\n/** A shareable link that opens the site pre-filled — bot buttons, referral posts. */\nexport function deepLink(opts: DeepLinkOptions = {}): string {\n const base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n const sp = new URLSearchParams();\n sp.set('tab', opts.tab ?? 'swap');\n if (opts.chain !== undefined) sp.set('chain', String(resolveChain(opts.chain)));\n if (opts.tokenIn) sp.set('in', opts.tokenIn);\n if (opts.tokenOut) sp.set('out', opts.tokenOut);\n if (opts.amount) sp.set('amt', opts.amount);\n return `${base}/?${sp.toString()}`;\n}\n","// =============================================================================\n// BlazePhoenix Router + Quoter ABI fragments (match the v1.0.0 deployments).\n// The Route/Hop/Leg tuple mirrors BlazePhoenixCore.sol — a decoded route from\n// `previewPlan` round-trips verbatim into `swapExactIn`.\n// =============================================================================\n\nconst LEG_COMPONENTS = [\n { name: 'pool', type: 'address' },\n { name: 'hooks', type: 'address' },\n { name: 'kind', type: 'uint8' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'stable', type: 'bool' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'auxId', type: 'bytes32' },\n] as const;\n\nconst HOP_COMPONENTS = [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'legs', type: 'tuple[]', components: LEG_COMPONENTS },\n] as const;\n\nconst ROUTE_COMPONENTS = [\n { name: 'hops', type: 'tuple[]', components: HOP_COMPONENTS },\n { name: 'totalOut', type: 'uint256' },\n { name: 'singleOut', type: 'uint256' },\n { name: 'singleOutFloor', type: 'uint256' },\n { name: 'expectedImpactBps', type: 'uint256' },\n { name: 'confidenceWad', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hasSurplus', type: 'bool' },\n { name: 'isV4Bundle', type: 'bool' },\n] as const;\n\nconst PREVIEW_COMPONENTS = [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'grossOut', type: 'uint256' },\n { name: 'protocolFee', type: 'uint256' },\n { name: 'safetyBuffer', type: 'uint256' },\n { name: 'netOut', type: 'uint256' },\n { name: 'ironFloor', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'effectiveMinOut', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hops', type: 'uint256' },\n { name: 'legs', type: 'uint256' },\n { name: 'topology', type: 'uint8' },\n { name: 'bridgeUsed', type: 'address' },\n { name: 'canExecute', type: 'bool' },\n] as const;\n\nexport const QUOTER_ABI = [\n {\n type: 'function',\n name: 'previewPlan',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'pv', type: 'tuple', components: PREVIEW_COMPONENTS },\n { name: 'fallbackRoute', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'hasFallback', type: 'bool' },\n ],\n },\n {\n type: 'function',\n name: 'previewPlanExact',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'exactOut', type: 'uint256' },\n ],\n },\n] as const;\n\nexport const ROUTER_ABI = [\n {\n type: 'function',\n name: 'swapExactIn',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'amountIn', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'event',\n name: 'Swap',\n inputs: [\n { name: 'user', type: 'address', indexed: true },\n { name: 'tokenIn', type: 'address', indexed: true },\n { name: 'tokenOut', type: 'address', indexed: true },\n { name: 'amountIn', type: 'uint256', indexed: false },\n { name: 'amountOut', type: 'uint256', indexed: false },\n { name: 'legs', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Surplus',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'amount', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// =============================================================================\n// ERC-20 helpers — zero dependencies. Completes the integration loop:\n// quote → buildApproveTx (once per token) → buildSwapTx → send.\n// Plus human-amount conversion so callers never hand-count decimals.\n// =============================================================================\n\nimport { CHAINS, resolveChain } from './constants.js';\nimport type { Address, ChainRef, Hex, QuoteTx } from './types.js';\n\n/** Unlimited allowance (2^256 − 1). Prefer EXACT amounts — pass the amount you\n * are about to swap; use MAX_UINT256 only when you consciously want one\n * approval forever (bots with their own key management). */\nexport const MAX_UINT256 = (1n << 256n) - 1n;\n\nconst HEX_ADDR = /^0x[0-9a-fA-F]{40}$/;\n\n// approve(address,uint256)\nconst APPROVE_SELECTOR = '0x095ea7b3';\n\nfunction pad32(hexNo0x: string): string {\n return hexNo0x.padStart(64, '0');\n}\n\nexport interface ApproveOptions {\n /** ERC-20 token to approve (the swap's tokenIn). */\n token: Address;\n /** Chain id or name — picks the Router as the default spender. */\n chain: ChainRef;\n /** Allowance in base units. Be exact; MAX_UINT256 opts into unlimited. */\n amount: bigint;\n /** Override the spender (defaults to the BlazePhoenix Router). */\n spender?: Address;\n}\n\n/** Ready-to-send `approve` transaction for the Router (or a custom spender).\n * Send it once per token before the first swap; then swap freely. */\nexport function buildApproveTx(opts: ApproveOptions): QuoteTx {\n const chainId = resolveChain(opts.chain);\n const spender = opts.spender ?? CHAINS[chainId].contracts.router;\n if (!HEX_ADDR.test(opts.token)) throw new Error(`invalid token address: ${opts.token}`);\n if (!HEX_ADDR.test(spender)) throw new Error(`invalid spender address: ${spender}`);\n if (opts.amount < 0n || opts.amount > MAX_UINT256) throw new Error('amount out of uint256 range');\n const data = (APPROVE_SELECTOR\n + pad32(spender.slice(2).toLowerCase())\n + pad32(opts.amount.toString(16))) as Hex;\n return { to: opts.token, data, value: '0' };\n}\n\n/** \"1.5\" + 18 decimals → 1500000000000000000n. Pure string math — no floats,\n * no precision loss. Rejects more fractional digits than the token carries. */\nexport function toBaseUnits(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const s = amount.trim();\n const m = /^(\\d+)(?:\\.(\\d+))?$/.exec(s);\n if (!m) throw new Error(`invalid amount: \"${amount}\" (use e.g. \"1.5\")`);\n const [, whole, frac = ''] = m;\n if (frac.length > decimals) {\n throw new Error(`\"${amount}\" has ${frac.length} fractional digits — token only carries ${decimals}`);\n }\n return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(frac.padEnd(decimals, '0') || '0');\n}\n\n/** 1500000000000000000n + 18 decimals → \"1.5\" (trailing zeros trimmed).\n * `maxDp` optionally truncates the fractional part for display. */\nexport function fromBaseUnits(v: bigint | string, decimals: number, maxDp?: number): string {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const n = typeof v === 'bigint' ? v : BigInt(v);\n const neg = n < 0n;\n const abs = neg ? -n : n;\n const base = 10n ** BigInt(decimals);\n const whole = abs / base;\n let frac = (abs % base).toString().padStart(decimals, '0');\n if (maxDp !== undefined) frac = frac.slice(0, Math.max(0, maxDp));\n frac = frac.replace(/0+$/, '');\n return `${neg ? '-' : ''}${whole}${frac ? `.${frac}` : ''}`;\n}\n","// =============================================================================\n// On-chain module — skip HTTP entirely: quote on the Quoter from your own\n// node and watch the Router's fills. Needs the optional `viem` peer:\n// npm i viem\n// You supply the RPC URL — the SDK ships no keys and no default endpoints.\n// =============================================================================\n\nimport { QUOTER_ABI, ROUTER_ABI } from './abis.js';\nimport { CHAINS, PUBLIC_RPCS, resolveChain, type SupportedChainId } from './constants.js';\nimport type { Address, Fill } from './types.js';\n\nasync function loadViem() {\n try {\n return await import('viem');\n } catch {\n throw new Error(\"this feature needs the optional peer dependency 'viem' — npm i viem\");\n }\n}\n\nexport interface OnChainOptions {\n chain: number | string;\n /** Your RPC endpoint. OPTIONAL since v0.4.0 — omitted, the SDK falls back\n * across public keyless endpoints (fine for dev/bots; bring your own node\n * for production throughput). The SDK still ships no providers and no keys. */\n rpcUrl?: string;\n}\n\n/** viem transport: caller's RPC when given, else public-endpoint fallback. */\nasync function transportFor(chainId: SupportedChainId, rpcUrl?: string) {\n const { http, fallback } = await loadViem();\n return rpcUrl ? http(rpcUrl) : fallback(PUBLIC_RPCS[chainId].map((u) => http(u)));\n}\n\n/** previewPlan straight from the chain — the exact numbers the API serves. */\nexport async function quoteOnChain(\n opts: OnChainOptions & { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n) {\n const { createPublicClient } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const [pv, , hasFallback] = (await client.readContract({\n address: CHAINS[chainId].contracts.quoter,\n abi: QUOTER_ABI,\n functionName: 'previewPlan',\n args: [opts.tokenIn, opts.tokenOut, opts.amountIn],\n })) as readonly [Record<string, unknown>, unknown, boolean];\n return { preview: pv, hasFallback, chainId };\n}\n\nexport interface WatchFillsOptions extends OnChainOptions {\n onFill: (fill: Fill) => void;\n /** Poll interval in ms (default 4000). */\n pollMs?: number;\n}\n\n/** Stream every BlazePhoenix fill on a chain (one Router `Swap` event per\n * swap). Returns an unwatch function. */\nexport async function watchFills(opts: WatchFillsOptions): Promise<() => void> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n return client.watchEvent({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n pollingInterval: opts.pollMs ?? 4_000,\n onLogs: (logs) => {\n for (const log of logs) {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n opts.onFill({\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n });\n }\n },\n });\n}\n\n/** Historic fills over a block range (for indexing / the quoted-vs-executed\n * verification pattern documented at https://blazephoenix.xyz/?tab=api). */\nexport async function getFills(\n opts: OnChainOptions & { fromBlock: bigint; toBlock: bigint },\n): Promise<Fill[]> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const logs = await client.getLogs({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n fromBlock: opts.fromBlock,\n toBlock: opts.toBlock,\n });\n return logs.map((log) => {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n return {\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n };\n });\n}\n\nexport { ROUTER_ABI, QUOTER_ABI };\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/resilience.ts","../src/client.ts","../src/abis.ts","../src/erc20.ts","../src/onchain.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// =============================================================================\n// Protocol constants — BlazePhoenix v1.0.0 deployments.\n// Source of truth at runtime: GET https://blazephoenix.xyz/api/manifest\n// (these statics let the SDK work fully offline / on-chain-only).\n// =============================================================================\n\nexport const API_BASE = 'https://blazephoenix.xyz';\n\nexport type SupportedChainId = 1 | 8453 | 10 | 42161 | 4663;\n\nexport interface ChainInfo {\n chainId: SupportedChainId;\n name: string;\n explorer: string;\n weth: `0x${string}`;\n usdc: `0x${string}`;\n bzpx?: `0x${string}`;\n contracts: {\n hub: `0x${string}`;\n solver: `0x${string}`;\n router: `0x${string}`;\n quoter: `0x${string}`;\n };\n}\n\nexport const CHAINS: Record<SupportedChainId, ChainInfo> = {\n 1: {\n chainId: 1,\n name: 'Ethereum',\n explorer: 'https://etherscan.io',\n weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n contracts: {\n hub: '0xc4FA9a5720fe3294D3AA9fc427E2a760591E57ae',\n solver: '0xc124d91258db0C14bf13b826CF64E16bfEA8a73e',\n router: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n quoter: '0x4a20AA0912388ff7A9221Ab6BFC224cc20Baa0c3',\n },\n },\n 8453: {\n chainId: 8453,\n name: 'Base',\n explorer: 'https://basescan.org',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n bzpx: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n contracts: {\n hub: '0x428554DEe93A1B8B5Bc6Fd19adDAfe55106fc04C',\n solver: '0xB1902990260975dD4C89ad74B1f317bc100CB830',\n router: '0x2a779f9Be49aac57495A8B6467Cc325a8a47Eb9f',\n quoter: '0x4cEF0615614B212895F45Aa1D4833B16666E18d3',\n },\n },\n 10: {\n chainId: 10,\n name: 'Optimism',\n explorer: 'https://optimistic.etherscan.io',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n 42161: {\n chainId: 42161,\n name: 'Arbitrum',\n explorer: 'https://arbiscan.io',\n weth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n // Robinhood Chain — the same bytecode as every other deployment, so every\n // property proven elsewhere holds here. Note the USD asset is USDG, not\n // USDC: the `usdc` field carries the chain's canonical dollar token, which\n // on this chain is USDG. Explorer is Blockscout rather than an Etherscan.\n 4663: {\n chainId: 4663,\n name: 'Robinhood',\n explorer: 'https://robinhoodchain.blockscout.com',\n weth: '0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73',\n usdc: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n },\n },\n};\n\n/** Accepts a chain id (number or numeric string) or a human alias. */\nexport function resolveChain(chain: number | string): SupportedChainId {\n const aliases: Record<string, SupportedChainId> = {\n '1': 1, eth: 1, ethereum: 1, mainnet: 1,\n '8453': 8453, base: 8453,\n '10': 10, op: 10, optimism: 10,\n '42161': 42161, arb: 42161, arbitrum: 42161, 'arbitrum-one': 42161,\n '4663': 4663, rh: 4663, robinhood: 4663, 'robinhood-chain': 4663,\n };\n const id = aliases[String(chain).trim().toLowerCase()];\n if (!id) {\n throw new Error(\n `Unsupported chain \"${chain}\" — use 8453/base, 1/eth, 10/optimism, `\n + `42161/arbitrum or 4663/robinhood`,\n );\n }\n return id;\n}\n\n/** Public, KEYLESS RPC endpoints per chain — community infrastructure, no\n * providers, no keys (enforced by tests). They make the on-chain module work\n * with ZERO configuration; production integrations should still bring their\n * own `rpcUrl` for guaranteed throughput. */\nexport const PUBLIC_RPCS: Record<SupportedChainId, string[]> = {\n 1: [\n 'https://ethereum-rpc.publicnode.com',\n 'https://cloudflare-eth.com',\n 'https://1rpc.io/eth',\n ],\n 8453: [\n 'https://mainnet.base.org',\n 'https://base-rpc.publicnode.com',\n 'https://1rpc.io/base',\n ],\n 10: [\n 'https://optimism-rpc.publicnode.com',\n 'https://mainnet.optimism.io',\n 'https://1rpc.io/op',\n ],\n 42161: [\n 'https://arbitrum-one-rpc.publicnode.com',\n 'https://arb1.arbitrum.io/rpc',\n 'https://1rpc.io/arb',\n ],\n 4663: [\n 'https://rpc.mainnet.chain.robinhood.com',\n ],\n};\n\n/** Protocol fee (bps) applied to quoted output; execution surplus is fee-exempt. */\nexport const FEE_BPS = 28;\n\n/** Router event topic0 hashes (one `Swap` per fill — index everything with them).\n * Verified against the ABIs by `npm test` (viem toEventSelector). */\nexport const SWAP_TOPIC0 =\n '0xd6d34547c69c5ee3d2667625c188acf1006abb93e0ee7cf03925c67cf7760413' as const;\nexport const SURPLUS_TOPIC0 =\n '0x1a3afef0f067eb51a6bfec6ab3625a4408dd8c3571b72836483e68feb70d1026' as const;\n","// =============================================================================\n// Resilience core — the SDK ships the same meta-patterns the BlazePhoenix\n// edge runs, so every integration is polite and outage-proof by default:\n//\n// • singleflight — identical concurrent calls share ONE request\n// • micro-TTL — a tiny preview cache (default 1s ≈ intra-block) absorbs\n// hot loops without ever serving stale execution data\n// • retry — transient failures (network, 429, 502/503) retry with\n// backoff and RESPECT the server's retry-after header\n//\n// Execution-grade requests (recipient / exact=1) are never TTL-cached here,\n// mirroring the server's own red line.\n// =============================================================================\n\nconst INFLIGHT = new Map<string, Promise<unknown>>();\nconst MEM = new Map<string, { at: number; data: unknown }>();\n\n/** Coalesce concurrent identical work — leader runs, followers share. */\nexport async function singleflight<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const existing = INFLIGHT.get(key) as Promise<T> | undefined;\n if (existing) return existing;\n const flight = fn();\n INFLIGHT.set(key, flight as Promise<unknown>);\n try {\n return await flight;\n } finally {\n INFLIGHT.delete(key);\n }\n}\n\nexport function memGet(key: string, ttlMs: number, now = Date.now()): unknown | undefined {\n if (ttlMs <= 0) return undefined;\n const hit = MEM.get(key);\n return hit && now - hit.at < ttlMs ? hit.data : undefined;\n}\n\nexport function memPut(key: string, data: unknown, now = Date.now()): void {\n MEM.set(key, { at: now, data });\n // Bound the cache — a long-running bot must never leak memory here.\n if (MEM.size > 500) {\n const oldest = MEM.keys().next().value;\n if (oldest !== undefined) MEM.delete(oldest);\n }\n}\n\nexport interface RetryOptions {\n /** Extra attempts after the first (default 2). */\n retries?: number;\n /** Base backoff in ms; grows ×3 per attempt with jitter (default 250). */\n backoffMs?: number;\n timeoutMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction retryDelayMs(res: Response | undefined, attempt: number, base: number): number {\n const ra = Number(res?.headers.get('retry-after'));\n if (Number.isFinite(ra) && ra > 0) return Math.min(10_000, ra * 1000);\n return base * 3 ** attempt + Math.floor(Math.random() * base);\n}\n\n/** Quote reads are idempotent — transient failures deserve another shot. */\nfunction isTransient(res: Response | undefined): boolean {\n return !res || res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504;\n}\n\n/** fetch with timeout + polite retries. Returns the final Response (which may\n * still be an error status — non-transient statuses are never retried). */\nexport async function resilientFetch(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit | undefined,\n opts: RetryOptions = {},\n): Promise<Response> {\n const { retries = 2, backoffMs = 250, timeoutMs = 15_000 } = opts;\n let lastErr: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n let res: Response | undefined;\n try {\n res = await fetchFn(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n if (!isTransient(res)) return res;\n if (attempt === retries) return res;\n } catch (e) {\n lastErr = e;\n if (attempt === retries) throw e;\n }\n await sleep(retryDelayMs(res, attempt, backoffMs));\n }\n /* istanbul ignore next -- loop always returns or throws */\n throw lastErr instanceof Error ? lastErr : new Error('request failed');\n}\n\n/** Test hook. */\nexport function __resetResilience(): void {\n INFLIGHT.clear();\n MEM.clear();\n}\n","// =============================================================================\n// HTTP client — zero dependencies (native fetch). Every quote is computed\n// on-chain by the BlazePhoenix Quoter; the API is a thin mirror of the chain.\n// No API key. Open CORS. https://blazephoenix.xyz/?tab=api\n// =============================================================================\n\nimport { API_BASE, resolveChain } from './constants.js';\nimport { memGet, memPut, resilientFetch, singleflight } from './resilience.js';\nimport type {\n BatchResponse, HealthResponse, ManifestResponse, QuoteRequest, QuoteResponse, QuoteTx,\n} from './types.js';\n\nexport class BlazeApiError extends Error {\n readonly code: string;\n readonly status: number;\n constructor(code: string, message: string, status: number) {\n super(message);\n this.name = 'BlazeApiError';\n this.code = code;\n this.status = status;\n }\n}\n\nexport interface ClientOptions {\n /** Override the API origin (e.g. a mirror). Default: https://blazephoenix.xyz */\n baseUrl?: string;\n /** Custom fetch (tests, proxies). Default: globalThis.fetch. */\n fetchFn?: typeof fetch;\n /** Per-request timeout in ms. Default 15000. */\n timeoutMs?: number;\n /** Extra attempts on transient failures (network, 429, 502-504), honouring\n * the server's retry-after. Default 2. Set 0 to disable. */\n retries?: number;\n /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot\n * loops without serving stale execution data. Default 1000ms; 0 disables. */\n cacheTtlMs?: number;\n /**\n * YOUR OWN https RPC endpoint, applied to every request that does not set its\n * own. The API reads through your node instead of its shared pool.\n *\n * The service stays free and keyless either way — this exists so sustained\n * automation carries its own read volume, which is what keeps the free path\n * viable for callers who cannot bring a node. Your node is tried first and\n * ours remain the fallback, so this can only improve reliability. If you are\n * running a bot, this is the single most considerate line you can add.\n */\n rpc?: string;\n}\n\nfunction toSearch(req: QuoteRequest): URLSearchParams {\n const sp = new URLSearchParams();\n sp.set('chain', String(resolveChain(req.chain)));\n sp.set('in', req.tokenIn.trim());\n sp.set('out', req.tokenOut.trim());\n sp.set('amountIn', typeof req.amountIn === 'bigint' ? req.amountIn.toString() : String(req.amountIn).trim());\n if (req.recipient) sp.set('recipient', req.recipient);\n if (req.slippageBps !== undefined) sp.set('slippageBps', String(req.slippageBps));\n if (req.deadlineSec !== undefined) sp.set('deadlineSec', String(req.deadlineSec));\n if (req.exact) sp.set('exact', '1');\n // The caller's own node, when they brought one. The API validates it and\n // silently ignores anything unsafe, so a bad value degrades to the normal\n // free path rather than failing the request.\n if (req.rpc) sp.set('rpc', req.rpc.trim());\n return sp;\n}\n\nexport class BlazePhoenix {\n private readonly base: string;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly cacheTtlMs: number;\n /** Default BYO-RPC endpoint applied to every request that does not set one. */\n private readonly rpc?: string;\n\n constructor(opts: ClientOptions = {}) {\n this.base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n this.fetchFn = opts.fetchFn ?? globalThis.fetch;\n this.timeoutMs = opts.timeoutMs ?? 15_000;\n this.retries = opts.retries ?? 2;\n this.cacheTtlMs = opts.cacheTtlMs ?? 1_000;\n this.rpc = opts.rpc;\n if (!this.fetchFn) throw new Error('No fetch available — Node >= 18 required (or pass fetchFn)');\n }\n\n /** Fold the client-wide BYO-RPC default into a request that omits one. */\n private withRpc(req: QuoteRequest): QuoteRequest {\n return this.rpc && !req.rpc ? { ...req, rpc: this.rpc } : req;\n }\n\n /** Build the GET /api/quote URL for a request (useful for logging/debugging). */\n quoteUrl(req: QuoteRequest): string {\n return `${this.base}/api/quote?${toSearch(this.withRpc(req)).toString()}`;\n }\n\n private async call<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {\n retries: this.retries,\n timeoutMs: this.timeoutMs,\n });\n const body = (await res.json().catch(() => null)) as\n | (T & { ok: true })\n | { ok: false; code?: string; error?: string }\n | null;\n if (!body || typeof body !== 'object') {\n throw new BlazeApiError('bad_response', `non-JSON response (HTTP ${res.status})`, res.status);\n }\n if ('ok' in body && body.ok === false) {\n throw new BlazeApiError(body.code ?? 'error', body.error ?? 'request failed', res.status);\n }\n return body as T;\n }\n\n /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.\n * Identical concurrent calls share one request; preview quotes ride a tiny\n * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */\n async quote(reqIn: QuoteRequest): Promise<QuoteResponse> {\n const req = this.withRpc(reqIn);\n const qs = toSearch(req).toString();\n const key = `Q ${this.base}?${qs}`;\n const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;\n if (cacheable) {\n const hit = memGet(key, this.cacheTtlMs);\n if (hit) return hit as QuoteResponse;\n }\n const q = await singleflight(key, () => this.call<QuoteResponse>(`/api/quote?${qs}`));\n if (cacheable) memPut(key, q);\n return q;\n }\n\n /** Up to 10 quotes in one round-trip (screeners / arb loops).\n * Per-item failures come back inline — the batch itself only throws on\n * transport/validation errors. Identical concurrent batches coalesce. */\n quoteBatch(reqs: QuoteRequest[]): Promise<BatchResponse> {\n const body = JSON.stringify({\n requests: reqs.map((r) => Object.fromEntries(toSearch(r).entries())),\n });\n return singleflight(`B ${this.base} ${body}`, () =>\n this.call<BatchResponse>('/api/quote/batch', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body,\n }));\n }\n\n /** Service health + per-chain live flags. Zero upstream cost server-side —\n * poll it from your monitor as often as you like. */\n health(): Promise<HealthResponse> {\n return this.call<HealthResponse>('/api/health');\n }\n\n /** Machine-readable protocol manifest — near-static, cached for 1h. */\n async manifest(): Promise<ManifestResponse> {\n const key = `M ${this.base}`;\n const hit = memGet(key, 3_600_000);\n if (hit) return hit as ManifestResponse;\n const m = await singleflight(key, () => this.call<ManifestResponse>('/api/manifest'));\n memPut(key, m);\n return m;\n }\n}\n\nexport interface PollOptions {\n /** Tick interval in ms (min 500, default 4000). */\n intervalMs?: number;\n onError?: (e: unknown) => void;\n}\n\n/** Poll a pair and get called back with each fresh quote — the heartbeat of a\n * price bot in one line. Overlap-safe (a slow tick is skipped, not stacked).\n * Returns a stop function. */\nexport function pollQuote(\n client: BlazePhoenix,\n req: QuoteRequest,\n onQuote: (q: QuoteResponse) => void,\n opts: PollOptions = {},\n): () => void {\n const interval = Math.max(500, opts.intervalMs ?? 4_000);\n let stopped = false;\n let busy = false;\n const tick = async () => {\n if (stopped || busy) return;\n busy = true;\n try {\n const q = await client.quote(req);\n if (!stopped) onQuote(q);\n } catch (e) {\n if (!stopped) opts.onError?.(e);\n } finally {\n busy = false;\n }\n };\n void tick();\n const timer = setInterval(() => { void tick(); }, interval);\n return () => { stopped = true; clearInterval(timer); };\n}\n\n/** The ready-to-broadcast transaction from a quote (requires `recipient` in the\n * request and an ERC-20 input). Throws with a precise reason otherwise. */\nexport function buildSwapTx(q: QuoteResponse): QuoteTx {\n if (q.tx) return q.tx;\n if (q.wrapRequired) {\n throw new Error('native ETH input: wrap to WETH first (WETH.deposit), then re-quote with in=WETH');\n }\n throw new Error('no tx in quote — pass `recipient` in the request (and check quote.canExecute)');\n}\n\nexport interface DeepLinkOptions {\n chain?: number | string;\n tokenIn?: string;\n tokenOut?: string;\n /** Human units for the pay field (e.g. \"0.5\"). */\n amount?: string;\n tab?: 'home' | 'swap' | 'staking' | 'airdrop' | 'api';\n baseUrl?: string;\n}\n\n/** A shareable link that opens the site pre-filled — bot buttons, referral posts. */\nexport function deepLink(opts: DeepLinkOptions = {}): string {\n const base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n const sp = new URLSearchParams();\n sp.set('tab', opts.tab ?? 'swap');\n if (opts.chain !== undefined) sp.set('chain', String(resolveChain(opts.chain)));\n if (opts.tokenIn) sp.set('in', opts.tokenIn);\n if (opts.tokenOut) sp.set('out', opts.tokenOut);\n if (opts.amount) sp.set('amt', opts.amount);\n return `${base}/?${sp.toString()}`;\n}\n","// =============================================================================\n// BlazePhoenix Router + Quoter ABI fragments (match the v1.0.0 deployments).\n// The Route/Hop/Leg tuple mirrors BlazePhoenixCore.sol — a decoded route from\n// `previewPlan` round-trips verbatim into `swapExactIn`.\n// =============================================================================\n\nconst LEG_COMPONENTS = [\n { name: 'pool', type: 'address' },\n { name: 'hooks', type: 'address' },\n { name: 'kind', type: 'uint8' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'stable', type: 'bool' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'auxId', type: 'bytes32' },\n] as const;\n\nconst HOP_COMPONENTS = [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'legs', type: 'tuple[]', components: LEG_COMPONENTS },\n] as const;\n\nconst ROUTE_COMPONENTS = [\n { name: 'hops', type: 'tuple[]', components: HOP_COMPONENTS },\n { name: 'totalOut', type: 'uint256' },\n { name: 'singleOut', type: 'uint256' },\n { name: 'singleOutFloor', type: 'uint256' },\n { name: 'expectedImpactBps', type: 'uint256' },\n { name: 'confidenceWad', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hasSurplus', type: 'bool' },\n { name: 'isV4Bundle', type: 'bool' },\n] as const;\n\nconst PREVIEW_COMPONENTS = [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'grossOut', type: 'uint256' },\n { name: 'protocolFee', type: 'uint256' },\n { name: 'safetyBuffer', type: 'uint256' },\n { name: 'netOut', type: 'uint256' },\n { name: 'ironFloor', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'effectiveMinOut', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hops', type: 'uint256' },\n { name: 'legs', type: 'uint256' },\n { name: 'topology', type: 'uint8' },\n { name: 'bridgeUsed', type: 'address' },\n { name: 'canExecute', type: 'bool' },\n] as const;\n\nexport const QUOTER_ABI = [\n {\n type: 'function',\n name: 'previewPlan',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'pv', type: 'tuple', components: PREVIEW_COMPONENTS },\n { name: 'fallbackRoute', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'hasFallback', type: 'bool' },\n ],\n },\n {\n type: 'function',\n name: 'previewPlanExact',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'exactOut', type: 'uint256' },\n ],\n },\n] as const;\n\nexport const ROUTER_ABI = [\n {\n type: 'function',\n name: 'swapExactIn',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'amountIn', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'event',\n name: 'Swap',\n inputs: [\n { name: 'user', type: 'address', indexed: true },\n { name: 'tokenIn', type: 'address', indexed: true },\n { name: 'tokenOut', type: 'address', indexed: true },\n { name: 'amountIn', type: 'uint256', indexed: false },\n { name: 'amountOut', type: 'uint256', indexed: false },\n { name: 'legs', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Surplus',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'amount', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// =============================================================================\n// ERC-20 helpers — zero dependencies. Completes the integration loop:\n// quote → buildApproveTx (once per token) → buildSwapTx → send.\n// Plus human-amount conversion so callers never hand-count decimals.\n// =============================================================================\n\nimport { CHAINS, resolveChain } from './constants.js';\nimport type { Address, ChainRef, Hex, QuoteTx } from './types.js';\n\n/** Unlimited allowance (2^256 − 1). Prefer EXACT amounts — pass the amount you\n * are about to swap; use MAX_UINT256 only when you consciously want one\n * approval forever (bots with their own key management). */\nexport const MAX_UINT256 = (1n << 256n) - 1n;\n\nconst HEX_ADDR = /^0x[0-9a-fA-F]{40}$/;\n\n// approve(address,uint256)\nconst APPROVE_SELECTOR = '0x095ea7b3';\n\nfunction pad32(hexNo0x: string): string {\n return hexNo0x.padStart(64, '0');\n}\n\nexport interface ApproveOptions {\n /** ERC-20 token to approve (the swap's tokenIn). */\n token: Address;\n /** Chain id or name — picks the Router as the default spender. */\n chain: ChainRef;\n /** Allowance in base units. Be exact; MAX_UINT256 opts into unlimited. */\n amount: bigint;\n /** Override the spender (defaults to the BlazePhoenix Router). */\n spender?: Address;\n}\n\n/** Ready-to-send `approve` transaction for the Router (or a custom spender).\n * Send it once per token before the first swap; then swap freely. */\nexport function buildApproveTx(opts: ApproveOptions): QuoteTx {\n const chainId = resolveChain(opts.chain);\n const spender = opts.spender ?? CHAINS[chainId].contracts.router;\n if (!HEX_ADDR.test(opts.token)) throw new Error(`invalid token address: ${opts.token}`);\n if (!HEX_ADDR.test(spender)) throw new Error(`invalid spender address: ${spender}`);\n if (opts.amount < 0n || opts.amount > MAX_UINT256) throw new Error('amount out of uint256 range');\n const data = (APPROVE_SELECTOR\n + pad32(spender.slice(2).toLowerCase())\n + pad32(opts.amount.toString(16))) as Hex;\n return { to: opts.token, data, value: '0' };\n}\n\n/** \"1.5\" + 18 decimals → 1500000000000000000n. Pure string math — no floats,\n * no precision loss. Rejects more fractional digits than the token carries. */\nexport function toBaseUnits(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const s = amount.trim();\n const m = /^(\\d+)(?:\\.(\\d+))?$/.exec(s);\n if (!m) throw new Error(`invalid amount: \"${amount}\" (use e.g. \"1.5\")`);\n const [, whole, frac = ''] = m;\n if (frac.length > decimals) {\n throw new Error(`\"${amount}\" has ${frac.length} fractional digits — token only carries ${decimals}`);\n }\n return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(frac.padEnd(decimals, '0') || '0');\n}\n\n/** 1500000000000000000n + 18 decimals → \"1.5\" (trailing zeros trimmed).\n * `maxDp` optionally truncates the fractional part for display. */\nexport function fromBaseUnits(v: bigint | string, decimals: number, maxDp?: number): string {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const n = typeof v === 'bigint' ? v : BigInt(v);\n const neg = n < 0n;\n const abs = neg ? -n : n;\n const base = 10n ** BigInt(decimals);\n const whole = abs / base;\n let frac = (abs % base).toString().padStart(decimals, '0');\n if (maxDp !== undefined) frac = frac.slice(0, Math.max(0, maxDp));\n frac = frac.replace(/0+$/, '');\n return `${neg ? '-' : ''}${whole}${frac ? `.${frac}` : ''}`;\n}\n","// =============================================================================\n// On-chain module — skip HTTP entirely: quote on the Quoter from your own\n// node and watch the Router's fills. Needs the optional `viem` peer:\n// npm i viem\n// You supply the RPC URL — the SDK ships no keys and no default endpoints.\n// =============================================================================\n\nimport { QUOTER_ABI, ROUTER_ABI } from './abis.js';\nimport { CHAINS, PUBLIC_RPCS, resolveChain, type SupportedChainId } from './constants.js';\nimport type { Address, Fill } from './types.js';\n\nasync function loadViem() {\n try {\n return await import('viem');\n } catch {\n throw new Error(\"this feature needs the optional peer dependency 'viem' — npm i viem\");\n }\n}\n\nexport interface OnChainOptions {\n chain: number | string;\n /** Your RPC endpoint. OPTIONAL since v0.4.0 — omitted, the SDK falls back\n * across public keyless endpoints (fine for dev/bots; bring your own node\n * for production throughput). The SDK still ships no providers and no keys. */\n rpcUrl?: string;\n}\n\n/** viem transport: caller's RPC when given, else public-endpoint fallback. */\nasync function transportFor(chainId: SupportedChainId, rpcUrl?: string) {\n const { http, fallback } = await loadViem();\n return rpcUrl ? http(rpcUrl) : fallback(PUBLIC_RPCS[chainId].map((u) => http(u)));\n}\n\n/** previewPlan straight from the chain — the exact numbers the API serves. */\nexport async function quoteOnChain(\n opts: OnChainOptions & { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n) {\n const { createPublicClient } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const [pv, , hasFallback] = (await client.readContract({\n address: CHAINS[chainId].contracts.quoter,\n abi: QUOTER_ABI,\n functionName: 'previewPlan',\n args: [opts.tokenIn, opts.tokenOut, opts.amountIn],\n })) as readonly [Record<string, unknown>, unknown, boolean];\n return { preview: pv, hasFallback, chainId };\n}\n\nexport interface WatchFillsOptions extends OnChainOptions {\n onFill: (fill: Fill) => void;\n /** Poll interval in ms (default 4000). */\n pollMs?: number;\n}\n\n/** Stream every BlazePhoenix fill on a chain (one Router `Swap` event per\n * swap). Returns an unwatch function. */\nexport async function watchFills(opts: WatchFillsOptions): Promise<() => void> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n return client.watchEvent({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n pollingInterval: opts.pollMs ?? 4_000,\n onLogs: (logs) => {\n for (const log of logs) {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n opts.onFill({\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n });\n }\n },\n });\n}\n\n/** Historic fills over a block range (for indexing / the quoted-vs-executed\n * verification pattern documented at https://blazephoenix.xyz/?tab=api). */\nexport async function getFills(\n opts: OnChainOptions & { fromBlock: bigint; toBlock: bigint },\n): Promise<Fill[]> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const logs = await client.getLogs({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n fromBlock: opts.fromBlock,\n toBlock: opts.toBlock,\n });\n return logs.map((log) => {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n return {\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n };\n });\n}\n\nexport { ROUTER_ABI, QUOTER_ABI };\n"]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,7 @@
1
1
  type Address = `0x${string}`;
2
2
  type Hex = `0x${string}`;
3
- /** Chain selector: id (1, 8453, 10, 42161) or name ("base", "eth", …). */
3
+ /** Chain selector: id (1, 8453, 10, 42161, 4663) or name ("base", "eth",
4
+ * "optimism", "arbitrum", "robinhood", …). */
4
5
  type ChainRef = number | string;
5
6
  /** Token selector: 0x-address, ETH / WETH / USDC / BZPX, or (single-quote
6
7
  * endpoint only) ANY traded symbol — the API resolves unknown tickers to the
@@ -22,6 +23,21 @@ interface QuoteRequest {
22
23
  deadlineSec?: number;
23
24
  /** Execution-grade re-quote (previewPlanExact) — slower, sharper. */
24
25
  exact?: boolean;
26
+ /**
27
+ * YOUR OWN https RPC endpoint. When set, the API performs the read through
28
+ * your node instead of its shared pool.
29
+ *
30
+ * The service is free either way and always has been — this exists so that
31
+ * sustained automation can carry its own read volume, which is what keeps the
32
+ * free path viable for callers who cannot. Your node is tried first and the
33
+ * public pool remains the fallback, so supplying one can only make the call
34
+ * more reliable, never less. `meta.rpc` in the response reads "byo" when your
35
+ * node answered and "shared" when it did not.
36
+ *
37
+ * Set it once on the client (`new BlazePhoenix({ rpc })`) rather than per
38
+ * call, unless a particular request needs a different node.
39
+ */
40
+ rpc?: string;
25
41
  }
26
42
  interface QuoteLeg {
27
43
  pool: Address;
@@ -72,6 +88,31 @@ interface QuoteTx {
72
88
  data: Hex;
73
89
  value: '0';
74
90
  }
91
+ /** Phoenix Check — deterministic quote invariants, derived on-chain, that an
92
+ * agent can act on. Fails closed: `verdict` is never greener than its weakest
93
+ * invariant (blocked | danger | caution | ok). */
94
+ interface QuoteChecks {
95
+ verdict: 'blocked' | 'danger' | 'caution' | 'ok';
96
+ priceImpact: {
97
+ bps: number;
98
+ verdict: 'blocked' | 'danger' | 'caution' | 'ok';
99
+ hardLineBps: number;
100
+ note: string;
101
+ };
102
+ ironFloor: {
103
+ enforcedOnChain: boolean;
104
+ armed: boolean;
105
+ ironFloor: string;
106
+ effectiveMinOut: string;
107
+ note: string;
108
+ };
109
+ crossCheck: {
110
+ basis: string;
111
+ reproducible: boolean;
112
+ note: string;
113
+ };
114
+ disclaimer: string;
115
+ }
75
116
  interface QuoteResponse {
76
117
  ok: true;
77
118
  mode: 'preview' | 'exact';
@@ -82,6 +123,8 @@ interface QuoteResponse {
82
123
  /** Net output after the protocol fee — the number to compare across venues. */
83
124
  amountOut: string;
84
125
  quote?: QuoteSummary;
126
+ /** Phoenix Check verdicts — quote these when asked whether a swap is safe. */
127
+ checks?: QuoteChecks;
85
128
  route: QuoteRoute;
86
129
  tx?: QuoteTx;
87
130
  wrapRequired: boolean;
@@ -198,6 +241,17 @@ interface ClientOptions {
198
241
  /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot
199
242
  * loops without serving stale execution data. Default 1000ms; 0 disables. */
200
243
  cacheTtlMs?: number;
244
+ /**
245
+ * YOUR OWN https RPC endpoint, applied to every request that does not set its
246
+ * own. The API reads through your node instead of its shared pool.
247
+ *
248
+ * The service stays free and keyless either way — this exists so sustained
249
+ * automation carries its own read volume, which is what keeps the free path
250
+ * viable for callers who cannot bring a node. Your node is tried first and
251
+ * ours remain the fallback, so this can only improve reliability. If you are
252
+ * running a bot, this is the single most considerate line you can add.
253
+ */
254
+ rpc?: string;
201
255
  }
202
256
  declare class BlazePhoenix {
203
257
  private readonly base;
@@ -205,14 +259,18 @@ declare class BlazePhoenix {
205
259
  private readonly timeoutMs;
206
260
  private readonly retries;
207
261
  private readonly cacheTtlMs;
262
+ /** Default BYO-RPC endpoint applied to every request that does not set one. */
263
+ private readonly rpc?;
208
264
  constructor(opts?: ClientOptions);
265
+ /** Fold the client-wide BYO-RPC default into a request that omits one. */
266
+ private withRpc;
209
267
  /** Build the GET /api/quote URL for a request (useful for logging/debugging). */
210
268
  quoteUrl(req: QuoteRequest): string;
211
269
  private call;
212
270
  /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.
213
271
  * Identical concurrent calls share one request; preview quotes ride a tiny
214
272
  * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */
215
- quote(req: QuoteRequest): Promise<QuoteResponse>;
273
+ quote(reqIn: QuoteRequest): Promise<QuoteResponse>;
216
274
  /** Up to 10 quotes in one round-trip (screeners / arb loops).
217
275
  * Per-item failures come back inline — the batch itself only throws on
218
276
  * transport/validation errors. Identical concurrent batches coalesce. */
@@ -261,7 +319,7 @@ interface RetryOptions {
261
319
  declare function resilientFetch(fetchFn: typeof fetch, url: string, init: RequestInit | undefined, opts?: RetryOptions): Promise<Response>;
262
320
 
263
321
  declare const API_BASE = "https://blazephoenix.xyz";
264
- type SupportedChainId = 1 | 8453 | 10 | 42161;
322
+ type SupportedChainId = 1 | 8453 | 10 | 42161 | 4663;
265
323
  interface ChainInfo {
266
324
  chainId: SupportedChainId;
267
325
  name: string;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  type Address = `0x${string}`;
2
2
  type Hex = `0x${string}`;
3
- /** Chain selector: id (1, 8453, 10, 42161) or name ("base", "eth", …). */
3
+ /** Chain selector: id (1, 8453, 10, 42161, 4663) or name ("base", "eth",
4
+ * "optimism", "arbitrum", "robinhood", …). */
4
5
  type ChainRef = number | string;
5
6
  /** Token selector: 0x-address, ETH / WETH / USDC / BZPX, or (single-quote
6
7
  * endpoint only) ANY traded symbol — the API resolves unknown tickers to the
@@ -22,6 +23,21 @@ interface QuoteRequest {
22
23
  deadlineSec?: number;
23
24
  /** Execution-grade re-quote (previewPlanExact) — slower, sharper. */
24
25
  exact?: boolean;
26
+ /**
27
+ * YOUR OWN https RPC endpoint. When set, the API performs the read through
28
+ * your node instead of its shared pool.
29
+ *
30
+ * The service is free either way and always has been — this exists so that
31
+ * sustained automation can carry its own read volume, which is what keeps the
32
+ * free path viable for callers who cannot. Your node is tried first and the
33
+ * public pool remains the fallback, so supplying one can only make the call
34
+ * more reliable, never less. `meta.rpc` in the response reads "byo" when your
35
+ * node answered and "shared" when it did not.
36
+ *
37
+ * Set it once on the client (`new BlazePhoenix({ rpc })`) rather than per
38
+ * call, unless a particular request needs a different node.
39
+ */
40
+ rpc?: string;
25
41
  }
26
42
  interface QuoteLeg {
27
43
  pool: Address;
@@ -72,6 +88,31 @@ interface QuoteTx {
72
88
  data: Hex;
73
89
  value: '0';
74
90
  }
91
+ /** Phoenix Check — deterministic quote invariants, derived on-chain, that an
92
+ * agent can act on. Fails closed: `verdict` is never greener than its weakest
93
+ * invariant (blocked | danger | caution | ok). */
94
+ interface QuoteChecks {
95
+ verdict: 'blocked' | 'danger' | 'caution' | 'ok';
96
+ priceImpact: {
97
+ bps: number;
98
+ verdict: 'blocked' | 'danger' | 'caution' | 'ok';
99
+ hardLineBps: number;
100
+ note: string;
101
+ };
102
+ ironFloor: {
103
+ enforcedOnChain: boolean;
104
+ armed: boolean;
105
+ ironFloor: string;
106
+ effectiveMinOut: string;
107
+ note: string;
108
+ };
109
+ crossCheck: {
110
+ basis: string;
111
+ reproducible: boolean;
112
+ note: string;
113
+ };
114
+ disclaimer: string;
115
+ }
75
116
  interface QuoteResponse {
76
117
  ok: true;
77
118
  mode: 'preview' | 'exact';
@@ -82,6 +123,8 @@ interface QuoteResponse {
82
123
  /** Net output after the protocol fee — the number to compare across venues. */
83
124
  amountOut: string;
84
125
  quote?: QuoteSummary;
126
+ /** Phoenix Check verdicts — quote these when asked whether a swap is safe. */
127
+ checks?: QuoteChecks;
85
128
  route: QuoteRoute;
86
129
  tx?: QuoteTx;
87
130
  wrapRequired: boolean;
@@ -198,6 +241,17 @@ interface ClientOptions {
198
241
  /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot
199
242
  * loops without serving stale execution data. Default 1000ms; 0 disables. */
200
243
  cacheTtlMs?: number;
244
+ /**
245
+ * YOUR OWN https RPC endpoint, applied to every request that does not set its
246
+ * own. The API reads through your node instead of its shared pool.
247
+ *
248
+ * The service stays free and keyless either way — this exists so sustained
249
+ * automation carries its own read volume, which is what keeps the free path
250
+ * viable for callers who cannot bring a node. Your node is tried first and
251
+ * ours remain the fallback, so this can only improve reliability. If you are
252
+ * running a bot, this is the single most considerate line you can add.
253
+ */
254
+ rpc?: string;
201
255
  }
202
256
  declare class BlazePhoenix {
203
257
  private readonly base;
@@ -205,14 +259,18 @@ declare class BlazePhoenix {
205
259
  private readonly timeoutMs;
206
260
  private readonly retries;
207
261
  private readonly cacheTtlMs;
262
+ /** Default BYO-RPC endpoint applied to every request that does not set one. */
263
+ private readonly rpc?;
208
264
  constructor(opts?: ClientOptions);
265
+ /** Fold the client-wide BYO-RPC default into a request that omits one. */
266
+ private withRpc;
209
267
  /** Build the GET /api/quote URL for a request (useful for logging/debugging). */
210
268
  quoteUrl(req: QuoteRequest): string;
211
269
  private call;
212
270
  /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.
213
271
  * Identical concurrent calls share one request; preview quotes ride a tiny
214
272
  * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */
215
- quote(req: QuoteRequest): Promise<QuoteResponse>;
273
+ quote(reqIn: QuoteRequest): Promise<QuoteResponse>;
216
274
  /** Up to 10 quotes in one round-trip (screeners / arb loops).
217
275
  * Per-item failures come back inline — the batch itself only throws on
218
276
  * transport/validation errors. Identical concurrent batches coalesce. */
@@ -261,7 +319,7 @@ interface RetryOptions {
261
319
  declare function resilientFetch(fetchFn: typeof fetch, url: string, init: RequestInit | undefined, opts?: RetryOptions): Promise<Response>;
262
320
 
263
321
  declare const API_BASE = "https://blazephoenix.xyz";
264
- type SupportedChainId = 1 | 8453 | 10 | 42161;
322
+ type SupportedChainId = 1 | 8453 | 10 | 42161 | 4663;
265
323
  interface ChainInfo {
266
324
  chainId: SupportedChainId;
267
325
  name: string;
package/dist/index.js CHANGED
@@ -53,6 +53,23 @@ var CHAINS = {
53
53
  router: "0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A",
54
54
  quoter: "0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2"
55
55
  }
56
+ },
57
+ // Robinhood Chain — the same bytecode as every other deployment, so every
58
+ // property proven elsewhere holds here. Note the USD asset is USDG, not
59
+ // USDC: the `usdc` field carries the chain's canonical dollar token, which
60
+ // on this chain is USDG. Explorer is Blockscout rather than an Etherscan.
61
+ 4663: {
62
+ chainId: 4663,
63
+ name: "Robinhood",
64
+ explorer: "https://robinhoodchain.blockscout.com",
65
+ weth: "0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73",
66
+ usdc: "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
67
+ contracts: {
68
+ hub: "0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483",
69
+ solver: "0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f",
70
+ router: "0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A",
71
+ quoter: "0xE1aE5f49013920CF71De8CED4043e14C4d63416b"
72
+ }
56
73
  }
57
74
  };
58
75
  function resolveChain(chain) {
@@ -69,12 +86,16 @@ function resolveChain(chain) {
69
86
  "42161": 42161,
70
87
  arb: 42161,
71
88
  arbitrum: 42161,
72
- "arbitrum-one": 42161
89
+ "arbitrum-one": 42161,
90
+ "4663": 4663,
91
+ rh: 4663,
92
+ robinhood: 4663,
93
+ "robinhood-chain": 4663
73
94
  };
74
95
  const id = aliases[String(chain).trim().toLowerCase()];
75
96
  if (!id) {
76
97
  throw new Error(
77
- `Unsupported chain "${chain}" \u2014 use 8453/base, 1/eth, 10/optimism or 42161/arbitrum`
98
+ `Unsupported chain "${chain}" \u2014 use 8453/base, 1/eth, 10/optimism, 42161/arbitrum or 4663/robinhood`
78
99
  );
79
100
  }
80
101
  return id;
@@ -99,6 +120,9 @@ var PUBLIC_RPCS = {
99
120
  "https://arbitrum-one-rpc.publicnode.com",
100
121
  "https://arb1.arbitrum.io/rpc",
101
122
  "https://1rpc.io/arb"
123
+ ],
124
+ 4663: [
125
+ "https://rpc.mainnet.chain.robinhood.com"
102
126
  ]
103
127
  };
104
128
  var FEE_BPS = 28;
@@ -179,6 +203,7 @@ function toSearch(req) {
179
203
  if (req.slippageBps !== void 0) sp.set("slippageBps", String(req.slippageBps));
180
204
  if (req.deadlineSec !== void 0) sp.set("deadlineSec", String(req.deadlineSec));
181
205
  if (req.exact) sp.set("exact", "1");
206
+ if (req.rpc) sp.set("rpc", req.rpc.trim());
182
207
  return sp;
183
208
  }
184
209
  var BlazePhoenix = class {
@@ -187,17 +212,24 @@ var BlazePhoenix = class {
187
212
  timeoutMs;
188
213
  retries;
189
214
  cacheTtlMs;
215
+ /** Default BYO-RPC endpoint applied to every request that does not set one. */
216
+ rpc;
190
217
  constructor(opts = {}) {
191
218
  this.base = (opts.baseUrl ?? API_BASE).replace(/\/+$/, "");
192
219
  this.fetchFn = opts.fetchFn ?? globalThis.fetch;
193
220
  this.timeoutMs = opts.timeoutMs ?? 15e3;
194
221
  this.retries = opts.retries ?? 2;
195
222
  this.cacheTtlMs = opts.cacheTtlMs ?? 1e3;
223
+ this.rpc = opts.rpc;
196
224
  if (!this.fetchFn) throw new Error("No fetch available \u2014 Node >= 18 required (or pass fetchFn)");
197
225
  }
226
+ /** Fold the client-wide BYO-RPC default into a request that omits one. */
227
+ withRpc(req) {
228
+ return this.rpc && !req.rpc ? { ...req, rpc: this.rpc } : req;
229
+ }
198
230
  /** Build the GET /api/quote URL for a request (useful for logging/debugging). */
199
231
  quoteUrl(req) {
200
- return `${this.base}/api/quote?${toSearch(req).toString()}`;
232
+ return `${this.base}/api/quote?${toSearch(this.withRpc(req)).toString()}`;
201
233
  }
202
234
  async call(path, init) {
203
235
  const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {
@@ -216,7 +248,8 @@ var BlazePhoenix = class {
216
248
  /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.
217
249
  * Identical concurrent calls share one request; preview quotes ride a tiny
218
250
  * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */
219
- async quote(req) {
251
+ async quote(reqIn) {
252
+ const req = this.withRpc(reqIn);
220
253
  const qs = toSearch(req).toString();
221
254
  const key = `Q ${this.base}?${qs}`;
222
255
  const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/resilience.ts","../src/client.ts","../src/abis.ts","../src/erc20.ts","../src/onchain.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// =============================================================================\n// Protocol constants — BlazePhoenix v1.0.0 deployments.\n// Source of truth at runtime: GET https://blazephoenix.xyz/api/manifest\n// (these statics let the SDK work fully offline / on-chain-only).\n// =============================================================================\n\nexport const API_BASE = 'https://blazephoenix.xyz';\n\nexport type SupportedChainId = 1 | 8453 | 10 | 42161;\n\nexport interface ChainInfo {\n chainId: SupportedChainId;\n name: string;\n explorer: string;\n weth: `0x${string}`;\n usdc: `0x${string}`;\n bzpx?: `0x${string}`;\n contracts: {\n hub: `0x${string}`;\n solver: `0x${string}`;\n router: `0x${string}`;\n quoter: `0x${string}`;\n };\n}\n\nexport const CHAINS: Record<SupportedChainId, ChainInfo> = {\n 1: {\n chainId: 1,\n name: 'Ethereum',\n explorer: 'https://etherscan.io',\n weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n contracts: {\n hub: '0xc4FA9a5720fe3294D3AA9fc427E2a760591E57ae',\n solver: '0xc124d91258db0C14bf13b826CF64E16bfEA8a73e',\n router: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n quoter: '0x4a20AA0912388ff7A9221Ab6BFC224cc20Baa0c3',\n },\n },\n 8453: {\n chainId: 8453,\n name: 'Base',\n explorer: 'https://basescan.org',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n bzpx: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n contracts: {\n hub: '0x428554DEe93A1B8B5Bc6Fd19adDAfe55106fc04C',\n solver: '0xB1902990260975dD4C89ad74B1f317bc100CB830',\n router: '0x2a779f9Be49aac57495A8B6467Cc325a8a47Eb9f',\n quoter: '0x4cEF0615614B212895F45Aa1D4833B16666E18d3',\n },\n },\n 10: {\n chainId: 10,\n name: 'Optimism',\n explorer: 'https://optimistic.etherscan.io',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n 42161: {\n chainId: 42161,\n name: 'Arbitrum',\n explorer: 'https://arbiscan.io',\n weth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n};\n\n/** Accepts a chain id (number or numeric string) or a human alias. */\nexport function resolveChain(chain: number | string): SupportedChainId {\n const aliases: Record<string, SupportedChainId> = {\n '1': 1, eth: 1, ethereum: 1, mainnet: 1,\n '8453': 8453, base: 8453,\n '10': 10, op: 10, optimism: 10,\n '42161': 42161, arb: 42161, arbitrum: 42161, 'arbitrum-one': 42161,\n };\n const id = aliases[String(chain).trim().toLowerCase()];\n if (!id) {\n throw new Error(\n `Unsupported chain \"${chain}\" — use 8453/base, 1/eth, 10/optimism or 42161/arbitrum`,\n );\n }\n return id;\n}\n\n/** Public, KEYLESS RPC endpoints per chain — community infrastructure, no\n * providers, no keys (enforced by tests). They make the on-chain module work\n * with ZERO configuration; production integrations should still bring their\n * own `rpcUrl` for guaranteed throughput. */\nexport const PUBLIC_RPCS: Record<SupportedChainId, string[]> = {\n 1: [\n 'https://ethereum-rpc.publicnode.com',\n 'https://cloudflare-eth.com',\n 'https://1rpc.io/eth',\n ],\n 8453: [\n 'https://mainnet.base.org',\n 'https://base-rpc.publicnode.com',\n 'https://1rpc.io/base',\n ],\n 10: [\n 'https://optimism-rpc.publicnode.com',\n 'https://mainnet.optimism.io',\n 'https://1rpc.io/op',\n ],\n 42161: [\n 'https://arbitrum-one-rpc.publicnode.com',\n 'https://arb1.arbitrum.io/rpc',\n 'https://1rpc.io/arb',\n ],\n};\n\n/** Protocol fee (bps) applied to quoted output; execution surplus is fee-exempt. */\nexport const FEE_BPS = 28;\n\n/** Router event topic0 hashes (one `Swap` per fill — index everything with them).\n * Verified against the ABIs by `npm test` (viem toEventSelector). */\nexport const SWAP_TOPIC0 =\n '0xd6d34547c69c5ee3d2667625c188acf1006abb93e0ee7cf03925c67cf7760413' as const;\nexport const SURPLUS_TOPIC0 =\n '0x1a3afef0f067eb51a6bfec6ab3625a4408dd8c3571b72836483e68feb70d1026' as const;\n","// =============================================================================\n// Resilience core — the SDK ships the same meta-patterns the BlazePhoenix\n// edge runs, so every integration is polite and outage-proof by default:\n//\n// • singleflight — identical concurrent calls share ONE request\n// • micro-TTL — a tiny preview cache (default 1s ≈ intra-block) absorbs\n// hot loops without ever serving stale execution data\n// • retry — transient failures (network, 429, 502/503) retry with\n// backoff and RESPECT the server's retry-after header\n//\n// Execution-grade requests (recipient / exact=1) are never TTL-cached here,\n// mirroring the server's own red line.\n// =============================================================================\n\nconst INFLIGHT = new Map<string, Promise<unknown>>();\nconst MEM = new Map<string, { at: number; data: unknown }>();\n\n/** Coalesce concurrent identical work — leader runs, followers share. */\nexport async function singleflight<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const existing = INFLIGHT.get(key) as Promise<T> | undefined;\n if (existing) return existing;\n const flight = fn();\n INFLIGHT.set(key, flight as Promise<unknown>);\n try {\n return await flight;\n } finally {\n INFLIGHT.delete(key);\n }\n}\n\nexport function memGet(key: string, ttlMs: number, now = Date.now()): unknown | undefined {\n if (ttlMs <= 0) return undefined;\n const hit = MEM.get(key);\n return hit && now - hit.at < ttlMs ? hit.data : undefined;\n}\n\nexport function memPut(key: string, data: unknown, now = Date.now()): void {\n MEM.set(key, { at: now, data });\n // Bound the cache — a long-running bot must never leak memory here.\n if (MEM.size > 500) {\n const oldest = MEM.keys().next().value;\n if (oldest !== undefined) MEM.delete(oldest);\n }\n}\n\nexport interface RetryOptions {\n /** Extra attempts after the first (default 2). */\n retries?: number;\n /** Base backoff in ms; grows ×3 per attempt with jitter (default 250). */\n backoffMs?: number;\n timeoutMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction retryDelayMs(res: Response | undefined, attempt: number, base: number): number {\n const ra = Number(res?.headers.get('retry-after'));\n if (Number.isFinite(ra) && ra > 0) return Math.min(10_000, ra * 1000);\n return base * 3 ** attempt + Math.floor(Math.random() * base);\n}\n\n/** Quote reads are idempotent — transient failures deserve another shot. */\nfunction isTransient(res: Response | undefined): boolean {\n return !res || res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504;\n}\n\n/** fetch with timeout + polite retries. Returns the final Response (which may\n * still be an error status — non-transient statuses are never retried). */\nexport async function resilientFetch(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit | undefined,\n opts: RetryOptions = {},\n): Promise<Response> {\n const { retries = 2, backoffMs = 250, timeoutMs = 15_000 } = opts;\n let lastErr: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n let res: Response | undefined;\n try {\n res = await fetchFn(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n if (!isTransient(res)) return res;\n if (attempt === retries) return res;\n } catch (e) {\n lastErr = e;\n if (attempt === retries) throw e;\n }\n await sleep(retryDelayMs(res, attempt, backoffMs));\n }\n /* istanbul ignore next -- loop always returns or throws */\n throw lastErr instanceof Error ? lastErr : new Error('request failed');\n}\n\n/** Test hook. */\nexport function __resetResilience(): void {\n INFLIGHT.clear();\n MEM.clear();\n}\n","// =============================================================================\n// HTTP client — zero dependencies (native fetch). Every quote is computed\n// on-chain by the BlazePhoenix Quoter; the API is a thin mirror of the chain.\n// No API key. Open CORS. https://blazephoenix.xyz/?tab=api\n// =============================================================================\n\nimport { API_BASE, resolveChain } from './constants.js';\nimport { memGet, memPut, resilientFetch, singleflight } from './resilience.js';\nimport type {\n BatchResponse, HealthResponse, ManifestResponse, QuoteRequest, QuoteResponse, QuoteTx,\n} from './types.js';\n\nexport class BlazeApiError extends Error {\n readonly code: string;\n readonly status: number;\n constructor(code: string, message: string, status: number) {\n super(message);\n this.name = 'BlazeApiError';\n this.code = code;\n this.status = status;\n }\n}\n\nexport interface ClientOptions {\n /** Override the API origin (e.g. a mirror). Default: https://blazephoenix.xyz */\n baseUrl?: string;\n /** Custom fetch (tests, proxies). Default: globalThis.fetch. */\n fetchFn?: typeof fetch;\n /** Per-request timeout in ms. Default 15000. */\n timeoutMs?: number;\n /** Extra attempts on transient failures (network, 429, 502-504), honouring\n * the server's retry-after. Default 2. Set 0 to disable. */\n retries?: number;\n /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot\n * loops without serving stale execution data. Default 1000ms; 0 disables. */\n cacheTtlMs?: number;\n}\n\nfunction toSearch(req: QuoteRequest): URLSearchParams {\n const sp = new URLSearchParams();\n sp.set('chain', String(resolveChain(req.chain)));\n sp.set('in', req.tokenIn.trim());\n sp.set('out', req.tokenOut.trim());\n sp.set('amountIn', typeof req.amountIn === 'bigint' ? req.amountIn.toString() : String(req.amountIn).trim());\n if (req.recipient) sp.set('recipient', req.recipient);\n if (req.slippageBps !== undefined) sp.set('slippageBps', String(req.slippageBps));\n if (req.deadlineSec !== undefined) sp.set('deadlineSec', String(req.deadlineSec));\n if (req.exact) sp.set('exact', '1');\n return sp;\n}\n\nexport class BlazePhoenix {\n private readonly base: string;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly cacheTtlMs: number;\n\n constructor(opts: ClientOptions = {}) {\n this.base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n this.fetchFn = opts.fetchFn ?? globalThis.fetch;\n this.timeoutMs = opts.timeoutMs ?? 15_000;\n this.retries = opts.retries ?? 2;\n this.cacheTtlMs = opts.cacheTtlMs ?? 1_000;\n if (!this.fetchFn) throw new Error('No fetch available — Node >= 18 required (or pass fetchFn)');\n }\n\n /** Build the GET /api/quote URL for a request (useful for logging/debugging). */\n quoteUrl(req: QuoteRequest): string {\n return `${this.base}/api/quote?${toSearch(req).toString()}`;\n }\n\n private async call<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {\n retries: this.retries,\n timeoutMs: this.timeoutMs,\n });\n const body = (await res.json().catch(() => null)) as\n | (T & { ok: true })\n | { ok: false; code?: string; error?: string }\n | null;\n if (!body || typeof body !== 'object') {\n throw new BlazeApiError('bad_response', `non-JSON response (HTTP ${res.status})`, res.status);\n }\n if ('ok' in body && body.ok === false) {\n throw new BlazeApiError(body.code ?? 'error', body.error ?? 'request failed', res.status);\n }\n return body as T;\n }\n\n /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.\n * Identical concurrent calls share one request; preview quotes ride a tiny\n * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */\n async quote(req: QuoteRequest): Promise<QuoteResponse> {\n const qs = toSearch(req).toString();\n const key = `Q ${this.base}?${qs}`;\n const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;\n if (cacheable) {\n const hit = memGet(key, this.cacheTtlMs);\n if (hit) return hit as QuoteResponse;\n }\n const q = await singleflight(key, () => this.call<QuoteResponse>(`/api/quote?${qs}`));\n if (cacheable) memPut(key, q);\n return q;\n }\n\n /** Up to 10 quotes in one round-trip (screeners / arb loops).\n * Per-item failures come back inline — the batch itself only throws on\n * transport/validation errors. Identical concurrent batches coalesce. */\n quoteBatch(reqs: QuoteRequest[]): Promise<BatchResponse> {\n const body = JSON.stringify({\n requests: reqs.map((r) => Object.fromEntries(toSearch(r).entries())),\n });\n return singleflight(`B ${this.base} ${body}`, () =>\n this.call<BatchResponse>('/api/quote/batch', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body,\n }));\n }\n\n /** Service health + per-chain live flags. Zero upstream cost server-side —\n * poll it from your monitor as often as you like. */\n health(): Promise<HealthResponse> {\n return this.call<HealthResponse>('/api/health');\n }\n\n /** Machine-readable protocol manifest — near-static, cached for 1h. */\n async manifest(): Promise<ManifestResponse> {\n const key = `M ${this.base}`;\n const hit = memGet(key, 3_600_000);\n if (hit) return hit as ManifestResponse;\n const m = await singleflight(key, () => this.call<ManifestResponse>('/api/manifest'));\n memPut(key, m);\n return m;\n }\n}\n\nexport interface PollOptions {\n /** Tick interval in ms (min 500, default 4000). */\n intervalMs?: number;\n onError?: (e: unknown) => void;\n}\n\n/** Poll a pair and get called back with each fresh quote — the heartbeat of a\n * price bot in one line. Overlap-safe (a slow tick is skipped, not stacked).\n * Returns a stop function. */\nexport function pollQuote(\n client: BlazePhoenix,\n req: QuoteRequest,\n onQuote: (q: QuoteResponse) => void,\n opts: PollOptions = {},\n): () => void {\n const interval = Math.max(500, opts.intervalMs ?? 4_000);\n let stopped = false;\n let busy = false;\n const tick = async () => {\n if (stopped || busy) return;\n busy = true;\n try {\n const q = await client.quote(req);\n if (!stopped) onQuote(q);\n } catch (e) {\n if (!stopped) opts.onError?.(e);\n } finally {\n busy = false;\n }\n };\n void tick();\n const timer = setInterval(() => { void tick(); }, interval);\n return () => { stopped = true; clearInterval(timer); };\n}\n\n/** The ready-to-broadcast transaction from a quote (requires `recipient` in the\n * request and an ERC-20 input). Throws with a precise reason otherwise. */\nexport function buildSwapTx(q: QuoteResponse): QuoteTx {\n if (q.tx) return q.tx;\n if (q.wrapRequired) {\n throw new Error('native ETH input: wrap to WETH first (WETH.deposit), then re-quote with in=WETH');\n }\n throw new Error('no tx in quote — pass `recipient` in the request (and check quote.canExecute)');\n}\n\nexport interface DeepLinkOptions {\n chain?: number | string;\n tokenIn?: string;\n tokenOut?: string;\n /** Human units for the pay field (e.g. \"0.5\"). */\n amount?: string;\n tab?: 'home' | 'swap' | 'staking' | 'airdrop' | 'api';\n baseUrl?: string;\n}\n\n/** A shareable link that opens the site pre-filled — bot buttons, referral posts. */\nexport function deepLink(opts: DeepLinkOptions = {}): string {\n const base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n const sp = new URLSearchParams();\n sp.set('tab', opts.tab ?? 'swap');\n if (opts.chain !== undefined) sp.set('chain', String(resolveChain(opts.chain)));\n if (opts.tokenIn) sp.set('in', opts.tokenIn);\n if (opts.tokenOut) sp.set('out', opts.tokenOut);\n if (opts.amount) sp.set('amt', opts.amount);\n return `${base}/?${sp.toString()}`;\n}\n","// =============================================================================\n// BlazePhoenix Router + Quoter ABI fragments (match the v1.0.0 deployments).\n// The Route/Hop/Leg tuple mirrors BlazePhoenixCore.sol — a decoded route from\n// `previewPlan` round-trips verbatim into `swapExactIn`.\n// =============================================================================\n\nconst LEG_COMPONENTS = [\n { name: 'pool', type: 'address' },\n { name: 'hooks', type: 'address' },\n { name: 'kind', type: 'uint8' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'stable', type: 'bool' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'auxId', type: 'bytes32' },\n] as const;\n\nconst HOP_COMPONENTS = [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'legs', type: 'tuple[]', components: LEG_COMPONENTS },\n] as const;\n\nconst ROUTE_COMPONENTS = [\n { name: 'hops', type: 'tuple[]', components: HOP_COMPONENTS },\n { name: 'totalOut', type: 'uint256' },\n { name: 'singleOut', type: 'uint256' },\n { name: 'singleOutFloor', type: 'uint256' },\n { name: 'expectedImpactBps', type: 'uint256' },\n { name: 'confidenceWad', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hasSurplus', type: 'bool' },\n { name: 'isV4Bundle', type: 'bool' },\n] as const;\n\nconst PREVIEW_COMPONENTS = [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'grossOut', type: 'uint256' },\n { name: 'protocolFee', type: 'uint256' },\n { name: 'safetyBuffer', type: 'uint256' },\n { name: 'netOut', type: 'uint256' },\n { name: 'ironFloor', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'effectiveMinOut', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hops', type: 'uint256' },\n { name: 'legs', type: 'uint256' },\n { name: 'topology', type: 'uint8' },\n { name: 'bridgeUsed', type: 'address' },\n { name: 'canExecute', type: 'bool' },\n] as const;\n\nexport const QUOTER_ABI = [\n {\n type: 'function',\n name: 'previewPlan',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'pv', type: 'tuple', components: PREVIEW_COMPONENTS },\n { name: 'fallbackRoute', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'hasFallback', type: 'bool' },\n ],\n },\n {\n type: 'function',\n name: 'previewPlanExact',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'exactOut', type: 'uint256' },\n ],\n },\n] as const;\n\nexport const ROUTER_ABI = [\n {\n type: 'function',\n name: 'swapExactIn',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'amountIn', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'event',\n name: 'Swap',\n inputs: [\n { name: 'user', type: 'address', indexed: true },\n { name: 'tokenIn', type: 'address', indexed: true },\n { name: 'tokenOut', type: 'address', indexed: true },\n { name: 'amountIn', type: 'uint256', indexed: false },\n { name: 'amountOut', type: 'uint256', indexed: false },\n { name: 'legs', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Surplus',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'amount', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// =============================================================================\n// ERC-20 helpers — zero dependencies. Completes the integration loop:\n// quote → buildApproveTx (once per token) → buildSwapTx → send.\n// Plus human-amount conversion so callers never hand-count decimals.\n// =============================================================================\n\nimport { CHAINS, resolveChain } from './constants.js';\nimport type { Address, ChainRef, Hex, QuoteTx } from './types.js';\n\n/** Unlimited allowance (2^256 − 1). Prefer EXACT amounts — pass the amount you\n * are about to swap; use MAX_UINT256 only when you consciously want one\n * approval forever (bots with their own key management). */\nexport const MAX_UINT256 = (1n << 256n) - 1n;\n\nconst HEX_ADDR = /^0x[0-9a-fA-F]{40}$/;\n\n// approve(address,uint256)\nconst APPROVE_SELECTOR = '0x095ea7b3';\n\nfunction pad32(hexNo0x: string): string {\n return hexNo0x.padStart(64, '0');\n}\n\nexport interface ApproveOptions {\n /** ERC-20 token to approve (the swap's tokenIn). */\n token: Address;\n /** Chain id or name — picks the Router as the default spender. */\n chain: ChainRef;\n /** Allowance in base units. Be exact; MAX_UINT256 opts into unlimited. */\n amount: bigint;\n /** Override the spender (defaults to the BlazePhoenix Router). */\n spender?: Address;\n}\n\n/** Ready-to-send `approve` transaction for the Router (or a custom spender).\n * Send it once per token before the first swap; then swap freely. */\nexport function buildApproveTx(opts: ApproveOptions): QuoteTx {\n const chainId = resolveChain(opts.chain);\n const spender = opts.spender ?? CHAINS[chainId].contracts.router;\n if (!HEX_ADDR.test(opts.token)) throw new Error(`invalid token address: ${opts.token}`);\n if (!HEX_ADDR.test(spender)) throw new Error(`invalid spender address: ${spender}`);\n if (opts.amount < 0n || opts.amount > MAX_UINT256) throw new Error('amount out of uint256 range');\n const data = (APPROVE_SELECTOR\n + pad32(spender.slice(2).toLowerCase())\n + pad32(opts.amount.toString(16))) as Hex;\n return { to: opts.token, data, value: '0' };\n}\n\n/** \"1.5\" + 18 decimals → 1500000000000000000n. Pure string math — no floats,\n * no precision loss. Rejects more fractional digits than the token carries. */\nexport function toBaseUnits(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const s = amount.trim();\n const m = /^(\\d+)(?:\\.(\\d+))?$/.exec(s);\n if (!m) throw new Error(`invalid amount: \"${amount}\" (use e.g. \"1.5\")`);\n const [, whole, frac = ''] = m;\n if (frac.length > decimals) {\n throw new Error(`\"${amount}\" has ${frac.length} fractional digits — token only carries ${decimals}`);\n }\n return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(frac.padEnd(decimals, '0') || '0');\n}\n\n/** 1500000000000000000n + 18 decimals → \"1.5\" (trailing zeros trimmed).\n * `maxDp` optionally truncates the fractional part for display. */\nexport function fromBaseUnits(v: bigint | string, decimals: number, maxDp?: number): string {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const n = typeof v === 'bigint' ? v : BigInt(v);\n const neg = n < 0n;\n const abs = neg ? -n : n;\n const base = 10n ** BigInt(decimals);\n const whole = abs / base;\n let frac = (abs % base).toString().padStart(decimals, '0');\n if (maxDp !== undefined) frac = frac.slice(0, Math.max(0, maxDp));\n frac = frac.replace(/0+$/, '');\n return `${neg ? '-' : ''}${whole}${frac ? `.${frac}` : ''}`;\n}\n","// =============================================================================\n// On-chain module — skip HTTP entirely: quote on the Quoter from your own\n// node and watch the Router's fills. Needs the optional `viem` peer:\n// npm i viem\n// You supply the RPC URL — the SDK ships no keys and no default endpoints.\n// =============================================================================\n\nimport { QUOTER_ABI, ROUTER_ABI } from './abis.js';\nimport { CHAINS, PUBLIC_RPCS, resolveChain, type SupportedChainId } from './constants.js';\nimport type { Address, Fill } from './types.js';\n\nasync function loadViem() {\n try {\n return await import('viem');\n } catch {\n throw new Error(\"this feature needs the optional peer dependency 'viem' — npm i viem\");\n }\n}\n\nexport interface OnChainOptions {\n chain: number | string;\n /** Your RPC endpoint. OPTIONAL since v0.4.0 — omitted, the SDK falls back\n * across public keyless endpoints (fine for dev/bots; bring your own node\n * for production throughput). The SDK still ships no providers and no keys. */\n rpcUrl?: string;\n}\n\n/** viem transport: caller's RPC when given, else public-endpoint fallback. */\nasync function transportFor(chainId: SupportedChainId, rpcUrl?: string) {\n const { http, fallback } = await loadViem();\n return rpcUrl ? http(rpcUrl) : fallback(PUBLIC_RPCS[chainId].map((u) => http(u)));\n}\n\n/** previewPlan straight from the chain — the exact numbers the API serves. */\nexport async function quoteOnChain(\n opts: OnChainOptions & { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n) {\n const { createPublicClient } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const [pv, , hasFallback] = (await client.readContract({\n address: CHAINS[chainId].contracts.quoter,\n abi: QUOTER_ABI,\n functionName: 'previewPlan',\n args: [opts.tokenIn, opts.tokenOut, opts.amountIn],\n })) as readonly [Record<string, unknown>, unknown, boolean];\n return { preview: pv, hasFallback, chainId };\n}\n\nexport interface WatchFillsOptions extends OnChainOptions {\n onFill: (fill: Fill) => void;\n /** Poll interval in ms (default 4000). */\n pollMs?: number;\n}\n\n/** Stream every BlazePhoenix fill on a chain (one Router `Swap` event per\n * swap). Returns an unwatch function. */\nexport async function watchFills(opts: WatchFillsOptions): Promise<() => void> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n return client.watchEvent({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n pollingInterval: opts.pollMs ?? 4_000,\n onLogs: (logs) => {\n for (const log of logs) {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n opts.onFill({\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n });\n }\n },\n });\n}\n\n/** Historic fills over a block range (for indexing / the quoted-vs-executed\n * verification pattern documented at https://blazephoenix.xyz/?tab=api). */\nexport async function getFills(\n opts: OnChainOptions & { fromBlock: bigint; toBlock: bigint },\n): Promise<Fill[]> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const logs = await client.getLogs({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n fromBlock: opts.fromBlock,\n toBlock: opts.toBlock,\n });\n return logs.map((log) => {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n return {\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n };\n });\n}\n\nexport { ROUTER_ABI, QUOTER_ABI };\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/resilience.ts","../src/client.ts","../src/abis.ts","../src/erc20.ts","../src/onchain.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// =============================================================================\n// Protocol constants — BlazePhoenix v1.0.0 deployments.\n// Source of truth at runtime: GET https://blazephoenix.xyz/api/manifest\n// (these statics let the SDK work fully offline / on-chain-only).\n// =============================================================================\n\nexport const API_BASE = 'https://blazephoenix.xyz';\n\nexport type SupportedChainId = 1 | 8453 | 10 | 42161 | 4663;\n\nexport interface ChainInfo {\n chainId: SupportedChainId;\n name: string;\n explorer: string;\n weth: `0x${string}`;\n usdc: `0x${string}`;\n bzpx?: `0x${string}`;\n contracts: {\n hub: `0x${string}`;\n solver: `0x${string}`;\n router: `0x${string}`;\n quoter: `0x${string}`;\n };\n}\n\nexport const CHAINS: Record<SupportedChainId, ChainInfo> = {\n 1: {\n chainId: 1,\n name: 'Ethereum',\n explorer: 'https://etherscan.io',\n weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n contracts: {\n hub: '0xc4FA9a5720fe3294D3AA9fc427E2a760591E57ae',\n solver: '0xc124d91258db0C14bf13b826CF64E16bfEA8a73e',\n router: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n quoter: '0x4a20AA0912388ff7A9221Ab6BFC224cc20Baa0c3',\n },\n },\n 8453: {\n chainId: 8453,\n name: 'Base',\n explorer: 'https://basescan.org',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n bzpx: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n contracts: {\n hub: '0x428554DEe93A1B8B5Bc6Fd19adDAfe55106fc04C',\n solver: '0xB1902990260975dD4C89ad74B1f317bc100CB830',\n router: '0x2a779f9Be49aac57495A8B6467Cc325a8a47Eb9f',\n quoter: '0x4cEF0615614B212895F45Aa1D4833B16666E18d3',\n },\n },\n 10: {\n chainId: 10,\n name: 'Optimism',\n explorer: 'https://optimistic.etherscan.io',\n weth: '0x4200000000000000000000000000000000000006',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n 42161: {\n chainId: 42161,\n name: 'Arbitrum',\n explorer: 'https://arbiscan.io',\n weth: '0x82aF49447D8a07e3bd95BD0d56f35241523fBab1',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xfB18EF6f62A0278A273Af4b7A46b454F9E482dc2',\n },\n },\n // Robinhood Chain — the same bytecode as every other deployment, so every\n // property proven elsewhere holds here. Note the USD asset is USDG, not\n // USDC: the `usdc` field carries the chain's canonical dollar token, which\n // on this chain is USDG. Explorer is Blockscout rather than an Etherscan.\n 4663: {\n chainId: 4663,\n name: 'Robinhood',\n explorer: 'https://robinhoodchain.blockscout.com',\n weth: '0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73',\n usdc: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168',\n contracts: {\n hub: '0x23113e72165a034265Ab8Bf2277CCB7a85Cb7483',\n solver: '0x0c0d96B237FABa8FE5e8aE77754Ef29109D2B33f',\n router: '0x7262e7483ab6f0db7b8f90eC3a9de3B02Ab36F6A',\n quoter: '0xE1aE5f49013920CF71De8CED4043e14C4d63416b',\n },\n },\n};\n\n/** Accepts a chain id (number or numeric string) or a human alias. */\nexport function resolveChain(chain: number | string): SupportedChainId {\n const aliases: Record<string, SupportedChainId> = {\n '1': 1, eth: 1, ethereum: 1, mainnet: 1,\n '8453': 8453, base: 8453,\n '10': 10, op: 10, optimism: 10,\n '42161': 42161, arb: 42161, arbitrum: 42161, 'arbitrum-one': 42161,\n '4663': 4663, rh: 4663, robinhood: 4663, 'robinhood-chain': 4663,\n };\n const id = aliases[String(chain).trim().toLowerCase()];\n if (!id) {\n throw new Error(\n `Unsupported chain \"${chain}\" — use 8453/base, 1/eth, 10/optimism, `\n + `42161/arbitrum or 4663/robinhood`,\n );\n }\n return id;\n}\n\n/** Public, KEYLESS RPC endpoints per chain — community infrastructure, no\n * providers, no keys (enforced by tests). They make the on-chain module work\n * with ZERO configuration; production integrations should still bring their\n * own `rpcUrl` for guaranteed throughput. */\nexport const PUBLIC_RPCS: Record<SupportedChainId, string[]> = {\n 1: [\n 'https://ethereum-rpc.publicnode.com',\n 'https://cloudflare-eth.com',\n 'https://1rpc.io/eth',\n ],\n 8453: [\n 'https://mainnet.base.org',\n 'https://base-rpc.publicnode.com',\n 'https://1rpc.io/base',\n ],\n 10: [\n 'https://optimism-rpc.publicnode.com',\n 'https://mainnet.optimism.io',\n 'https://1rpc.io/op',\n ],\n 42161: [\n 'https://arbitrum-one-rpc.publicnode.com',\n 'https://arb1.arbitrum.io/rpc',\n 'https://1rpc.io/arb',\n ],\n 4663: [\n 'https://rpc.mainnet.chain.robinhood.com',\n ],\n};\n\n/** Protocol fee (bps) applied to quoted output; execution surplus is fee-exempt. */\nexport const FEE_BPS = 28;\n\n/** Router event topic0 hashes (one `Swap` per fill — index everything with them).\n * Verified against the ABIs by `npm test` (viem toEventSelector). */\nexport const SWAP_TOPIC0 =\n '0xd6d34547c69c5ee3d2667625c188acf1006abb93e0ee7cf03925c67cf7760413' as const;\nexport const SURPLUS_TOPIC0 =\n '0x1a3afef0f067eb51a6bfec6ab3625a4408dd8c3571b72836483e68feb70d1026' as const;\n","// =============================================================================\n// Resilience core — the SDK ships the same meta-patterns the BlazePhoenix\n// edge runs, so every integration is polite and outage-proof by default:\n//\n// • singleflight — identical concurrent calls share ONE request\n// • micro-TTL — a tiny preview cache (default 1s ≈ intra-block) absorbs\n// hot loops without ever serving stale execution data\n// • retry — transient failures (network, 429, 502/503) retry with\n// backoff and RESPECT the server's retry-after header\n//\n// Execution-grade requests (recipient / exact=1) are never TTL-cached here,\n// mirroring the server's own red line.\n// =============================================================================\n\nconst INFLIGHT = new Map<string, Promise<unknown>>();\nconst MEM = new Map<string, { at: number; data: unknown }>();\n\n/** Coalesce concurrent identical work — leader runs, followers share. */\nexport async function singleflight<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const existing = INFLIGHT.get(key) as Promise<T> | undefined;\n if (existing) return existing;\n const flight = fn();\n INFLIGHT.set(key, flight as Promise<unknown>);\n try {\n return await flight;\n } finally {\n INFLIGHT.delete(key);\n }\n}\n\nexport function memGet(key: string, ttlMs: number, now = Date.now()): unknown | undefined {\n if (ttlMs <= 0) return undefined;\n const hit = MEM.get(key);\n return hit && now - hit.at < ttlMs ? hit.data : undefined;\n}\n\nexport function memPut(key: string, data: unknown, now = Date.now()): void {\n MEM.set(key, { at: now, data });\n // Bound the cache — a long-running bot must never leak memory here.\n if (MEM.size > 500) {\n const oldest = MEM.keys().next().value;\n if (oldest !== undefined) MEM.delete(oldest);\n }\n}\n\nexport interface RetryOptions {\n /** Extra attempts after the first (default 2). */\n retries?: number;\n /** Base backoff in ms; grows ×3 per attempt with jitter (default 250). */\n backoffMs?: number;\n timeoutMs?: number;\n}\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));\n\nfunction retryDelayMs(res: Response | undefined, attempt: number, base: number): number {\n const ra = Number(res?.headers.get('retry-after'));\n if (Number.isFinite(ra) && ra > 0) return Math.min(10_000, ra * 1000);\n return base * 3 ** attempt + Math.floor(Math.random() * base);\n}\n\n/** Quote reads are idempotent — transient failures deserve another shot. */\nfunction isTransient(res: Response | undefined): boolean {\n return !res || res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504;\n}\n\n/** fetch with timeout + polite retries. Returns the final Response (which may\n * still be an error status — non-transient statuses are never retried). */\nexport async function resilientFetch(\n fetchFn: typeof fetch,\n url: string,\n init: RequestInit | undefined,\n opts: RetryOptions = {},\n): Promise<Response> {\n const { retries = 2, backoffMs = 250, timeoutMs = 15_000 } = opts;\n let lastErr: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n let res: Response | undefined;\n try {\n res = await fetchFn(url, { ...init, signal: AbortSignal.timeout(timeoutMs) });\n if (!isTransient(res)) return res;\n if (attempt === retries) return res;\n } catch (e) {\n lastErr = e;\n if (attempt === retries) throw e;\n }\n await sleep(retryDelayMs(res, attempt, backoffMs));\n }\n /* istanbul ignore next -- loop always returns or throws */\n throw lastErr instanceof Error ? lastErr : new Error('request failed');\n}\n\n/** Test hook. */\nexport function __resetResilience(): void {\n INFLIGHT.clear();\n MEM.clear();\n}\n","// =============================================================================\n// HTTP client — zero dependencies (native fetch). Every quote is computed\n// on-chain by the BlazePhoenix Quoter; the API is a thin mirror of the chain.\n// No API key. Open CORS. https://blazephoenix.xyz/?tab=api\n// =============================================================================\n\nimport { API_BASE, resolveChain } from './constants.js';\nimport { memGet, memPut, resilientFetch, singleflight } from './resilience.js';\nimport type {\n BatchResponse, HealthResponse, ManifestResponse, QuoteRequest, QuoteResponse, QuoteTx,\n} from './types.js';\n\nexport class BlazeApiError extends Error {\n readonly code: string;\n readonly status: number;\n constructor(code: string, message: string, status: number) {\n super(message);\n this.name = 'BlazeApiError';\n this.code = code;\n this.status = status;\n }\n}\n\nexport interface ClientOptions {\n /** Override the API origin (e.g. a mirror). Default: https://blazephoenix.xyz */\n baseUrl?: string;\n /** Custom fetch (tests, proxies). Default: globalThis.fetch. */\n fetchFn?: typeof fetch;\n /** Per-request timeout in ms. Default 15000. */\n timeoutMs?: number;\n /** Extra attempts on transient failures (network, 429, 502-504), honouring\n * the server's retry-after. Default 2. Set 0 to disable. */\n retries?: number;\n /** Micro-cache for PREVIEW quotes (no recipient, no exact) — absorbs hot\n * loops without serving stale execution data. Default 1000ms; 0 disables. */\n cacheTtlMs?: number;\n /**\n * YOUR OWN https RPC endpoint, applied to every request that does not set its\n * own. The API reads through your node instead of its shared pool.\n *\n * The service stays free and keyless either way — this exists so sustained\n * automation carries its own read volume, which is what keeps the free path\n * viable for callers who cannot bring a node. Your node is tried first and\n * ours remain the fallback, so this can only improve reliability. If you are\n * running a bot, this is the single most considerate line you can add.\n */\n rpc?: string;\n}\n\nfunction toSearch(req: QuoteRequest): URLSearchParams {\n const sp = new URLSearchParams();\n sp.set('chain', String(resolveChain(req.chain)));\n sp.set('in', req.tokenIn.trim());\n sp.set('out', req.tokenOut.trim());\n sp.set('amountIn', typeof req.amountIn === 'bigint' ? req.amountIn.toString() : String(req.amountIn).trim());\n if (req.recipient) sp.set('recipient', req.recipient);\n if (req.slippageBps !== undefined) sp.set('slippageBps', String(req.slippageBps));\n if (req.deadlineSec !== undefined) sp.set('deadlineSec', String(req.deadlineSec));\n if (req.exact) sp.set('exact', '1');\n // The caller's own node, when they brought one. The API validates it and\n // silently ignores anything unsafe, so a bad value degrades to the normal\n // free path rather than failing the request.\n if (req.rpc) sp.set('rpc', req.rpc.trim());\n return sp;\n}\n\nexport class BlazePhoenix {\n private readonly base: string;\n private readonly fetchFn: typeof fetch;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly cacheTtlMs: number;\n /** Default BYO-RPC endpoint applied to every request that does not set one. */\n private readonly rpc?: string;\n\n constructor(opts: ClientOptions = {}) {\n this.base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n this.fetchFn = opts.fetchFn ?? globalThis.fetch;\n this.timeoutMs = opts.timeoutMs ?? 15_000;\n this.retries = opts.retries ?? 2;\n this.cacheTtlMs = opts.cacheTtlMs ?? 1_000;\n this.rpc = opts.rpc;\n if (!this.fetchFn) throw new Error('No fetch available — Node >= 18 required (or pass fetchFn)');\n }\n\n /** Fold the client-wide BYO-RPC default into a request that omits one. */\n private withRpc(req: QuoteRequest): QuoteRequest {\n return this.rpc && !req.rpc ? { ...req, rpc: this.rpc } : req;\n }\n\n /** Build the GET /api/quote URL for a request (useful for logging/debugging). */\n quoteUrl(req: QuoteRequest): string {\n return `${this.base}/api/quote?${toSearch(this.withRpc(req)).toString()}`;\n }\n\n private async call<T>(path: string, init?: RequestInit): Promise<T> {\n const res = await resilientFetch(this.fetchFn, `${this.base}${path}`, init, {\n retries: this.retries,\n timeoutMs: this.timeoutMs,\n });\n const body = (await res.json().catch(() => null)) as\n | (T & { ok: true })\n | { ok: false; code?: string; error?: string }\n | null;\n if (!body || typeof body !== 'object') {\n throw new BlazeApiError('bad_response', `non-JSON response (HTTP ${res.status})`, res.status);\n }\n if ('ok' in body && body.ok === false) {\n throw new BlazeApiError(body.code ?? 'error', body.error ?? 'request failed', res.status);\n }\n return body as T;\n }\n\n /** One quote — previewPlan computed on-chain. Throws BlazeApiError on failure.\n * Identical concurrent calls share one request; preview quotes ride a tiny\n * micro-cache (cacheTtlMs) so hot loops never hammer the wire. */\n async quote(reqIn: QuoteRequest): Promise<QuoteResponse> {\n const req = this.withRpc(reqIn);\n const qs = toSearch(req).toString();\n const key = `Q ${this.base}?${qs}`;\n const cacheable = !req.recipient && !req.exact && this.cacheTtlMs > 0;\n if (cacheable) {\n const hit = memGet(key, this.cacheTtlMs);\n if (hit) return hit as QuoteResponse;\n }\n const q = await singleflight(key, () => this.call<QuoteResponse>(`/api/quote?${qs}`));\n if (cacheable) memPut(key, q);\n return q;\n }\n\n /** Up to 10 quotes in one round-trip (screeners / arb loops).\n * Per-item failures come back inline — the batch itself only throws on\n * transport/validation errors. Identical concurrent batches coalesce. */\n quoteBatch(reqs: QuoteRequest[]): Promise<BatchResponse> {\n const body = JSON.stringify({\n requests: reqs.map((r) => Object.fromEntries(toSearch(r).entries())),\n });\n return singleflight(`B ${this.base} ${body}`, () =>\n this.call<BatchResponse>('/api/quote/batch', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body,\n }));\n }\n\n /** Service health + per-chain live flags. Zero upstream cost server-side —\n * poll it from your monitor as often as you like. */\n health(): Promise<HealthResponse> {\n return this.call<HealthResponse>('/api/health');\n }\n\n /** Machine-readable protocol manifest — near-static, cached for 1h. */\n async manifest(): Promise<ManifestResponse> {\n const key = `M ${this.base}`;\n const hit = memGet(key, 3_600_000);\n if (hit) return hit as ManifestResponse;\n const m = await singleflight(key, () => this.call<ManifestResponse>('/api/manifest'));\n memPut(key, m);\n return m;\n }\n}\n\nexport interface PollOptions {\n /** Tick interval in ms (min 500, default 4000). */\n intervalMs?: number;\n onError?: (e: unknown) => void;\n}\n\n/** Poll a pair and get called back with each fresh quote — the heartbeat of a\n * price bot in one line. Overlap-safe (a slow tick is skipped, not stacked).\n * Returns a stop function. */\nexport function pollQuote(\n client: BlazePhoenix,\n req: QuoteRequest,\n onQuote: (q: QuoteResponse) => void,\n opts: PollOptions = {},\n): () => void {\n const interval = Math.max(500, opts.intervalMs ?? 4_000);\n let stopped = false;\n let busy = false;\n const tick = async () => {\n if (stopped || busy) return;\n busy = true;\n try {\n const q = await client.quote(req);\n if (!stopped) onQuote(q);\n } catch (e) {\n if (!stopped) opts.onError?.(e);\n } finally {\n busy = false;\n }\n };\n void tick();\n const timer = setInterval(() => { void tick(); }, interval);\n return () => { stopped = true; clearInterval(timer); };\n}\n\n/** The ready-to-broadcast transaction from a quote (requires `recipient` in the\n * request and an ERC-20 input). Throws with a precise reason otherwise. */\nexport function buildSwapTx(q: QuoteResponse): QuoteTx {\n if (q.tx) return q.tx;\n if (q.wrapRequired) {\n throw new Error('native ETH input: wrap to WETH first (WETH.deposit), then re-quote with in=WETH');\n }\n throw new Error('no tx in quote — pass `recipient` in the request (and check quote.canExecute)');\n}\n\nexport interface DeepLinkOptions {\n chain?: number | string;\n tokenIn?: string;\n tokenOut?: string;\n /** Human units for the pay field (e.g. \"0.5\"). */\n amount?: string;\n tab?: 'home' | 'swap' | 'staking' | 'airdrop' | 'api';\n baseUrl?: string;\n}\n\n/** A shareable link that opens the site pre-filled — bot buttons, referral posts. */\nexport function deepLink(opts: DeepLinkOptions = {}): string {\n const base = (opts.baseUrl ?? API_BASE).replace(/\\/+$/, '');\n const sp = new URLSearchParams();\n sp.set('tab', opts.tab ?? 'swap');\n if (opts.chain !== undefined) sp.set('chain', String(resolveChain(opts.chain)));\n if (opts.tokenIn) sp.set('in', opts.tokenIn);\n if (opts.tokenOut) sp.set('out', opts.tokenOut);\n if (opts.amount) sp.set('amt', opts.amount);\n return `${base}/?${sp.toString()}`;\n}\n","// =============================================================================\n// BlazePhoenix Router + Quoter ABI fragments (match the v1.0.0 deployments).\n// The Route/Hop/Leg tuple mirrors BlazePhoenixCore.sol — a decoded route from\n// `previewPlan` round-trips verbatim into `swapExactIn`.\n// =============================================================================\n\nconst LEG_COMPONENTS = [\n { name: 'pool', type: 'address' },\n { name: 'hooks', type: 'address' },\n { name: 'kind', type: 'uint8' },\n { name: 'fee', type: 'uint24' },\n { name: 'tickSpacing', type: 'int24' },\n { name: 'zeroForOne', type: 'bool' },\n { name: 'stable', type: 'bool' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'auxId', type: 'bytes32' },\n] as const;\n\nconst HOP_COMPONENTS = [\n { name: 'tokenIn', type: 'address' },\n { name: 'tokenOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n { name: 'expectedOut', type: 'uint256' },\n { name: 'legs', type: 'tuple[]', components: LEG_COMPONENTS },\n] as const;\n\nconst ROUTE_COMPONENTS = [\n { name: 'hops', type: 'tuple[]', components: HOP_COMPONENTS },\n { name: 'totalOut', type: 'uint256' },\n { name: 'singleOut', type: 'uint256' },\n { name: 'singleOutFloor', type: 'uint256' },\n { name: 'expectedImpactBps', type: 'uint256' },\n { name: 'confidenceWad', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hasSurplus', type: 'bool' },\n { name: 'isV4Bundle', type: 'bool' },\n] as const;\n\nconst PREVIEW_COMPONENTS = [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'grossOut', type: 'uint256' },\n { name: 'protocolFee', type: 'uint256' },\n { name: 'safetyBuffer', type: 'uint256' },\n { name: 'netOut', type: 'uint256' },\n { name: 'ironFloor', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'effectiveMinOut', type: 'uint256' },\n { name: 'estGas', type: 'uint256' },\n { name: 'hops', type: 'uint256' },\n { name: 'legs', type: 'uint256' },\n { name: 'topology', type: 'uint8' },\n { name: 'bridgeUsed', type: 'address' },\n { name: 'canExecute', type: 'bool' },\n] as const;\n\nexport const QUOTER_ABI = [\n {\n type: 'function',\n name: 'previewPlan',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'pv', type: 'tuple', components: PREVIEW_COMPONENTS },\n { name: 'fallbackRoute', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'hasFallback', type: 'bool' },\n ],\n },\n {\n type: 'function',\n name: 'previewPlanExact',\n stateMutability: 'view',\n inputs: [\n { name: 'tIn', type: 'address' },\n { name: 'tOut', type: 'address' },\n { name: 'amountIn', type: 'uint256' },\n ],\n outputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'exactOut', type: 'uint256' },\n ],\n },\n] as const;\n\nexport const ROUTER_ABI = [\n {\n type: 'function',\n name: 'swapExactIn',\n stateMutability: 'nonpayable',\n inputs: [\n { name: 'route', type: 'tuple', components: ROUTE_COMPONENTS },\n { name: 'amountIn', type: 'uint256' },\n { name: 'userMinOut', type: 'uint256' },\n { name: 'recipient', type: 'address' },\n { name: 'deadline', type: 'uint256' },\n ],\n outputs: [{ name: 'amountOut', type: 'uint256' }],\n },\n {\n type: 'event',\n name: 'Swap',\n inputs: [\n { name: 'user', type: 'address', indexed: true },\n { name: 'tokenIn', type: 'address', indexed: true },\n { name: 'tokenOut', type: 'address', indexed: true },\n { name: 'amountIn', type: 'uint256', indexed: false },\n { name: 'amountOut', type: 'uint256', indexed: false },\n { name: 'legs', type: 'uint256', indexed: false },\n ],\n },\n {\n type: 'event',\n name: 'Surplus',\n inputs: [\n { name: 'token', type: 'address', indexed: true },\n { name: 'amount', type: 'uint256', indexed: false },\n ],\n },\n] as const;\n","// =============================================================================\n// ERC-20 helpers — zero dependencies. Completes the integration loop:\n// quote → buildApproveTx (once per token) → buildSwapTx → send.\n// Plus human-amount conversion so callers never hand-count decimals.\n// =============================================================================\n\nimport { CHAINS, resolveChain } from './constants.js';\nimport type { Address, ChainRef, Hex, QuoteTx } from './types.js';\n\n/** Unlimited allowance (2^256 − 1). Prefer EXACT amounts — pass the amount you\n * are about to swap; use MAX_UINT256 only when you consciously want one\n * approval forever (bots with their own key management). */\nexport const MAX_UINT256 = (1n << 256n) - 1n;\n\nconst HEX_ADDR = /^0x[0-9a-fA-F]{40}$/;\n\n// approve(address,uint256)\nconst APPROVE_SELECTOR = '0x095ea7b3';\n\nfunction pad32(hexNo0x: string): string {\n return hexNo0x.padStart(64, '0');\n}\n\nexport interface ApproveOptions {\n /** ERC-20 token to approve (the swap's tokenIn). */\n token: Address;\n /** Chain id or name — picks the Router as the default spender. */\n chain: ChainRef;\n /** Allowance in base units. Be exact; MAX_UINT256 opts into unlimited. */\n amount: bigint;\n /** Override the spender (defaults to the BlazePhoenix Router). */\n spender?: Address;\n}\n\n/** Ready-to-send `approve` transaction for the Router (or a custom spender).\n * Send it once per token before the first swap; then swap freely. */\nexport function buildApproveTx(opts: ApproveOptions): QuoteTx {\n const chainId = resolveChain(opts.chain);\n const spender = opts.spender ?? CHAINS[chainId].contracts.router;\n if (!HEX_ADDR.test(opts.token)) throw new Error(`invalid token address: ${opts.token}`);\n if (!HEX_ADDR.test(spender)) throw new Error(`invalid spender address: ${spender}`);\n if (opts.amount < 0n || opts.amount > MAX_UINT256) throw new Error('amount out of uint256 range');\n const data = (APPROVE_SELECTOR\n + pad32(spender.slice(2).toLowerCase())\n + pad32(opts.amount.toString(16))) as Hex;\n return { to: opts.token, data, value: '0' };\n}\n\n/** \"1.5\" + 18 decimals → 1500000000000000000n. Pure string math — no floats,\n * no precision loss. Rejects more fractional digits than the token carries. */\nexport function toBaseUnits(amount: string, decimals: number): bigint {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const s = amount.trim();\n const m = /^(\\d+)(?:\\.(\\d+))?$/.exec(s);\n if (!m) throw new Error(`invalid amount: \"${amount}\" (use e.g. \"1.5\")`);\n const [, whole, frac = ''] = m;\n if (frac.length > decimals) {\n throw new Error(`\"${amount}\" has ${frac.length} fractional digits — token only carries ${decimals}`);\n }\n return BigInt(whole) * 10n ** BigInt(decimals) + BigInt(frac.padEnd(decimals, '0') || '0');\n}\n\n/** 1500000000000000000n + 18 decimals → \"1.5\" (trailing zeros trimmed).\n * `maxDp` optionally truncates the fractional part for display. */\nexport function fromBaseUnits(v: bigint | string, decimals: number, maxDp?: number): string {\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 77) {\n throw new Error(`invalid decimals: ${decimals}`);\n }\n const n = typeof v === 'bigint' ? v : BigInt(v);\n const neg = n < 0n;\n const abs = neg ? -n : n;\n const base = 10n ** BigInt(decimals);\n const whole = abs / base;\n let frac = (abs % base).toString().padStart(decimals, '0');\n if (maxDp !== undefined) frac = frac.slice(0, Math.max(0, maxDp));\n frac = frac.replace(/0+$/, '');\n return `${neg ? '-' : ''}${whole}${frac ? `.${frac}` : ''}`;\n}\n","// =============================================================================\n// On-chain module — skip HTTP entirely: quote on the Quoter from your own\n// node and watch the Router's fills. Needs the optional `viem` peer:\n// npm i viem\n// You supply the RPC URL — the SDK ships no keys and no default endpoints.\n// =============================================================================\n\nimport { QUOTER_ABI, ROUTER_ABI } from './abis.js';\nimport { CHAINS, PUBLIC_RPCS, resolveChain, type SupportedChainId } from './constants.js';\nimport type { Address, Fill } from './types.js';\n\nasync function loadViem() {\n try {\n return await import('viem');\n } catch {\n throw new Error(\"this feature needs the optional peer dependency 'viem' — npm i viem\");\n }\n}\n\nexport interface OnChainOptions {\n chain: number | string;\n /** Your RPC endpoint. OPTIONAL since v0.4.0 — omitted, the SDK falls back\n * across public keyless endpoints (fine for dev/bots; bring your own node\n * for production throughput). The SDK still ships no providers and no keys. */\n rpcUrl?: string;\n}\n\n/** viem transport: caller's RPC when given, else public-endpoint fallback. */\nasync function transportFor(chainId: SupportedChainId, rpcUrl?: string) {\n const { http, fallback } = await loadViem();\n return rpcUrl ? http(rpcUrl) : fallback(PUBLIC_RPCS[chainId].map((u) => http(u)));\n}\n\n/** previewPlan straight from the chain — the exact numbers the API serves. */\nexport async function quoteOnChain(\n opts: OnChainOptions & { tokenIn: Address; tokenOut: Address; amountIn: bigint },\n) {\n const { createPublicClient } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const [pv, , hasFallback] = (await client.readContract({\n address: CHAINS[chainId].contracts.quoter,\n abi: QUOTER_ABI,\n functionName: 'previewPlan',\n args: [opts.tokenIn, opts.tokenOut, opts.amountIn],\n })) as readonly [Record<string, unknown>, unknown, boolean];\n return { preview: pv, hasFallback, chainId };\n}\n\nexport interface WatchFillsOptions extends OnChainOptions {\n onFill: (fill: Fill) => void;\n /** Poll interval in ms (default 4000). */\n pollMs?: number;\n}\n\n/** Stream every BlazePhoenix fill on a chain (one Router `Swap` event per\n * swap). Returns an unwatch function. */\nexport async function watchFills(opts: WatchFillsOptions): Promise<() => void> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n return client.watchEvent({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n pollingInterval: opts.pollMs ?? 4_000,\n onLogs: (logs) => {\n for (const log of logs) {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n opts.onFill({\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n });\n }\n },\n });\n}\n\n/** Historic fills over a block range (for indexing / the quoted-vs-executed\n * verification pattern documented at https://blazephoenix.xyz/?tab=api). */\nexport async function getFills(\n opts: OnChainOptions & { fromBlock: bigint; toBlock: bigint },\n): Promise<Fill[]> {\n const { createPublicClient, parseAbiItem } = await loadViem();\n const chainId = resolveChain(opts.chain);\n const client = createPublicClient({ transport: await transportFor(chainId, opts.rpcUrl) });\n const logs = await client.getLogs({\n address: CHAINS[chainId].contracts.router,\n event: parseAbiItem(\n 'event Swap(address indexed user, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, uint256 legs)',\n ),\n fromBlock: opts.fromBlock,\n toBlock: opts.toBlock,\n });\n return logs.map((log) => {\n const a = log.args as {\n user: Address; tokenIn: Address; tokenOut: Address;\n amountIn: bigint; amountOut: bigint; legs: bigint;\n };\n return {\n txHash: log.transactionHash as `0x${string}`,\n blockNumber: log.blockNumber ?? 0n,\n user: a.user, tokenIn: a.tokenIn, tokenOut: a.tokenOut,\n amountIn: a.amountIn, amountOut: a.amountOut, legs: a.legs,\n };\n });\n}\n\nexport { ROUTER_ABI, QUOTER_ABI };\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blazephoenix/sdk",
3
- "version": "0.4.0",
4
- "description": "Official TypeScript SDK for BlazePhoenix — the on-chain DEX aggregator. Quote, build, execute and index swaps on Base, Ethereum, Optimism and Arbitrum. No API key required.",
3
+ "version": "0.5.2",
4
+ "description": "Official TypeScript SDK for BlazePhoenix — the on-chain DEX aggregator. Quote, build, execute and index swaps on Base, Ethereum, Optimism, Arbitrum and Robinhood Chain. No API key required.",
5
5
  "keywords": [
6
6
  "blazephoenix",
7
7
  "bzpx",