@chipi-stack/shared 14.12.0 → 14.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/index.d.mts +6 -1
- package/dist/constants/index.d.ts +6 -1
- package/dist/constants/index.js +6 -5
- package/dist/constants/index.js.map +1 -1
- package/dist/constants/index.mjs +6 -6
- package/dist/constants/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -43,6 +43,11 @@ type RpcEndpoint = {
|
|
|
43
43
|
url: string;
|
|
44
44
|
headers?: Record<string, string>;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Read an env var defensively: this module is bundled into browser-facing packages
|
|
48
|
+
* where `process` may not exist. Empty / whitespace-only values are treated as unset.
|
|
49
|
+
*/
|
|
50
|
+
declare function readEnv(name: string): string | undefined;
|
|
46
51
|
/**
|
|
47
52
|
* Build the ordered endpoint chain.
|
|
48
53
|
*
|
|
@@ -262,4 +267,4 @@ declare const SESSION_ENTRYPOINTS: {
|
|
|
262
267
|
readonly REMOVE_SPENDING_POLICY: "remove_spending_policy";
|
|
263
268
|
};
|
|
264
269
|
|
|
265
|
-
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, type RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, rpcProviderFor, withRpcFallback };
|
|
270
|
+
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, type RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, readEnv, rpcProviderFor, withRpcFallback };
|
|
@@ -43,6 +43,11 @@ type RpcEndpoint = {
|
|
|
43
43
|
url: string;
|
|
44
44
|
headers?: Record<string, string>;
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* Read an env var defensively: this module is bundled into browser-facing packages
|
|
48
|
+
* where `process` may not exist. Empty / whitespace-only values are treated as unset.
|
|
49
|
+
*/
|
|
50
|
+
declare function readEnv(name: string): string | undefined;
|
|
46
51
|
/**
|
|
47
52
|
* Build the ordered endpoint chain.
|
|
48
53
|
*
|
|
@@ -262,4 +267,4 @@ declare const SESSION_ENTRYPOINTS: {
|
|
|
262
267
|
readonly REMOVE_SPENDING_POLICY: "remove_spending_policy";
|
|
263
268
|
};
|
|
264
269
|
|
|
265
|
-
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, type RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, rpcProviderFor, withRpcFallback };
|
|
270
|
+
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, type RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, readEnv, rpcProviderFor, withRpcFallback };
|
package/dist/constants/index.js
CHANGED
|
@@ -172,10 +172,10 @@ var API_VERSIONING = {
|
|
|
172
172
|
// Detailed version - sent as query param for tracking
|
|
173
173
|
};
|
|
174
174
|
var STARKNET_NETWORKS = {
|
|
175
|
-
MAINNET:
|
|
175
|
+
MAINNET: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
176
176
|
// Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.
|
|
177
177
|
MAINNET_FALLBACK: LAVA_MAINNET_RPC,
|
|
178
|
-
SEPOLIA:
|
|
178
|
+
SEPOLIA: readEnv("STARKNET_RPC_URL_SEPOLIA") ?? DEFAULT_SEPOLIA_RPC
|
|
179
179
|
};
|
|
180
180
|
var CONTRACT_ADDRESSES = {
|
|
181
181
|
USDC_MAINNET: "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb",
|
|
@@ -313,9 +313,9 @@ function isKnownShhhClassHash(classHash) {
|
|
|
313
313
|
return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);
|
|
314
314
|
}
|
|
315
315
|
var WALLET_RPC_ENDPOINTS = {
|
|
316
|
-
CHIPI:
|
|
317
|
-
READY:
|
|
318
|
-
SHHH:
|
|
316
|
+
CHIPI: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
317
|
+
READY: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
318
|
+
SHHH: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC
|
|
319
319
|
};
|
|
320
320
|
var PAYMASTER_CONFIG = {
|
|
321
321
|
URL: "https://paymaster.chipipay.com"
|
|
@@ -393,6 +393,7 @@ exports.buildRpcChain = buildRpcChain;
|
|
|
393
393
|
exports.getWalletTypeFromClassHash = getWalletTypeFromClassHash;
|
|
394
394
|
exports.isKnownShhhClassHash = isKnownShhhClassHash;
|
|
395
395
|
exports.makeRpcBaseFetch = makeRpcBaseFetch;
|
|
396
|
+
exports.readEnv = readEnv;
|
|
396
397
|
exports.rpcProviderFor = rpcProviderFor;
|
|
397
398
|
exports.withRpcFallback = withRpcFallback;
|
|
398
399
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants/rpc.ts","../../src/constants/index.ts"],"names":["RpcProvider"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\nexport const STARKNET_NETWORKS = {\n MAINNET: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: process.env.STARKNET_RPC_URL_SEPOLIA ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n READY: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n SHHH: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/constants/rpc.ts","../../src/constants/index.ts"],"names":["RpcProvider"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC, readEnv } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\n// These evaluate at MODULE SCOPE, and this module is bundled into browser-facing\n// packages, so a bare `process.env` read throws at import time anywhere `process`\n// is not defined. It has worked so far only because bundlers inject a shim, which\n// makes client-side imports of this package accidental rather than supported.\n// `readEnv` is the same guard ./rpc.ts already uses; server behaviour is identical.\nexport const STARKNET_NETWORKS = {\n MAINNET: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: readEnv(\"STARKNET_RPC_URL_SEPOLIA\") ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n READY: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n SHHH: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n"]}
|
package/dist/constants/index.mjs
CHANGED
|
@@ -170,10 +170,10 @@ var API_VERSIONING = {
|
|
|
170
170
|
// Detailed version - sent as query param for tracking
|
|
171
171
|
};
|
|
172
172
|
var STARKNET_NETWORKS = {
|
|
173
|
-
MAINNET:
|
|
173
|
+
MAINNET: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
174
174
|
// Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.
|
|
175
175
|
MAINNET_FALLBACK: LAVA_MAINNET_RPC,
|
|
176
|
-
SEPOLIA:
|
|
176
|
+
SEPOLIA: readEnv("STARKNET_RPC_URL_SEPOLIA") ?? DEFAULT_SEPOLIA_RPC
|
|
177
177
|
};
|
|
178
178
|
var CONTRACT_ADDRESSES = {
|
|
179
179
|
USDC_MAINNET: "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb",
|
|
@@ -311,9 +311,9 @@ function isKnownShhhClassHash(classHash) {
|
|
|
311
311
|
return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);
|
|
312
312
|
}
|
|
313
313
|
var WALLET_RPC_ENDPOINTS = {
|
|
314
|
-
CHIPI:
|
|
315
|
-
READY:
|
|
316
|
-
SHHH:
|
|
314
|
+
CHIPI: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
315
|
+
READY: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
316
|
+
SHHH: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC
|
|
317
317
|
};
|
|
318
318
|
var PAYMASTER_CONFIG = {
|
|
319
319
|
URL: "https://paymaster.chipipay.com"
|
|
@@ -361,6 +361,6 @@ var SESSION_ENTRYPOINTS = {
|
|
|
361
361
|
REMOVE_SPENDING_POLICY: "remove_spending_policy"
|
|
362
362
|
};
|
|
363
363
|
|
|
364
|
-
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, rpcProviderFor, withRpcFallback };
|
|
364
|
+
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, readEnv, rpcProviderFor, withRpcFallback };
|
|
365
365
|
//# sourceMappingURL=index.mjs.map
|
|
366
366
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/constants/rpc.ts","../../src/constants/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\nexport const STARKNET_NETWORKS = {\n MAINNET: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: process.env.STARKNET_RPC_URL_SEPOLIA ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n READY: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n SHHH: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/constants/rpc.ts","../../src/constants/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC, readEnv } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\n// These evaluate at MODULE SCOPE, and this module is bundled into browser-facing\n// packages, so a bare `process.env` read throws at import time anywhere `process`\n// is not defined. It has worked so far only because bundlers inject a shim, which\n// makes client-side imports of this package accidental rather than supported.\n// `readEnv` is the same guard ./rpc.ts already uses; server behaviour is identical.\nexport const STARKNET_NETWORKS = {\n MAINNET: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: readEnv(\"STARKNET_RPC_URL_SEPOLIA\") ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n READY: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n SHHH: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createPaginatedResponse, deepMerge, formatAmount, isValidAddress, isValidApiKey, parseAmount, retry, sanitizeUrl, sleep, validatePagination } from './utils/index.mjs';
|
|
2
|
-
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, rpcProviderFor, withRpcFallback } from './constants/index.mjs';
|
|
2
|
+
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, readEnv, rpcProviderFor, withRpcFallback } from './constants/index.mjs';
|
|
3
3
|
import { ErrorWithCode } from '@chipi-stack/types';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import 'starknet';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { createPaginatedResponse, deepMerge, formatAmount, isValidAddress, isValidApiKey, parseAmount, retry, sanitizeUrl, sleep, validatePagination } from './utils/index.js';
|
|
2
|
-
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, rpcProviderFor, withRpcFallback } from './constants/index.js';
|
|
2
|
+
export { API_ENDPOINTS, API_VERSIONING, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, RpcEndpoint, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, buildRpcChain, getWalletTypeFromClassHash, isKnownShhhClassHash, makeRpcBaseFetch, readEnv, rpcProviderFor, withRpcFallback } from './constants/index.js';
|
|
3
3
|
import { ErrorWithCode } from '@chipi-stack/types';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import 'starknet';
|
package/dist/index.js
CHANGED
|
@@ -257,10 +257,10 @@ var API_VERSIONING = {
|
|
|
257
257
|
// Detailed version - sent as query param for tracking
|
|
258
258
|
};
|
|
259
259
|
var STARKNET_NETWORKS = {
|
|
260
|
-
MAINNET:
|
|
260
|
+
MAINNET: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
261
261
|
// Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.
|
|
262
262
|
MAINNET_FALLBACK: LAVA_MAINNET_RPC,
|
|
263
|
-
SEPOLIA:
|
|
263
|
+
SEPOLIA: readEnv("STARKNET_RPC_URL_SEPOLIA") ?? DEFAULT_SEPOLIA_RPC
|
|
264
264
|
};
|
|
265
265
|
var CONTRACT_ADDRESSES = {
|
|
266
266
|
USDC_MAINNET: "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb",
|
|
@@ -398,9 +398,9 @@ function isKnownShhhClassHash(classHash) {
|
|
|
398
398
|
return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);
|
|
399
399
|
}
|
|
400
400
|
var WALLET_RPC_ENDPOINTS = {
|
|
401
|
-
CHIPI:
|
|
402
|
-
READY:
|
|
403
|
-
SHHH:
|
|
401
|
+
CHIPI: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
402
|
+
READY: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
403
|
+
SHHH: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC
|
|
404
404
|
};
|
|
405
405
|
var PAYMASTER_CONFIG = {
|
|
406
406
|
URL: "https://paymaster.chipipay.com"
|
|
@@ -682,6 +682,7 @@ exports.isValidAddress = isValidAddress;
|
|
|
682
682
|
exports.isValidApiKey = isValidApiKey;
|
|
683
683
|
exports.makeRpcBaseFetch = makeRpcBaseFetch;
|
|
684
684
|
exports.parseAmount = parseAmount;
|
|
685
|
+
exports.readEnv = readEnv;
|
|
685
686
|
exports.retry = retry;
|
|
686
687
|
exports.rpcProviderFor = rpcProviderFor;
|
|
687
688
|
exports.sanitizeUrl = sanitizeUrl;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/index.ts","../src/constants/rpc.ts","../src/constants/index.ts","../src/errors.ts","../src/formatters.ts","../src/validation.ts"],"names":["amountBN","RpcProvider","z"],"mappings":"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","file":"index.js","sourcesContent":["import type { PaginationQuery, PaginatedResponse, Currency } from \"@chipi-stack/types\";\nimport { API_ENDPOINTS } from \"../constants\";\n\n/**\n * Utility functions used across Chipi SDK packages\n */\n\nexport function isValidAddress(address: string): boolean {\n // Validate Starknet address format\n return /^0x[0-9a-fA-F]{1,64}$/.test(address);\n}\n\nexport function isValidApiKey(apiKey: string): boolean {\n // Validate API key format (pk_dev_ or pk_prod_)\n return /^pk_(dev|prod)_[a-zA-Z0-9]{32,}$/.test(apiKey);\n}\n\nexport function formatAmount(amount: string, decimals: number = 18): string {\n // If it's an integer, multiply by 10^decimals\n if (!amount.includes(\".\")) {\n const amountBN = BigInt(amount) * BigInt(10) ** BigInt(decimals);\n return amountBN.toString();\n }\n\n // If it has decimals, handle properly\n const [integerPart, decimalPart = \"\"] = amount.split(\".\");\n const paddedDecimal = decimalPart.padEnd(decimals, \"0\").slice(0, decimals);\n const amountBN = BigInt(integerPart + paddedDecimal);\n\n return amountBN.toString();\n}\n\nexport function parseAmount(amount: string, decimals: number = 18): number {\n const amountBN = BigInt(amount);\n const divisor = BigInt(10) ** BigInt(decimals);\n return Number(amountBN) / Number(divisor);\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function retry<T>(\n fn: () => Promise<T>,\n options: {\n maxAttempts?: number;\n delay?: number;\n backoff?: boolean;\n } = {}\n): Promise<T> {\n const { maxAttempts = 3, delay = 1000, backoff = true } = options;\n\n return new Promise((resolve, reject) => {\n let attempt = 0;\n\n const tryFn = async () => {\n try {\n const result = await fn();\n resolve(result);\n } catch (error) {\n attempt++;\n\n if (attempt >= maxAttempts) {\n reject(error);\n return;\n }\n\n const waitTime = backoff ? delay * Math.pow(2, attempt - 1) : delay;\n setTimeout(tryFn, waitTime);\n }\n };\n\n tryFn();\n });\n}\n\nexport function createPaginatedResponse<T>(\n data: T[],\n query: PaginationQuery,\n total: number\n): PaginatedResponse<T> {\n const page = query.page || 1;\n const limit = query.limit || 10;\n const totalPages = Math.ceil(total / limit);\n\n return {\n data,\n total,\n page,\n limit,\n totalPages,\n };\n}\n\nexport function validatePagination(query: PaginationQuery): {\n page: number;\n limit: number;\n} {\n const page = Math.max(1, query.page || 1);\n const limit = Math.min(100, Math.max(1, query.limit || 10));\n\n return { page, limit };\n}\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.toString();\n } catch (error) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\nexport function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] !== undefined) {\n const sourceValue = source[key];\n if (\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof result[key] === \"object\" &&\n result[key] !== null &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(result[key], sourceValue);\n } else {\n result[key] = sourceValue as T[Extract<keyof T, string>];\n }\n }\n }\n\n return result;\n}\n","/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\nexport const STARKNET_NETWORKS = {\n MAINNET: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: process.env.STARKNET_RPC_URL_SEPOLIA ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n READY: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n SHHH: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n","import type { ErrorWithCode } from \"@chipi-stack/types\";\n\n/**\n * Error classes and utilities for Chipi SDK\n */\n\nexport class ChipiError extends Error implements ErrorWithCode {\n public readonly code: string;\n public readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = \"ChipiError\";\n this.code = code;\n this.status = status;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ChipiError);\n }\n }\n}\n\nexport class ChipiApiError extends ChipiError {\n constructor(message: string, code: string, status: number) {\n super(message, code, status);\n this.name = \"ChipiApiError\";\n }\n}\n\nexport class ChipiWalletError extends ChipiError {\n constructor(message: string, code: string = \"WALLET_ERROR\") {\n super(message, code);\n this.name = \"ChipiWalletError\";\n }\n}\n\nexport class ChipiTransactionError extends ChipiError {\n constructor(message: string, code: string = \"TRANSACTION_ERROR\") {\n super(message, code);\n this.name = \"ChipiTransactionError\";\n }\n}\n\nexport class ChipiSessionError extends ChipiError {\n constructor(message: string, code: string = \"SESSION_ERROR\") {\n super(message, code);\n this.name = \"ChipiSessionError\";\n }\n}\n\nexport class ChipiSkuError extends ChipiError {\n constructor(message: string, code: string = \"SKU_ERROR\") {\n super(message, code);\n this.name = \"ChipiSkuError\";\n }\n}\n\nexport class ChipiValidationError extends ChipiError {\n constructor(message: string, code: string = \"VALIDATION_ERROR\") {\n super(message, code, 400);\n this.name = \"ChipiValidationError\";\n }\n}\n\nexport class ChipiAuthError extends ChipiError {\n constructor(message: string, code: string = \"AUTH_ERROR\") {\n super(message, code, 401);\n this.name = \"ChipiAuthError\";\n }\n}\n\nexport class WalletNotCompatibleError extends ChipiWalletError {\n constructor(message: string) {\n super(message, \"WALLET_NOT_COMPATIBLE\");\n this.name = \"WalletNotCompatibleError\";\n }\n}\n\nexport class WalletClassHashNotFoundError extends ChipiWalletError {\n constructor(walletType: string) {\n super(\n `No class hash registered for wallet type '${walletType}'. Register it via customWalletTypes in SDK config.`,\n \"WALLET_CLASS_HASH_NOT_FOUND\"\n );\n this.name = \"WalletClassHashNotFoundError\";\n }\n}\n\nexport class PaymasterIncompatibleError extends ChipiError {\n constructor(classHash: string) {\n super(\n `Wallet class hash ${classHash} is not compatible with Chipi paymaster. Account must implement SNIP-9 (outside_execution_v2).`,\n \"PAYMASTER_INCOMPATIBLE\",\n 400\n );\n this.name = \"PaymasterIncompatibleError\";\n }\n}\n\nexport function isChipiError(error: unknown): error is ChipiError {\n return error instanceof ChipiError;\n}\n\n/**\n * Type guard to check if an error has an HTTP status property.\n * Useful for retry logic where you need to distinguish API errors\n * (which have status codes) from network errors (which don't).\n */\nexport function hasHttpStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as { status: unknown }).status === \"number\"\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handleApiError(error: any): ChipiError {\n if (isChipiError(error)) {\n return error;\n }\n\n if (typeof error?.response?.status === \"number\") {\n const status = error.response.status;\n const message = error.response.data?.message || error.message || \"API request failed\";\n const code = error.response.data?.code || `HTTP_${status}`;\n\n return new ChipiApiError(message, code, status);\n }\n\n // Handle errors with direct status property (non-Axios)\n if (error?.status && typeof error.status === \"number\") {\n const message = error?.message || \"API request failed\";\n const code = error?.code || `HTTP_${error.status}`;\n return new ChipiApiError(message, code, error.status);\n }\n\n return new ChipiError(error?.message || \"An unknown error occurred\", \"UNKNOWN_ERROR\");\n}\n","/**\n * Data formatters and transformers for Chipi SDK\n */\n\nexport function formatCurrency(\n amount: number,\n currency: string = \"USD\",\n locale: string = \"en-US\"\n): string {\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n }).format(amount);\n}\n\nexport function formatNumber(\n value: number,\n options: {\n decimals?: number;\n locale?: string;\n compact?: boolean;\n } = {}\n): string {\n const { decimals = 2, locale = \"en-US\", compact = false } = options;\n\n return new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n notation: compact ? \"compact\" : \"standard\",\n }).format(value);\n}\n\nexport function formatDate(\n date: Date | string,\n options: {\n locale?: string;\n dateStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n timeStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n } = {}\n): string {\n const { locale = \"en-US\", dateStyle = \"medium\", timeStyle } = options;\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle,\n }).format(dateObj);\n}\n\nexport function formatAddress(address: string, length: number = 8): string {\n if (address.length <= length * 2) {\n return address;\n }\n\n return `${address.slice(0, length)}...${address.slice(-length)}`;\n}\n\nexport function formatTransactionHash(hash: string): string {\n return formatAddress(hash, 6);\n}\n\nexport function camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { z } from \"zod\";\n\n// Base API response schema\nexport const ApiResponseSchema = z.object({\n data: z.unknown(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n// Error response schema\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n code: z.string().optional(),\n status: z.number().optional(),\n});\n\n// Generic success response schema\nexport const SuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\n ApiResponseSchema.extend({\n data: dataSchema,\n });\n\n// Type helpers\nexport type ApiResponse<T> = {\n data: T;\n message?: string;\n code?: string;\n};\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n// Validation functions\n// This is not very good nor useful without passing a data schema\nexport function validateApiResponse<T>(response: unknown, dataSchema: z.ZodType<T>): void {\n // Validate with specific data schema\n const result = SuccessResponseSchema(dataSchema).safeParse(response);\n if (!result.success) {\n throw new Error(`Invalid API response format: ${result.error.message}`);\n }\n}\n\nexport function validateErrorResponse(response: unknown): ErrorResponse {\n const result = ErrorResponseSchema.safeParse(response);\n if (result.success) {\n return result.data;\n }\n\n // Fallback for malformed error responses\n return {\n message: \"Unknown error occurred\",\n code: \"UNKNOWN_ERROR\",\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/index.ts","../src/constants/rpc.ts","../src/constants/index.ts","../src/errors.ts","../src/formatters.ts","../src/validation.ts"],"names":["amountBN","RpcProvider","z"],"mappings":"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","file":"index.js","sourcesContent":["import type { PaginationQuery, PaginatedResponse, Currency } from \"@chipi-stack/types\";\nimport { API_ENDPOINTS } from \"../constants\";\n\n/**\n * Utility functions used across Chipi SDK packages\n */\n\nexport function isValidAddress(address: string): boolean {\n // Validate Starknet address format\n return /^0x[0-9a-fA-F]{1,64}$/.test(address);\n}\n\nexport function isValidApiKey(apiKey: string): boolean {\n // Validate API key format (pk_dev_ or pk_prod_)\n return /^pk_(dev|prod)_[a-zA-Z0-9]{32,}$/.test(apiKey);\n}\n\nexport function formatAmount(amount: string, decimals: number = 18): string {\n // If it's an integer, multiply by 10^decimals\n if (!amount.includes(\".\")) {\n const amountBN = BigInt(amount) * BigInt(10) ** BigInt(decimals);\n return amountBN.toString();\n }\n\n // If it has decimals, handle properly\n const [integerPart, decimalPart = \"\"] = amount.split(\".\");\n const paddedDecimal = decimalPart.padEnd(decimals, \"0\").slice(0, decimals);\n const amountBN = BigInt(integerPart + paddedDecimal);\n\n return amountBN.toString();\n}\n\nexport function parseAmount(amount: string, decimals: number = 18): number {\n const amountBN = BigInt(amount);\n const divisor = BigInt(10) ** BigInt(decimals);\n return Number(amountBN) / Number(divisor);\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function retry<T>(\n fn: () => Promise<T>,\n options: {\n maxAttempts?: number;\n delay?: number;\n backoff?: boolean;\n } = {}\n): Promise<T> {\n const { maxAttempts = 3, delay = 1000, backoff = true } = options;\n\n return new Promise((resolve, reject) => {\n let attempt = 0;\n\n const tryFn = async () => {\n try {\n const result = await fn();\n resolve(result);\n } catch (error) {\n attempt++;\n\n if (attempt >= maxAttempts) {\n reject(error);\n return;\n }\n\n const waitTime = backoff ? delay * Math.pow(2, attempt - 1) : delay;\n setTimeout(tryFn, waitTime);\n }\n };\n\n tryFn();\n });\n}\n\nexport function createPaginatedResponse<T>(\n data: T[],\n query: PaginationQuery,\n total: number\n): PaginatedResponse<T> {\n const page = query.page || 1;\n const limit = query.limit || 10;\n const totalPages = Math.ceil(total / limit);\n\n return {\n data,\n total,\n page,\n limit,\n totalPages,\n };\n}\n\nexport function validatePagination(query: PaginationQuery): {\n page: number;\n limit: number;\n} {\n const page = Math.max(1, query.page || 1);\n const limit = Math.min(100, Math.max(1, query.limit || 10));\n\n return { page, limit };\n}\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.toString();\n } catch (error) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\nexport function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] !== undefined) {\n const sourceValue = source[key];\n if (\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof result[key] === \"object\" &&\n result[key] !== null &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(result[key], sourceValue);\n } else {\n result[key] = sourceValue as T[Extract<keyof T, string>];\n }\n }\n }\n\n return result;\n}\n","/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC, readEnv } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\n// These evaluate at MODULE SCOPE, and this module is bundled into browser-facing\n// packages, so a bare `process.env` read throws at import time anywhere `process`\n// is not defined. It has worked so far only because bundlers inject a shim, which\n// makes client-side imports of this package accidental rather than supported.\n// `readEnv` is the same guard ./rpc.ts already uses; server behaviour is identical.\nexport const STARKNET_NETWORKS = {\n MAINNET: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: readEnv(\"STARKNET_RPC_URL_SEPOLIA\") ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n READY: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n SHHH: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n","import type { ErrorWithCode } from \"@chipi-stack/types\";\n\n/**\n * Error classes and utilities for Chipi SDK\n */\n\nexport class ChipiError extends Error implements ErrorWithCode {\n public readonly code: string;\n public readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = \"ChipiError\";\n this.code = code;\n this.status = status;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ChipiError);\n }\n }\n}\n\nexport class ChipiApiError extends ChipiError {\n constructor(message: string, code: string, status: number) {\n super(message, code, status);\n this.name = \"ChipiApiError\";\n }\n}\n\nexport class ChipiWalletError extends ChipiError {\n constructor(message: string, code: string = \"WALLET_ERROR\") {\n super(message, code);\n this.name = \"ChipiWalletError\";\n }\n}\n\nexport class ChipiTransactionError extends ChipiError {\n constructor(message: string, code: string = \"TRANSACTION_ERROR\") {\n super(message, code);\n this.name = \"ChipiTransactionError\";\n }\n}\n\nexport class ChipiSessionError extends ChipiError {\n constructor(message: string, code: string = \"SESSION_ERROR\") {\n super(message, code);\n this.name = \"ChipiSessionError\";\n }\n}\n\nexport class ChipiSkuError extends ChipiError {\n constructor(message: string, code: string = \"SKU_ERROR\") {\n super(message, code);\n this.name = \"ChipiSkuError\";\n }\n}\n\nexport class ChipiValidationError extends ChipiError {\n constructor(message: string, code: string = \"VALIDATION_ERROR\") {\n super(message, code, 400);\n this.name = \"ChipiValidationError\";\n }\n}\n\nexport class ChipiAuthError extends ChipiError {\n constructor(message: string, code: string = \"AUTH_ERROR\") {\n super(message, code, 401);\n this.name = \"ChipiAuthError\";\n }\n}\n\nexport class WalletNotCompatibleError extends ChipiWalletError {\n constructor(message: string) {\n super(message, \"WALLET_NOT_COMPATIBLE\");\n this.name = \"WalletNotCompatibleError\";\n }\n}\n\nexport class WalletClassHashNotFoundError extends ChipiWalletError {\n constructor(walletType: string) {\n super(\n `No class hash registered for wallet type '${walletType}'. Register it via customWalletTypes in SDK config.`,\n \"WALLET_CLASS_HASH_NOT_FOUND\"\n );\n this.name = \"WalletClassHashNotFoundError\";\n }\n}\n\nexport class PaymasterIncompatibleError extends ChipiError {\n constructor(classHash: string) {\n super(\n `Wallet class hash ${classHash} is not compatible with Chipi paymaster. Account must implement SNIP-9 (outside_execution_v2).`,\n \"PAYMASTER_INCOMPATIBLE\",\n 400\n );\n this.name = \"PaymasterIncompatibleError\";\n }\n}\n\nexport function isChipiError(error: unknown): error is ChipiError {\n return error instanceof ChipiError;\n}\n\n/**\n * Type guard to check if an error has an HTTP status property.\n * Useful for retry logic where you need to distinguish API errors\n * (which have status codes) from network errors (which don't).\n */\nexport function hasHttpStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as { status: unknown }).status === \"number\"\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handleApiError(error: any): ChipiError {\n if (isChipiError(error)) {\n return error;\n }\n\n if (typeof error?.response?.status === \"number\") {\n const status = error.response.status;\n const message = error.response.data?.message || error.message || \"API request failed\";\n const code = error.response.data?.code || `HTTP_${status}`;\n\n return new ChipiApiError(message, code, status);\n }\n\n // Handle errors with direct status property (non-Axios)\n if (error?.status && typeof error.status === \"number\") {\n const message = error?.message || \"API request failed\";\n const code = error?.code || `HTTP_${error.status}`;\n return new ChipiApiError(message, code, error.status);\n }\n\n return new ChipiError(error?.message || \"An unknown error occurred\", \"UNKNOWN_ERROR\");\n}\n","/**\n * Data formatters and transformers for Chipi SDK\n */\n\nexport function formatCurrency(\n amount: number,\n currency: string = \"USD\",\n locale: string = \"en-US\"\n): string {\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n }).format(amount);\n}\n\nexport function formatNumber(\n value: number,\n options: {\n decimals?: number;\n locale?: string;\n compact?: boolean;\n } = {}\n): string {\n const { decimals = 2, locale = \"en-US\", compact = false } = options;\n\n return new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n notation: compact ? \"compact\" : \"standard\",\n }).format(value);\n}\n\nexport function formatDate(\n date: Date | string,\n options: {\n locale?: string;\n dateStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n timeStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n } = {}\n): string {\n const { locale = \"en-US\", dateStyle = \"medium\", timeStyle } = options;\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle,\n }).format(dateObj);\n}\n\nexport function formatAddress(address: string, length: number = 8): string {\n if (address.length <= length * 2) {\n return address;\n }\n\n return `${address.slice(0, length)}...${address.slice(-length)}`;\n}\n\nexport function formatTransactionHash(hash: string): string {\n return formatAddress(hash, 6);\n}\n\nexport function camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { z } from \"zod\";\n\n// Base API response schema\nexport const ApiResponseSchema = z.object({\n data: z.unknown(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n// Error response schema\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n code: z.string().optional(),\n status: z.number().optional(),\n});\n\n// Generic success response schema\nexport const SuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\n ApiResponseSchema.extend({\n data: dataSchema,\n });\n\n// Type helpers\nexport type ApiResponse<T> = {\n data: T;\n message?: string;\n code?: string;\n};\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n// Validation functions\n// This is not very good nor useful without passing a data schema\nexport function validateApiResponse<T>(response: unknown, dataSchema: z.ZodType<T>): void {\n // Validate with specific data schema\n const result = SuccessResponseSchema(dataSchema).safeParse(response);\n if (!result.success) {\n throw new Error(`Invalid API response format: ${result.error.message}`);\n }\n}\n\nexport function validateErrorResponse(response: unknown): ErrorResponse {\n const result = ErrorResponseSchema.safeParse(response);\n if (result.success) {\n return result.data;\n }\n\n // Fallback for malformed error responses\n return {\n message: \"Unknown error occurred\",\n code: \"UNKNOWN_ERROR\",\n };\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -255,10 +255,10 @@ var API_VERSIONING = {
|
|
|
255
255
|
// Detailed version - sent as query param for tracking
|
|
256
256
|
};
|
|
257
257
|
var STARKNET_NETWORKS = {
|
|
258
|
-
MAINNET:
|
|
258
|
+
MAINNET: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
259
259
|
// Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.
|
|
260
260
|
MAINNET_FALLBACK: LAVA_MAINNET_RPC,
|
|
261
|
-
SEPOLIA:
|
|
261
|
+
SEPOLIA: readEnv("STARKNET_RPC_URL_SEPOLIA") ?? DEFAULT_SEPOLIA_RPC
|
|
262
262
|
};
|
|
263
263
|
var CONTRACT_ADDRESSES = {
|
|
264
264
|
USDC_MAINNET: "0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb",
|
|
@@ -396,9 +396,9 @@ function isKnownShhhClassHash(classHash) {
|
|
|
396
396
|
return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);
|
|
397
397
|
}
|
|
398
398
|
var WALLET_RPC_ENDPOINTS = {
|
|
399
|
-
CHIPI:
|
|
400
|
-
READY:
|
|
401
|
-
SHHH:
|
|
399
|
+
CHIPI: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
400
|
+
READY: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC,
|
|
401
|
+
SHHH: readEnv("STARKNET_RPC_URL") ?? DEFAULT_MAINNET_RPC
|
|
402
402
|
};
|
|
403
403
|
var PAYMASTER_CONFIG = {
|
|
404
404
|
URL: "https://paymaster.chipipay.com"
|
|
@@ -620,6 +620,6 @@ function validateErrorResponse(response) {
|
|
|
620
620
|
};
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
-
export { API_ENDPOINTS, API_VERSIONING, ApiResponseSchema, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, ChipiApiError, ChipiAuthError, ChipiError, ChipiSessionError, ChipiSkuError, ChipiTransactionError, ChipiValidationError, ChipiWalletError, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, ErrorResponseSchema, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, PaymasterIncompatibleError, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, SuccessResponseSchema, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, WalletClassHashNotFoundError, WalletNotCompatibleError, buildRpcChain, camelToSnake, capitalizeFirst, createPaginatedResponse, deepMerge, formatAddress, formatAmount, formatCurrency, formatDate, formatNumber, formatTransactionHash, getWalletTypeFromClassHash, handleApiError, hasHttpStatus, isChipiError, isKnownShhhClassHash, isValidAddress, isValidApiKey, makeRpcBaseFetch, parseAmount, retry, rpcProviderFor, sanitizeUrl, sleep, snakeToCamel, validateApiResponse, validateErrorResponse, validatePagination, withRpcFallback };
|
|
623
|
+
export { API_ENDPOINTS, API_VERSIONING, ApiResponseSchema, CARRIER_IDS, CHAIN_TOKEN_TYPES, CHAIN_TYPES, CONTRACT_ADDRESSES, ChipiApiError, ChipiAuthError, ChipiError, ChipiSessionError, ChipiSkuError, ChipiTransactionError, ChipiValidationError, ChipiWalletError, DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, ERRORS, ErrorResponseSchema, LAVA_MAINNET_RPC, LEGACY_CHIPI_CLASS_HASHES, LEGACY_SHHH_CLASS_HASHES, PAYMASTER_CONFIG, PaymasterIncompatibleError, SERVICE_TYPES, SESSION_DEFAULTS, SESSION_ENTRYPOINTS, SESSION_ERRORS, SHHH_ENVELOPE_TAGS, SHHH_KIND_GAS_OVERHEAD, SHHH_VERIFIER_CLASS_HASHES, SKU_CONTRACTS, STARKNET_NETWORKS, STARKSCAN_MAINNET_RPC, SuccessResponseSchema, TOKEN_DECIMALS, WALLET_CLASS_HASHES, WALLET_RPC_ENDPOINTS, WalletClassHashNotFoundError, WalletNotCompatibleError, buildRpcChain, camelToSnake, capitalizeFirst, createPaginatedResponse, deepMerge, formatAddress, formatAmount, formatCurrency, formatDate, formatNumber, formatTransactionHash, getWalletTypeFromClassHash, handleApiError, hasHttpStatus, isChipiError, isKnownShhhClassHash, isValidAddress, isValidApiKey, makeRpcBaseFetch, parseAmount, readEnv, retry, rpcProviderFor, sanitizeUrl, sleep, snakeToCamel, validateApiResponse, validateErrorResponse, validatePagination, withRpcFallback };
|
|
624
624
|
//# sourceMappingURL=index.mjs.map
|
|
625
625
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/index.ts","../src/constants/rpc.ts","../src/constants/index.ts","../src/errors.ts","../src/formatters.ts","../src/validation.ts"],"names":["amountBN"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { PaginationQuery, PaginatedResponse, Currency } from \"@chipi-stack/types\";\nimport { API_ENDPOINTS } from \"../constants\";\n\n/**\n * Utility functions used across Chipi SDK packages\n */\n\nexport function isValidAddress(address: string): boolean {\n // Validate Starknet address format\n return /^0x[0-9a-fA-F]{1,64}$/.test(address);\n}\n\nexport function isValidApiKey(apiKey: string): boolean {\n // Validate API key format (pk_dev_ or pk_prod_)\n return /^pk_(dev|prod)_[a-zA-Z0-9]{32,}$/.test(apiKey);\n}\n\nexport function formatAmount(amount: string, decimals: number = 18): string {\n // If it's an integer, multiply by 10^decimals\n if (!amount.includes(\".\")) {\n const amountBN = BigInt(amount) * BigInt(10) ** BigInt(decimals);\n return amountBN.toString();\n }\n\n // If it has decimals, handle properly\n const [integerPart, decimalPart = \"\"] = amount.split(\".\");\n const paddedDecimal = decimalPart.padEnd(decimals, \"0\").slice(0, decimals);\n const amountBN = BigInt(integerPart + paddedDecimal);\n\n return amountBN.toString();\n}\n\nexport function parseAmount(amount: string, decimals: number = 18): number {\n const amountBN = BigInt(amount);\n const divisor = BigInt(10) ** BigInt(decimals);\n return Number(amountBN) / Number(divisor);\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function retry<T>(\n fn: () => Promise<T>,\n options: {\n maxAttempts?: number;\n delay?: number;\n backoff?: boolean;\n } = {}\n): Promise<T> {\n const { maxAttempts = 3, delay = 1000, backoff = true } = options;\n\n return new Promise((resolve, reject) => {\n let attempt = 0;\n\n const tryFn = async () => {\n try {\n const result = await fn();\n resolve(result);\n } catch (error) {\n attempt++;\n\n if (attempt >= maxAttempts) {\n reject(error);\n return;\n }\n\n const waitTime = backoff ? delay * Math.pow(2, attempt - 1) : delay;\n setTimeout(tryFn, waitTime);\n }\n };\n\n tryFn();\n });\n}\n\nexport function createPaginatedResponse<T>(\n data: T[],\n query: PaginationQuery,\n total: number\n): PaginatedResponse<T> {\n const page = query.page || 1;\n const limit = query.limit || 10;\n const totalPages = Math.ceil(total / limit);\n\n return {\n data,\n total,\n page,\n limit,\n totalPages,\n };\n}\n\nexport function validatePagination(query: PaginationQuery): {\n page: number;\n limit: number;\n} {\n const page = Math.max(1, query.page || 1);\n const limit = Math.min(100, Math.max(1, query.limit || 10));\n\n return { page, limit };\n}\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.toString();\n } catch (error) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\nexport function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] !== undefined) {\n const sourceValue = source[key];\n if (\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof result[key] === \"object\" &&\n result[key] !== null &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(result[key], sourceValue);\n } else {\n result[key] = sourceValue as T[Extract<keyof T, string>];\n }\n }\n }\n\n return result;\n}\n","/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nfunction readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\nexport const STARKNET_NETWORKS = {\n MAINNET: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: process.env.STARKNET_RPC_URL_SEPOLIA ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n READY: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n SHHH: process.env.STARKNET_RPC_URL ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n","import type { ErrorWithCode } from \"@chipi-stack/types\";\n\n/**\n * Error classes and utilities for Chipi SDK\n */\n\nexport class ChipiError extends Error implements ErrorWithCode {\n public readonly code: string;\n public readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = \"ChipiError\";\n this.code = code;\n this.status = status;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ChipiError);\n }\n }\n}\n\nexport class ChipiApiError extends ChipiError {\n constructor(message: string, code: string, status: number) {\n super(message, code, status);\n this.name = \"ChipiApiError\";\n }\n}\n\nexport class ChipiWalletError extends ChipiError {\n constructor(message: string, code: string = \"WALLET_ERROR\") {\n super(message, code);\n this.name = \"ChipiWalletError\";\n }\n}\n\nexport class ChipiTransactionError extends ChipiError {\n constructor(message: string, code: string = \"TRANSACTION_ERROR\") {\n super(message, code);\n this.name = \"ChipiTransactionError\";\n }\n}\n\nexport class ChipiSessionError extends ChipiError {\n constructor(message: string, code: string = \"SESSION_ERROR\") {\n super(message, code);\n this.name = \"ChipiSessionError\";\n }\n}\n\nexport class ChipiSkuError extends ChipiError {\n constructor(message: string, code: string = \"SKU_ERROR\") {\n super(message, code);\n this.name = \"ChipiSkuError\";\n }\n}\n\nexport class ChipiValidationError extends ChipiError {\n constructor(message: string, code: string = \"VALIDATION_ERROR\") {\n super(message, code, 400);\n this.name = \"ChipiValidationError\";\n }\n}\n\nexport class ChipiAuthError extends ChipiError {\n constructor(message: string, code: string = \"AUTH_ERROR\") {\n super(message, code, 401);\n this.name = \"ChipiAuthError\";\n }\n}\n\nexport class WalletNotCompatibleError extends ChipiWalletError {\n constructor(message: string) {\n super(message, \"WALLET_NOT_COMPATIBLE\");\n this.name = \"WalletNotCompatibleError\";\n }\n}\n\nexport class WalletClassHashNotFoundError extends ChipiWalletError {\n constructor(walletType: string) {\n super(\n `No class hash registered for wallet type '${walletType}'. Register it via customWalletTypes in SDK config.`,\n \"WALLET_CLASS_HASH_NOT_FOUND\"\n );\n this.name = \"WalletClassHashNotFoundError\";\n }\n}\n\nexport class PaymasterIncompatibleError extends ChipiError {\n constructor(classHash: string) {\n super(\n `Wallet class hash ${classHash} is not compatible with Chipi paymaster. Account must implement SNIP-9 (outside_execution_v2).`,\n \"PAYMASTER_INCOMPATIBLE\",\n 400\n );\n this.name = \"PaymasterIncompatibleError\";\n }\n}\n\nexport function isChipiError(error: unknown): error is ChipiError {\n return error instanceof ChipiError;\n}\n\n/**\n * Type guard to check if an error has an HTTP status property.\n * Useful for retry logic where you need to distinguish API errors\n * (which have status codes) from network errors (which don't).\n */\nexport function hasHttpStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as { status: unknown }).status === \"number\"\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handleApiError(error: any): ChipiError {\n if (isChipiError(error)) {\n return error;\n }\n\n if (typeof error?.response?.status === \"number\") {\n const status = error.response.status;\n const message = error.response.data?.message || error.message || \"API request failed\";\n const code = error.response.data?.code || `HTTP_${status}`;\n\n return new ChipiApiError(message, code, status);\n }\n\n // Handle errors with direct status property (non-Axios)\n if (error?.status && typeof error.status === \"number\") {\n const message = error?.message || \"API request failed\";\n const code = error?.code || `HTTP_${error.status}`;\n return new ChipiApiError(message, code, error.status);\n }\n\n return new ChipiError(error?.message || \"An unknown error occurred\", \"UNKNOWN_ERROR\");\n}\n","/**\n * Data formatters and transformers for Chipi SDK\n */\n\nexport function formatCurrency(\n amount: number,\n currency: string = \"USD\",\n locale: string = \"en-US\"\n): string {\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n }).format(amount);\n}\n\nexport function formatNumber(\n value: number,\n options: {\n decimals?: number;\n locale?: string;\n compact?: boolean;\n } = {}\n): string {\n const { decimals = 2, locale = \"en-US\", compact = false } = options;\n\n return new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n notation: compact ? \"compact\" : \"standard\",\n }).format(value);\n}\n\nexport function formatDate(\n date: Date | string,\n options: {\n locale?: string;\n dateStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n timeStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n } = {}\n): string {\n const { locale = \"en-US\", dateStyle = \"medium\", timeStyle } = options;\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle,\n }).format(dateObj);\n}\n\nexport function formatAddress(address: string, length: number = 8): string {\n if (address.length <= length * 2) {\n return address;\n }\n\n return `${address.slice(0, length)}...${address.slice(-length)}`;\n}\n\nexport function formatTransactionHash(hash: string): string {\n return formatAddress(hash, 6);\n}\n\nexport function camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { z } from \"zod\";\n\n// Base API response schema\nexport const ApiResponseSchema = z.object({\n data: z.unknown(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n// Error response schema\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n code: z.string().optional(),\n status: z.number().optional(),\n});\n\n// Generic success response schema\nexport const SuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\n ApiResponseSchema.extend({\n data: dataSchema,\n });\n\n// Type helpers\nexport type ApiResponse<T> = {\n data: T;\n message?: string;\n code?: string;\n};\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n// Validation functions\n// This is not very good nor useful without passing a data schema\nexport function validateApiResponse<T>(response: unknown, dataSchema: z.ZodType<T>): void {\n // Validate with specific data schema\n const result = SuccessResponseSchema(dataSchema).safeParse(response);\n if (!result.success) {\n throw new Error(`Invalid API response format: ${result.error.message}`);\n }\n}\n\nexport function validateErrorResponse(response: unknown): ErrorResponse {\n const result = ErrorResponseSchema.safeParse(response);\n if (result.success) {\n return result.data;\n }\n\n // Fallback for malformed error responses\n return {\n message: \"Unknown error occurred\",\n code: \"UNKNOWN_ERROR\",\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/index.ts","../src/constants/rpc.ts","../src/constants/index.ts","../src/errors.ts","../src/formatters.ts","../src/validation.ts"],"names":["amountBN"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { PaginationQuery, PaginatedResponse, Currency } from \"@chipi-stack/types\";\nimport { API_ENDPOINTS } from \"../constants\";\n\n/**\n * Utility functions used across Chipi SDK packages\n */\n\nexport function isValidAddress(address: string): boolean {\n // Validate Starknet address format\n return /^0x[0-9a-fA-F]{1,64}$/.test(address);\n}\n\nexport function isValidApiKey(apiKey: string): boolean {\n // Validate API key format (pk_dev_ or pk_prod_)\n return /^pk_(dev|prod)_[a-zA-Z0-9]{32,}$/.test(apiKey);\n}\n\nexport function formatAmount(amount: string, decimals: number = 18): string {\n // If it's an integer, multiply by 10^decimals\n if (!amount.includes(\".\")) {\n const amountBN = BigInt(amount) * BigInt(10) ** BigInt(decimals);\n return amountBN.toString();\n }\n\n // If it has decimals, handle properly\n const [integerPart, decimalPart = \"\"] = amount.split(\".\");\n const paddedDecimal = decimalPart.padEnd(decimals, \"0\").slice(0, decimals);\n const amountBN = BigInt(integerPart + paddedDecimal);\n\n return amountBN.toString();\n}\n\nexport function parseAmount(amount: string, decimals: number = 18): number {\n const amountBN = BigInt(amount);\n const divisor = BigInt(10) ** BigInt(decimals);\n return Number(amountBN) / Number(divisor);\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function retry<T>(\n fn: () => Promise<T>,\n options: {\n maxAttempts?: number;\n delay?: number;\n backoff?: boolean;\n } = {}\n): Promise<T> {\n const { maxAttempts = 3, delay = 1000, backoff = true } = options;\n\n return new Promise((resolve, reject) => {\n let attempt = 0;\n\n const tryFn = async () => {\n try {\n const result = await fn();\n resolve(result);\n } catch (error) {\n attempt++;\n\n if (attempt >= maxAttempts) {\n reject(error);\n return;\n }\n\n const waitTime = backoff ? delay * Math.pow(2, attempt - 1) : delay;\n setTimeout(tryFn, waitTime);\n }\n };\n\n tryFn();\n });\n}\n\nexport function createPaginatedResponse<T>(\n data: T[],\n query: PaginationQuery,\n total: number\n): PaginatedResponse<T> {\n const page = query.page || 1;\n const limit = query.limit || 10;\n const totalPages = Math.ceil(total / limit);\n\n return {\n data,\n total,\n page,\n limit,\n totalPages,\n };\n}\n\nexport function validatePagination(query: PaginationQuery): {\n page: number;\n limit: number;\n} {\n const page = Math.max(1, query.page || 1);\n const limit = Math.min(100, Math.max(1, query.limit || 10));\n\n return { page, limit };\n}\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.toString();\n } catch (error) {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\nexport function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n if (source[key] !== undefined) {\n const sourceValue = source[key];\n if (\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof result[key] === \"object\" &&\n result[key] !== null &&\n !Array.isArray(result[key])\n ) {\n result[key] = deepMerge(result[key], sourceValue);\n } else {\n result[key] = sourceValue as T[Extract<keyof T, string>];\n }\n }\n }\n\n return result;\n}\n","/**\n * Ordered Starknet RPC provider chain with transport-level failover.\n *\n * ## Published-SDK contract (read before changing anything here)\n *\n * `@chipi-stack/*` is consumed by external integrators who do NOT have Chipi's\n * Starkscan API key. The keyless path must keep working with zero configuration,\n * so Starkscan is layered on top rather than baked in:\n *\n * - `STARKSCAN_API_KEY` set (Chipi's own server-side deployments) → Starkscan is\n * the primary endpoint, key travelling in a header.\n * - `STARKSCAN_API_KEY` unset (every integrator) → the chain HEAD is byte-identical\n * to the endpoint the SDK resolved before this module existed\n * (`STARKNET_RPC_URL` when set, else the default Infura mainnet URL). The only\n * difference is that the SDK now retries on additional nodes instead of failing.\n *\n * Starkscan is MAINNET-ONLY (`SN_SEPOLIA` answers `unsupported_chain`), so a\n * non-mainnet configuration never gets it (and never gets mainnet fallbacks\n * either; see `buildRpcChain`).\n *\n * The custom `baseFetch` transport classifier is installed ONLY on providers this module\n * builds for the chain. A provider an integrator constructs themselves from\n * `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keeps stock starknet.js behaviour, so the\n * blast radius of coupling to starknet.js internals is limited to the chain helper.\n */\nimport { RpcProvider } from \"starknet\";\n\n/**\n * Starkscan's JSON-RPC route. Mainnet only. The key rides in the canonical\n * `X-Starkscan-Api-Key` header, never in the URL.\n */\nexport const STARKSCAN_MAINNET_RPC = \"https://api.starkscan.co/v1/SN_MAIN/rpc\";\n\n/** Public keyless mainnet node used as the last resort in the chain. */\nexport const LAVA_MAINNET_RPC = \"https://rpc.starknet.lava.build\";\n\n/** Keyless default mainnet RPC. This is the value published SDKs resolve to today. Do not change. */\nexport const DEFAULT_MAINNET_RPC =\n \"https://starknet-mainnet.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\n/** Keyless default sepolia RPC. Starkscan is never layered onto this. */\nexport const DEFAULT_SEPOLIA_RPC =\n \"https://starknet-sepolia.infura.io/v3/4a4a1fdd7d704509aa99154fb29886e2\";\n\nexport type RpcEndpoint = { label: string; url: string; headers?: Record<string, string> };\n\n/**\n * Read an env var defensively: this module is bundled into browser-facing packages\n * where `process` may not exist. Empty / whitespace-only values are treated as unset.\n */\nexport function readEnv(name: string): string | undefined {\n if (typeof process === \"undefined\" || !process.env) return undefined;\n const value = process.env[name];\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Anything that is clearly not Starknet mainnet. A non-mainnet head must never be\n * followed by mainnet fallbacks (answering a sepolia question with mainnet state is\n * worse than failing), so such a chain stays single-entry.\n */\nfunction looksNonMainnet(url: string): boolean {\n return /sepolia|goerli|testnet|devnet|localhost|127\\.0\\.0\\.1|0\\.0\\.0\\.0/i.test(url);\n}\n\n/**\n * Build the ordered endpoint chain.\n *\n * @param opts.fallbackUrl the URL this call site resolved on its own (e.g.\n * `WALLET_RPC_ENDPOINTS[walletType]` or an integrator-supplied `nodeUrl`). It is the\n * first KEYLESS entry, which is what keeps the no-Starkscan behaviour byte-identical\n * to today.\n *\n * Order: starkscan (only with a key) → caller URL → `STARKNET_RPC_URL` → Infura default\n * → lava. De-duplicated by URL so an operator who points `STARKNET_RPC_URL` at lava does\n * not get the same node twice (which would make \"fallback\" a no-op).\n */\nexport function buildRpcChain(opts?: { fallbackUrl?: string }): RpcEndpoint[] {\n const callerUrl = opts?.fallbackUrl?.trim() || undefined;\n const envUrl = readEnv(\"STARKNET_RPC_URL\");\n\n // The endpoint this call site would have used before this module existed.\n const head = callerUrl ?? envUrl ?? DEFAULT_MAINNET_RPC;\n\n // Non-mainnet deployments keep exactly one endpoint: no Starkscan (it rejects\n // SN_SEPOLIA with `unsupported_chain`) and no cross-chain fallback.\n if (looksNonMainnet(head)) {\n return [{ label: \"configured\", url: head }];\n }\n\n const chain: RpcEndpoint[] = [];\n const seen = new Set<string>();\n\n const push = (label: string, url: string | undefined, headers?: Record<string, string>) => {\n if (!url) return;\n const nodeUrl = url.trim();\n if (!nodeUrl) return;\n const key = nodeUrl.replace(/\\/+$/, \"\").toLowerCase();\n if (seen.has(key)) return;\n seen.add(key);\n chain.push(headers ? { label, url: nodeUrl, headers } : { label, url: nodeUrl });\n };\n\n // Server-only key. Never logged, never interpolated into a URL, never shipped in a\n // browser bundle's env. Absent (every external integrator) → chain is unchanged.\n const starkscanApiKey = readEnv(\"STARKSCAN_API_KEY\");\n if (starkscanApiKey) {\n push(\"starkscan\", STARKSCAN_MAINNET_RPC, { \"X-Starkscan-Api-Key\": starkscanApiKey });\n }\n\n push(\"caller\", callerUrl);\n push(\"env\", envUrl);\n push(\"default\", DEFAULT_MAINNET_RPC);\n push(\"lava\", LAVA_MAINNET_RPC);\n\n return chain;\n}\n\n/**\n * Marker on transport-class failures we raise ourselves. starknet.js re-wraps thrown\n * fetch errors as a plain `Error(message)`, so the error *instance* does not survive the\n * round trip. Only the message text does.\n */\nconst TRANSPORT_MARKER = \"[chipi-rpc-transport]\";\n\n/**\n * HTTP statuses that mean \"this endpoint did not answer\" rather than \"the chain says no\":\n * 429/5xx (rate limited / node broken) plus 401/403/404, which is what a missing, wrong,\n * rotated or unprovisioned API key looks like. Falling through is exactly right there.\n */\nfunction isTransportStatus(status: number): boolean {\n return status === 401 || status === 403 || status === 404 || status === 429 || status >= 500;\n}\n\n/** Per-request budget for one RPC round-trip before we call it a transport failure. */\nconst RPC_TIMEOUT_MS = 15_000;\n\n/**\n * Wraps global fetch so an HTTP-level failure is classified while the status code is\n * still visible.\n *\n * This is necessary because **starknet.js never inspects the HTTP status**:\n * `RpcChannel.fetchEndpoint` goes straight to `.json()`. Without this wrapper a rate-limit\n * page or an auth rejection surfaces either as an opaque JSON parse error or, when the body\n * happens to be valid JSON, as a silent `undefined` result.\n *\n * Scope note (published SDK): this wrapper is installed ONLY on providers built by\n * `rpcProviderFor` for the fallback chain. Providers an integrator constructs themselves\n * from `WALLET_RPC_ENDPOINTS` / `STARKNET_NETWORKS` keep stock starknet.js fetch behaviour.\n */\nexport function makeRpcBaseFetch(label: string): typeof fetch {\n return async (input, init) => {\n let response: Response;\n try {\n response = await fetch(input, {\n ...init,\n // RN and older runtimes may not have AbortSignal.timeout. Only use it when present.\n signal:\n init?.signal ??\n (typeof AbortSignal !== \"undefined\" && typeof AbortSignal.timeout === \"function\"\n ? AbortSignal.timeout(RPC_TIMEOUT_MS)\n : undefined),\n });\n } catch (err) {\n // Network unreachable, DNS failure, connection reset, timeout/abort.\n const detail = err instanceof Error ? err.message : String(err);\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" fetch failed: ${detail}`);\n }\n\n if (response.ok) return response;\n\n // Non-2xx. A node that actually answered still returns a JSON-RPC envelope; anything\n // else (rate-limit page, REST-shaped auth rejection, gateway error) is a transport failure.\n const body = await response.text();\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n parsed = undefined;\n }\n const isJsonRpcEnvelope =\n !!parsed && typeof parsed === \"object\" && (\"error\" in parsed || \"result\" in parsed);\n\n if (isJsonRpcEnvelope && response.status !== 429 && response.status < 500) {\n // A well-formed JSON-RPC error that merely arrived over a non-200 status. Hand it back\n // so starknet.js raises a proper RpcError instead of a parse error, and so the chain\n // does NOT burn other endpoints on a question they would all answer identically.\n return new Response(body, { status: 200, headers: { \"content-type\": \"application/json\" } });\n }\n\n // Label only: never the URL (query params) and never the headers (API key).\n throw new Error(`${TRANSPORT_MARKER} endpoint \"${label}\" returned HTTP ${response.status}`);\n };\n}\n\nconst TRANSPORT_MESSAGE_HINTS = [\n TRANSPORT_MARKER,\n // network / socket\n \"fetch failed\",\n \"failed to fetch\",\n \"network error\",\n \"networkerror\",\n \"socket hang up\",\n \"econnreset\",\n \"econnrefused\",\n \"econnaborted\",\n \"enotfound\",\n \"etimedout\",\n \"ehostunreach\",\n \"enetunreach\",\n \"epipe\",\n // timeouts / cancellation\n \"timeout\",\n \"timed out\",\n \"aborted\",\n // JSON parse failure: an error page or truncated body instead of a JSON-RPC envelope\n \"unexpected token\",\n \"unexpected end of json\",\n \"is not valid json\",\n \"invalid json\",\n \"json parse\",\n];\n\n/**\n * True only for transport-class failures (network/fetch error, timeout, HTTP 401/403/404/\n * 429/5xx, JSON parse failure).\n *\n * A well-formed JSON-RPC error (\"Contract not found\", \"Invalid params\") means the node\n * answered correctly: it is NOT a transport failure, so the caller rethrows immediately\n * instead of burning the rest of the chain on a question every node answers the same way.\n */\nfunction isTransportFailure(err: unknown): boolean {\n if (!err) return false;\n\n const e = err as {\n name?: string;\n message?: string;\n baseError?: unknown;\n status?: number;\n statusCode?: number;\n cause?: unknown;\n };\n\n // starknet.js RpcError: the node replied with a JSON-RPC error envelope. Duck-typed\n // rather than `instanceof` so unit tests that mock the starknet module still take this path.\n if (e.name === \"RpcError\" || e.baseError !== undefined) return false;\n\n const status = typeof e.status === \"number\" ? e.status : e.statusCode;\n if (typeof status === \"number\" && isTransportStatus(status)) return true;\n\n if (e.name === \"AbortError\" || e.name === \"TimeoutError\" || e.name === \"SyntaxError\") return true;\n\n const message = typeof e.message === \"string\" ? e.message.toLowerCase() : \"\";\n if (message && TRANSPORT_MESSAGE_HINTS.some((hint) => message.includes(hint))) return true;\n\n // Node's fetch wraps the underlying socket error in `cause`.\n if (e.cause && e.cause !== err) return isTransportFailure(e.cause);\n\n return false;\n}\n\nconst providerCache = new Map<string, RpcProvider>();\n\n/** Memoized provider for one endpoint. */\nexport function rpcProviderFor(endpoint: RpcEndpoint): RpcProvider {\n const cacheKey = `${endpoint.label}|${endpoint.url}|${endpoint.headers ? \"auth\" : \"anon\"}`;\n const cached = providerCache.get(cacheKey);\n if (cached) return cached;\n\n const provider = new RpcProvider({\n nodeUrl: endpoint.url,\n baseFetch: makeRpcBaseFetch(endpoint.label),\n ...(endpoint.headers ? { headers: endpoint.headers } : {}),\n });\n providerCache.set(cacheKey, provider);\n return provider;\n}\n\n/**\n * Run a read against the endpoint chain, advancing to the next endpoint only when the\n * current one fails at transport level.\n *\n * Use for reads and for confirmation polling (both idempotent). Do NOT use it to wrap a\n * transaction submission: a retry on a different node could double-submit.\n */\nexport async function withRpcFallback<T>(\n fn: (provider: RpcProvider) => Promise<T>,\n opts?: { fallbackUrl?: string }\n): Promise<T> {\n const chain = buildRpcChain(opts);\n if (chain.length === 0) {\n // Defensive: buildRpcChain always appends a keyless endpoint, so this is unreachable.\n throw new Error(\"No Starknet RPC endpoint configured\");\n }\n\n let lastError: unknown;\n\n for (let i = 0; i < chain.length; i++) {\n const endpoint = chain[i];\n const isLast = i === chain.length - 1;\n\n try {\n const result = await fn(rpcProviderFor(endpoint));\n\n // An empty result is a transport failure in disguise, NOT a valid answer.\n // Starkscan rejects a bad/missing/expired API key with HTTP 401 carrying a\n // REST-shaped body (`{\"code\":\"unauthorized\",\"message\":\"Unauthorized\",...}`)\n // instead of a JSON-RPC error object. starknet.js cannot parse that: on both\n // 9.2.1 and 9.4.2, `getBlockNumber()` / `callContract()` resolve to `undefined`\n // and DO NOT THROW. Without this guard a wrong key would silently return\n // `undefined` from every SDK read with no error at all. Discriminate on\n // `undefined`/`null` ONLY: `0`, `\"0x0\"`, `false` and `[]` are legitimate\n // results (a balance read legitimately returns `[\"0x0\",\"0x0\"]`).\n if (result === undefined || result === null) {\n if (isLast) {\n throw new Error(\n `Starknet RPC endpoint \"${endpoint.label}\" returned an empty response ` +\n `(no JSON-RPC result). If this endpoint requires an API key, the key is ` +\n `likely missing, wrong or expired.`\n );\n }\n lastError = new Error(\n `${TRANSPORT_MARKER} endpoint \"${endpoint.label}\" returned an empty response`\n );\n continue;\n }\n\n return result;\n } catch (error) {\n if (isLast || !isTransportFailure(error)) throw error;\n lastError = error;\n // Label only: never the endpoint URL, headers or the API key.\n console.warn(\n `[chipi:rpc] transport failure on \"${endpoint.label}\" (${i + 1}/${chain.length}), falling through`\n );\n }\n }\n\n throw lastError instanceof Error\n ? lastError\n : new Error(`All Starknet RPC endpoints failed: ${String(lastError)}`);\n}\n","/**\n * Constants used across Chipi SDK packages\n */\n\nimport type { ShhhSignerKind, WalletType } from \"@chipi-stack/types\";\nimport { DEFAULT_MAINNET_RPC, DEFAULT_SEPOLIA_RPC, LAVA_MAINNET_RPC, readEnv } from \"./rpc\";\n\n// Ordered RPC chain + transport-level failover (Starkscan is primary only when\n// STARKSCAN_API_KEY is set; keyless integrators keep today's endpoint).\nexport * from \"./rpc\";\n\n/**\n * API Versioning\n * - VERSION: Major version for path-based versioning (/v1, /v2, etc.)\n * - VERSION_DATE: Detailed version for tracking breaking changes (YYYY-MM-DD format)\n *\n * Update VERSION_DATE when making API changes.\n * Update VERSION when making major breaking changes (typically 1-2 times per year).\n */\nexport const API_VERSIONING = {\n VERSION: \"1\", // Major version - used in URL path\n VERSION_DATE: \"2025-12-30\", // Detailed version - sent as query param for tracking\n} as const;\n\n// Default RPC URLs — override via STARKNET_RPC_URL / STARKNET_RPC_URL_SEPOLIA env vars.\n// The URL literals now live in ./rpc.ts alongside the failover chain that uses them;\n// the resolved values here are unchanged.\n\n// These evaluate at MODULE SCOPE, and this module is bundled into browser-facing\n// packages, so a bare `process.env` read throws at import time anywhere `process`\n// is not defined. It has worked so far only because bundlers inject a shim, which\n// makes client-side imports of this package accidental rather than supported.\n// `readEnv` is the same guard ./rpc.ts already uses; server behaviour is identical.\nexport const STARKNET_NETWORKS = {\n MAINNET: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n // Last resort of the mainnet chain built by buildRpcChain(), no longer a dead constant.\n MAINNET_FALLBACK: LAVA_MAINNET_RPC,\n SEPOLIA: readEnv(\"STARKNET_RPC_URL_SEPOLIA\") ?? DEFAULT_SEPOLIA_RPC,\n} as const;\n\nexport const CONTRACT_ADDRESSES = {\n USDC_MAINNET: \"0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb\", // Changed to Native USDC (was bridged USDC.e)\n VESU_USDC_MAINNET: \"0x017f19582c61479f2fe0b6606300e975c0a8f439102f43eeecc1d0e9b3d84350\",\n} as const;\n\nexport const TOKEN_DECIMALS = {\n USDC: 6,\n USDT: 6,\n ETH: 18,\n STRK: 18,\n DAI: 18,\n} as const;\n\nexport const API_ENDPOINTS = {\n CHIPI_WALLETS: \"/chipi-wallets\",\n TRANSACTIONS: \"/transactions\",\n SKUS: \"/skus\",\n SKU_PURCHASES: \"/sku-purchases\",\n EXCHANGES: \"/exchanges\",\n USERS: \"/users\",\n // SHHH multisig coordination (Plus Wave 9 / P1): SDK-exposed treasury\n // propose / sign / execute / list, owner-signature-authed.\n TREASURIES: \"/treasuries\",\n} as const;\n\nexport const ERRORS = {\n INVALID_API_KEY: \"INVALID_API_KEY\",\n WALLET_NOT_FOUND: \"WALLET_NOT_FOUND\",\n INSUFFICIENT_BALANCE: \"INSUFFICIENT_BALANCE\",\n TRANSACTION_FAILED: \"TRANSACTION_FAILED\",\n INVALID_SIGNATURE: \"INVALID_SIGNATURE\",\n SKU_NOT_FOUND: \"SKU_NOT_FOUND\",\n SKU_UNAVAILABLE: \"SKU_UNAVAILABLE\",\n} as const;\n\nexport const SKU_CONTRACTS = {\n RECHARGER_WITH_STRK_MAINNET: \"0x02d65bb726d2c29e3c97669cf297c5145eac19284fb6f935c05c0bfc68dae2b7\", //changed contract address used to be 0x0f3\n CHIPI_BILL_SERVICE: \"0x4e8150110d580069de26adec9b179023289d55859ea07487aaade5458d7aa8b\",\n} as const;\n\n// Service types\nexport const SERVICE_TYPES = {\n BUY_SERVICE: \"BUY_SERVICE\",\n} as const;\n\n// Carrier IDs\nexport const CARRIER_IDS = {\n CHIPI_PAY: \"chipi_pay\",\n} as const;\n\nexport const CHAIN_TYPES = {\n STARKNET: \"STARKNET\",\n} as const;\n\nexport const CHAIN_TOKEN_TYPES = {\n USDC: \"USDC\", // Changed to Native USDC (was bridged USDC.e)\n USDT: \"USDT\",\n ETH: \"ETH\",\n STRK: \"STRK\",\n DAI: \"DAI\",\n WBTC: \"WBTC\",\n OTHER: \"OTHER\",\n} as const;\n\nexport const WALLET_CLASS_HASHES: Record<string, string> = {\n CHIPI: \"0x053f4f8791ed5bed0fddaa553d180c664e32cfaf8316bb232ae77bb08f459f2a\", // v29 — must match backend until coordinated v33 upgrade\n READY: \"0x036078334509b514626504edc9fb252328d1a240e4e948bef8d0c08dff45927f\",\n SHHH: \"0x075dfb396145926bffa6beb659897f46cc082a50b211d80871cff7f1038fa58a\", // V8.4 ShhhAccount — declared 2026-05-15, audit-closed\n};\n\n/**\n * Previous CHIPI wallet class hashes that are still deployed on-chain.\n * Used by getWalletTypeFromClassHash() to identify legacy wallets.\n * Ordered newest → oldest.\n */\nexport const LEGACY_CHIPI_CLASS_HASHES: string[] = [\n \"0x0484bbd2404b3c7264bea271f7267d6d4004821ac7787a9eed7f472e79ef40d1\", // v33 — wallets created during brief v33 window\n \"0x035a2251aca25daba18a5d8950deffa8372a7d84774554e75283cb85552eebc9\", // v32 — audit 3\n \"0x0254f6dd0427319ec614c29e4e3929500d1ba95d0da87ff81d67051ce572667\", // v31\n \"0x072b77b033a874fa1b8f7ff52e18be8fb5ce01a00c59cd184ae15f5b29bc0e57\", // v30\n \"0x02de1565226d5215a38b68c4d9a4913989b54edff64c68c45e453c417b44cd83\", // v28\n];\n\n/**\n * Deprecated SHHH class hashes that may exist on-chain but must NOT be routed\n * for new deploys. V8 series ships without an `upgrade` selector, so existing\n * instances at deprecated classes cannot self-upgrade — they redeploy at the\n * current SHHH class hash.\n */\nexport const LEGACY_SHHH_CLASS_HASHES: string[] = [\n \"0x03bc539295abd3e59bd9ea799d12fe3331748d484bc77bff45b302b1636a87d9\", // V8.3 — deprecated 2026-05-15, no stranded-bootstrap recovery\n];\n\n/**\n * SHHH ShhhAccount verifier class hashes (V8.4, mainnet).\n *\n * The ShhhAccount dispatches `verify` to one of these verifier classes via\n * `library_call_syscall` based on the owner's `kind_tag`. Verifier classes are\n * pinned to deterministic outputs of `scarb build` at commit `3975532` (tag\n * v8.4) — Chipi routes to these hashes as a consumer; we do not redeclare.\n */\nexport const SHHH_VERIFIER_CLASS_HASHES: Record<ShhhSignerKind, string> = {\n STARK: \"0x00d09209b2da9d49fc805ba26380ba4ce25aa641116c10eb178e1051a71dbf68\",\n ED25519: \"0x030a7dfc03e59cef6e41699e734abd2df53ce393a052221c02c6e07665949f74\",\n SECP256K1: \"0x03e81667a46bd5287e09a9600fa98d28fdc477735f2689f5f4e8e95f37b67b74\",\n EIP191_SECP256K1: \"0x03a75997862059c36cb8e204fb3027eb6d1fdf933488d42c2db4528118d084e6\",\n EIP712_SECP256K1: \"0x072a3f77e8c28bfea2ade91ec3fb83b6290169d1ed8c1b2396704231841c6474\",\n P256: \"0x01b600709af54c8838e5f18ddad3a26feeb47cb124c239f55a0f1b7a780e2d8a\",\n WEBAUTHN_P256: \"0x074f6efd2af9025cd8cab41a4565bc73b6ef097214c31352838fcdbac0a44657\",\n JWT_ES256: \"0x002efce875fa3e73e04d825d8ebade53e188cc995dfe0c55a6a2f7fa6c59f497\",\n JWT_ES256_APPLE_SUB: \"0x06b67762218a25fdd28e25b063480893a5cef9cdeecbc663e32d444d5734c471\",\n BLS12_381: \"0x02623721e74a9ad3e0ba639065f5631a09bf900913de6ab21ea6984973cd2cd1\",\n};\n\n/**\n * Upper-bound l2_gas overhead per SHHH signer kind, in addition to base\n * paymaster execution cost. Numbers from snforge runs at tag v8.4\n * (252-byte calls, single owner, no session key). Paymaster adds ~5M safety\n * margin on top.\n *\n * Threshold envelopes: sum the per-owner cost + ~3M aggregation overhead.\n * Session-key envelopes (SNIP-163 4-felt): ~2M + session-policy enforcement.\n */\nexport const SHHH_KIND_GAS_OVERHEAD: Record<ShhhSignerKind, number> = {\n STARK: 2_000_000,\n SECP256K1: 5_000_000,\n EIP191_SECP256K1: 10_000_000,\n EIP712_SECP256K1: 12_000_000,\n P256: 30_000_000,\n ED25519: 33_000_000,\n WEBAUTHN_P256: 35_000_000,\n JWT_ES256: 60_000_000,\n JWT_ES256_APPLE_SUB: 62_000_000,\n BLS12_381: 80_000_000,\n};\n\n/**\n * Inner-envelope routing tags per the V8.4 Pluggable-Signer SNIP draft.\n * The ShhhAccount strips the version tag and library_calls the verifier;\n * Chipi paymaster does NOT need to parse the inner payload but DOES need\n * to pass the entire signature span verbatim to `execute_from_outside_v2`.\n */\nexport const SHHH_ENVELOPE_TAGS = {\n V2_SNIP12: \"V2_SNIP12\",\n V2_THRESHOLD: \"V2_THRESHOLD\",\n // Session-key envelopes are the SNIP-163 4-felt format (no version tag prefix).\n} as const;\n\n/**\n * Determine wallet type from an on-chain class hash.\n * - If it matches the READY hash → READY\n * - If it matches the current CHIPI hash or a legacy CHIPI hash → CHIPI\n * - If it matches the current SHHH hash or a legacy SHHH hash → SHHH\n * - Otherwise → null (unknown class hash, caller should handle accordingly)\n */\nexport function getWalletTypeFromClassHash(classHash: string): WalletType | null {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.READY) === normalized) {\n return \"READY\";\n }\n if (normalize(WALLET_CLASS_HASHES.CHIPI) === normalized) {\n return \"CHIPI\";\n }\n if (LEGACY_CHIPI_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"CHIPI\";\n }\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) {\n return \"SHHH\";\n }\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) {\n return \"SHHH\";\n }\n // Unknown class hash — return null so callers can handle explicitly\n return null;\n}\n\n/**\n * Returns true if a class hash is a registered SHHH ShhhAccount class\n * (current or legacy) OR one of the 10 V8.4 verifier classes. Used by the\n * backend to reject unknown class hashes when an integrator opts into SHHH\n * via `walletType: \"SHHH\"` (D4 safety net — open SDK option, no per-org gate).\n */\nexport function isKnownShhhClassHash(classHash: string): boolean {\n const normalize = (h: string) => h.toLowerCase().replace(/^0x0+/, \"0x\");\n const normalized = normalize(classHash);\n\n if (normalize(WALLET_CLASS_HASHES.SHHH) === normalized) return true;\n if (LEGACY_SHHH_CLASS_HASHES.some((h) => normalize(h) === normalized)) return true;\n return Object.values(SHHH_VERIFIER_CLASS_HASHES).some((h) => normalize(h) === normalized);\n}\n\n// RPC endpoints per wallet type — any standard Starknet RPC works for all wallet types.\n// Override via STARKNET_RPC_URL env var; falls back to the default Infura endpoint.\n//\n// Deliberately still a Record<string, string> of plain URLs: it is a published API\n// consumed as URL strings in ~8 places, so widening it would be a breaking change.\n// A Starkscan endpoint cannot be represented here anyway (its key must travel in a\n// header, never in the URL). Pass these values as `buildRpcChain({ fallbackUrl })` /\n// `withRpcFallback(fn, { fallbackUrl })` to get the header-authed chain on top.\nexport const WALLET_RPC_ENDPOINTS: Record<string, string> = {\n CHIPI: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n READY: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n SHHH: readEnv(\"STARKNET_RPC_URL\") ?? DEFAULT_MAINNET_RPC,\n};\n\n// Paymaster configuration\nexport const PAYMASTER_CONFIG = {\n URL: \"https://paymaster.chipipay.com\",\n} as const;\n\n// Session key configuration (CHIPI wallets only - SNIP-9 compatible)\nexport const SESSION_DEFAULTS = {\n /** Default session duration: 6 hours in seconds */\n DURATION_SECONDS: 21600,\n /** Default max calls per session */\n MAX_CALLS: 1000,\n} as const;\n\n// Session-specific error codes\nexport const SESSION_ERRORS = {\n /** Session keys only work with CHIPI wallets */\n INVALID_WALLET_TYPE_FOR_SESSION: \"INVALID_WALLET_TYPE_FOR_SESSION\",\n /** Session has expired (validUntil < now) */\n SESSION_EXPIRED: \"SESSION_EXPIRED\",\n /** Session key not registered on contract */\n SESSION_NOT_REGISTERED: \"SESSION_NOT_REGISTERED\",\n /** Session key has been revoked */\n SESSION_REVOKED: \"SESSION_REVOKED\",\n /** Session has exceeded max calls */\n SESSION_MAX_CALLS_EXCEEDED: \"SESSION_MAX_CALLS_EXCEEDED\",\n /** Entrypoint not allowed for this session */\n SESSION_ENTRYPOINT_NOT_ALLOWED: \"SESSION_ENTRYPOINT_NOT_ALLOWED\",\n /** Failed to decrypt session private key */\n SESSION_DECRYPTION_FAILED: \"SESSION_DECRYPTION_FAILED\",\n /** Failed to create session key */\n SESSION_CREATION_FAILED: \"SESSION_CREATION_FAILED\",\n /** Backend returned an invalid response shape */\n SESSION_INVALID_RESPONSE: \"SESSION_INVALID_RESPONSE\",\n /** Invalid spending policy configuration */\n INVALID_SPENDING_POLICY: \"INVALID_SPENDING_POLICY\",\n} as const;\n\n// Session contract entrypoint names\nexport const SESSION_ENTRYPOINTS = {\n /** Add or update a session key (owner only) */\n ADD_OR_UPDATE: \"add_or_update_session_key\",\n /** Revoke a session key (owner only) */\n REVOKE: \"revoke_session_key\",\n /** Query session data (public read) */\n GET_DATA: \"get_session_data\",\n /** Set a spending policy for a session key + token pair (owner only) */\n SET_SPENDING_POLICY: \"set_spending_policy\",\n /** Query a spending policy (public read) */\n GET_SPENDING_POLICY: \"get_spending_policy\",\n /** Remove a spending policy (owner only) */\n REMOVE_SPENDING_POLICY: \"remove_spending_policy\",\n} as const;\n","import type { ErrorWithCode } from \"@chipi-stack/types\";\n\n/**\n * Error classes and utilities for Chipi SDK\n */\n\nexport class ChipiError extends Error implements ErrorWithCode {\n public readonly code: string;\n public readonly status?: number;\n\n constructor(message: string, code: string, status?: number) {\n super(message);\n this.name = \"ChipiError\";\n this.code = code;\n this.status = status;\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, ChipiError);\n }\n }\n}\n\nexport class ChipiApiError extends ChipiError {\n constructor(message: string, code: string, status: number) {\n super(message, code, status);\n this.name = \"ChipiApiError\";\n }\n}\n\nexport class ChipiWalletError extends ChipiError {\n constructor(message: string, code: string = \"WALLET_ERROR\") {\n super(message, code);\n this.name = \"ChipiWalletError\";\n }\n}\n\nexport class ChipiTransactionError extends ChipiError {\n constructor(message: string, code: string = \"TRANSACTION_ERROR\") {\n super(message, code);\n this.name = \"ChipiTransactionError\";\n }\n}\n\nexport class ChipiSessionError extends ChipiError {\n constructor(message: string, code: string = \"SESSION_ERROR\") {\n super(message, code);\n this.name = \"ChipiSessionError\";\n }\n}\n\nexport class ChipiSkuError extends ChipiError {\n constructor(message: string, code: string = \"SKU_ERROR\") {\n super(message, code);\n this.name = \"ChipiSkuError\";\n }\n}\n\nexport class ChipiValidationError extends ChipiError {\n constructor(message: string, code: string = \"VALIDATION_ERROR\") {\n super(message, code, 400);\n this.name = \"ChipiValidationError\";\n }\n}\n\nexport class ChipiAuthError extends ChipiError {\n constructor(message: string, code: string = \"AUTH_ERROR\") {\n super(message, code, 401);\n this.name = \"ChipiAuthError\";\n }\n}\n\nexport class WalletNotCompatibleError extends ChipiWalletError {\n constructor(message: string) {\n super(message, \"WALLET_NOT_COMPATIBLE\");\n this.name = \"WalletNotCompatibleError\";\n }\n}\n\nexport class WalletClassHashNotFoundError extends ChipiWalletError {\n constructor(walletType: string) {\n super(\n `No class hash registered for wallet type '${walletType}'. Register it via customWalletTypes in SDK config.`,\n \"WALLET_CLASS_HASH_NOT_FOUND\"\n );\n this.name = \"WalletClassHashNotFoundError\";\n }\n}\n\nexport class PaymasterIncompatibleError extends ChipiError {\n constructor(classHash: string) {\n super(\n `Wallet class hash ${classHash} is not compatible with Chipi paymaster. Account must implement SNIP-9 (outside_execution_v2).`,\n \"PAYMASTER_INCOMPATIBLE\",\n 400\n );\n this.name = \"PaymasterIncompatibleError\";\n }\n}\n\nexport function isChipiError(error: unknown): error is ChipiError {\n return error instanceof ChipiError;\n}\n\n/**\n * Type guard to check if an error has an HTTP status property.\n * Useful for retry logic where you need to distinguish API errors\n * (which have status codes) from network errors (which don't).\n */\nexport function hasHttpStatus(error: unknown): error is { status: number } {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"status\" in error &&\n typeof (error as { status: unknown }).status === \"number\"\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function handleApiError(error: any): ChipiError {\n if (isChipiError(error)) {\n return error;\n }\n\n if (typeof error?.response?.status === \"number\") {\n const status = error.response.status;\n const message = error.response.data?.message || error.message || \"API request failed\";\n const code = error.response.data?.code || `HTTP_${status}`;\n\n return new ChipiApiError(message, code, status);\n }\n\n // Handle errors with direct status property (non-Axios)\n if (error?.status && typeof error.status === \"number\") {\n const message = error?.message || \"API request failed\";\n const code = error?.code || `HTTP_${error.status}`;\n return new ChipiApiError(message, code, error.status);\n }\n\n return new ChipiError(error?.message || \"An unknown error occurred\", \"UNKNOWN_ERROR\");\n}\n","/**\n * Data formatters and transformers for Chipi SDK\n */\n\nexport function formatCurrency(\n amount: number,\n currency: string = \"USD\",\n locale: string = \"en-US\"\n): string {\n return new Intl.NumberFormat(locale, {\n style: \"currency\",\n currency,\n }).format(amount);\n}\n\nexport function formatNumber(\n value: number,\n options: {\n decimals?: number;\n locale?: string;\n compact?: boolean;\n } = {}\n): string {\n const { decimals = 2, locale = \"en-US\", compact = false } = options;\n\n return new Intl.NumberFormat(locale, {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n notation: compact ? \"compact\" : \"standard\",\n }).format(value);\n}\n\nexport function formatDate(\n date: Date | string,\n options: {\n locale?: string;\n dateStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n timeStyle?: \"full\" | \"long\" | \"medium\" | \"short\";\n } = {}\n): string {\n const { locale = \"en-US\", dateStyle = \"medium\", timeStyle } = options;\n const dateObj = typeof date === \"string\" ? new Date(date) : date;\n\n return new Intl.DateTimeFormat(locale, {\n dateStyle,\n timeStyle,\n }).format(dateObj);\n}\n\nexport function formatAddress(address: string, length: number = 8): string {\n if (address.length <= length * 2) {\n return address;\n }\n\n return `${address.slice(0, length)}...${address.slice(-length)}`;\n}\n\nexport function formatTransactionHash(hash: string): string {\n return formatAddress(hash, 6);\n}\n\nexport function camelToSnake(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\nexport function snakeToCamel(str: string): string {\n return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());\n}\n\nexport function capitalizeFirst(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1);\n}\n","import { z } from \"zod\";\n\n// Base API response schema\nexport const ApiResponseSchema = z.object({\n data: z.unknown(),\n message: z.string().optional(),\n code: z.string().optional(),\n});\n\n// Error response schema\nexport const ErrorResponseSchema = z.object({\n message: z.string(),\n code: z.string().optional(),\n status: z.number().optional(),\n});\n\n// Generic success response schema\nexport const SuccessResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>\n ApiResponseSchema.extend({\n data: dataSchema,\n });\n\n// Type helpers\nexport type ApiResponse<T> = {\n data: T;\n message?: string;\n code?: string;\n};\nexport type ErrorResponse = z.infer<typeof ErrorResponseSchema>;\n\n// Validation functions\n// This is not very good nor useful without passing a data schema\nexport function validateApiResponse<T>(response: unknown, dataSchema: z.ZodType<T>): void {\n // Validate with specific data schema\n const result = SuccessResponseSchema(dataSchema).safeParse(response);\n if (!result.success) {\n throw new Error(`Invalid API response format: ${result.error.message}`);\n }\n}\n\nexport function validateErrorResponse(response: unknown): ErrorResponse {\n const result = ErrorResponseSchema.safeParse(response);\n if (result.success) {\n return result.data;\n }\n\n // Fallback for malformed error responses\n return {\n message: \"Unknown error occurred\",\n code: \"UNKNOWN_ERROR\",\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chipi-stack/shared",
|
|
3
|
-
"version": "14.12.
|
|
3
|
+
"version": "14.12.1",
|
|
4
4
|
"description": "Shared utilities and helpers for Chipi SDK packages",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chipi",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"starknet": ">=9.2.1",
|
|
76
76
|
"zod": "^4.0.17",
|
|
77
|
-
"@chipi-stack/types": "^14.12.
|
|
77
|
+
"@chipi-stack/types": "^14.12.1"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/node": "^22.15.15",
|