@gala-chain/gswap-sdk 1.2.0-rc.8 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +25 -10
  2. package/dist/browser/classes/dex_fees.js.map +1 -1
  3. package/dist/browser/classes/gateway.js.map +1 -1
  4. package/dist/browser/classes/gdex_stream.js.map +1 -1
  5. package/dist/browser/classes/gswap.js.map +1 -1
  6. package/dist/browser/classes/gswap_sdk_error.js.map +1 -1
  7. package/dist/browser/classes/pending_swap_fate.js +2 -0
  8. package/dist/browser/classes/pending_swap_fate.js.map +1 -0
  9. package/dist/browser/classes/pending_swaps.js +1 -1
  10. package/dist/browser/classes/pending_swaps.js.map +1 -1
  11. package/dist/browser/classes/positions.js +1 -1
  12. package/dist/browser/classes/positions.js.map +1 -1
  13. package/dist/browser/classes/shadow_submit.js +1 -1
  14. package/dist/browser/classes/shadow_submit.js.map +1 -1
  15. package/dist/browser/classes/signers.js.map +1 -1
  16. package/dist/browser/classes/storage_adapters.js +2 -0
  17. package/dist/browser/classes/storage_adapters.js.map +1 -0
  18. package/dist/browser/classes/submitted_transaction.js.map +1 -1
  19. package/dist/browser/classes/symbols.js +1 -1
  20. package/dist/browser/classes/symbols.js.map +1 -1
  21. package/dist/browser/index.js +1 -1
  22. package/dist/browser/utils/chain_dto_signing.js.map +1 -1
  23. package/dist/browser/utils/class_key.js +2 -0
  24. package/dist/browser/utils/class_key.js.map +1 -0
  25. package/dist/browser/utils/classification.js +2 -0
  26. package/dist/browser/utils/classification.js.map +1 -0
  27. package/dist/browser/utils/dto_builders.js +1 -1
  28. package/dist/browser/utils/dto_builders.js.map +1 -1
  29. package/dist/browser/utils/eip712.js.map +1 -1
  30. package/dist/browser/utils/failure_classification.js +1 -1
  31. package/dist/browser/utils/failure_classification.js.map +1 -1
  32. package/dist/browser/utils/failure_guards.js +2 -0
  33. package/dist/browser/utils/failure_guards.js.map +1 -0
  34. package/dist/browser/utils/ordering.js +1 -1
  35. package/dist/browser/utils/ordering.js.map +1 -1
  36. package/dist/browser/utils/tick_align.js +2 -0
  37. package/dist/browser/utils/tick_align.js.map +1 -0
  38. package/dist/browser/utils/tick_math.js +2 -0
  39. package/dist/browser/utils/tick_math.js.map +1 -0
  40. package/dist/browser/utils/tick_range.js +2 -0
  41. package/dist/browser/utils/tick_range.js.map +1 -0
  42. package/dist/browser/utils/ticks.js +1 -1
  43. package/dist/browser/utils/ticks.js.map +1 -1
  44. package/dist/browser/utils/transport.js +1 -1
  45. package/dist/browser/utils/transport.js.map +1 -1
  46. package/dist/browser/utils/validation.js +1 -1
  47. package/dist/browser/utils/validation.js.map +1 -1
  48. package/dist/browser/version.js +1 -1
  49. package/dist/browser/version.js.map +1 -1
  50. package/dist/index.cjs +641 -336
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.d.cts +470 -186
  53. package/dist/index.d.ts +470 -186
  54. package/dist/index.mjs +636 -337
  55. package/dist/index.mjs.map +1 -1
  56. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["isRecord","isRecord","asRecord","malformed","BigNumber","Decimal","BigNumber","isRecord","trimTrailingSlash","asRecord","BigNumber","BigNumber","BigNumber","textEncoder","secp256k1","bytesToHex","keccak_256","globalObject","BigNumber","keccak_256","isRecord"],"sources":["../src/utils/confirmation_schedule.ts","../src/utils/server_message.ts","../src/utils/unique_key_syntax.ts","../src/utils/error_brand.ts","../src/classes/error_phases.ts","../src/utils/failure_outcomes.ts","../src/utils/failure_view.ts","../src/classes/error_phase_table.ts","../src/classes/error_catalog.ts","../src/classes/gswap_sdk_error.ts","../src/version.ts","../src/utils/transport.ts","../src/classes/apply_results.ts","../src/types/fees.ts","../src/utils/ticks.ts","../src/utils/validation.ts","../src/classes/assets.ts","../src/utils/wallet_rejection.ts","../src/utils/pre_send.ts","../src/classes/dex_fees.ts","../src/utils/shadow_errors.ts","../src/classes/submitted_transaction.ts","../src/classes/gateway.ts","../src/types/env.ts","../src/utils/debug.ts","../src/utils/reconnection.ts","../src/classes/gdex_stream.ts","../src/classes/http_client.ts","../src/utils/lenient.ts","../src/utils/ordering.ts","../src/classes/symbols.ts","../src/classes/pools.ts","../src/utils/unique_key.ts","../src/utils/dto_builders.ts","../src/classes/positions.ts","../src/classes/quoting.ts","../src/classes/shadow_submit.ts","../src/classes/swaps.ts","../src/classes/gswap.ts","../src/utils/failure_classification.ts","../src/classes/pending_swaps.ts","../src/utils/eip712.ts","../src/utils/signing.ts","../src/classes/signers.ts","../src/utils/chain_dto_signing.ts","../src/utils/typed_data.ts","../src/utils/axios_requestor.ts","../src/utils/ethers_provider.ts","../src/utils/confirmation_state.ts","../src/utils/fetch_failure.ts","../src/utils/submit_state.ts"],"sourcesContent":["import type { ConfirmOptions } from '../types/confirm_options.js';\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst MIN_POLL_INTERVAL_MS = 500;\nconst MAX_BACKOFF_MS = 8_000;\n\n/** The pacing of confirmation reads: one initial delay, then jittered exponential backoff. */\nexport interface ConfirmationSchedule {\n /**\n * Waits for the next read. Resolves `true` when the caller should read, `false` when the\n * deadline leaves no room for another read. The very first call always resolves `true` (at\n * least one read is made, even when the deadline is already past). Rejects with the abort\n * error when the caller's signal aborts, before or during the wait.\n */\n waitForRead(retryAfterMs?: number): Promise<boolean>;\n}\n\n/**\n * Builds the schedule for one `confirm()` call. `abortError` creates the error thrown when\n * `options.signal` aborts, so each confirmation kind keeps its own error type and details.\n */\nexport function createConfirmationSchedule(\n options: ConfirmOptions | undefined,\n defaultInitialDelayMs: number,\n abortError: (cause?: unknown) => Error,\n): ConfirmationSchedule {\n const timeoutMs = Math.max(0, options?.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n const pollIntervalMs = Math.max(\n MIN_POLL_INTERVAL_MS,\n options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,\n );\n const initialDelayMs = Math.max(0, options?.initialDelayMs ?? defaultInitialDelayMs);\n const signal = options?.signal;\n const deadline = Date.now() + timeoutMs;\n let firstRead = true;\n let attempt = 0;\n return {\n async waitForRead(retryAfterMs?: number): Promise<boolean> {\n throwIfAborted(signal, abortError);\n if (firstRead) {\n firstRead = false;\n const remaining = Math.max(0, deadline - Date.now());\n await delay(Math.min(initialDelayMs, remaining), signal, abortError);\n return true;\n }\n const backoff = Math.min(MAX_BACKOFF_MS, pollIntervalMs * 2 ** Math.min(attempt, 5));\n attempt += 1;\n const waitMs = retryAfterMs === undefined ? jitter(backoff) : Math.max(0, retryAfterMs);\n if (Date.now() + waitMs > deadline) return false;\n await delay(waitMs, signal, abortError);\n return true;\n },\n };\n}\n\n/** Throws `abortError(signal.reason)` when the signal has aborted. */\nexport function throwIfAborted(\n signal: AbortSignal | undefined,\n abortError: (cause?: unknown) => Error,\n): void {\n if (signal?.aborted === true) throw abortError(signal.reason);\n}\n\nfunction delay(\n milliseconds: number,\n signal: AbortSignal | undefined,\n abortError: (cause?: unknown) => Error,\n): Promise<void> {\n if (signal?.aborted === true) return Promise.reject(abortError(signal.reason));\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(abortError(signal?.reason));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, milliseconds);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nfunction jitter(milliseconds: number): number {\n return Math.max(0, Math.round(milliseconds * (0.9 + Math.random() * 0.2)));\n}\n","import type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nfunction nonEmptyString(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const field = (value as Record<string, unknown>)[property];\n return typeof field === 'string' && field !== '' ? field : undefined;\n}\n\n/**\n * The human message a failing JSON body carries, as the server wrote it: the first non-empty\n * string of `message`, `Message`, `error.message`, `error.Message` (NestJS, the gateway filter\n * and the chain each use one of these shapes), else `''`. A body that is not JSON (an HTML 502\n * page, an empty body), or whose `message` is not a string (a validation error's list), has no\n * message. This is the single reader behind every `serverMessage` param.\n *\n * The text is DATA from the server, not SDK text: it is English, unstable, and may be empty. The\n * SDK exposes it so an app can relay it or ignore it; it is never part of `error.message`.\n */\nexport function serverMessageOfBody(body: unknown): string {\n const nested =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)['error']\n : undefined;\n return (\n nonEmptyString(body, 'message') ??\n nonEmptyString(body, 'Message') ??\n nonEmptyString(nested, 'message') ??\n nonEmptyString(nested, 'Message') ??\n ''\n );\n}\n\n/**\n * The message the server put in a failing answer: the `serverMessage` param of a code that relays\n * it, else the message of the JSON body ({@link serverMessageOfBody}). Internal: the SDK reads it\n * ONLY to classify a failure (a quote that says \"no pools\"); it is English from the server, never\n * part of the SDK's own `message`, and not exported from the package.\n */\nexport function readServerMessage(error: GSwapSDKError): string | undefined {\n const params: Readonly<Record<string, string | number | boolean>> = error.params;\n const fromParams = params['serverMessage'];\n if (typeof fromParams === 'string' && fromParams !== '') return fromParams;\n const fromBody = serverMessageOfBody(error.body);\n return fromBody === '' ? undefined : fromBody;\n}\n","/**\n * The shape of a write `uniqueKey`, with NO imports: the pending-swap store and the failure guards\n * need only this check, and importing it from `unique_key.ts` would drag in `GSwapSDKError` and the\n * whole error catalog for it.\n */\n\n/** The swap backend's apply-results key constraint (`apply-results.dto.ts`). */\nconst UNIQUE_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/u;\n\n/**\n * True when `uniqueKey` is a usable write key: 1 to 128 characters of `A-Za-z0-9._:-`, the shape\n * the apply-results route accepts. The one definition behind `assertUniqueKey`, `confirm()` and\n * the pending-swap store, so they can never disagree about what a valid key is.\n */\nexport function isValidUniqueKey(uniqueKey: unknown): uniqueKey is string {\n return typeof uniqueKey === 'string' && UNIQUE_KEY_PATTERN.test(uniqueKey);\n}\n","/**\n * The brand every `GSwapSDKError` carries, and the duck-type check for the \"failure shape\". This\n * module has NO imports on purpose: it is part of the light `@gala-chain/gswap-sdk/wallet` entry,\n * which must never pull the error catalog or the main bundle in.\n */\n\n/**\n * The brand of an SDK error: `error[GSWAP_ERROR_BRAND] === true`. It is a registered symbol\n * (`Symbol.for`), so two copies of the SDK in one page (a wallet bundle and an app bundle) still\n * recognise each other's errors, which `instanceof` cannot do.\n */\nexport const GSWAP_ERROR_BRAND: unique symbol = Symbol.for('@gala-chain/gswap-sdk/error');\n\n/** The least an object must have to be read as an SDK error or its plain-object view. */\nexport interface GSwapErrorShape {\n readonly code: string;\n readonly params: Readonly<Record<string, unknown>>;\n}\n\nfunction isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** True when `value` carries the SDK error brand (a real `GSwapSDKError`, from any copy of the SDK). */\nexport function hasGSwapErrorBrand(value: unknown): boolean {\n return isRecord(value) && value[GSWAP_ERROR_BRAND] === true;\n}\n\n/**\n * True when `value` is an SDK error (it carries the brand) or a plain-object VIEW of one: a string\n * `code` and an object `params`, which is the shape of `GSwapSDKError` and of the wrapper objects\n * an app builds from one (`{ code, params, status?, phase?, ... }`). A wallet's own error (an\n * EIP-1193 numeric `code`, an ethers error with a string `code` and no `params`) is neither. It\n * says the value has the SDK's shape, not that `code` is a code the SDK knows.\n *\n * @example\n * ```ts\n * if (isGSwapErrorLike(error)) report(error.code, error.params); // no `instanceof`, no SDK import\n * ```\n */\nexport function isGSwapErrorLike(value: unknown): value is GSwapErrorShape {\n if (hasGSwapErrorBrand(value)) return true;\n return (\n isRecord(value) &&\n typeof value['code'] === 'string' &&\n isRecord(value['params']) &&\n !Array.isArray(value['params'])\n );\n}\n","/**\n * How far an operation had got when it failed, measured against the request it exists to send:\n * for a write, the POST that carries the signed DTO to the gateway; for a read, the GET.\n *\n * - `pre_send`: NOTHING was transmitted. Everything up to the request (validation, symbol\n * resolution, the signer, the wallet, a key provider) ran and failed, so no write can have been\n * queued. A write that failed `pre_send` is never \"maybe applied\".\n * - `in_flight`: the request left (or may have left) and no answer was read: a timeout, a broken\n * connection, a stream that dropped. For a write the outcome is unknown.\n * - `post_send`: an answer was read, or the write was already accepted: a refusal, an\n * acknowledgement that proves nothing, an unusable body, and every failure of a confirmation.\n *\n * Each catalog entry declares the phase its code is thrown in; a throw site where the same code\n * can occur in another phase overrides it (`GSwapErrorContext.phase`). It is a typed property of\n * every `GSwapSDKError` (`error.phase`) and `isPreSendError(error)` reads it.\n *\n * This module has no imports, on purpose: it is the closed set of phases, shared by the catalog,\n * the light phase table (`error_phase_table.ts`) and the failure view.\n */\nexport const GSWAP_ERROR_PHASES = ['pre_send', 'in_flight', 'post_send'] as const;\n\n/** One member of {@link GSWAP_ERROR_PHASES}. */\nexport type GSwapErrorPhase = (typeof GSWAP_ERROR_PHASES)[number];\n","/**\n * What a failure means for the operation that raised it, as one vocabulary for every app.\n *\n * - `rejected`: the CHAIN refused the request (a definite no). Nothing was applied, so a NEW\n * request is safe.\n * - `unknown`: the request MAY have been applied (a timeout, a broken connection, an\n * acknowledgement that proves nothing, a failed confirmation). Never submit again under a fresh\n * key: keep `error.uniqueKey` and confirm it.\n * - `not_queued`: the gateway refused the write before queueing it. Nothing is pending.\n * - `not_sent`: the request never left (`error.phase === 'pre_send'`) for a reason outside the\n * call itself: the signer or the wallet failed (locked, unreachable, the person declined), the\n * key provider or the token resolver failed, or no key was available yet. Nothing is pending and\n * nothing was transmitted, so repeating the call is safe and may succeed once the cause (an\n * unlocked wallet) is gone.\n * - `invalid_input`: the call itself cannot work (a bad argument, a missing signer or wallet, an\n * unknown token or pool, a corrupt stored key). Repeating the same call fails the same way.\n * Such an error is also pre-send (`isPreSendError`), but the input is what has to change.\n * - `transient`: a read or connection failed with no state change. Repeating the same call is safe\n * and may succeed.\n *\n * This module has no imports: the failure view (`FailureView.outcome`) and the classifier both\n * read the closed set from here.\n */\nexport const FAILURE_OUTCOMES = [\n 'rejected',\n 'unknown',\n 'not_queued',\n 'not_sent',\n 'invalid_input',\n 'transient',\n] as const;\n\n/** One member of {@link FAILURE_OUTCOMES}. */\nexport type FailureOutcome = (typeof FAILURE_OUTCOMES)[number];\n","import { GSWAP_ERROR_PHASES, type GSwapErrorPhase } from '../classes/error_phases.js';\nimport { FAILURE_OUTCOMES, type FailureOutcome } from './failure_outcomes.js';\n\n/**\n * A failure as a PLAIN OBJECT: the facts the SDK's guards and `classifyFailure` read, and nothing\n * else. A real `GSwapSDKError` is one (every field below is on it); so is the wrapper an app makes\n * from an SDK error to carry through its own layers (frontend_v2's `V2Failure`, the wallet's\n * `WalletSwapError` data), which has a `code` and `params` but is not an `instanceof` anything the\n * SDK owns. `classifyFailure`, `isRelayableRefusal`, `isUnprovenAcknowledgement`,\n * `isUninterpretedAnswer`, `isPreSendError`, `isShadowError`, `isNoMarket` and `mayHaveBeenQueued`\n * all accept such an object wherever they accept an SDK error, and decide from the SAME fields in\n * the same way, so an app never has to keep the original error just to ask.\n *\n * Only `code` is required. A field that is missing, or has the wrong type, reads as absent: a view\n * with no `status` is not a 404. Nothing here is text: the SDK never reads `message` of a view.\n *\n * READ OR WRITE: a view is a WRITE's unless it says it is a read. This fails CLOSED on purpose:\n * a 5xx on a write may have been queued (`unknown`, no retry) and the same 5xx on a read changed\n * nothing (`transient`, retry), so a wrapper that drops its `uniqueKey` must never turn the first\n * into the second. A view is a read ONLY when it states `write: false` and has no `uniqueKey`;\n * `GSwapSDKError.write` is already set that way for every SDK read. {@link isWriteView}\n * is the one definition.\n *\n * APP ERRORS: a code the SDK catalog does not define is `unknown` (the SDK cannot say what\n * happened, and a wrong \"failed\" invites a duplicate), unless the view declares `outcome`.\n */\nexport interface FailureView {\n /** The catalog code (`'HTTP_ERROR'`, `'CHAIN_REJECTED'`, ...). A string the SDK does not know classifies as `unknown`. */\n readonly code: string;\n /** The error's flat params (`status` of an `HTTP_ERROR`, `reason` of a `SIGNING_FAILED`, ...). */\n readonly params?: Readonly<Record<string, unknown>> | undefined;\n /** The HTTP status of the answer the failure was made from. */\n readonly status?: number | undefined;\n /** How far the request got; when absent, the catalog's phase for `code`. */\n readonly phase?: GSwapErrorPhase | undefined;\n /** The `uniqueKey` of the WRITE this is about; its presence makes the failure a write's. */\n readonly uniqueKey?: string | undefined;\n /**\n * `false` says the failed call was a READ (no `uniqueKey` to confirm, nothing pending). Anything\n * else, including absent, is a write: see the note on {@link FailureView}. With a `uniqueKey`\n * the failure is a write whatever this says.\n */\n readonly write?: boolean | undefined;\n /**\n * What an error the APP raised means, for a `code` the SDK catalog does not define (`'POSITION_STALE'`,\n * `'AMOUNT_SIDE'`): `not_sent` for a step that failed before anything was signed or sent, and so\n * on. The SDK honours it ONLY for such a code: for a catalog code the SDK's own table decides, so\n * an app cannot declare a refusal the SDK knows to be unknown as safe. A non-catalog code with no\n * `outcome` stays `unknown`, and `mayHaveBeenQueued` is then `true`.\n */\n readonly outcome?: FailureOutcome | undefined;\n /**\n * WITHHOLD-ONLY: `false` takes Retry away from the declared `outcome` (an app's `DID_NOT_QUEUE`\n * is `{ outcome: 'not_queued', retryable: false }`, the SDK's `NOT_QUEUED_FINAL`). Any other\n * value, `true` included, reads as absent: a view can never GRANT Retry to an outcome that does\n * not have it, and it is read only together with `outcome`, for a code the catalog does not\n * define.\n */\n readonly retryable?: false | undefined;\n /** True when the failure came from the shadow (dark) path. */\n readonly shadow?: boolean | undefined;\n /** True for \"that market does not exist\" (`GSwapSDKError.notFound`). */\n readonly notFound?: boolean | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * Reads the failure view of any value: a `GSwapSDKError`, or a plain object with a string `code`\n * (and, optionally, `params`, `status`, `phase`, `uniqueKey`, `shadow`, `notFound`). Anything else\n * (a string, a wallet error with a numeric `code`, `null`) has no view and is `undefined`.\n *\n * Having a view does not mean the SDK knows the code: an ethers error is `{ code:\n * 'ACTION_REJECTED' }` and has a view too. The SDK's guards compare the code with the catalog.\n *\n * @example\n * ```ts\n * const view = toFailureView(error); // an SDK error, or an app's `{ code, params, status }` wrapper\n * if (view?.code === 'CHAIN_REJECTED') showChainRejection(view.params);\n * ```\n */\nexport function toFailureView(value: unknown): FailureView | undefined {\n if (!isRecord(value)) return undefined;\n const { code, params, status, phase, uniqueKey, write, outcome, retryable, shadow, notFound } =\n value;\n if (typeof code !== 'string' || code === '') return undefined;\n return {\n code,\n params: isRecord(params) && !Array.isArray(params) ? params : undefined,\n status: typeof status === 'number' && Number.isFinite(status) ? status : undefined,\n phase: GSWAP_ERROR_PHASES.find((known) => known === phase),\n uniqueKey: typeof uniqueKey === 'string' && uniqueKey !== '' ? uniqueKey : undefined,\n write: typeof write === 'boolean' ? write : undefined,\n outcome: FAILURE_OUTCOMES.find((known) => known === outcome),\n retryable: retryable === false ? false : undefined,\n shadow: typeof shadow === 'boolean' ? shadow : undefined,\n notFound: typeof notFound === 'boolean' ? notFound : undefined,\n };\n}\n\n/**\n * True when a failure is a WRITE's: it names a `uniqueKey`, or it does not say `write: false`.\n * Fail-closed (see {@link FailureView}): only an explicit read is a read.\n */\nexport function isWriteView(view: FailureView): boolean {\n return view.uniqueKey !== undefined || view.write !== false;\n}\n\n/** A param of a view, when it is a string. */\nexport function stringParamOf(view: FailureView, name: string): string | undefined {\n const value = view.params?.[name];\n return typeof value === 'string' ? value : undefined;\n}\n\n/** A param of a view, when it is a finite number. */\nexport function numberParamOf(view: FailureView, name: string): number | undefined {\n const value = view.params?.[name];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n","import type { GSWAP_ERROR_CATALOG, GSwapErrorCode } from './error_catalog.js';\nimport type { GSwapErrorPhase } from './error_phases.js';\nimport type { FailureView } from '../utils/failure_view.js';\n\n/**\n * The phase of every catalog code, WITHOUT the catalog. The failure guards (`classifyFailure`,\n * `mayHaveBeenQueued`, ...) need only a code's phase, and the catalog's English templates are\n * ~20 kB: reading the phase from here keeps an app shell that imports a guard from loading them.\n * The catalog entry is still where a code is declared; this table is checked against it AT\n * COMPILE TIME, in both directions (a missing code, an extra code or a different phase is a type\n * error), so the two cannot drift.\n */\nexport const GSWAP_ERROR_PHASE_BY_CODE = {\n HTTP_ERROR: 'post_send',\n UPDATE_REQUIRED: 'post_send',\n REQUEST_TIMEOUT: 'in_flight',\n TRANSPORT_ERROR: 'in_flight',\n REQUEST_FAILED: 'in_flight',\n INVALID_TIMEOUT: 'pre_send',\n METHOD_NOT_SUPPORTED: 'pre_send',\n SUBMISSION_OUTCOME_UNKNOWN: 'in_flight',\n GATEWAY_REPORTED_ERROR: 'post_send',\n GATEWAY_DATA_MISSING: 'post_send',\n GATEWAY_MODE_INVALID: 'post_send',\n GATEWAY_SYNC_REQUEST_TRADE: 'post_send',\n MISSING_UNIQUE_KEY: 'post_send',\n UNIQUE_KEY_MISMATCH: 'post_send',\n SHADOW_NOT_QUEUED: 'post_send',\n SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS: 'pre_send',\n METHOD_NOT_ALLOWED: 'post_send',\n SIGNATURE_INVALID: 'post_send',\n SIGNER_MISMATCH: 'post_send',\n DTO_INVALID: 'post_send',\n BOUNDS_VIOLATION: 'post_send',\n SYMBOL_CONFLICT: 'post_send',\n RATE_LIMITED: 'post_send',\n CHAIN_DISPATCH_FAILED: 'post_send',\n GATEWAY_REJECTED: 'post_send',\n CHAIN_REJECTED: 'post_send',\n INVALID_CHAIN_RESPONSE: 'post_send',\n INVALID_POSITION_RESPONSE: 'post_send',\n CONFIRMATION_TIMEOUT: 'post_send',\n CONFIRMATION_ABORTED: 'post_send',\n CONFIRMATION_FAILED: 'post_send',\n CONFIRMATION_MALFORMED: 'post_send',\n CONFIRMATION_KEY_MISMATCH: 'post_send',\n NO_SIGNER: 'pre_send',\n NO_WALLET_ADDRESS: 'post_send',\n NO_POOL_AVAILABLE: 'post_send',\n INSUFFICIENT_LIQUIDITY: 'post_send',\n UNKNOWN_TOKEN: 'pre_send',\n SYMBOL_NOT_FOUND: 'pre_send',\n STREAM_API_KEY_UNUSABLE: 'pre_send',\n STREAM_WEBSOCKET_UNAVAILABLE: 'pre_send',\n STREAM_NOT_CONNECTED: 'pre_send',\n STREAM_DISCONNECTED: 'in_flight',\n STREAM_REQUEST_TIMEOUT: 'in_flight',\n STREAM_CONNECT_FAILED: 'in_flight',\n STREAM_CLOSED_BEFORE_CONNECT: 'in_flight',\n STREAM_CONNECTION_CLOSED: 'in_flight',\n GALA_WALLET_NOT_AVAILABLE: 'pre_send',\n WALLET_UNAVAILABLE: 'pre_send',\n MALFORMED_WALLET_REQUEST: 'pre_send',\n UNSUPPORTED_WALLET_METHOD: 'pre_send',\n INVALID_SIGNATURE: 'pre_send',\n INVALID_CHAIN_ID: 'pre_send',\n SIGNER_ADDRESS_MISMATCH: 'pre_send',\n INVALID_PRIVATE_KEY: 'pre_send',\n SIGNING_FAILED: 'pre_send',\n KEY_PROVIDER_FAILED: 'pre_send',\n TOKEN_RESOLUTION_FAILED: 'pre_send',\n INVALID_SIGNING_HASH_LENGTH: 'pre_send',\n MISSING_WALLET_ADDRESS: 'pre_send',\n INVALID_WALLET_ADDRESS: 'pre_send',\n INVALID_DECIMAL: 'pre_send',\n PERSONAL_SIGN_NOT_JSON: 'pre_send',\n PERSONAL_SIGN_NOT_OBJECT: 'pre_send',\n PERSONAL_SIGN_BAD_PREFIX: 'pre_send',\n PERSONAL_SIGN_ENVELOPE_FIELDS: 'pre_send',\n PERSONAL_SIGN_NOT_CANONICAL: 'pre_send',\n EIP712_NAME_COLLISION: 'pre_send',\n EIP712_UNSUPPORTED_VALUE: 'pre_send',\n TYPED_DATA_NOT_STRING: 'pre_send',\n TYPED_DATA_UNPAIRED_SURROGATE: 'pre_send',\n TYPED_DATA_NOT_HEX_BYTES: 'pre_send',\n TYPED_DATA_NOT_SAFE_INTEGER: 'pre_send',\n TYPED_DATA_NOT_INTEGER: 'pre_send',\n TYPED_DATA_NOT_BOOLEAN: 'pre_send',\n TYPED_DATA_BAD_ADDRESS: 'pre_send',\n TYPED_DATA_BAD_CHECKSUM: 'pre_send',\n TYPED_DATA_BYTES_LENGTH: 'pre_send',\n TYPED_DATA_OUT_OF_BOUNDS: 'pre_send',\n TYPED_DATA_UNSUPPORTED_TYPE: 'pre_send',\n TYPED_DATA_FIELDS_NOT_LIST: 'pre_send',\n TYPED_DATA_FIELD_MALFORMED: 'pre_send',\n TYPED_DATA_INVALID_FIELD_NAME: 'pre_send',\n TYPED_DATA_DUPLICATE_FIELD: 'pre_send',\n TYPED_DATA_INVALID_TYPE_NAME: 'pre_send',\n TYPED_DATA_CIRCULAR_TYPE: 'pre_send',\n TYPED_DATA_UNKNOWN_FIELD_TYPE: 'pre_send',\n TYPED_DATA_NO_PRIMARY_TYPE: 'pre_send',\n TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE: 'pre_send',\n TYPED_DATA_ARRAY_EXPECTED: 'pre_send',\n TYPED_DATA_ARRAY_LENGTH_MISMATCH: 'pre_send',\n TYPED_DATA_STRUCT_NOT_OBJECT: 'pre_send',\n TYPED_DATA_MISSING_FIELD: 'pre_send',\n TYPED_DATA_DOMAIN_NOT_OBJECT: 'pre_send',\n TYPED_DATA_INVALID_DOMAIN_KEY: 'pre_send',\n NON_CANONICAL_PAIR: 'pre_send',\n UNORDERABLE_SYMBOLS: 'pre_send',\n INVALID_TOKEN_CLASS_KEY: 'pre_send',\n INCOMPLETE_TOKEN_CLASS_KEY: 'pre_send',\n INVALID_TRADING_SYMBOL: 'pre_send',\n NO_VALID_TRADING_SYMBOL: 'pre_send',\n TOKEN_SYMBOL_NOT_REGISTERED: 'pre_send',\n SYMBOL_DISAGREES_WITH_REGISTRY: 'pre_send',\n CREATE_POOL_NEEDS_CLASS_KEY: 'pre_send',\n INVALID_UNIQUE_KEY: 'pre_send',\n INVALID_UNIQUE_KEY_PREFIX: 'pre_send',\n AMOUNT_IS_JS_NUMBER: 'pre_send',\n AMOUNT_NOT_FINITE: 'pre_send',\n AMOUNT_NOT_POSITIVE: 'pre_send',\n AMOUNT_NEGATIVE: 'pre_send',\n PRICE_VALUES_IS_JS_NUMBER: 'pre_send',\n INVALID_PRICE_VALUES: 'pre_send',\n INVALID_PRICE_RANGE: 'pre_send',\n INVALID_PRICE_BOUNDS: 'pre_send',\n PRICE_BOUNDS_ORDER: 'pre_send',\n INVALID_STARTING_PRICE: 'pre_send',\n INVALID_SQRT_PRICE: 'pre_send',\n INVALID_TOKEN_DECIMALS: 'pre_send',\n TICKS_NOT_INTEGERS: 'pre_send',\n INVALID_TICK_RANGE: 'pre_send',\n TICKS_OUT_OF_BOUNDS: 'pre_send',\n TICKS_NOT_ALIGNED: 'pre_send',\n INVALID_TICK_SPACING: 'pre_send',\n INVALID_FEE: 'pre_send',\n EXACT_AMOUNT_REQUIRED: 'pre_send',\n EXACTLY_ONE_OF_REQUIRED: 'pre_send',\n AT_MOST_ONE_OF_ALLOWED: 'pre_send',\n POOL_MISMATCH: 'pre_send',\n INVALID_DTO: 'pre_send',\n DTO_NOT_CANONICAL: 'pre_send',\n SEARCH_TOO_LONG: 'pre_send',\n INVALID_SORT_BY: 'pre_send',\n INVALID_SORT_ORDER: 'pre_send',\n INVALID_PAGE: 'pre_send',\n INVALID_LIMIT: 'pre_send',\n} as const satisfies {\n readonly [C in GSwapErrorCode]: (typeof GSWAP_ERROR_CATALOG)[C]['phase'];\n};\n\n/** True for a code the SDK catalog defines. */\nexport function isCatalogCode(code: string): code is GSwapErrorCode {\n return Object.hasOwn(GSWAP_ERROR_PHASE_BY_CODE, code);\n}\n\n/** The phase of a view: the one it states, else the catalog's phase for its code, else `undefined`. */\nexport function phaseOfView(view: FailureView): GSwapErrorPhase | undefined {\n if (view.phase !== undefined) return view.phase;\n return isCatalogCode(view.code) ? GSWAP_ERROR_PHASE_BY_CODE[view.code] : undefined;\n}\n","/**\n * The catalog of every error the SDK throws: the SINGLE source of truth for its `code`, the\n * named parameters it carries and the English template its `message` is generated from.\n *\n * - `code` is the only discriminator. It is stable: apps branch on it, never on message text.\n * - `params` are the named placeholders of the error: a flat object of primitives (string,\n * number, boolean) that an app feeds to its own localization (i18next, ICU, FormatJS).\n * Raw server payloads are never params (they are `error.body` / `error.bodyText`), and no\n * secret (private key, signature, raw DTO) ever is.\n * - `template` is English with `{placeholder}` markers. `error.message` is generated from it\n * and the params, so the two cannot drift. It is for logs and developers: it is not stable and\n * must not be shown to users or matched on.\n *\n * Every placeholder in a template is a declared param and every declared param is a placeholder,\n * except the few `unrendered` params that carry server text for the app and are kept out of\n * `message` on purpose (pinned by tests/error_catalog.test.ts). Facts that are not placeholders (HTTP status, URL,\n * `uniqueKey`, transaction ids, the raw body, the cause) are typed properties of the error, see\n * {@link GSwapErrorContext}.\n */\n\nimport type { GSwapErrorPhase } from './error_phases.js';\n\n/**\n * The kinds a param can have: a primitive, or a CLOSED set of string tokens (a readonly tuple).\n * A closed set is a documented union: an app maps each member to its own text and can check that\n * it covered all of them, and a new member is a compile error until it does.\n */\nexport type GSwapErrorParamKind = 'string' | 'number' | 'boolean' | readonly string[];\n\n/** One catalog entry. */\nexport interface GSwapErrorCatalogEntry {\n /** The phase this code is thrown in, unless a throw site says otherwise (see {@link GSwapErrorPhase}). */\n readonly phase: GSwapErrorPhase;\n /** English message template with `{placeholder}` markers. */\n readonly template: string;\n /** Param name to kind. Every param is required and appears in the template, except `unrendered`. */\n readonly params: Readonly<Record<string, GSwapErrorParamKind>>;\n /**\n * Params that are carried for the app but deliberately NOT placeholders of the template. Used\n * for `serverMessage` on the codes whose failing answer may be anything (a proxy's page, a\n * validation list): the server's text is data for the app to relay or ignore, and keeping it out\n * of `message` means it cannot reach a log line or a user interface by accident.\n */\n readonly unrendered?: readonly string[];\n}\n\n/**\n * Why a private key was refused (`INVALID_PRIVATE_KEY.params.reason`). A token for the app to map\n * to its own text, never English and never any part of the key.\n *\n * - `wrong_length`: raw bytes that are not 32 bytes long.\n * - `bad_encoding`: a string that is neither 64 hex characters (optionally `0x`-prefixed, 63 is\n * left-padded) nor a 44-character base64 string.\n * - `not_on_curve`: 32 bytes that are not a valid secp256k1 secret scalar.\n * - `no_key_provided`: a lazy key provider returned something that is not a string.\n */\nexport const INVALID_PRIVATE_KEY_REASONS = [\n 'wrong_length',\n 'bad_encoding',\n 'not_on_curve',\n 'no_key_provided',\n] as const;\n\n/** One member of {@link INVALID_PRIVATE_KEY_REASONS}. */\nexport type InvalidPrivateKeyReason = (typeof INVALID_PRIVATE_KEY_REASONS)[number];\n\n/**\n * Why the outcome of a write submission is unknown (`SUBMISSION_OUTCOME_UNKNOWN.params.reason`).\n * Both say the same thing about the swap (it MAY have been queued: never resubmit under a fresh\n * key, confirm `error.uniqueKey` instead) and differ only in what happened to the request.\n *\n * - `timeout`: the POST exceeded the gateway's timeout; the request may still be running.\n * - `transport`: the POST failed before an HTTP answer was read (offline, connection reset, DNS,\n * CORS, a body that broke off). The bytes may have reached the server and been queued, so this\n * does NOT prove the swap was not sent.\n */\nexport const SUBMISSION_OUTCOME_UNKNOWN_REASONS = ['timeout', 'transport'] as const;\n\n/** One member of {@link SUBMISSION_OUTCOME_UNKNOWN_REASONS}. */\nexport type SubmissionOutcomeUnknownReason = (typeof SUBMISSION_OUTCOME_UNKNOWN_REASONS)[number];\n\n/**\n * Why a signer could not produce a signature (`SIGNING_FAILED.params.reason`). A token for the\n * app to map to its own text.\n *\n * - `user_rejected`: the person declined in their wallet (an EIP-1193 `4001`, an ethers\n * `ACTION_REJECTED`, or a wallet that words it \"User rejected/denied ...\"). Nothing is wrong:\n * they may simply try again.\n * - `failed`: anything else the signer threw (a locked wallet, an unreachable extension, a wallet\n * that refused). The original error is `cause`.\n */\nexport const SIGNING_FAILURE_REASONS = ['user_rejected', 'failed'] as const;\n\n/** One member of {@link SIGNING_FAILURE_REASONS}. */\nexport type SigningFailureReason = (typeof SIGNING_FAILURE_REASONS)[number];\n\n/** The fee tiers as they appear in `INVALID_FEE.allowed`. */\nexport const ALLOWED_FEE_TIERS_TEXT = '0,500,3000,10000';\n\n/** The whole catalog. Add a code here before throwing it anywhere. */\nexport const GSWAP_ERROR_CATALOG = {\n // ---------------------------------------------------------------------------------- transport\n HTTP_ERROR: {\n phase: 'post_send',\n template: 'Unexpected HTTP error {status} from {url}.',\n params: { status: 'number', url: 'string', serverMessage: 'string' },\n unrendered: ['serverMessage'],\n },\n UPDATE_REQUIRED: {\n phase: 'post_send',\n template:\n 'The backend refused this app version and requires an update (HTTP {status}); nothing was queued.',\n params: { status: 'number' },\n },\n REQUEST_TIMEOUT: {\n phase: 'in_flight',\n template: 'Request to {url} timed out after {timeoutMs} ms.',\n params: { url: 'string', timeoutMs: 'number' },\n },\n TRANSPORT_ERROR: {\n phase: 'in_flight',\n template: 'The request to {url} failed before the server answered.',\n params: { url: 'string' },\n },\n REQUEST_FAILED: {\n phase: 'in_flight',\n template: 'The {operation} request failed.',\n params: { operation: 'string' },\n },\n INVALID_TIMEOUT: {\n phase: 'pre_send',\n template:\n '{field} must be a positive number of milliseconds, or Infinity for no timeout (got {value}).',\n params: { field: 'string', value: 'number' },\n },\n\n // ----------------------------------------------------------------------------------- gateway\n METHOD_NOT_SUPPORTED: {\n phase: 'pre_send',\n template: 'The method {method} is not supported; swaps are queued through RequestTrade.',\n params: { method: 'string' },\n },\n SUBMISSION_OUTCOME_UNKNOWN: {\n phase: 'in_flight',\n template:\n 'The submission outcome is unknown ({reason}): the request may have reached the gateway. Confirm before retrying.',\n params: { reason: SUBMISSION_OUTCOME_UNKNOWN_REASONS },\n },\n GATEWAY_REPORTED_ERROR: {\n phase: 'post_send',\n template: 'The gateway reported an error for this write: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n GATEWAY_DATA_MISSING: {\n phase: 'post_send',\n template: 'The gateway response is missing its data object.',\n params: {},\n },\n GATEWAY_MODE_INVALID: {\n phase: 'post_send',\n template:\n 'Gateway response must contain data.mode=\"sync\" with data.result, or data.mode=\"queued\".',\n params: {},\n },\n GATEWAY_SYNC_REQUEST_TRADE: {\n phase: 'post_send',\n template:\n 'The gateway executed RequestTrade synchronously, which this SDK refuses; RequestTrade must be queued.',\n params: {},\n },\n MISSING_UNIQUE_KEY: {\n phase: 'post_send',\n template:\n 'The gateway acknowledged RequestTrade without echoing its uniqueKey, so it cannot be tied to the signed request.',\n params: {},\n },\n UNIQUE_KEY_MISMATCH: {\n phase: 'post_send',\n template: 'Gateway response data.uniqueKey must match the signed RequestTrade uniqueKey.',\n params: {},\n },\n SHADOW_NOT_QUEUED: {\n phase: 'post_send',\n template: 'The swap backend did not queue the shadow request.',\n params: {},\n },\n SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS: {\n phase: 'pre_send',\n template:\n 'A shadow submission needs a walletAddress (the X-Wallet-Address header): pass one to the GSwap constructor or to this call.',\n params: {},\n },\n METHOD_NOT_ALLOWED: {\n phase: 'post_send',\n template: 'The gateway does not expose this contract method: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SIGNATURE_INVALID: {\n phase: 'post_send',\n template: 'The gateway could not verify the signature: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SIGNER_MISMATCH: {\n phase: 'post_send',\n template:\n 'The recovered signer does not match an actor named by the operation: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n DTO_INVALID: {\n phase: 'post_send',\n template: 'The gateway rejected the DTO shape: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n BOUNDS_VIOLATION: {\n phase: 'post_send',\n template: 'The gateway rejected a numeric, tick, symbol or range bound: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SYMBOL_CONFLICT: {\n phase: 'post_send',\n template: 'The CreatePool symbol is already owned by another class: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n RATE_LIMITED: {\n phase: 'post_send',\n template: 'The gateway rate-limited this signer: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n CHAIN_DISPATCH_FAILED: {\n phase: 'post_send',\n template: 'The chain dispatch failed (chain error key \"{errorKey}\"): {serverMessage}',\n params: { errorKey: 'string', serverMessage: 'string' },\n },\n GATEWAY_REJECTED: {\n phase: 'post_send',\n template: 'Gateway rejected {gatewayCode}: {serverMessage}',\n params: { gatewayCode: 'string', serverMessage: 'string' },\n },\n CHAIN_REJECTED: {\n phase: 'post_send',\n template: 'GalaChain error {errorKey}: {serverMessage}',\n params: { errorKey: 'string', serverMessage: 'string' },\n },\n INVALID_CHAIN_RESPONSE: {\n phase: 'post_send',\n template: 'Backend returned an invalid {resource}.',\n params: { resource: 'string' },\n },\n INVALID_POSITION_RESPONSE: {\n phase: 'post_send',\n template: 'Backend returned an invalid position ({reason}).',\n params: { reason: 'string' },\n },\n\n // -------------------------------------------------------------------------------- confirmation\n CONFIRMATION_TIMEOUT: {\n phase: 'post_send',\n template:\n 'Transaction confirmation timed out; the trade may still apply. Confirm the same uniqueKey again later instead of resubmitting.',\n params: {},\n },\n CONFIRMATION_ABORTED: {\n phase: 'post_send',\n template: 'Transaction confirmation was aborted.',\n params: {},\n },\n CONFIRMATION_FAILED: {\n phase: 'post_send',\n template: 'Transaction confirmation failed with HTTP {status}.',\n params: { status: 'number', serverMessage: 'string' },\n unrendered: ['serverMessage'],\n },\n CONFIRMATION_MALFORMED: {\n phase: 'post_send',\n template: 'Transaction confirmation returned a malformed body.',\n params: {},\n },\n CONFIRMATION_KEY_MISMATCH: {\n phase: 'post_send',\n template: 'Apply result key did not match the requested key.',\n params: {},\n },\n\n // ----------------------------------------------------------------------------------- services\n NO_SIGNER: {\n phase: 'pre_send',\n template: 'This method requires a signer. Please provide a signer to the GSwap constructor.',\n params: {},\n },\n NO_WALLET_ADDRESS: {\n phase: 'post_send',\n template:\n 'Cannot confirm this write: no walletAddress was provided to the GSwap constructor, so the resulting position cannot be looked up to confirm it landed on chain.',\n params: {},\n },\n NO_POOL_AVAILABLE: {\n phase: 'post_send',\n template: 'No pool is available for {tokenIn}/{tokenOut} (fee tier {fee}).',\n params: { tokenIn: 'string', tokenOut: 'string', fee: 'string' },\n },\n INSUFFICIENT_LIQUIDITY: {\n phase: 'post_send',\n template:\n 'The selected pool has insufficient liquidity for {tokenIn}/{tokenOut} (fee tier {fee}).',\n params: { tokenIn: 'string', tokenOut: 'string', fee: 'string' },\n },\n UNKNOWN_TOKEN: {\n phase: 'pre_send',\n template: 'Token {token} is not registered on the DEX contract: it has no trading symbol.',\n params: { token: 'string' },\n },\n SYMBOL_NOT_FOUND: {\n phase: 'pre_send',\n template: 'Token {token} could not be resolved to a trading symbol.',\n params: { token: 'string' },\n },\n STREAM_API_KEY_UNUSABLE: {\n phase: 'pre_send',\n template:\n 'GdexStreamConfig.apiKey needs a non-empty key and an explicit webSocketImpl that accepts upgrade headers as its third argument (the \"ws\" package, or React Native). A browser WebSocket cannot send x-api-key, so the key would be silently dropped.',\n params: {},\n },\n STREAM_WEBSOCKET_UNAVAILABLE: {\n phase: 'pre_send',\n template:\n 'GdexStreamService requires a standards-compatible WebSocket constructor. Node.js versions before 22 must provide one with config.webSocketImpl (for example, from the \"ws\" package).',\n params: {},\n },\n STREAM_NOT_CONNECTED: {\n phase: 'pre_send',\n template: 'GDEX stream is not connected. Call connect() first.',\n params: {},\n },\n STREAM_DISCONNECTED: {\n phase: 'in_flight',\n template: 'GDEX stream disconnected.',\n params: {},\n },\n STREAM_REQUEST_TIMEOUT: {\n phase: 'in_flight',\n template: 'GDEX request \"{method}\" timed out after {timeoutMs} ms.',\n params: { method: 'string', timeoutMs: 'number' },\n },\n STREAM_CONNECT_FAILED: {\n phase: 'in_flight',\n template: 'Failed to connect to GDEX stream at {url}.',\n params: { url: 'string' },\n },\n STREAM_CLOSED_BEFORE_CONNECT: {\n phase: 'in_flight',\n template: 'GDEX stream closed before connecting (code {closeCode}).',\n params: { closeCode: 'number' },\n },\n STREAM_CONNECTION_CLOSED: {\n phase: 'in_flight',\n template: 'GDEX stream connection closed (code {closeCode}).',\n params: { closeCode: 'number' },\n },\n\n // ------------------------------------------------------------------------------ wallet / keys\n GALA_WALLET_NOT_AVAILABLE: {\n phase: 'pre_send',\n template: 'Gala wallet is not available. Please ensure the Gala wallet is connected.',\n params: {},\n },\n WALLET_UNAVAILABLE: {\n phase: 'pre_send',\n template: 'No wallet is connected.',\n params: {},\n },\n MALFORMED_WALLET_REQUEST: {\n phase: 'pre_send',\n template: 'Wallet {method} request is malformed.',\n params: { method: 'string' },\n },\n UNSUPPORTED_WALLET_METHOD: {\n phase: 'pre_send',\n template: 'Unsupported wallet method {method}.',\n params: { method: 'string' },\n },\n INVALID_SIGNATURE: {\n phase: 'pre_send',\n template: 'Wallet returned an invalid {scheme} signature.',\n params: { scheme: 'string' },\n },\n INVALID_CHAIN_ID: {\n phase: 'pre_send',\n template: 'Wallet returned an invalid chain id ({chainId}).',\n params: { chainId: 'string' },\n },\n SIGNER_ADDRESS_MISMATCH: {\n phase: 'pre_send',\n template: 'The signing key does not belong to the expected account.',\n params: {},\n },\n INVALID_PRIVATE_KEY: {\n phase: 'pre_send',\n template: 'Invalid private key: {reason}.',\n params: { reason: INVALID_PRIVATE_KEY_REASONS },\n },\n SIGNING_FAILED: {\n phase: 'pre_send',\n template: 'Signing the {method} request failed ({reason}); nothing was sent.',\n params: { method: 'string', reason: SIGNING_FAILURE_REASONS },\n },\n KEY_PROVIDER_FAILED: {\n phase: 'pre_send',\n template: 'The signing key could not be fetched; nothing was sent.',\n params: {},\n },\n TOKEN_RESOLUTION_FAILED: {\n phase: 'pre_send',\n template: 'Token {token} could not be looked up; nothing was sent.',\n params: { token: 'string' },\n },\n INVALID_SIGNING_HASH_LENGTH: {\n phase: 'pre_send',\n template: 'secp256k1 can only sign a 32-byte hash (got {length}).',\n params: { length: 'number' },\n },\n MISSING_WALLET_ADDRESS: {\n phase: 'pre_send',\n template:\n 'Invalid wallet address: No wallet address provided. Either provide a wallet address to the function you are calling, or set one when instantiating GSwapSDK.',\n params: {},\n },\n INVALID_WALLET_ADDRESS: {\n phase: 'pre_send',\n template: 'Invalid {field}: \"{value}\" is not an accepted wallet address form.',\n params: { field: 'string', value: 'string' },\n },\n INVALID_DECIMAL: {\n phase: 'pre_send',\n template: 'Invalid decimal quantity: {value}',\n params: { value: 'string' },\n },\n\n // ------------------------------------------------------------------------- personal-sign DTOs\n PERSONAL_SIGN_NOT_JSON: {\n phase: 'pre_send',\n template: 'Personal-sign DTO is not valid JSON',\n params: {},\n },\n PERSONAL_SIGN_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Personal-sign DTO must be a JSON object',\n params: {},\n },\n PERSONAL_SIGN_BAD_PREFIX: {\n phase: 'pre_send',\n template: 'Personal-sign DTO prefix is not an EIP-191 \"Ethereum Signed Message\" header',\n params: {},\n },\n PERSONAL_SIGN_ENVELOPE_FIELDS: {\n phase: 'pre_send',\n template: 'Personal-sign DTO carries signing-envelope field(s): {fields}',\n params: { fields: 'string' },\n },\n PERSONAL_SIGN_NOT_CANONICAL: {\n phase: 'pre_send',\n template: 'Personal-sign DTO is not in canonical serialized form',\n params: {},\n },\n\n // ------------------------------------------------------------------ EIP-712 payload derivation\n EIP712_NAME_COLLISION: {\n phase: 'pre_send',\n template: 'Name collisions are not supported when deriving EIP-712 types ({name}).',\n params: { name: 'string' },\n },\n EIP712_UNSUPPORTED_VALUE: {\n phase: 'pre_send',\n template: 'Unsupported EIP-712 value of type {valueType}.',\n params: { valueType: 'string' },\n },\n\n // ----------------------------------------------------------------------------- EIP-712 typed data\n TYPED_DATA_NOT_STRING: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be a string',\n params: { what: 'string' },\n },\n TYPED_DATA_UNPAIRED_SURROGATE: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} has an unpaired surrogate',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_HEX_BYTES: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be an even-length 0x hex string',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_SAFE_INTEGER: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be a safe integer',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_INTEGER: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be an integer',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_BOOLEAN: {\n phase: 'pre_send',\n template: 'Invalid typed data: bool must be a boolean',\n params: {},\n },\n TYPED_DATA_BAD_ADDRESS: {\n phase: 'pre_send',\n template: 'Invalid typed data: address must be 0x followed by 40 hex digits',\n params: {},\n },\n TYPED_DATA_BAD_CHECKSUM: {\n phase: 'pre_send',\n template: 'Invalid typed data: address has a bad checksum',\n params: {},\n },\n TYPED_DATA_BYTES_LENGTH: {\n phase: 'pre_send',\n template: 'Invalid typed data: {type} must be exactly {width} bytes',\n params: { type: 'string', width: 'number' },\n },\n TYPED_DATA_OUT_OF_BOUNDS: {\n phase: 'pre_send',\n template: 'Invalid typed data: value out of bounds for {type}',\n params: { type: 'string' },\n },\n TYPED_DATA_UNSUPPORTED_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: unsupported type \"{type}\"',\n params: { type: 'string' },\n },\n TYPED_DATA_FIELDS_NOT_LIST: {\n phase: 'pre_send',\n template: 'Invalid typed data: type {typeName} must be a list of fields',\n params: { typeName: 'string' },\n },\n TYPED_DATA_FIELD_MALFORMED: {\n phase: 'pre_send',\n template: 'Invalid typed data: type {typeName} has a field without a string name and type',\n params: { typeName: 'string' },\n },\n TYPED_DATA_INVALID_FIELD_NAME: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid field name \"{name}\"',\n params: { name: 'string' },\n },\n TYPED_DATA_DUPLICATE_FIELD: {\n phase: 'pre_send',\n template: 'Invalid typed data: duplicate field \"{name}\" in {typeName}',\n params: { name: 'string', typeName: 'string' },\n },\n TYPED_DATA_INVALID_TYPE_NAME: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid type name \"{name}\"',\n params: { name: 'string' },\n },\n TYPED_DATA_CIRCULAR_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: circular type reference in {typeName}',\n params: { typeName: 'string' },\n },\n TYPED_DATA_UNKNOWN_FIELD_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: unknown type \"{type}\" in {typeName}',\n params: { type: 'string', typeName: 'string' },\n },\n TYPED_DATA_NO_PRIMARY_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: missing primary type',\n params: {},\n },\n TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: ambiguous primary types or unused types ({roots})',\n params: { roots: 'string' },\n },\n TYPED_DATA_ARRAY_EXPECTED: {\n phase: 'pre_send',\n template: 'Invalid typed data: {type} array value must be an array',\n params: { type: 'string' },\n },\n TYPED_DATA_ARRAY_LENGTH_MISMATCH: {\n phase: 'pre_send',\n template: 'Invalid typed data: array length mismatch',\n params: {},\n },\n TYPED_DATA_STRUCT_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Invalid typed data: {typeName} value must be an object',\n params: { typeName: 'string' },\n },\n TYPED_DATA_MISSING_FIELD: {\n phase: 'pre_send',\n template: 'Invalid typed data: {typeName} value is missing field \"{field}\"',\n params: { typeName: 'string', field: 'string' },\n },\n TYPED_DATA_DOMAIN_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Invalid typed data: domain must be an object',\n params: {},\n },\n TYPED_DATA_INVALID_DOMAIN_KEY: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid typed-data domain key {key}',\n params: { key: 'string' },\n },\n\n // ------------------------------------------------------------------------ input validation\n NON_CANONICAL_PAIR: {\n phase: 'pre_send',\n template:\n 'The pair {token0}/{token1} is not in canonical order: token0 must sort before token1.',\n params: { token0: 'string', token1: 'string' },\n },\n UNORDERABLE_SYMBOLS: {\n phase: 'pre_send',\n template: 'Unable to order trading symbols: expected a pair of symbols, got {received}.',\n params: { received: 'string' },\n },\n INVALID_TOKEN_CLASS_KEY: {\n phase: 'pre_send',\n template:\n 'Invalid token class key \"{tokenClassKey}\": expected a collection followed by category, type and additionalKey',\n params: { tokenClassKey: 'string' },\n },\n INCOMPLETE_TOKEN_CLASS_KEY: {\n phase: 'pre_send',\n template: 'Token class key \"{compositeKey}\" is missing {part}.',\n params: { compositeKey: 'string', part: 'string' },\n },\n INVALID_TRADING_SYMBOL: {\n phase: 'pre_send',\n template:\n 'Invalid trading symbol \"{symbol}\": must be 1-32 ASCII letters and digits and not a reserved word (Token, Unit, none).',\n params: { symbol: 'string' },\n },\n NO_VALID_TRADING_SYMBOL: {\n phase: 'pre_send',\n template:\n 'No valid trading symbol for token class {classKey}: \"{displaySymbol}\" is not an acceptable symbol and none is registered',\n params: { classKey: 'string', displaySymbol: 'string' },\n },\n TOKEN_SYMBOL_NOT_REGISTERED: {\n phase: 'pre_send',\n template:\n 'Token {token} is not registered in the trading-symbol registry yet; pass token0Symbol/token1Symbol (the token class symbol) to propose one. A symbol cannot be derived from a class key.',\n params: { token: 'string' },\n },\n SYMBOL_DISAGREES_WITH_REGISTRY: {\n phase: 'pre_send',\n template:\n 'Supplied symbol {suppliedSymbol} for {token} disagrees with the registered trading symbol {registeredSymbol}.',\n params: { token: 'string', suppliedSymbol: 'string', registeredSymbol: 'string' },\n },\n CREATE_POOL_NEEDS_CLASS_KEY: {\n phase: 'pre_send',\n template:\n 'createPool needs each token as a class key; {token} is a bare trading symbol, which does not carry one.',\n params: { token: 'string' },\n },\n INVALID_UNIQUE_KEY: {\n phase: 'pre_send',\n template:\n 'The uniqueKey \"{uniqueKey}\" must be 1-128 characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n params: { uniqueKey: 'string' },\n },\n INVALID_UNIQUE_KEY_PREFIX: {\n phase: 'pre_send',\n template:\n 'uniqueKeyPrefix \"{uniqueKeyPrefix}\" must be at most {maxLength} characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n params: { uniqueKeyPrefix: 'string', maxLength: 'number' },\n },\n AMOUNT_IS_JS_NUMBER: {\n phase: 'pre_send',\n template: 'Invalid {field}: use a decimal string or BigNumber, not a JavaScript number',\n params: { field: 'string' },\n },\n AMOUNT_NOT_FINITE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be a finite number (got {value})',\n params: { field: 'string', value: 'string' },\n },\n AMOUNT_NOT_POSITIVE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be positive (got {value})',\n params: { field: 'string', value: 'string' },\n },\n AMOUNT_NEGATIVE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must not be negative (got {value})',\n params: { field: 'string', value: 'string' },\n },\n PRICE_VALUES_IS_JS_NUMBER: {\n phase: 'pre_send',\n template:\n 'Invalid price values: use decimal strings or BigNumber values, not JavaScript numbers',\n params: {},\n },\n INVALID_PRICE_VALUES: {\n phase: 'pre_send',\n template:\n 'Invalid price values: all prices must be finite and positive (spot {spotPrice}, lower {lowerPrice}, upper {upperPrice})',\n params: { spotPrice: 'string', lowerPrice: 'string', upperPrice: 'string' },\n },\n INVALID_PRICE_RANGE: {\n phase: 'pre_send',\n template:\n 'Invalid price range: lower price {lowerPrice} must be less than or equal to upper price {upperPrice}',\n params: { lowerPrice: 'string', upperPrice: 'string' },\n },\n INVALID_PRICE_BOUNDS: {\n phase: 'pre_send',\n template:\n 'Price bounds must be finite and positive (minPrice {minPrice}, maxPrice {maxPrice}).',\n params: { minPrice: 'string', maxPrice: 'string' },\n },\n PRICE_BOUNDS_ORDER: {\n phase: 'pre_send',\n template: 'minPrice {minPrice} must be less than or equal to maxPrice {maxPrice}.',\n params: { minPrice: 'string', maxPrice: 'string' },\n },\n INVALID_STARTING_PRICE: {\n phase: 'pre_send',\n template: 'Starting price must be finite and positive (got {value}).',\n params: { value: 'string' },\n },\n INVALID_SQRT_PRICE: {\n phase: 'pre_send',\n template: 'Cannot invert a non-positive sqrt price ({sqrtPrice}).',\n params: { sqrtPrice: 'string' },\n },\n INVALID_TOKEN_DECIMALS: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be a non-negative integer (got {value})',\n params: { field: 'string', value: 'number' },\n },\n TICKS_NOT_INTEGERS: {\n phase: 'pre_send',\n template: 'Invalid tick values: ticks must be integers (got {tickLower} and {tickUpper})',\n params: { tickLower: 'number', tickUpper: 'number' },\n },\n INVALID_TICK_RANGE: {\n phase: 'pre_send',\n template: 'Invalid tick range: tickLower {tickLower} must be less than tickUpper {tickUpper}',\n params: { tickLower: 'number', tickUpper: 'number' },\n },\n TICKS_OUT_OF_BOUNDS: {\n phase: 'pre_send',\n template:\n 'Invalid tick range: ticks {tickLower} and {tickUpper} must be between {minTick} and {maxTick}',\n params: { tickLower: 'number', tickUpper: 'number', minTick: 'number', maxTick: 'number' },\n },\n TICKS_NOT_ALIGNED: {\n phase: 'pre_send',\n template: 'Ticks {tickLower} and {tickUpper} must be aligned to spacing {spacing}.',\n params: { tickLower: 'number', tickUpper: 'number', spacing: 'number' },\n },\n INVALID_TICK_SPACING: {\n phase: 'pre_send',\n template: 'Invalid tick spacing: must be a positive integer (got {value})',\n params: { value: 'number' },\n },\n INVALID_FEE: {\n phase: 'pre_send',\n template: 'Invalid {field}: {value} is not a supported fee tier; must be one of {allowed}.',\n params: { field: 'string', value: 'number', allowed: 'string' },\n },\n EXACT_AMOUNT_REQUIRED: {\n phase: 'pre_send',\n template: '{field} is required for this swap.',\n params: { field: 'string' },\n },\n EXACTLY_ONE_OF_REQUIRED: {\n phase: 'pre_send',\n template: 'Provide exactly one of {first} or {second}.',\n params: { first: 'string', second: 'string' },\n },\n AT_MOST_ONE_OF_ALLOWED: {\n phase: 'pre_send',\n template: 'Provide at most one of {first} or {second}.',\n params: { first: 'string', second: 'string' },\n },\n POOL_MISMATCH: {\n phase: 'pre_send',\n template:\n 'tokenIn {tokenIn} and tokenOut {tokenOut} must be the two tokens of the pinned pool {poolToken0}/{poolToken1}.',\n params: {\n tokenIn: 'string',\n tokenOut: 'string',\n poolToken0: 'string',\n poolToken1: 'string',\n },\n },\n INVALID_DTO: {\n phase: 'pre_send',\n template: '{method} DTO field {field} is invalid (expected {expected}).',\n params: { method: 'string', field: 'string', expected: 'string' },\n },\n DTO_NOT_CANONICAL: {\n phase: 'pre_send',\n template:\n 'The {method} DTO is not in the form the SDK builders produce; build it with the matching build function and submit that.',\n params: { method: 'string' },\n },\n SEARCH_TOO_LONG: {\n phase: 'pre_send',\n template: 'search must be at most {maxLength} characters (got {length}).',\n params: { length: 'number', maxLength: 'number' },\n },\n INVALID_SORT_BY: {\n phase: 'pre_send',\n template: 'sortBy \"{value}\" is not allowed; it must be one of {allowed}.',\n params: { value: 'string', allowed: 'string' },\n },\n INVALID_SORT_ORDER: {\n phase: 'pre_send',\n template: 'sortOrder \"{value}\" is not allowed; it must be asc or desc.',\n params: { value: 'string' },\n },\n INVALID_PAGE: {\n phase: 'pre_send',\n template: 'page must be an integer of at least 1 (got {value}).',\n params: { value: 'number' },\n },\n INVALID_LIMIT: {\n phase: 'pre_send',\n template: 'limit must be an integer from {min} to {max} (got {value}).',\n params: { value: 'number', min: 'number', max: 'number' },\n },\n} as const satisfies Record<string, GSwapErrorCatalogEntry>;\n\n/** Every error code the SDK can throw. */\nexport type GSwapErrorCode = keyof typeof GSWAP_ERROR_CATALOG;\n\ninterface KindToType {\n string: string;\n number: number;\n boolean: boolean;\n}\n\n/** The value type of a param kind: a primitive, or the union of a closed set's members. */\ntype ParamValue<K> = K extends readonly (infer Member)[]\n ? Member\n : K extends keyof KindToType\n ? KindToType[K]\n : never;\n\n/** The named params of one error code: a flat object of primitives (or closed string tokens). */\nexport type GSwapErrorParams<C extends GSwapErrorCode> = {\n readonly [P in keyof (typeof GSWAP_ERROR_CATALOG)[C]['params']]: ParamValue<\n (typeof GSWAP_ERROR_CATALOG)[C]['params'][P]\n >;\n};\n\n/**\n * The English template of every error code, `{placeholder}` markers included. An optional seed\n * or fallback for an app's own translations; the SDK's `message` is generated from it.\n */\nexport const gswapErrorTemplates: { readonly [C in GSwapErrorCode]: string } = Object.fromEntries(\n Object.entries(GSWAP_ERROR_CATALOG).map(([code, entry]) => [code, entry.template]),\n) as { readonly [C in GSwapErrorCode]: string };\n\nconst PLACEHOLDER = /\\{([A-Za-z0-9_]+)\\}/gu;\n\n/** Fills a template's `{placeholders}` from `params`; an unknown placeholder is left as written. */\nexport function renderGSwapErrorTemplate(\n template: string,\n params: Readonly<Record<string, unknown>>,\n): string {\n return template.replace(PLACEHOLDER, (whole, name: string) => {\n const value = params[name];\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n ? String(value)\n : whole;\n });\n}\n\n/** The placeholder names a template uses, in order of first appearance. */\nexport function templatePlaceholders(template: string): string[] {\n return [...new Set([...template.matchAll(PLACEHOLDER)].map((match) => match[1] as string))];\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { HTTPResponse } from '../types/http_requestor.js';\nimport { GSWAP_ERROR_BRAND } from '../utils/error_brand.js';\nimport { toFailureView } from '../utils/failure_view.js';\nimport { phaseOfView } from './error_phase_table.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport {\n GSWAP_ERROR_CATALOG,\n renderGSwapErrorTemplate,\n type GSwapErrorCode,\n type GSwapErrorParams,\n} from './error_catalog.js';\nimport type { GSwapErrorPhase } from './error_phases.js';\n\n/**\n * The HTTP status of a version wall: the backend refuses an app version that is too old (HTTP 426\n * Upgrade Required). It is `UPDATE_REQUIRED` on every request the SDK sends, whatever else the body\n * says; a confirmation read keeps `CONFIRMATION_FAILED` because the write it confirms may be applied.\n */\nexport const UPDATE_REQUIRED_STATUS = 426;\n\n/**\n * The facts of an error that are not placeholders of its message: where it happened and what the\n * server said. All optional; none is localized text.\n */\nexport interface GSwapErrorContext {\n /** The HTTP status of the response that caused the error. */\n status?: number | undefined;\n /**\n * The response body: parsed JSON when the failing response had it, else the raw text (which\n * the error then exposes as {@link GSwapSDKError.bodyText}).\n */\n body?: unknown;\n /** The URL the failing request went to. */\n url?: string | undefined;\n /** The `uniqueKey` of the write this error is about: the handle for `confirm()` and recovery. */\n uniqueKey?: string | undefined;\n /** The transaction id of the queued request, `null` when unknown. */\n requestTransactionId?: string | null | undefined;\n /** The transaction id of the apply, `null` when unknown. */\n applyTransactionId?: string | null | undefined;\n /** The block the apply landed in, `null` when unknown. */\n blockNumber?: number | null | undefined;\n /** How long to wait before retrying, from the server's `Retry-After`. */\n retryAfterMs?: number | undefined;\n /** The error that caused this one (a transport failure, a wallet rejection). */\n cause?: unknown;\n /**\n * The phase of THIS occurrence when it differs from the code's catalog phase (see\n * {@link GSwapErrorPhase}): for example `UNKNOWN_TOKEN` is `pre_send` from the symbol registry\n * but `post_send` when it is derived from a quote answer.\n */\n phase?: GSwapErrorPhase | undefined;\n /** True when the failing operation was on the shadow (dark) path; see {@link GSwapSDKError.shadow}. */\n shadow?: boolean | undefined;\n /**\n * `false` for the failure of a READ (see {@link GSwapSDKError.write}); anything else, including\n * absent, is a write (fail-closed). Ignored when `uniqueKey` is set: that is a write.\n */\n write?: boolean | undefined;\n /** The wallet's own code on the error a signer threw; see {@link GSwapSDKError.walletCode}. */\n walletCode?: number | string | undefined;\n}\n\n/** What {@link GSwapSDKError.fromStatus} may be told about the HTTP answer. */\nexport interface GSwapStatusErrorOptions {\n /** The URL the request went to. */\n url?: string | undefined;\n /** The signed `uniqueKey` of the WRITE the answer is for; its presence makes this a write. */\n uniqueKey?: string | undefined;\n /** Say it outright: `true` for a write (needs `uniqueKey`), `false` for a read. */\n write?: boolean | undefined;\n /** The server's own text, for `HTTP_ERROR.params.serverMessage` (`''` when none). */\n serverMessage?: string | undefined;\n /** The response body, kept as `error.body` (or `bodyText` for a string). */\n body?: unknown;\n /** How long the server asked to wait (`Retry-After`), in milliseconds. */\n retryAfterMs?: number | undefined;\n}\n\n/**\n * Error raised by the SDK for validation, gateway, chain, or transaction failures.\n *\n * Branch on {@link code} (stable) and render {@link params} through your own localization.\n * {@link message} is English generated from the catalog template for logs and developers: it\n * is not stable and must never be shown to a user or matched on.\n */\nexport class GSwapSDKError<C extends GSwapErrorCode = GSwapErrorCode> extends Error {\n /** The stable, machine-readable code. */\n public readonly code: C;\n /** The named placeholders of the error: a flat object of primitives, safe to localize with. */\n public readonly params: GSwapErrorParams<C>;\n public readonly retryAfterMs: number | undefined;\n /** The HTTP status of the response that caused this error, when there was one. */\n public readonly status: number | undefined;\n /**\n * The response body parsed as JSON, when the failing response had one; `undefined` for a body\n * that was not JSON (see {@link bodyText}). Never part of {@link message}.\n */\n public readonly body: unknown;\n /**\n * The raw text of a failing response whose body was NOT JSON (a proxy's HTML 502, a WAF page,\n * an empty body). It is kept here for diagnostics and is never copied into {@link message},\n * so it cannot reach a user interface by accident.\n */\n public readonly bodyText: string | undefined;\n /** The URL the failing request went to, when there was one. */\n public readonly url: string | undefined;\n /** The `uniqueKey` of the write this error is about, when there is one. */\n public readonly uniqueKey: string | undefined;\n /** The transaction id of the queued request, when known. */\n public readonly requestTransactionId: string | null | undefined;\n /** The transaction id of the apply, when known. */\n public readonly applyTransactionId: string | null | undefined;\n /** The block the apply landed in, when known. */\n public readonly blockNumber: number | null | undefined;\n /**\n * How far the operation had got when this was thrown, against the request it exists to send\n * (see {@link GSwapErrorPhase}): `pre_send` means NOTHING was transmitted, so a write that\n * failed this way cannot have been queued; `in_flight` means the request left and no answer was\n * read; `post_send` means an answer was read or the write was already accepted. Every catalog\n * code declares its phase, and a throw site can refine it. Read it with\n * {@link isPreSendError}; `classifyFailure` already folds it into `outcome` and `retryable`.\n */\n public readonly phase: GSwapErrorPhase;\n /**\n * True when this error came from the shadow (dark) path: `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`, whatever failed there (a validation error, the signer, the\n * transport, `SHADOW_NOT_QUEUED`). The classification is the same as on the public path; this\n * is how an app applies its own dark-swap policy (the wallet and frontend_v2 never offer a\n * public fallback or Retry after one). A shadow gateway refusal that RESOLVES (`{ ok: false }`)\n * is not an error and has no flag: the call itself says it was shadow.\n */\n public readonly shadow: boolean;\n /**\n * Whether this failure is a WRITE's, as the guards read it: `false` only for the failure of a\n * READ (a quote, a pool list, an apply-results read), which has no `uniqueKey` to confirm and\n * nothing pending, so a 5xx there is `transient` and retryable. It is `true` for everything else,\n * and always when {@link uniqueKey} is set. That is fail-closed: a failure that does not say it\n * is a read is judged a write, where a 5xx is `unknown` and never retried. Apps that carry an\n * error through their own wrapper copy this field next to `uniqueKey` (`FailureView.write`).\n */\n public readonly write: boolean;\n /**\n * On `SIGNING_FAILED`: the code the wallet put on the error its signer threw, when it set one: an\n * EIP-1193 / JSON-RPC number such as `4001` (the person declined) or `-32603`, or an ethers /\n * viem string such as `'ACTION_REJECTED'`. It is read from the `cause`'s own `code` and is\n * always a short primitive; `undefined` when the wallet sent none, and on every other code. It is\n * a typed field, not a param: it is data for an app's analytics or its own wallet-specific\n * wording, never part of `message`, and `params.reason` stays the stable thing to branch on.\n */\n public readonly walletCode: number | string | undefined;\n\n constructor(code: C, params: GSwapErrorParams<C>, context: GSwapErrorContext = {}) {\n super(\n renderGSwapErrorTemplate(GSWAP_ERROR_CATALOG[code].template, params),\n context.cause === undefined ? undefined : { cause: context.cause },\n );\n this.name = 'GSwapSDKError';\n this.code = code;\n this.params = params;\n this.retryAfterMs = context.retryAfterMs;\n this.status = context.status;\n this.body = typeof context.body === 'string' ? undefined : context.body;\n this.bodyText = typeof context.body === 'string' ? context.body : undefined;\n this.url = context.url;\n this.uniqueKey = context.uniqueKey;\n this.requestTransactionId = context.requestTransactionId;\n this.applyTransactionId = context.applyTransactionId;\n this.blockNumber = context.blockNumber;\n this.phase = context.phase ?? GSWAP_ERROR_CATALOG[code].phase;\n this.shadow = context.shadow ?? false;\n this.write =\n context.uniqueKey !== undefined && context.uniqueKey !== '' ? true : context.write !== false;\n this.walletCode = context.walletCode;\n }\n\n /**\n * The SDK error brand (`Symbol.for('@gala-chain/gswap-sdk/error')`), always `true`. The\n * dependency-free helpers (`isWalletUserRejection`, `isGSwapErrorLike`) recognise an SDK error\n * by it instead of `instanceof`, so they work across copies of the SDK and without importing\n * this class. It lives on the prototype: it is not an own property and is never copied or logged.\n */\n public get [GSWAP_ERROR_BRAND](): true {\n return true;\n }\n\n /**\n * True when the failure means \"that market, pool or position does not exist\" rather than\n * \"something went wrong\": an HTTP 404, a pair with no pool at any fee tier\n * (`NO_POOL_AVAILABLE`), or a token the DEX contract has no trading symbol for\n * (`UNKNOWN_TOKEN`). A pool that exists but is too thin (`INSUFFICIENT_LIQUIDITY`) is NOT\n * not-found.\n */\n public get notFound(): boolean {\n return (\n this.status === 404 || this.code === 'NO_POOL_AVAILABLE' || this.code === 'UNKNOWN_TOKEN'\n );\n }\n\n /** Create the standard missing-signer error. */\n public static noSignerError(): GSwapSDKError<'NO_SIGNER'> {\n return new GSwapSDKError('NO_SIGNER', {});\n }\n\n /** Create the error used when confirming a position write without a configured wallet address. */\n public static noWalletAddressError(): GSwapSDKError<'NO_WALLET_ADDRESS'> {\n return new GSwapSDKError('NO_WALLET_ADDRESS', {});\n }\n\n /**\n * Create the error used when no pool can quote the requested pair. `source` is the backend\n * answer that said so; its status and body are kept.\n */\n public static noPoolAvailableError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n source?: GSwapSDKError,\n ): GSwapSDKError<'NO_POOL_AVAILABLE'> {\n return new GSwapSDKError(\n 'NO_POOL_AVAILABLE',\n { tokenIn: tokenText(tokenIn), tokenOut: tokenText(tokenOut), fee: feeText(fee) },\n sourceContext(source),\n );\n }\n\n /** Create the error used when a pool lacks liquidity for a quote. `source` as for {@link noPoolAvailableError}. */\n public static insufficientLiquidityError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n source?: GSwapSDKError,\n ): GSwapSDKError<'INSUFFICIENT_LIQUIDITY'> {\n return new GSwapSDKError(\n 'INSUFFICIENT_LIQUIDITY',\n { tokenIn: tokenText(tokenIn), tokenOut: tokenText(tokenOut), fee: feeText(fee) },\n sourceContext(source),\n );\n }\n\n /**\n * Convert a chain-gateway bounce into a typed SDK error: the gateway's own code when the SDK\n * knows it, `GATEWAY_REJECTED` (with the code as `params.gatewayCode`) when it does not.\n * `serverMessage` is the gateway's English text: for logs, not for a user interface. For\n * `CHAIN_DISPATCH_FAILED`, `params.errorKey` is the chain's `ErrorKey` from the body's\n * top-level `errorKey` (`''` when the gateway sent none): map it, not the text.\n */\n public static fromGatewayBounce(\n gatewayCode: string,\n serverMessage: string,\n status: number,\n body: unknown,\n url: string,\n retryAfterMs?: number,\n uniqueKey?: string,\n ): GSwapSDKError {\n const context: GSwapErrorContext = { status, body, url, retryAfterMs, uniqueKey };\n const params = { serverMessage };\n switch (gatewayCode) {\n case 'METHOD_NOT_ALLOWED':\n return new GSwapSDKError('METHOD_NOT_ALLOWED', params, context);\n case 'SIGNATURE_INVALID':\n return new GSwapSDKError('SIGNATURE_INVALID', params, context);\n case 'SIGNER_MISMATCH':\n return new GSwapSDKError('SIGNER_MISMATCH', params, context);\n case 'DTO_INVALID':\n return new GSwapSDKError('DTO_INVALID', params, context);\n case 'BOUNDS_VIOLATION':\n return new GSwapSDKError('BOUNDS_VIOLATION', params, context);\n case 'SYMBOL_CONFLICT':\n return new GSwapSDKError('SYMBOL_CONFLICT', params, context);\n case 'RATE_LIMITED':\n return new GSwapSDKError('RATE_LIMITED', params, context);\n case 'CHAIN_DISPATCH_FAILED':\n // The gateway adds the chain's own machine-readable key as a top-level `errorKey`, only\n // when the chain supplied one; an older gateway sends none, which is the empty string.\n return new GSwapSDKError(\n 'CHAIN_DISPATCH_FAILED',\n { ...params, errorKey: getStringProperty(body, 'errorKey') ?? '' },\n context,\n );\n default:\n return new GSwapSDKError('GATEWAY_REJECTED', { gatewayCode, serverMessage }, context);\n }\n }\n\n /** Convert a GalaChain `Status: 0` response into a typed SDK error. */\n public static fromChainError(\n errorKey: string,\n serverMessage: string,\n context?: GSwapErrorContext,\n ): GSwapSDKError<'CHAIN_REJECTED'> {\n return new GSwapSDKError('CHAIN_REJECTED', { errorKey, serverMessage }, context);\n }\n\n /**\n * Create the error used when a token is not registered by the current DEX contract. `source` is\n * the backend answer that said so (a quote); its status, body and url are kept.\n */\n public static unknownTokenError(\n token: GalaChainTokenClassKey | string,\n source?: GSwapSDKError,\n ): GSwapSDKError<'UNKNOWN_TOKEN'> {\n return new GSwapSDKError('UNKNOWN_TOKEN', { token: tokenText(token) }, sourceContext(source));\n }\n\n /** Create the error used when apply-results confirmation does not arrive in time. */\n public static confirmationTimeoutError(\n uniqueKey: string,\n cause?: unknown,\n ): GSwapSDKError<'CONFIRMATION_TIMEOUT'> {\n return new GSwapSDKError('CONFIRMATION_TIMEOUT', {}, { uniqueKey, cause });\n }\n\n /**\n * Builds, synchronously, the error the SDK itself throws for an HTTP answer of this `status`\n * that has no gateway or chain code: `UPDATE_REQUIRED` for the version wall (426, whatever\n * else is true), `HTTP_ERROR` for every other status. It is for an app that holds a resolved\n * HTTP answer the SDK did not read (a v1 endpoint, an interceptor's rejection) and wants the\n * SDK's classification of it (`classifyFailure`) instead of building the error by hand.\n *\n * Reads and writes differ exactly as they do in the gateway (`classifyFailure`): a WRITE\n * carries the signed `uniqueKey` (the handle to confirm it), a READ carries none. Pass\n * `uniqueKey` for a write, or `write: true` with it; `write: false` builds a read and drops any\n * `uniqueKey`. `write: true` without a non-empty `uniqueKey` throws `INVALID_UNIQUE_KEY`: a\n * write error with no key would be classified as a read, which is a different answer. Either\n * way an answer was read, so the phase is `post_send`.\n *\n * @example\n * ```ts\n * const read = GSwapSDKError.fromStatus(503, { url });\n * classifyFailure(read); // { outcome: 'transient', retryable: true }\n * const write = GSwapSDKError.fromStatus(503, { url, uniqueKey });\n * classifyFailure(write); // { outcome: 'unknown', retryable: false }: it may have been queued\n * classifyFailure(GSwapSDKError.fromStatus(426)); // invalid_input: only an update helps\n * ```\n */\n public static fromStatus(\n status: number,\n options: GSwapStatusErrorOptions = {},\n ): GSwapSDKError<'UPDATE_REQUIRED' | 'HTTP_ERROR'> {\n const { url, uniqueKey, write, serverMessage, body, retryAfterMs } = options;\n const isWrite = write ?? (uniqueKey !== undefined && uniqueKey !== '');\n if (isWrite && (uniqueKey === undefined || uniqueKey === '')) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY', { uniqueKey: uniqueKey ?? '' });\n }\n const context: GSwapErrorContext = {\n status,\n body,\n url,\n retryAfterMs,\n uniqueKey: isWrite ? uniqueKey : undefined,\n write: isWrite,\n phase: 'post_send',\n };\n return status === UPDATE_REQUIRED_STATUS\n ? new GSwapSDKError('UPDATE_REQUIRED', { status }, context)\n : new GSwapSDKError(\n 'HTTP_ERROR',\n { status, url: url ?? '', serverMessage: serverMessage ?? '' },\n context,\n );\n }\n\n /** Convert an unexpected HTTP response into an SDK error. */\n public static async fromErrorResponse(\n url: string,\n response: HTTPResponse,\n ): Promise<GSwapSDKError> {\n const bodyText = await response.text();\n const bodyJson: unknown = parseJson(bodyText);\n const errorObject = getObjectProperty(bodyJson, 'error');\n const errorKey = getStringProperty(errorObject, 'ErrorKey');\n const message = getStringProperty(errorObject, 'Message');\n // Every request that goes through `HttpClient` is a READ (a quote, a list, an apply-results\n // GET); writes go through the gateway, which builds its own errors with the signed key.\n const context: GSwapErrorContext = {\n status: response.status,\n body: bodyJson ?? bodyText,\n url,\n write: false,\n };\n\n if (response.status === UPDATE_REQUIRED_STATUS) {\n return new GSwapSDKError('UPDATE_REQUIRED', { status: response.status }, context);\n }\n\n if (errorKey !== undefined && message !== undefined) {\n return new GSwapSDKError('CHAIN_REJECTED', { errorKey, serverMessage: message }, context);\n }\n\n return new GSwapSDKError(\n 'HTTP_ERROR',\n { status: response.status, url, serverMessage: serverMessageOfBody(bodyJson) },\n context,\n );\n }\n}\n\n/** A token as the text a param carries: a string as is, a class key as its `$` composite. */\nfunction tokenText(token: GalaChainTokenClassKey | string): string {\n return typeof token === 'string'\n ? token\n : [token.collection, token.category, token.type, token.additionalKey].join('$');\n}\n\nfunction feeText(fee: number | undefined): string {\n return fee === undefined ? 'any' : String(fee);\n}\n\n/**\n * The HTTP facts of the error a classified error was derived from. An error derived from a\n * backend answer is `post_send`: the answer was read.\n */\nfunction sourceContext(source: GSwapSDKError | undefined): GSwapErrorContext {\n if (source === undefined) return {};\n return {\n status: source.status,\n body: source.body ?? source.bodyText,\n url: source.url,\n phase: 'post_send',\n write: source.write,\n };\n}\n\n/** Any thrown value that is an SDK error, narrowed to the union of every code. */\nexport type AnyGSwapError = { [C in GSwapErrorCode]: GSwapSDKError<C> }[GSwapErrorCode];\n\n/**\n * True when `value` is an SDK error and, when `code` is given, carries exactly that code. With a\n * code, `error.params` narrows to that code's params.\n *\n * @example\n * ```ts\n * if (isGSwapError(error, 'NON_CANONICAL_PAIR')) {\n * t('errors.NON_CANONICAL_PAIR', error.params); // { token0, token1 }\n * }\n * ```\n */\nexport function isGSwapError(value: unknown): value is AnyGSwapError;\nexport function isGSwapError<C extends GSwapErrorCode>(\n value: unknown,\n code: C,\n): value is GSwapSDKError<C>;\nexport function isGSwapError(value: unknown, code?: GSwapErrorCode): boolean {\n return value instanceof GSwapSDKError && (code === undefined || value.code === code);\n}\n\n/**\n * True when `value` is an SDK error that was thrown BEFORE anything was transmitted\n * (`error.phase === 'pre_send'`): validation, symbol resolution, the signer, the wallet, a key\n * provider. A write that failed this way cannot have been queued, so the failure never calls for\n * \"confirm before you retry\". Every failure of an app-supplied callback that runs BEFORE the\n * request leaves reaches you as an SDK error of this kind (`SIGNING_FAILED`,\n * `KEY_PROVIDER_FAILED`, `TOKEN_RESOLUTION_FAILED`, the original error as `cause`), so an app\n * never needs an error class of its own to tell \"nothing was sent\" apart.\n *\n * Whether to offer Retry is `classifyFailure(error).retryable`, not this: a pre-send validation\n * error is pre-send too, and repeating the same call fails the same way.\n *\n * It also answers for a plain-object view of an SDK error (`{ code, phase? }`, see\n * `FailureView`): the view's own `phase`, else the catalog's phase for its `code`. It is a plain\n * `boolean`, not a type guard (a view is not a `GSwapSDKError`); use `isGSwapError` to narrow.\n *\n * @example\n * ```ts\n * if (isPreSendError(error)) markNothingSent(); // no pending swap to confirm\n * ```\n */\nexport function isPreSendError(value: unknown): boolean {\n const view = toFailureView(value);\n return view !== undefined && phaseOfView(view) === 'pre_send';\n}\n\n/** Narrow an object property without trusting a cast at a network boundary. */\nexport function getObjectProperty(\n value: unknown,\n property: string,\n): Record<string, unknown> | undefined {\n if (typeof value !== 'object' || value === null || !(property in value)) return undefined;\n const propertyValue = (value as Record<string, unknown>)[property];\n return typeof propertyValue === 'object' && propertyValue !== null\n ? (propertyValue as Record<string, unknown>)\n : undefined;\n}\n\n/** Read a string property from an unknown object. */\nexport function getStringProperty(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null || !(property in value)) return undefined;\n const propertyValue = (value as Record<string, unknown>)[property];\n return typeof propertyValue === 'string' ? propertyValue : undefined;\n}\n\n/** Parse a response body, preserving non-JSON text for error reporting. */\nexport function parseJson(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n","declare const __GSWAP_SDK_VERSION__: string | undefined;\n\n/** Package version embedded by the bundler, with a source-test fallback. */\nexport const SDK_VERSION =\n typeof __GSWAP_SDK_VERSION__ === 'string' ? __GSWAP_SDK_VERSION__ : '1.2.0-rc.8';\n","import type { HTTPResponse, HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { GSwapSDKError, parseJson } from '../classes/gswap_sdk_error.js';\nimport { SDK_VERSION } from '../version.js';\n\n/**\n * Arms the abort timer for a request. `Infinity` means \"never time out\": `setTimeout` would turn\n * it into 1 ms, so no timer is armed at all. Returns a function that disarms it.\n */\nexport function armTimeout(controller: AbortController, timeoutMs: number): () => void {\n if (timeoutMs === Infinity) return () => undefined;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n return () => clearTimeout(timer);\n}\n\n/**\n * Validates a request timeout in milliseconds: a positive finite number, or `Infinity` for none.\n *\n * @throws GSwapSDKError `INVALID_TIMEOUT` (`params.field` = `name`) otherwise.\n */\nexport function validateTimeoutMs(timeoutMs: number, name: string): number {\n if (timeoutMs === Infinity || (Number.isFinite(timeoutMs) && timeoutMs > 0)) return timeoutMs;\n throw new GSwapSDKError('INVALID_TIMEOUT', { field: name, value: timeoutMs });\n}\n\nconst READABLE_QUERY_SAFE = /[A-Za-z0-9\\-._~!'()*$|:,]/u;\n\nfunction encodeReadable(text: string): string {\n let out = '';\n for (const char of text) {\n if (char === ' ') out += '+';\n else if (READABLE_QUERY_SAFE.test(char)) out += char;\n else out += encodeScalar(char);\n }\n return out;\n}\n\n/** Percent-encodes one code point; a lone surrogate becomes U+FFFD, as `URLSearchParams` does. */\nfunction encodeScalar(char: string): string {\n try {\n return encodeURIComponent(char);\n } catch {\n return '%EF%BF%BD';\n }\n}\n\n/** Serializes GET parameters, in insertion order, in the encoding the wire options select. */\nexport function buildQueryString(\n params: Record<string, string>,\n encoding: WireOptions['queryEncoding'] = 'standard',\n): string {\n if (encoding === 'readable') {\n return Object.entries(params)\n .map(([key, value]) => `${encodeReadable(key)}=${encodeReadable(value)}`)\n .join('&');\n }\n return new URLSearchParams(params).toString();\n}\n\n/** What an SDK request adds to the headers the wire options describe. */\nexport interface RequestHeaderParts {\n /** The request carries a JSON body: `Content-Type: application/json` unless `wire.headers` sets one. */\n json?: boolean | undefined;\n /** Headers the SDK sends unless `wire.headers` replaces them (for example `Accept`). */\n defaults?: Record<string, string> | undefined;\n /**\n * Headers that carry the request's meaning (`X-Wallet-Address`, `X-Shadow`). They come last and\n * replace a same-named `wire.headers` entry, so an app's static headers can never re-attribute\n * or un-shadow a write.\n */\n fixed?: Record<string, string> | undefined;\n}\n\n/**\n * The request headers for ANY SDK request, GET or POST, from one place so the wire options reach\n * every request alike. Order, which is the order the requestor sees them in: `User-Agent`\n * (`wire.userAgent`, default `GalaChain-SDK/<version>`, `false` omits it), `parts.defaults`,\n * `wire.headers`, `Content-Type` (JSON bodies only), `parts.fixed`. A later entry replaces an\n * earlier one of the same name regardless of case, so a header is never sent twice.\n */\nexport function buildRequestHeaders(\n wire: WireOptions | undefined,\n parts: RequestHeaderParts = {},\n): Record<string, string> {\n const entries = new Map<string, [name: string, value: string]>();\n const put = (headers: Record<string, string> | undefined, last = false): void => {\n for (const [name, value] of Object.entries(headers ?? {})) {\n // A fixed header leaves any earlier same-named entry behind, so it also keeps its place at the end.\n if (last) entries.delete(name.toLowerCase());\n entries.set(name.toLowerCase(), [name, value]);\n }\n };\n if (wire?.userAgent !== false) {\n put({ 'User-Agent': wire?.userAgent ?? `GalaChain-SDK/${SDK_VERSION}` });\n }\n put(parts.defaults);\n put(wire?.headers);\n if (parts.json === true && !entries.has('content-type')) {\n put({ 'Content-Type': 'application/json' });\n }\n put(parts.fixed, true);\n return Object.fromEntries(entries.values());\n}\n\n/**\n * The default requestor: the global `fetch`, with a failure before any answer (offline, DNS,\n * CORS) coded as `TRANSPORT_ERROR` and the original error kept as `cause`. An aborted request is\n * left to {@link requestWithTimeout}, which knows whether the timeout or the caller aborted it.\n * A requestor the app supplies is not wrapped: its rejection reaches the caller unchanged.\n */\nexport const fetchRequestor: HttpRequestor = async (url, init) => {\n try {\n return await fetch(url, init);\n } catch (error: unknown) {\n if (init?.signal?.aborted === true) throw error;\n throw new GSwapSDKError('TRANSPORT_ERROR', { url }, { url, cause: error });\n }\n};\n\nexport async function requestWithTimeout(\n requestor: HttpRequestor,\n url: string,\n options: RequestInit,\n timeoutMs: number,\n): Promise<HTTPResponse> {\n const controller = new AbortController();\n const disarm = armTimeout(controller, timeoutMs);\n const externalSignal = options.signal;\n const abortFromCaller = (): void => controller.abort();\n externalSignal?.addEventListener('abort', abortFromCaller, { once: true });\n try {\n return await requestor(url, { ...options, signal: controller.signal });\n } catch (error: unknown) {\n // The caller's own abort is theirs: it passes through as the abort it is, never as a timeout.\n if (externalSignal?.aborted === true) throw error;\n if (controller.signal.aborted) {\n throw new GSwapSDKError('REQUEST_TIMEOUT', { url, timeoutMs }, { url, cause: error });\n }\n // Anything else is the requestor's own rejection (an app's axios interceptor error, say):\n // rethrown as it is, because the app's error handling produced it.\n throw error;\n } finally {\n disarm();\n externalSignal?.removeEventListener('abort', abortFromCaller);\n }\n}\n\nexport async function readResponseBody(response: HTTPResponse): Promise<unknown> {\n const text = await response.text();\n return parseJson(text) ?? text;\n}\n\n/** Read a case-insensitive response header from either supported header shape. */\nexport function readHeader(response: HTTPResponse, name: string): string | undefined {\n const headers = response.headers;\n if (headers === undefined) return undefined;\n if (hasHeaderGetter(headers)) {\n const value = headers.get(name);\n return value === null || value === '' ? undefined : value;\n }\n const value = Object.entries(headers).find(\n ([key]) => key.toLowerCase() === name.toLowerCase(),\n )?.[1];\n return value === undefined || value === '' ? undefined : value;\n}\n\n/** Read a Retry-After header (delta-seconds or an HTTP date) as non-negative milliseconds. */\nexport function readRetryAfter(response: HTTPResponse): number | undefined {\n const raw = readHeader(response, 'retry-after');\n if (raw === undefined) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const timestamp = Date.parse(raw);\n return Number.isNaN(timestamp) ? undefined : Math.max(0, timestamp - Date.now());\n}\n\n/** Read a non-negative integer block number header. */\nexport function readBlockNumberHeader(\n response: HTTPResponse,\n headerName = 'x-block-number',\n): number | undefined {\n const raw = readHeader(response, headerName);\n if (raw === undefined) return undefined;\n const blockNumber = Number(raw);\n return Number.isInteger(blockNumber) && blockNumber >= 0 ? blockNumber : undefined;\n}\n\nfunction hasHeaderGetter(\n headers: NonNullable<HTTPResponse['headers']>,\n): headers is { get(name: string): string | null } {\n return 'get' in headers && typeof headers.get === 'function';\n}\n","import type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport type { AppliedTrade, TradeExecution } from '../types/v2_results.js';\nimport { createConfirmationSchedule, throwIfAborted } from '../utils/confirmation_schedule.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport { isValidUniqueKey } from '../utils/unique_key_syntax.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n} from '../utils/transport.js';\nimport type { GSwapErrorCode, GSwapErrorParams } from './error_catalog.js';\nimport { getStringProperty, GSwapSDKError, type GSwapErrorContext } from './gswap_sdk_error.js';\n\n/**\n * The AutoApplier waits at least 2 s before applying and the apply lands ~6-8 s after the\n * acknowledgement, so a read at t=0 is a guaranteed 404.\n */\nconst DEFAULT_INITIAL_DELAY_MS = 3_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * The outcome of a queued RequestTrade that could not be delivered as an {@link AppliedTrade}.\n * `code` says why:\n *\n * - `CONFIRMATION_TIMEOUT`: no terminal result before the deadline. The trade may still apply;\n * confirm the same `uniqueKey` again later and never resubmit.\n * - `CONFIRMATION_ABORTED`: the caller's `signal` aborted. Nothing is known about the outcome.\n * - `CONFIRMATION_FAILED`: the apply-results read got a terminal HTTP status (`params.status`;\n * `params.serverMessage` is the failing body's own message, `''` when it had none: server\n * text is data, relay it or ignore it). The outcome is unknown.\n * - `CONFIRMATION_MALFORMED` / `CONFIRMATION_KEY_MISMATCH`: the apply result is not a usable\n * answer for this key. The outcome is unknown.\n * - `INVALID_UNIQUE_KEY`: the key is not a valid apply-results key; nothing was read. TERMINAL:\n * no retry can ever succeed (the SDK never signs such a key, so a stored one is corrupt), so a\n * resume loop must forget the swap. `PendingSwapStore.list` already prunes such entries.\n * - `CHAIN_REJECTED`: the chain REJECTED the trade; `params.errorKey` is the chain `ErrorKey` (or\n * `CHAIN_ERROR`) and `params.serverMessage` its English message.\n *\n * `uniqueKey` is always set and, where known, `requestTransactionId`, `applyTransactionId`,\n * `blockNumber`, `status`, `body`, `url` and the last transport `cause`.\n */\nexport class AppliedTradeError<C extends GSwapErrorCode = GSwapErrorCode> extends GSwapSDKError<C> {\n constructor(code: C, params: GSwapErrorParams<C>, context: GSwapErrorContext = {}) {\n super(code, params, context);\n this.name = 'AppliedTradeError';\n }\n}\n\n/** The transport and backend a confirmation reads from. */\nexport interface ApplyResultsClient {\n /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com` (no trailing path). */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-read timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /** Request headers of the poll (`userAgent`, `headers`); see {@link WireOptions}. */\n wire?: WireOptions | undefined;\n}\n\n/** What identifies the queued trade to confirm. */\nexport interface AppliedTradeInput {\n uniqueKey: string;\n /** The transaction id of the queued request, carried through to the result; `null` if unknown. */\n requestTransactionId: string | null;\n}\n\n/**\n * Polls `GET /v1/chain/apply-results/{uniqueKey}?channel=asset&contract=dex-contract` until the\n * queued RequestTrade reaches a terminal state.\n *\n * Pacing: wait `initialDelayMs` (default 3 s), then read; on 404, 429, 500, 502, 503, 504 or a\n * transport error wait with jittered exponential backoff (`pollIntervalMs` doubling to 8 s,\n * `Retry-After` honored as seconds or an HTTP date) until `timeoutMs`. Any other status is\n * terminal. At least one read is always made.\n *\n * @returns The applied trade.\n * @throws AppliedTradeError - see its documentation for every `code`.\n * @example\n * ```ts\n * const applied = await confirmAppliedTrade(\n * { dexBackendBaseUrl: 'https://dex-backend-prod1.defi.gala.com' },\n * { uniqueKey, requestTransactionId: null },\n * { initialDelayMs: 0, timeoutMs: 60_000, signal: controller.signal },\n * );\n * ```\n */\nexport async function confirmAppliedTrade(\n client: ApplyResultsClient,\n input: AppliedTradeInput,\n options?: ConfirmOptions,\n): Promise<AppliedTrade> {\n const { uniqueKey } = input;\n if (!isValidUniqueKey(uniqueKey)) {\n throw new AppliedTradeError(\n 'INVALID_UNIQUE_KEY',\n { uniqueKey: String(uniqueKey) },\n { uniqueKey },\n );\n }\n const requestor = client.httpRequestor ?? fetchRequestor;\n const requestTimeoutMs = client.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const signal = options?.signal;\n const abortError = (cause?: unknown): Error =>\n new AppliedTradeError('CONFIRMATION_ABORTED', {}, { uniqueKey, cause });\n const url = `${client.dexBackendBaseUrl.replace(/\\/$/u, '')}/v1/chain/apply-results/${encodeURIComponent(uniqueKey)}?channel=asset&contract=dex-contract`;\n\n const schedule = createConfirmationSchedule(options, DEFAULT_INITIAL_DELAY_MS, abortError);\n await schedule.waitForRead();\n let lastError: unknown;\n\n while (true) {\n throwIfAborted(signal, abortError);\n let response: HTTPResponse;\n let body: unknown;\n try {\n response = await requestWithTimeout(\n requestor,\n url,\n {\n method: 'GET',\n headers: buildRequestHeaders(client.wire),\n ...(signal === undefined ? {} : { signal }),\n },\n requestTimeoutMs,\n );\n body = await readResponseBody(response);\n } catch (error: unknown) {\n throwIfAborted(signal, abortError);\n lastError = error;\n if (!(await schedule.waitForRead())) break;\n continue;\n }\n throwIfAborted(signal, abortError);\n\n if (response.status === 200) return readAppliedResult(input, response, body, url);\n\n if (response.status === 404 || response.status === 429 || isTransient(response.status)) {\n const retryAfter = response.status === 429 ? readRetryAfter(response) : undefined;\n if (!(await schedule.waitForRead(retryAfter))) break;\n continue;\n }\n\n throw new AppliedTradeError(\n 'CONFIRMATION_FAILED',\n { status: response.status, serverMessage: serverMessageOfBody(body) },\n { uniqueKey, status: response.status, body, url },\n );\n }\n\n throw new AppliedTradeError(\n 'CONFIRMATION_TIMEOUT',\n {},\n { uniqueKey, requestTransactionId: input.requestTransactionId, url, cause: lastError },\n );\n}\n\nfunction readAppliedResult(\n input: AppliedTradeInput,\n response: HTTPResponse,\n body: unknown,\n url: string,\n): AppliedTrade {\n const { uniqueKey } = input;\n const record = asRecord(body);\n const responseKey = record?.['uniqueKey'] ?? record?.['UniqueKey'];\n if (typeof responseKey === 'string' && responseKey !== uniqueKey) {\n throw new AppliedTradeError(\n 'CONFIRMATION_KEY_MISMATCH',\n {},\n { uniqueKey, status: response.status, body, url },\n );\n }\n const status = record?.['Status'];\n const applyTransactionId = readHeader(response, 'x-apply-transaction-id') ?? null;\n const blockNumber = readBlockNumberHeader(response, 'x-apply-block-number') ?? null;\n if (status === 0) {\n const errorKey = getStringProperty(record, 'ErrorKey') ?? 'CHAIN_ERROR';\n const chainMessage = getStringProperty(record, 'Message') ?? '';\n throw new AppliedTradeError(\n 'CHAIN_REJECTED',\n { errorKey, serverMessage: chainMessage },\n {\n uniqueKey,\n requestTransactionId: input.requestTransactionId,\n applyTransactionId,\n blockNumber,\n status: response.status,\n body,\n url,\n },\n );\n }\n if (status !== 1) throw malformed(input, response, body, url);\n const result = parseTradeExecution(record?.['Data']);\n if (result === undefined) throw malformed(input, response, body, url);\n return {\n uniqueKey,\n transactionId: applyTransactionId,\n blockNumber,\n requestTransactionId: input.requestTransactionId,\n result,\n };\n}\n\nfunction malformed(\n input: AppliedTradeInput,\n response: HTTPResponse,\n body: unknown,\n url: string,\n): AppliedTradeError<'CONFIRMATION_MALFORMED'> {\n return new AppliedTradeError(\n 'CONFIRMATION_MALFORMED',\n {},\n { uniqueKey: input.uniqueKey, status: response.status, body, url },\n );\n}\n\nfunction parseTradeExecution(value: unknown): TradeExecution | undefined {\n const record = asRecord(value);\n if (\n record === undefined ||\n typeof record['token0'] !== 'string' ||\n typeof record['token1'] !== 'string' ||\n typeof record['fee'] !== 'number'\n ) {\n return undefined;\n }\n const optionalFields = [\n 'sell0Qty',\n 'sell1Qty',\n 'buy0Qty',\n 'buy1Qty',\n 'tradingFees',\n 'protocolFees',\n 'totalFees',\n ] as const;\n for (const field of optionalFields) {\n if (field in record && typeof record[field] !== 'string') return undefined;\n }\n return {\n token0: record['token0'],\n token1: record['token1'],\n fee: record['fee'],\n ...Object.fromEntries(\n optionalFields.flatMap((field) =>\n typeof record[field] === 'string' ? [[field, record[field]]] : [],\n ),\n ),\n };\n}\n\nfunction isTransient(status: number): boolean {\n return status === 500 || status === 502 || status === 503 || status === 504;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","/**\n * Fee tiers for pools.\n */\nexport enum FEE_TIER {\n /** No trading fee. */\n PERCENT_00_00 = 0,\n /** 0.05% fee tier */\n PERCENT_00_05 = 500,\n /** 0.3% fee tier */\n PERCENT_00_30 = 3000,\n /** 1.0% fee tier */\n PERCENT_01_00 = 10000,\n}\n\n/** Tick spacing required by the current GalaChainDex contract for each fee tier. */\nexport const TICK_SPACING_BY_FEE: Readonly<Record<FEE_TIER, number>> = {\n [FEE_TIER.PERCENT_00_00]: 200,\n [FEE_TIER.PERCENT_00_05]: 10,\n [FEE_TIER.PERCENT_00_30]: 60,\n [FEE_TIER.PERCENT_01_00]: 200,\n};\n\n/** All fee tiers supported by the current GalaChainDex contract. */\nexport const ALL_FEE_TIERS: readonly FEE_TIER[] = [\n FEE_TIER.PERCENT_00_00,\n FEE_TIER.PERCENT_00_05,\n FEE_TIER.PERCENT_00_30,\n FEE_TIER.PERCENT_01_00,\n];\n","import BigNumber from 'bignumber.js';\nimport { Decimal } from 'decimal.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\n\n/** Minimum tick supported by GalaChainDex. */\nexport const GC_MIN_TICK = -887272;\n/** Maximum tick supported by GalaChainDex. */\nexport const GC_MAX_TICK = 887272;\n\nconst DexMath = BigNumber.clone({\n DECIMAL_PLACES: 60,\n ROUNDING_MODE: BigNumber.ROUND_DOWN,\n});\nconst DexDecimal = Decimal.clone({ precision: 60 });\n\n/** Convert a tick to the corresponding square-root price. */\nexport function tickToSqrtPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick / 2).toString());\n}\n\n/** Return the greatest tick whose square-root price is no greater than the input. */\nexport function sqrtPriceToTick(sqrtPrice: BigNumber.Value): number {\n let value: BigNumber;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this function's contract is to signal an invalid input via NaN, not\n // to throw, so an unparseable value is just another case for the guard below.\n value = new DexMath(sqrtPrice);\n } catch {\n return Number.NaN;\n }\n if (!value.isFinite() || value.isLessThanOrEqualTo(0)) return Number.NaN;\n\n const approximate = Math.log(value.toNumber() ** 2) / Math.log(1.0001);\n if (!Number.isFinite(approximate)) return Number.NaN;\n // Clamp the seed before the correction loops below — an unclamped seed derived from an\n // out-of-range sqrtPrice (extreme but finite, e.g. 1e20) leaves the loops running past\n // GC_MIN_TICK/GC_MAX_TICK for a long time; an infinite (overflowed) seed would never\n // enter the increasing loop and never terminate the decreasing one.\n let tick = Math.min(GC_MAX_TICK, Math.max(GC_MIN_TICK, Math.floor(approximate)));\n while (tick < GC_MAX_TICK && tickToSqrtPrice(tick + 1).isLessThanOrEqualTo(value)) tick += 1;\n while (tick > GC_MIN_TICK && tickToSqrtPrice(tick).isGreaterThan(value)) tick -= 1;\n return tick;\n}\n\n/**\n * The token1/token0 price at `tick`: `1.0001 ** tick`, exact to 60 significant digits (the lower\n * edge of the tick's price range; `tickToSqrtPrice(tick) ** 2`). A tick outside the contract's\n * bounds is still computed; ask `assertTickRange` first when that matters. A non-integer tick is\n * computed as given.\n *\n * Use `.toNumber()` for a display value (it differs from `Math.exp(tick * Math.log(1.0001))` in\n * the last digits of a double: that expression multiplies in floating point first).\n */\nexport function tickToPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick).toString());\n}\n\n/** How {@link tickFromPrice} turns the exact logarithm into an integer tick. */\nexport interface TickFromPriceOptions {\n /**\n * `'floor'` (default): the greatest tick whose price is no greater than `price`, which is how\n * the contract places a price. `'nearest'`: the closest tick, a half rounding away from zero.\n * That is what a price INPUT wants (a person types a price, the field snaps to the nearest\n * tick), and it differs from `'floor'` for any price in the upper half of a tick's range.\n */\n rounding?: 'floor' | 'nearest' | undefined;\n}\n\n/**\n * Return the integer tick for a token1/token0 `price`: by default the greatest tick whose price\n * is no greater than `price`; `{ rounding: 'nearest' }` the closest tick. `NaN` for a price that\n * is not positive and finite.\n */\nexport function tickFromPrice(price: BigNumber.Value, options: TickFromPriceOptions = {}): number {\n const priceText =\n typeof price === 'string'\n ? price\n : typeof price === 'number'\n ? price.toString()\n : BigNumber.isBigNumber(price)\n ? price.toString()\n : 'NaN';\n const value = new DexDecimal(priceText);\n if (!value.isFinite() || value.lessThanOrEqualTo(0)) return Number.NaN;\n if (!Number.isFinite(value.toNumber())) return Number.NaN;\n const exact = value.ln().dividedBy(new DexDecimal(1.0001).ln());\n const tick = (options.rounding === 'nearest' ? exact.round() : exact.floor()).toNumber();\n return Number.isFinite(tick) ? tick : Number.NaN;\n}\n\n/** Align a tick down to the nearest multiple of a positive spacing. */\nexport function alignTickDown(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return Math.floor(tick / spacing) * spacing;\n}\n\n/** Align a tick up to the nearest multiple of a positive spacing. */\nexport function alignTickUp(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return Math.ceil(tick / spacing) * spacing;\n}\n\n/** Validate a position range against the global tick bounds and fee-tier spacing. */\nexport function assertTickRange(lower: number, upper: number, fee: FEE_TIER): void {\n const spacing = TICK_SPACING_BY_FEE[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower: lower, tickUpper: upper });\n }\n if (lower >= upper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower: lower, tickUpper: upper });\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower: lower,\n tickUpper: upper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new GSwapSDKError('TICKS_NOT_ALIGNED', {\n tickLower: lower,\n tickUpper: upper,\n spacing,\n });\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!Number.isInteger(spacing) || spacing <= 0) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: spacing });\n }\n}\n\n/** A pool's current price in the frame of the request that asked for it. */\nexport interface FramedSlot0 {\n /** The square-root price, token1 per token0 in the REQUESTED order. */\n sqrtPrice: string;\n /** The greatest tick whose square-root price is no greater than `sqrtPrice`. */\n tick: number;\n}\n\n/**\n * Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's\n * canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse\n * order the price is inverted here (at 60 significant digits, so a very large or very small\n * reciprocal keeps its precision) and the tick is re-derived from the inverted price with the\n * contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks\n * (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).\n *\n * @example\n * ```ts\n * const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);\n * const { sqrtPrice, tick } = frameSlot0(slot0);\n * ```\n */\nexport function frameSlot0(slot0: {\n sqrtPrice: string;\n tick: number;\n flippedFromRequest?: boolean | undefined;\n}): FramedSlot0 {\n if (slot0.flippedFromRequest !== true) return { sqrtPrice: slot0.sqrtPrice, tick: slot0.tick };\n const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));\n if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_SQRT_PRICE', { sqrtPrice: slot0.sqrtPrice });\n }\n const sqrtPrice = inverted.toString();\n return { sqrtPrice, tick: sqrtPriceToTick(sqrtPrice) };\n}\n","import BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { GC_MAX_TICK, GC_MIN_TICK } from './ticks.js';\n\nexport function validateNumericAmount(\n amount: NumericAmount,\n parameterName: string,\n allowZero = false,\n): void {\n if (typeof amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite() check below still catches\n // it and raises the same typed error, instead of a raw exception escaping.\n let bnAmount: BigNumber;\n try {\n bnAmount = BigNumber(amount);\n } catch {\n bnAmount = BigNumber(NaN);\n }\n\n if (!bnAmount.isFinite()) {\n throw new GSwapSDKError('AMOUNT_NOT_FINITE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError('AMOUNT_NOT_POSITIVE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError('AMOUNT_NEGATIVE', { field: parameterName, value: String(amount) });\n }\n}\n\nexport function validatePriceValues(\n spotPrice: NumericAmount,\n lowerPrice: NumericAmount,\n upperPrice: NumericAmount,\n): void {\n if ([spotPrice, lowerPrice, upperPrice].some((value) => typeof value === 'number')) {\n throw new GSwapSDKError('PRICE_VALUES_IS_JS_NUMBER', {});\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite()/isPositive() checks below\n // still catch it and raise the same typed error, instead of a raw exception escaping.\n const parse = (value: NumericAmount): BigNumber => {\n try {\n return BigNumber(value);\n } catch {\n return BigNumber(NaN);\n }\n };\n const bnSpotPrice = parse(spotPrice);\n const bnLowerPrice = parse(lowerPrice);\n let bnUpperPrice = parse(upperPrice);\n\n bnUpperPrice = bnUpperPrice.isFinite() ? bnUpperPrice : BigNumber(1e18);\n\n if (\n !bnSpotPrice.isFinite() ||\n !bnLowerPrice.isFinite() ||\n !bnUpperPrice.isFinite() ||\n !bnSpotPrice.isPositive() ||\n !bnLowerPrice.isPositive() ||\n !bnUpperPrice.isPositive()\n ) {\n throw new GSwapSDKError('INVALID_PRICE_VALUES', {\n spotPrice: String(spotPrice),\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError('INVALID_PRICE_RANGE', {\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n}\n\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError('INVALID_TOKEN_DECIMALS', { field: parameterName, value: decimals });\n }\n}\n\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower, tickUpper });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower, tickUpper });\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n}\n\nexport function validateFee(fee: number): asserts fee is FEE_TIER {\n if (!ALL_FEE_TIERS.some((tier) => Number(tier) === fee)) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: tickSpacing });\n }\n}\n\nexport function validateWalletAddress(address?: string): asserts address is string {\n if (address === undefined) {\n throw new GSwapSDKError('MISSING_WALLET_ADDRESS', {});\n }\n\n if (!address || typeof address !== 'string' || address.trim().length === 0) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', {\n field: 'walletAddress',\n value: String(address),\n });\n }\n}\n\n/** Words the chain gateway refuses as a trading symbol. */\nconst RESERVED_TRADING_SYMBOLS = new Set(['Token', 'Unit', 'none']);\nconst TRADING_SYMBOL_PATTERN = /^[A-Za-z0-9]+$/u;\nconst MAX_TRADING_SYMBOL_LENGTH = 32;\n\n/**\n * True when `symbol` is acceptable to propose into the trading-symbol registry: ASCII letters and\n * digits only, 1 to 32 characters, and not a reserved word (`Token`, `Unit`, `none`) — the rules\n * the chain gateway enforces on a CreatePool symbol.\n */\nexport function isProposableTradingSymbol(symbol: string): boolean {\n return (\n TRADING_SYMBOL_PATTERN.test(symbol) &&\n symbol.length <= MAX_TRADING_SYMBOL_LENGTH &&\n !RESERVED_TRADING_SYMBOLS.has(symbol)\n );\n}\n\n/**\n * Asserts that a pair is in the contract's canonical order (`token0 < token1` by plain string\n * comparison), which every write DTO requires. A pair a caller took from a stale quote or\n * position can be reversed; signing it would sign something other than what was priced.\n *\n * @throws GSwapSDKError `NON_CANONICAL_PAIR` (`params.token0`, `params.token1`) otherwise.\n */\nexport function assertCanonicalPair(token0: string, token1: string): void {\n if (!(token0 < token1)) {\n throw new GSwapSDKError('NON_CANONICAL_PAIR', { token0, token1 });\n }\n}\n","import type { UserAsset, UserAssetsResult } from '../types/v2_results.js';\nimport { validateWalletAddress } from '../utils/validation.js';\nimport { getObjectProperty, GSwapSDKError } from './gswap_sdk_error.js';\nimport type { HttpClient } from './http_client.js';\n\n/**\n * Service for handling user asset operations.\n * Provides functionality to retrieve user token balances and asset information.\n */\nexport class Assets {\n constructor(\n private readonly dexBackendBaseUrl: string,\n private readonly httpClient: HttpClient,\n ) {}\n\n /**\n * Gets all token assets owned by a user with their balances.\n * @param ownerAddress - The wallet address to get assets for.\n * @param page - Page number for pagination (default: 1).\n * @param limit - Maximum number of assets to return per page (default: 10).\n * @returns User assets including token information and balances.\n * @example\n * ```typescript\n * const assets = await assetsService.getUserAssets('eth|123...abc', 1, 20);\n * console.log(`User has ${assets.count} different tokens`);\n * assets.tokens.forEach(token => {\n * console.log(`${token.symbol}: ${token.quantity}`);\n * });\n * ```\n */\n async getUserAssets(\n ownerAddress: string,\n page: number = 1,\n limit: number = 10,\n ): Promise<UserAssetsResult> {\n validateWalletAddress(ownerAddress);\n\n if (!Number.isInteger(page) || page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: page });\n }\n\n if (!Number.isInteger(limit) || limit < 1 || limit > 100) {\n throw new GSwapSDKError('INVALID_LIMIT', { value: limit, min: 1, max: 100 });\n }\n\n const json: unknown = await this.httpClient.sendGetRequest(\n this.dexBackendBaseUrl,\n '/user/assets',\n '',\n { address: ownerAddress, page: page.toString(), limit: limit.toString() },\n );\n return parseUserAssets(json);\n }\n}\n\nfunction parseUserAssets(value: unknown): UserAssetsResult {\n const data = getObjectProperty(value, 'data');\n // Not getObjectProperty — that's typed for object properties, and Array.isArray on its\n // Record<string, unknown> return type narrows to any[] instead of a real array type.\n const tokens: unknown = data?.['token'];\n if (!Array.isArray(tokens) || !tokens.every(isRawUserAsset)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: 'user assets response' },\n { body: value },\n );\n }\n const count = data?.['count'];\n return {\n tokens: tokens.map((token) => ({ ...token, decimals: parseInt(token.decimals, 10) })),\n count: typeof count === 'number' ? count : 0,\n };\n}\n\ntype RawUserAsset = Omit<UserAsset, 'decimals'> & { decimals: string };\n\nfunction isRawUserAsset(value: unknown): value is RawUserAsset {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n typeof entry['image'] === 'string' &&\n typeof entry['name'] === 'string' &&\n typeof entry['decimals'] === 'string' &&\n /^\\d+$/u.test(entry['decimals']) &&\n typeof entry['verify'] === 'boolean' &&\n typeof entry['symbol'] === 'string' &&\n typeof entry['quantity'] === 'string'\n );\n}\n","/**\n * What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet\n * code of the app's own): the code the wallet put on it, and whether it means the person declined.\n * Both read only the wallet's own error value; neither shows or forwards its text.\n */\n\nimport { hasGSwapErrorBrand, isGSwapErrorLike } from './error_brand.js';\n\n// This module is the whole of the light `@gala-chain/gswap-sdk/wallet` entry (and the main entry\n// re-exports it, so there is one implementation). It must stay dependency-free: it may import\n// only `./error_brand.js`, never the error catalog, `GSwapSDKError` or the main index.\n\n/** Codes the EIP-1193 / ethers / viem families use for \"the person declined in the wallet\". */\nconst REJECTION_CODES: readonly unknown[] = [4001, 'ACTION_REJECTED', 'USER_REJECTED'];\n\n/** The `name` viem / wagmi give the error of a declined request. */\nconst REJECTION_NAME = 'UserRejectedRequestError';\n\n/**\n * Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for\n * wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on\n * purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle\n * match an unrelated message that uses these words.\n */\nconst REJECTION_PHRASES: readonly string[] = [\n 'user rejected',\n 'user denied',\n 'user cancel',\n 'rejected the request',\n 'request rejected',\n 'rejected by user',\n 'action_rejected',\n 'cancelled',\n 'canceled',\n];\n\n/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */\nconst TEXT_KEYS: readonly string[] = [\n 'message',\n 'Message',\n 'shortMessage',\n 'details',\n 'errorDetails',\n 'reason',\n];\n\n/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */\nconst MAX_TEXT_DEPTH = 3;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction textsOf(value: unknown, depth = 0): string[] {\n if (typeof value === 'string') return [value];\n if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];\n return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));\n}\n\nfunction wordsADecline(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) ||\n (lower.includes('signature') && lower.includes('cancel'))\n );\n}\n\n/**\n * True when a wallet's error (or just its message text) says the person DECLINED the request in\n * their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===\n * 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a\n * v1 write path) so an app keeps no matcher of its own.\n *\n * It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`\n * (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are\n * absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,\n * `reason`, up to three levels deep, or a bare string): \"user rejected\", \"user denied\", \"user\n * cancelled\", \"request rejected\", \"rejected by user\", \"rejected the request\", \"cancelled\" /\n * \"canceled\", or a \"signature ... cancel\" sentence. The wording fallback is a last resort for\n * wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.\n *\n * An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its\n * `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a\n * plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape\n * of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with\n * the wallet code list above still honoured for a view that is not branded, and its English is\n * never read. This works without `instanceof`, so it is safe across two copies of the SDK.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (isWalletUserRejection(error)) return; // the person said no: not an error to report\n * report(error);\n * }\n * ```\n */\nexport function isWalletUserRejection(value: unknown): boolean {\n if (isGSwapErrorLike(value)) {\n if (value.code === 'SIGNING_FAILED') return value.params['reason'] === 'user_rejected';\n return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);\n }\n if (isRecord(value)) {\n if (REJECTION_CODES.includes(value['code']) || value['name'] === REJECTION_NAME) return true;\n }\n return textsOf(value).some(wordsADecline);\n}\n\n/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */\nconst MAX_WALLET_CODE_LENGTH = 64;\n\n/**\n * The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an\n * ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything\n * else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so\n * the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.\n *\n * @example\n * ```ts\n * walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001\n * walletDeclineCode(new Error('locked')); // undefined\n * ```\n */\nexport function walletDeclineCode(value: unknown): number | string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const { code } = value as { code?: unknown };\n if (typeof code === 'number') return Number.isFinite(code) ? code : undefined;\n if (typeof code === 'string' && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) {\n return code;\n }\n return undefined;\n}\n","import { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\nimport type { GalaChainSigner, SignedDto } from '../classes/signers.js';\nimport { isWalletUserRejection, walletDeclineCode } from './wallet_rejection.js';\n\n/**\n * The boundary of \"nothing was sent\". Every place where the SDK hands control to code the APP\n * supplied BEFORE the request leaves (the signer, the token resolver) goes through here, so a\n * failure of that code reaches the caller as a catalogued, pre-send SDK error with the original as\n * `cause`, never as a bare value the SDK cannot classify. An SDK error thrown by that code is\n * already catalogued and passes through untouched. Nothing here is used after the request has\n * been sent: an app's own rejection AFTER send stays what it is, because the SDK cannot know what\n * the server did with the write.\n */\n\n/**\n * Signs a DTO with the app's signer. Whatever the signer throws that is not already an SDK error\n * (a locked wallet, an unreachable extension, a wallet that declined) is `SIGNING_FAILED`\n * (`reason` `user_rejected` or `failed`, the original as `cause`), and a signer that returns\n * something other than an object is `SIGNING_FAILED` too: both are pre-send, so a retry is safe.\n *\n * @throws GSwapSDKError SIGNING_FAILED, or the SDK error the signer itself threw.\n */\nexport async function signPreSend<T extends Record<string, unknown>>(\n signer: GalaChainSigner,\n method: string,\n dto: T,\n): Promise<SignedDto<T>> {\n let signed: SignedDto<T>;\n try {\n signed = await signer.signObject(method, dto);\n } catch (cause: unknown) {\n if (isGSwapError(cause)) throw cause;\n const reason = isWalletUserRejection(cause) ? 'user_rejected' : 'failed';\n throw new GSwapSDKError(\n 'SIGNING_FAILED',\n { method, reason },\n { cause, walletCode: walletDeclineCode(cause) },\n );\n }\n if (typeof signed !== 'object' || signed === null) {\n throw new GSwapSDKError('SIGNING_FAILED', { method, reason: 'failed' }, { cause: signed });\n }\n return signed;\n}\n\n/**\n * Runs a token-resolution step (a resolver's `resolve` / `orderPair`, which may read the registry\n * through the app's HTTP stack). A failure that is not an SDK error is `TOKEN_RESOLUTION_FAILED`\n * (`token` names what was being resolved, the original is `cause`); an SDK error passes through.\n *\n * @throws GSwapSDKError TOKEN_RESOLUTION_FAILED, or the SDK error the step itself threw.\n */\nexport async function resolvePreSend<T>(token: string, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause: unknown) {\n throw isGSwapError(cause)\n ? cause\n : new GSwapSDKError('TOKEN_RESOLUTION_FAILED', { token }, { cause });\n }\n}\n","import type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n} from '../utils/transport.js';\nimport { signPreSend } from '../utils/pre_send.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { GalaChainSigner } from './signers.js';\n\n/** DEX methods the backend accepts a fee quote for (its allow-list enumerates the same six). */\nexport const DEX_FEE_METHODS = [\n 'Swap',\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n 'CreatePool',\n] as const;\nexport type DexFeeMethod = (typeof DEX_FEE_METHODS)[number];\n\n/** Which pool contract the DTO being quoted targets: legacy (V3) or current (GalaChainDex). */\nexport type DexFeeContract = 'dexv3-contract' | 'dex-contract';\n\n/** The chain method name the signed DryRun wrapper is signed under. */\nexport const DRY_RUN_METHOD = 'DryRun';\n\n/** `uniqueKey` prefix of the DryRun WRAPPER (distinct from the inner DTO's key). */\nexport const DRY_RUN_UNIQUE_KEY_PREFIX = 'galaconnect-operation-';\n\n/** True when `method` is a DEX method a fee can be quoted for. */\nexport function isDexFeeMethod(method: unknown): method is DexFeeMethod {\n return typeof method === 'string' && (DEX_FEE_METHODS as readonly string[]).includes(method);\n}\n\n/** Current-contract typed DEX messages use trading symbols instead of TokenClassKey objects. */\nexport function isCurrentContractDexMessage(\n message: Record<string, unknown> | null | undefined,\n method: unknown,\n): boolean {\n return (\n isDexFeeMethod(method) &&\n typeof message?.['token0'] === 'string' &&\n typeof message['token1'] === 'string'\n );\n}\n\n/**\n * The backend's response. It ALWAYS carries a usable `fees[0].feeInGala`: the backend decides what\n * to serve when the chain cannot price the operation, so the client never invents a fee.\n *\n * `source` is informational: `'dry-run'` is simulated on chain and authoritative (possibly a\n * legitimate `'0'`), `'default'` means the chain could not price it and the platform default was\n * served.\n */\nexport interface DexFeeQuote {\n fees: Array<{ feeInGala: string }>;\n source: 'dry-run' | 'default';\n}\n\n/**\n * Reduces an EIP-712 approval `message` to the DTO the chain actually receives: drops the signing\n * envelope (`signature`, `prefix`, `types`, `domain`) and transport metadata (`trace`).\n */\nexport function toChainDto(message: Record<string, unknown>): Record<string, unknown> {\n const chainDto: Record<string, unknown> = { ...message };\n for (const field of ['signature', 'prefix', 'types', 'domain', 'trace']) {\n delete chainDto[field];\n }\n return chainDto;\n}\n\n/**\n * Signs the DryRun WRAPPER the gateway accepts for every contract:\n * `{ callerPublicKey, method, dto: <inner DTO object>, uniqueKey, signature }`. The inner DTO\n * travels unsigned and as an object; no `signerPublicKey` is sent because the signature already\n * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own\n * `uniqueKey`, distinct from the DTO's.\n */\nexport function buildDryRunWrapper(\n signer: GalaChainSigner,\n callerPublicKey: string,\n method: string,\n dto: Record<string, unknown>,\n uniqueKeyPrefix: string = DRY_RUN_UNIQUE_KEY_PREFIX,\n): Promise<Record<string, unknown>> {\n return signPreSend(signer, DRY_RUN_METHOD, {\n callerPublicKey,\n method,\n dto,\n uniqueKey: `${uniqueKeyPrefix}${globalThis.crypto.randomUUID()}`,\n });\n}\n\n/** The transport and backend a fee quote reads from. */\nexport interface DexFeesClient {\n /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com`. */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-request timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /**\n * Request headers of the fee POST (`userAgent`, `headers`); see {@link WireOptions}. The SDK's\n * `Accept: application/json` is a default that `wire.headers` may replace.\n */\n wire?: WireOptions | undefined;\n}\n\n/** Options for a single quote. */\nexport interface DexFeeQuoteOptions {\n /** GalaChain channel. Default `asset`. */\n channel?: string | undefined;\n /**\n * Contract the DTO targets. Default `dexv3-contract` (what every legacy caller quotes against);\n * a current-contract operation must pass `dex-contract` explicitly.\n */\n contract?: DexFeeContract | undefined;\n}\n\n/**\n * Network-fee quote for GalaChain DEX methods, derived from a server-side DryRun.\n *\n * The client only SIGNS the DryRun wrapper (with whatever {@link GalaChainSigner} it is given) and\n * the backend forwards it to the gateway, where the simulated writes carry the fee; the backend\n * never holds a key. Intended for wallets: the DTO quoted is the typed message a dApp handed over.\n *\n * @example\n * ```ts\n * const fees = new DexFees({ dexBackendBaseUrl }, new PrivateKeySigner(sessionKey));\n * const quote = await fees.quote(publicKey, 'RequestTrade', toChainDto(message), {\n * contract: 'dex-contract',\n * });\n * const feeInGala = quote?.fees[0]?.feeInGala;\n * ```\n */\nexport class DexFees {\n private readonly requestor: HttpRequestor;\n private readonly baseUrl: string;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n\n constructor(\n client: DexFeesClient,\n private readonly signer: GalaChainSigner | undefined,\n ) {\n this.requestor = client.httpRequestor ?? fetchRequestor;\n this.baseUrl = client.dexBackendBaseUrl.replace(/\\/$/u, '');\n this.requestTimeoutMs = client.requestTimeoutMs ?? 30_000;\n this.wire = client.wire;\n }\n\n /**\n * Quotes the network fee for `method` applied to `message`. The message is reduced with\n * {@link toChainDto} first, so an EIP-712 approval message can be passed as is.\n *\n * Resolves `null` when the BACKEND could not be reached or answered unusably (offline, 4xx/5xx,\n * malformed body): a transport outcome, not a fee. Deciding what to charge when the chain is\n * silent is the backend's job (it serves `source: 'default'`), so the client never substitutes\n * a fee of its own, with ONE exception that mirrors the wallet: a `dex-contract` quote answered\n * 403 or 404 means the contract has no fee route yet and resolves `{ source: 'default', '0' }`.\n * Never throws on transport, so a fee lookup cannot block or break a signing screen.\n *\n * @throws GSwapSDKError NO_SIGNER when constructed without a signer; `SIGNING_FAILED` or\n * `KEY_PROVIDER_FAILED` (a pre-send error, the original as `cause`) when the signer fails, for\n * example a locked wallet.\n */\n public async quote(\n callerPublicKey: string,\n method: DexFeeMethod,\n message: Record<string, unknown>,\n options: DexFeeQuoteOptions = {},\n ): Promise<DexFeeQuote | null> {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const channel = options.channel ?? 'asset';\n const contract = options.contract ?? 'dexv3-contract';\n const wrapper = await buildDryRunWrapper(\n this.signer,\n callerPublicKey,\n method,\n toChainDto(message),\n );\n const url = `${this.baseUrl}/wallet/connect/galachain/api/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;\n\n let status: number;\n let ok: boolean;\n let body: unknown;\n try {\n const response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers: buildRequestHeaders(this.wire, {\n json: true,\n defaults: { Accept: 'application/json' },\n }),\n body: JSON.stringify(wrapper),\n },\n this.requestTimeoutMs,\n );\n status = response.status;\n ok = response.ok;\n body = ok ? await readResponseBody(response) : undefined;\n } catch {\n return null;\n }\n\n if (!ok) {\n if (contract === 'dex-contract' && (status === 403 || status === 404)) {\n return { source: 'default', fees: [{ feeInGala: '0' }] };\n }\n return null;\n }\n // Accept whatever fee the backend served: 'default' is as usable as 'dry-run'. Only a body\n // missing the fee outright is unusable.\n return readQuote(body);\n }\n}\n\nfunction readQuote(body: unknown): DexFeeQuote | null {\n if (typeof body !== 'object' || body === null) return null;\n const fees = (body as { fees?: unknown }).fees;\n if (\n !Array.isArray(fees) ||\n typeof (fees[0] as { feeInGala?: unknown } | undefined)?.feeInGala !== 'string'\n ) {\n return null;\n }\n return body as DexFeeQuote;\n}\n","import { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\nimport { toFailureView } from './failure_view.js';\n\n/**\n * Failures of the shadow (dark) path carry that fact, so an app can apply its own policy (no\n * Retry, no public fallback) without tracking which call it made. An SDK error gets `shadow: true`;\n * a non-SDK object that escapes the path (an app requestor's own rejection) is remembered in a\n * WeakSet, which `isShadowError` reads. Nothing here changes what an error means, only where it\n * came from.\n */\nconst shadowRejections = new WeakSet<object>();\n\n/**\n * True when `value` is a failure of the shadow (dark) path: an SDK error with `shadow: true`, a\n * plain-object view of one (`{ code, shadow: true }`, see `FailureView`), or a non-SDK object (a requestor's own rejection) that escaped `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`. A primitive that was thrown (`throw 'x'`) cannot be remembered, so\n * it is never shadow; an app that cares tracks the call it made.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { retryable } = classifyFailure(error);\n * offerRetry(retryable && !isShadowError(error)); // never retry a dark swap in public\n * }\n * ```\n */\nexport function isShadowError(value: unknown): boolean {\n if (isGSwapError(value)) return value.shadow;\n if (toFailureView(value)?.shadow === true) return true;\n return typeof value === 'object' && value !== null && shadowRejections.has(value);\n}\n\n/**\n * The same failure, marked as shadow. An SDK error is COPIED (same code, params, status, body,\n * url, ids, cause, phase and stack), never mutated: one error object can be shared by several\n * callers (a registry read many swaps wait on), and only the shadow caller's copy is shadow.\n */\nfunction asShadowError(error: unknown): unknown {\n if (isGSwapError(error)) {\n if (error.shadow) return error;\n const copy = new GSwapSDKError(error.code, error.params, {\n status: error.status,\n body: error.body ?? error.bodyText,\n url: error.url,\n uniqueKey: error.uniqueKey,\n requestTransactionId: error.requestTransactionId,\n applyTransactionId: error.applyTransactionId,\n blockNumber: error.blockNumber,\n retryAfterMs: error.retryAfterMs,\n cause: error.cause,\n phase: error.phase,\n shadow: true,\n });\n if (error.stack !== undefined) copy.stack = error.stack;\n return copy;\n }\n if (typeof error === 'object' && error !== null) shadowRejections.add(error);\n return error;\n}\n\n/** Runs one shadow operation and marks whatever it throws as shadow (see {@link isShadowError}). */\nexport async function shadowFailures<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error: unknown) {\n throw asShadowError(error);\n }\n}\n","import type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { AppliedTrade, Position } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { createConfirmationSchedule, throwIfAborted } from '../utils/confirmation_schedule.js';\nimport type { SubmitStatus } from '../utils/submit_state.js';\nimport { armTimeout } from '../utils/transport.js';\nimport { confirmAppliedTrade } from './apply_results.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\n/** Result of one position-confirmation poll. */\nexport type PositionConfirmationResult =\n { confirmed: true; position: Position | null } | { confirmed: false; position?: Position | null };\n\n/** A submitted v2 transaction whose confirmation mode is explicit in the gateway response. */\nexport class SubmittedTransaction<TConfirmation = AppliedTrade | Position | null> {\n public readonly method: string;\n public readonly uniqueKey: string;\n public readonly transactionId: string | null;\n public readonly blockNumber: number | null;\n /** The gateway's `data.mode`: `'sync'` (executed, `result` is the chain result) or `'queued'`. */\n public readonly mode: 'sync' | 'queued';\n /**\n * What the gateway's answer established: `'executed'` for `mode: 'sync'`, `'queued'` for\n * `mode: 'queued'` (accepted, NOT executed: `await confirm()` for the outcome). A refused answer\n * never becomes a transaction, so there is no `'rejected'` here; see {@link classifySubmitEnvelope}\n * for classifying a raw envelope.\n */\n public readonly status: SubmitStatus;\n /** The synchronous gateway result, or `undefined` when `mode === 'queued'`. */\n public readonly result: unknown;\n /**\n * The gateway's whole JSON answer as it came (`{ status, message, error, data }`), for an app\n * that hands the backend's own envelope to its callers; `undefined` for a transaction built from\n * a uniqueKey alone.\n */\n public readonly envelope: unknown;\n private readonly backendBaseUrl: string;\n private readonly requestor: HttpRequestor;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n private readonly positionConfirmation:\n ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n\n /** Construct a submitted transaction from a successful gateway response.\n *\n * @example\n * ```ts\n * const transaction = new SubmittedTransaction({\n * method: 'RequestTrade', mode: 'queued', uniqueKey: 'swap-1',\n * transactionId: 'request-tx', result: undefined,\n * dexBackendBaseUrl: 'https://dex.example', httpRequestor,\n * });\n * ```\n */\n constructor(options: {\n method: string;\n uniqueKey: string;\n transactionId: string | null;\n mode: 'sync' | 'queued';\n result: unknown;\n dexBackendBaseUrl: string;\n httpRequestor: HttpRequestor;\n blockNumber?: number | null | undefined;\n envelope?: unknown;\n requestTimeoutMs?: number | undefined;\n /** Wire options of the apply-results polls `confirm()` makes. */\n wire?: WireOptions | undefined;\n positionConfirmation?:\n ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n }) {\n this.method = options.method;\n this.uniqueKey = options.uniqueKey;\n this.transactionId = options.transactionId;\n this.blockNumber = options.blockNumber ?? null;\n this.mode = options.mode;\n this.status = options.mode === 'queued' ? 'queued' : 'executed';\n this.result = options.result;\n this.envelope = options.envelope;\n this.backendBaseUrl = options.dexBackendBaseUrl.replace(/\\/$/u, '');\n this.requestor = options.httpRequestor;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;\n this.wire = options.wire;\n this.positionConfirmation = options.positionConfirmation;\n }\n\n /** Confirm a queued RequestTrade or prove the affected position for a liquidity write.\n *\n * For RequestTrade, calling this method is required to learn the outcome: the queued\n * acknowledgement proves acceptance, not execution.\n *\n * @example\n * ```ts\n * const applied = await submitted.confirm({ initialDelayMs: 3_000 });\n * ```\n */\n public async confirm(options?: ConfirmOptions): Promise<TConfirmation> {\n if (this.method === 'RequestTrade') {\n return this.confirmApplied(options) as Promise<TConfirmation>;\n }\n return this.confirmPosition(options) as Promise<TConfirmation>;\n }\n\n private confirmApplied(options?: ConfirmOptions): Promise<AppliedTrade> {\n return confirmAppliedTrade(\n {\n dexBackendBaseUrl: this.backendBaseUrl,\n httpRequestor: this.requestor,\n requestTimeoutMs: this.requestTimeoutMs,\n wire: this.wire,\n },\n { uniqueKey: this.uniqueKey, requestTransactionId: this.transactionId },\n options,\n );\n }\n\n /** Confirm a liquidity write against the position's observable effect.\n *\n * @returns The position after the write, or `null` for a confirmed full close.\n * @example\n * ```ts\n * const position = await submitted.confirm({ timeoutMs: 60_000 });\n * ```\n */\n private async confirmPosition(options?: ConfirmOptions): Promise<Position | null> {\n if (this.positionConfirmation === undefined) throw GSwapSDKError.noWalletAddressError();\n // A liquidity write has already executed when the gateway answers, so the first re-read\n // happens immediately unless the caller asks for a delay.\n const callerSignal = options?.signal;\n const abortError = (cause?: unknown): Error =>\n new GSwapSDKError('CONFIRMATION_ABORTED', {}, { uniqueKey: this.uniqueKey, cause });\n const schedule = createConfirmationSchedule(options, 0, abortError);\n await schedule.waitForRead();\n while (true) {\n const controller = new AbortController();\n const disarm = armTimeout(controller, this.requestTimeoutMs);\n const forwardAbort = (): void => controller.abort();\n callerSignal?.addEventListener('abort', forwardAbort, { once: true });\n try {\n const result = await this.positionConfirmation(controller.signal);\n if (result.confirmed) return result.position;\n } catch (error: unknown) {\n throwIfAborted(callerSignal, abortError);\n throw error;\n } finally {\n disarm();\n callerSignal?.removeEventListener('abort', forwardAbort);\n }\n if (!(await schedule.waitForRead())) break;\n }\n throw GSwapSDKError.confirmationTimeoutError(this.uniqueKey);\n }\n}\n","import type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n getObjectProperty,\n getStringProperty,\n GSwapSDKError,\n isGSwapError,\n UPDATE_REQUIRED_STATUS,\n type GSwapErrorContext,\n} from './gswap_sdk_error.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport type { SubmissionOutcomeUnknownReason } from './error_catalog.js';\nimport type { ShadowSubmitResult } from './shadow_submit.js';\nimport { SubmittedTransaction, type PositionConfirmationResult } from './submitted_transaction.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n validateTimeoutMs,\n} from '../utils/transport.js';\nimport type { AppliedTrade, Position } from '../types/v2_results.js';\n\n/** Options for a chain-gateway client. */\nexport interface ChainGatewayOptions {\n dexBackendBaseUrl: string;\n httpRequestor?: HttpRequestor | undefined;\n walletAddress?: string | undefined;\n /**\n * Timeout of every gateway request in milliseconds (default 30 000); also the per-read timeout\n * of the services built on this gateway and of `confirm()`. `Infinity` arms no timer, for an\n * app whose HTTP stack owns request lifetimes.\n */\n chainCallTimeoutMs?: number | undefined;\n /**\n * Wire format of every request of this gateway and of the services built on it: the headers\n * (`userAgent`, `headers`) of reads AND of the POSTs that submit writes, and the query encoding\n * of reads. `X-Wallet-Address` and `X-Shadow` always win over a same-named `wire.headers` entry.\n */\n wire?: WireOptions | undefined;\n /**\n * Tells the gateway which rejections of YOUR `httpRequestor` mean \"no HTTP answer arrived\" (the\n * connection failed, was reset or dropped), as opposed to an answer your requestor turned into\n * an error (an interceptor that rejects on a 4xx, a version wall). Used only when submitting a\n * write: a rejection it accepts becomes `SUBMISSION_OUTCOME_UNKNOWN` with `reason: 'transport'`\n * (the request may have been queued; the original error is `cause`), and any other rejection\n * reaches the caller unchanged. The SDK's own `TRANSPORT_ERROR` (the default `fetch` requestor,\n * `httpRequestorFromAxios`) always counts, so this is only for requestors that reject with\n * their own errors. Never throw from it; a throw is treated as \"not a transport failure\".\n *\n * @example\n * ```ts\n * new ChainGateway({\n * dexBackendBaseUrl,\n * httpRequestor: galaFetch, // a fetch wrapper: its TypeError is the network failing\n * isTransportFailure: (error) => error instanceof TypeError,\n * });\n * ```\n */\n isTransportFailure?: ((error: unknown) => boolean) | undefined;\n /**\n * Tells the gateway which rejections of YOUR `httpRequestor` are an HTTP ANSWER, and what the\n * answer was: a requestor built on an HTTP client that rejects every non-2xx (an interceptor\n * that throws on a 4xx, a version wall that throws on a 426) loses the answer the SDK reads\n * errors from. Return `{ status, body }` (the parsed JSON, or the raw text; `headers` for\n * `Retry-After`) for such a rejection and the write is handled exactly as if the requestor had\n * resolved that answer: the gateway's own code becomes its catalogued error\n * (`DTO_INVALID`, `RATE_LIMITED`, `CHAIN_DISPATCH_FAILED`, ...), an uncoded body `HTTP_ERROR`,\n * both carrying the signed `uniqueKey` and classified by `classifyFailure` as a write. Return\n * `undefined` for any other rejection: it reaches the caller unchanged. Used only when\n * submitting a write; `isTransportFailure` is asked first (no answer proves nothing, so\n * \"maybe queued\" wins), and a throw from this hook, or a `status` outside 100-599, means \"not an\n * answer\". Never throw from it.\n *\n * @example\n * ```ts\n * new ChainGateway({\n * dexBackendBaseUrl,\n * httpRequestor: httpRequestorFromAxios(instance, { rejectOnHttpError: true }),\n * answerOfRejection: (error) =>\n * error instanceof GatewayError && error.status !== undefined\n * ? { status: error.status, body: error.data }\n * : undefined,\n * });\n * ```\n */\n answerOfRejection?: ((error: unknown) => RejectedAnswer | undefined) | undefined;\n}\n\n/** The HTTP answer a rejection of the app's requestor stands for (see `ChainGatewayOptions.answerOfRejection`). */\nexport interface RejectedAnswer {\n /** The HTTP status of the answer (100-599). */\n status: number;\n /** The answer's body: parsed JSON when it was JSON, else the raw text. */\n body: unknown;\n /** The answer's headers, for `Retry-After`. */\n headers?: Record<string, string | undefined> | undefined;\n}\n\n/** Optional attribution and operation-specific confirmation hooks for a write. */\nexport interface ChainSubmitOptions {\n walletAddress?: string | undefined;\n positionConfirmation?: ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n}\n\n/** Thin client for backend-routed v2 writes: synchronous liquidity writes and queued RequestTrade. */\nexport class ChainGateway {\n private readonly requestor: HttpRequestor;\n private readonly walletAddress: string | undefined;\n private readonly chainCallTimeoutMs: number;\n private readonly isTransportFailure: ((error: unknown) => boolean) | undefined;\n private readonly answerOfRejectionHook:\n ((error: unknown) => RejectedAnswer | undefined) | undefined;\n public readonly requestTimeoutMs: number;\n public readonly dexBackendBaseUrl: string;\n /** Wire format shared by the read services built on this gateway. */\n public readonly wire: WireOptions;\n\n /** Create a chain gateway client. */\n constructor(options: ChainGatewayOptions) {\n this.dexBackendBaseUrl = trimTrailingSlash(options.dexBackendBaseUrl);\n this.requestor = options.httpRequestor ?? fetchRequestor;\n this.walletAddress = options.walletAddress;\n this.chainCallTimeoutMs = validateTimeoutMs(\n options.chainCallTimeoutMs ?? 30_000,\n 'chainCallTimeoutMs',\n );\n this.requestTimeoutMs = this.chainCallTimeoutMs;\n this.wire = options.wire ?? {};\n this.isTransportFailure = options.isTransportFailure;\n this.answerOfRejectionHook = options.answerOfRejection;\n }\n\n /**\n * Submit a signed v2 DTO through the chain gateway.\n *\n * @throws GSwapSDKError `SUBMISSION_OUTCOME_UNKNOWN` when no answer was read: `params.reason` is\n * `'timeout'` (the POST exceeded `chainCallTimeoutMs`) or `'transport'` (the connection failed\n * or broke off). Either way the write MAY have been queued: keep `error.uniqueKey` and confirm\n * it. Whether to offer the user a Retry (a NEW request under a fresh key) is the app's policy;\n * the SDK states only that the outcome is unknown. Reads keep `TRANSPORT_ERROR`.\n */\n public async submit(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>>;\n public async submit(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction<Position | null>>;\n public async submit(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction> {\n // The synchronous swap was removed from the contract and from this SDK. This is the only\n // place the retired name may appear in the write path; the class guard in\n // tests/foundation.test.ts pins that nothing signs or submits it.\n if (method === 'Trade') {\n throw new GSwapSDKError('METHOD_NOT_SUPPORTED', { method });\n }\n const url = this.writeUrl(method);\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n const headers = buildRequestHeaders(this.wire, {\n json: true,\n fixed: walletAddress === undefined ? {} : { 'X-Wallet-Address': walletAddress },\n });\n const { response, body } = await this.post(method, url, headers, signedBody);\n // Every failure after an answer names the write it is about, so an app can confirm it and a\n // failure classifier can tell a write's HTTP failure from a read's.\n const uniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\n const context = responseContext(response, body, url, uniqueKey);\n\n if (!response.ok) {\n throw gatewayError(response, body, url, uniqueKey);\n }\n\n const envelope = asRecord(body);\n // `error: true` is the gateway refusing the write, even inside a 2xx. It is never a transaction.\n if (envelope?.['error'] === true) {\n throw new GSwapSDKError(\n 'GATEWAY_REPORTED_ERROR',\n { serverMessage: serverMessageOfBody(envelope) },\n context,\n );\n }\n const data = asRecord(envelope?.['data'] ?? envelope?.['Data']);\n if (data === undefined) {\n throw new GSwapSDKError('GATEWAY_DATA_MISSING', {}, context);\n }\n\n const transactionId = getStringProperty(data, 'transactionId');\n const mode = getStringProperty(data, 'mode');\n const rawTransactionId = data['transactionId'];\n const bodyBlockNumber = data['blockNumber'];\n const invalidMode = (): GSwapSDKError<'GATEWAY_MODE_INVALID'> =>\n new GSwapSDKError('GATEWAY_MODE_INVALID', {}, context);\n if (mode !== 'sync' && mode !== 'queued') {\n throw invalidMode();\n }\n if (\n ('transactionId' in data && typeof rawTransactionId !== 'string') ||\n (bodyBlockNumber !== undefined && bodyBlockNumber !== null && !isBlockNumber(bodyBlockNumber))\n ) {\n throw invalidMode();\n }\n if (method === 'RequestTrade' && mode === 'sync') {\n throw new GSwapSDKError('GATEWAY_SYNC_REQUEST_TRADE', {}, context);\n }\n if (method === 'RequestTrade' && mode === 'queued') {\n assertQueuedUnderSignedKey(response, body, url, data, signedBody);\n } else if (mode === 'queued' || !('result' in data)) {\n throw invalidMode();\n }\n\n // Only synchronous writes carry an executed chain result in the gateway response.\n if (mode === 'sync') {\n const embeddedResult = asRecord(data['result']);\n if (embeddedResult !== undefined) {\n const resultStatus = embeddedResult['Status'];\n if (resultStatus !== undefined && resultStatus !== 1) {\n throw GSwapSDKError.fromChainError(\n getStringProperty(embeddedResult, 'ErrorKey') ?? 'CHAIN_ERROR',\n getStringProperty(embeddedResult, 'Message') ?? '',\n context,\n );\n }\n }\n }\n\n const headerTransactionId = readHeader(response, 'x-transaction-id');\n const resolvedTransactionId =\n transactionId === undefined || transactionId === '' ? headerTransactionId : transactionId;\n const blockNumber: number | undefined =\n bodyBlockNumber === null || bodyBlockNumber === undefined\n ? readBlockNumberHeader(response)\n : isBlockNumber(bodyBlockNumber)\n ? bodyBlockNumber\n : undefined;\n return new SubmittedTransaction({\n method,\n uniqueKey,\n transactionId:\n resolvedTransactionId === undefined || resolvedTransactionId === ''\n ? null\n : resolvedTransactionId,\n blockNumber: blockNumber ?? null,\n mode,\n result: mode === 'queued' ? undefined : data['result'],\n envelope: body,\n dexBackendBaseUrl: this.dexBackendBaseUrl,\n httpRequestor: this.requestor,\n requestTimeoutMs: this.chainCallTimeoutMs,\n wire: this.wire,\n ...(options?.positionConfirmation === undefined\n ? {}\n : { positionConfirmation: options.positionConfirmation }),\n });\n }\n\n /**\n * Submit a signed v2 DTO as a SHADOW (dark) write: the same route and body as {@link submit},\n * plus `X-Wallet-Address` and `X-Shadow: true`, so defi-backend marks the transaction private\n * before it reaches the contract. The wallet address is required (the backend resolves the\n * owner from it).\n *\n * Unlike `submit`, EVERY HTTP status resolves: the result is the raw `{ httpStatus, body }`,\n * because shadow failures are classified from the status together with the body's `code`\n * (`SHADOW_UNAVAILABLE`, `SHADOW_DISABLED`, `SHADOW_UNSUPPORTED_TYPE`, `SHADOW_RELAY_REJECTED`);\n * see `readShadowSubmitOutcome`. Only a failure to get an answer rejects, and it rejects with\n * `SUBMISSION_OUTCOME_UNKNOWN` (`params.reason` `'timeout'` or `'transport'`): the request may\n * have been accepted. Every error it throws has `error.shadow === true`, and a non-SDK object\n * that escapes (your requestor's own rejection) answers `isShadowError(error)`.\n *\n * @example\n * ```ts\n * const result = await gateway.submitShadow('RequestTrade', signedDto, { walletAddress });\n * const outcome = readShadowSubmitOutcome('RequestTrade', signedDto, result);\n * ```\n */\n public async submitShadow(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<ShadowSubmitResult> {\n return shadowFailures(() => this.sendShadow(method, signedBody, options));\n }\n\n private async sendShadow(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<ShadowSubmitResult> {\n if (method === 'Trade') {\n throw new GSwapSDKError('METHOD_NOT_SUPPORTED', { method });\n }\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n if (walletAddress === undefined) {\n throw new GSwapSDKError('SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS', {});\n }\n // Header order is frontend_v2's: X-Wallet-Address, then X-Shadow.\n const headers = buildRequestHeaders(this.wire, {\n json: true,\n fixed: { 'X-Wallet-Address': walletAddress, 'X-Shadow': 'true' },\n });\n const { response, body } = await this.post(method, this.writeUrl(method), headers, signedBody);\n return { httpStatus: response.status, body };\n }\n\n private writeUrl(method: string): string {\n return `${this.dexBackendBaseUrl}/v1/chain/asset/dex-contract/${method}`;\n }\n\n /**\n * POSTs a signed body and reads the answer. Neither a timeout nor a transport failure proves the\n * write was not submitted, so both are `SUBMISSION_OUTCOME_UNKNOWN` (`params.reason` says which),\n * never a retryable read failure. A rejection that is an answer (see `isTransportFailure`) is\n * rethrown unchanged.\n */\n private async post(\n method: string,\n url: string,\n headers: Record<string, string>,\n signedBody: Record<string, unknown>,\n ): Promise<{ response: HTTPResponse; body: unknown }> {\n // Serialized BEFORE the request is attempted and outside the try below: a body that cannot be\n // serialized (a cycle, a BigInt) was never sent, so it must not be mistaken for a transport\n // failure the app's `isTransportFailure` might claim, which would call it \"maybe queued\".\n let payload: string;\n try {\n payload = JSON.stringify(signedBody);\n } catch (cause: unknown) {\n throw new GSwapSDKError('SIGNING_FAILED', { method, reason: 'failed' }, { cause });\n }\n const outcomeUnknown = (\n reason: SubmissionOutcomeUnknownReason,\n cause: unknown,\n ): GSwapSDKError<'SUBMISSION_OUTCOME_UNKNOWN'> =>\n new GSwapSDKError(\n 'SUBMISSION_OUTCOME_UNKNOWN',\n { reason },\n { uniqueKey: getStringProperty(signedBody, 'uniqueKey') ?? '', url, cause },\n );\n let response: HTTPResponse;\n try {\n response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers,\n body: payload,\n },\n this.chainCallTimeoutMs,\n );\n } catch (error: unknown) {\n if (isGSwapError(error, 'REQUEST_TIMEOUT')) throw outcomeUnknown('timeout', error);\n if (isGSwapError(error, 'TRANSPORT_ERROR') || this.isTransportRejection(error)) {\n throw outcomeUnknown('transport', error);\n }\n // A rejection that IS an HTTP answer (the app's interceptor rejecting on a non-2xx, a\n // version wall) is handled exactly as the answer would have been, so the app does not\n // rebuild the SDK's error from it. Anything else the app's requestor threw reaches the\n // caller unchanged.\n const answered = this.answerOfRejection(error);\n if (answered !== undefined) return answered;\n throw error;\n }\n try {\n return { response, body: await readResponseBody(response) };\n } catch (error: unknown) {\n // The answer's headers arrived but its body broke off: the status alone does not say what\n // the gateway did with the write.\n throw outcomeUnknown('transport', error);\n }\n }\n\n /**\n * The HTTP answer a rejection of the app's requestor stands for, as the response the gateway\n * would have read. `undefined` when the app named none, when its hook throws, or when what it\n * returned is not an HTTP status; then the rejection is not an answer.\n */\n private answerOfRejection(error: unknown): { response: HTTPResponse; body: unknown } | undefined {\n let answer: RejectedAnswer | undefined;\n try {\n answer = this.answerOfRejectionHook?.(error);\n } catch {\n return undefined;\n }\n if (answer === undefined) return undefined;\n const { status, body, headers } = answer;\n if (!Number.isInteger(status) || status < 100 || status > 599) return undefined;\n const text = typeof body === 'string' ? body : '';\n const response: HTTPResponse = {\n ok: status >= 200 && status < 300,\n status,\n json: async () => body,\n text: async () => text,\n headers: headers ?? {},\n };\n return { response, body };\n }\n\n private isTransportRejection(error: unknown): boolean {\n try {\n return this.isTransportFailure?.(error) === true;\n } catch {\n return false;\n }\n }\n\n /** Expose the requestor for sibling read services that share this gateway transport. */\n public get httpRequestor(): HttpRequestor {\n return this.requestor;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/u, '');\n}\n\nfunction responseContext(\n response: HTTPResponse,\n body: unknown,\n url: string,\n uniqueKey?: string,\n): GSwapErrorContext {\n return {\n status: response.status,\n body,\n url,\n ...(uniqueKey === undefined || uniqueKey === '' ? {} : { uniqueKey }),\n };\n}\n\n/**\n * A queued RequestTrade acknowledgement is a swap only if it names the exact key that was signed:\n * the key is the only handle `confirm()` and every recovery path have on the trade, so an\n * acknowledgement without it (or with another) proves nothing about THIS request. Fails closed:\n * an absent echo is as unacceptable as a wrong one. The code is `MISSING_UNIQUE_KEY` or\n * `UNIQUE_KEY_MISMATCH`, `error.uniqueKey` the signed key.\n *\n * Only RequestTrade is checked: a synchronous write is proven by its own executed chain result,\n * and the apps never required an echo for it.\n */\nfunction assertQueuedUnderSignedKey(\n response: HTTPResponse,\n body: unknown,\n url: string,\n data: Record<string, unknown>,\n signedBody: Record<string, unknown>,\n): void {\n const signedUniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\n const echoed = data['uniqueKey'];\n if (typeof echoed === 'string' && echoed !== '' && echoed === signedUniqueKey) return;\n const missing = echoed === undefined || echoed === null || echoed === '';\n const context: GSwapErrorContext = {\n ...responseContext(response, body, url),\n uniqueKey: signedUniqueKey,\n };\n throw missing\n ? new GSwapSDKError('MISSING_UNIQUE_KEY', {}, context)\n : new GSwapSDKError('UNIQUE_KEY_MISMATCH', {}, context);\n}\n\nfunction gatewayError(\n response: HTTPResponse,\n body: unknown,\n url: string,\n uniqueKey: string,\n): GSwapSDKError {\n // The version wall is decided by the status alone, whatever the body names: nothing was queued.\n if (response.status === UPDATE_REQUIRED_STATUS) {\n return new GSwapSDKError(\n 'UPDATE_REQUIRED',\n { status: response.status },\n responseContext(response, body, url, uniqueKey),\n );\n }\n const object = asRecord(body);\n const nested = getObjectProperty(body, 'error');\n const code =\n getStringProperty(object, 'code') ??\n getStringProperty(nested, 'code') ??\n getStringProperty(nested, 'ErrorKey') ??\n 'HTTP_ERROR';\n // Missing server text is an empty param, never SDK-written English standing in for it. A body\n // that is not JSON (an HTML 502 page, a WAF block) is kept as error.bodyText.\n const message = serverMessageOfBody(body);\n const retryAfterMs = response.status === 429 ? readRetryAfter(response) : undefined;\n if (code === 'HTTP_ERROR') {\n return new GSwapSDKError(\n 'HTTP_ERROR',\n { status: response.status, url, serverMessage: message },\n responseContext(response, body, url, uniqueKey),\n );\n }\n return GSwapSDKError.fromGatewayBounce(\n code,\n message,\n response.status,\n body,\n url,\n retryAfterMs,\n uniqueKey === '' ? undefined : uniqueKey,\n );\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction isBlockNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n","/** SDK deployment environment. */\nexport type GSwapEnv = 'prod' | 'stage';\n\n/** Backend URLs used by one SDK deployment environment. */\nexport interface GSwapEnvironmentConfig {\n dexBackendBaseUrl: string;\n /** The realtime stream endpoint (raw WebSocket, JSON-RPC 2.0). */\n dexBackendWsUrl: string;\n}\n\n/** Built-in GalaSwap deployment environments. */\nexport const GSWAP_ENVIRONMENTS: Readonly<Record<GSwapEnv, GSwapEnvironmentConfig>> = {\n prod: {\n dexBackendBaseUrl: 'https://dex-backend-prod1.defi.gala.com',\n dexBackendWsUrl: 'wss://dex-backend-prod1.defi.gala.com/ws',\n },\n stage: {\n dexBackendBaseUrl: 'https://swap-backend.stage.defi.ovh.gala.com',\n dexBackendWsUrl: 'wss://swap-backend.stage.defi.ovh.gala.com/ws',\n },\n};\n","import debug from 'debug';\n\nexport const debugLog = debug('GSWAP_SDK');\n","/** Options for {@link ReconnectionBackoff}. */\nexport interface ReconnectionBackoffOptions {\n /** Attempts allowed before giving up. */\n maxAttempts: number;\n /** Delay before the first attempt, in milliseconds. */\n baseDelayMs: number;\n /** Ceiling the doubling delay never exceeds, in milliseconds. */\n maxDelayMs?: number;\n}\n\n/** Counts reconnect attempts and doubles the delay between them, up to a ceiling. */\nexport class ReconnectionBackoff {\n private attempts = 0;\n private delayMs: number;\n private readonly maxDelayMs: number;\n\n constructor(private readonly options: ReconnectionBackoffOptions) {\n this.delayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? 30_000;\n }\n\n /** Whether another attempt is allowed. */\n shouldRetry(): boolean {\n return this.attempts < this.options.maxAttempts;\n }\n\n /** The delay to wait before the next attempt. */\n nextDelayMs(): number {\n return this.delayMs;\n }\n\n /** Record that an attempt is being made, and double the next delay. */\n recordAttempt(): void {\n this.attempts += 1;\n this.delayMs = Math.min(this.delayMs * 2, this.maxDelayMs);\n }\n\n /** Forget every attempt: the connection is healthy again. */\n reset(): void {\n this.attempts = 0;\n this.delayMs = this.options.baseDelayMs;\n }\n\n get attemptCount(): number {\n return this.attempts;\n }\n\n get maxAttempts(): number {\n return this.options.maxAttempts;\n }\n}\n","import { GSWAP_ENVIRONMENTS } from '../types/env.js';\nimport { debugLog } from '../utils/debug.js';\nimport { ReconnectionBackoff } from '../utils/reconnection.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\nconst GDEX_SUBPROTOCOL = 'gdex.jsonrpc.v1';\nconst RATE_LIMITED = -32003;\nconst MAX_RESUBSCRIBE_RATE_RETRIES = 5;\nconst WEBSOCKET_OPEN = 1;\n\n/** Options for {@link GdexStreamService}. */\nexport interface GdexStreamConfig {\n /** Stream endpoint. Defaults to production (`wss://dex-backend-prod1.defi.gala.com/ws`). */\n url?: string | undefined;\n /** Reconnect attempts after an unexpected close. Default 5. */\n reconnectAttempts?: number | undefined;\n /** Delay before the first reconnect attempt; doubles each attempt. Default 2000 ms. */\n reconnectDelayMs?: number | undefined;\n /** How long a request waits for its response. Default 15000 ms. */\n requestTimeoutMs?: number | undefined;\n /**\n * A standards-compatible WebSocket constructor. Required on Node.js older than 22, which has no\n * global `WebSocket` (pass the one from the `ws` package).\n */\n webSocketImpl?: unknown;\n /**\n * Presents `x-api-key` on the WebSocket upgrade request, which defi-backend uses to serve the\n * PRIVILEGED view (shadow swaps with the wallet unredacted). Without it, or with a wrong key, the\n * connection is simply public: the server never says whether a privileged mode exists.\n *\n * It must travel as an HTTP header, because the server reads no other credential, and a browser\n * `WebSocket` cannot set headers. So this option needs a constructor that accepts them as its\n * third argument (`{ headers }`): the `ws` package on Node.js, or React Native's built-in\n * `WebSocket`. It therefore REQUIRES `webSocketImpl` (the platform default is never assumed to\n * honor headers, and a key that is silently dropped would look like a working privileged\n * connection); the constructor throws otherwise. Use it from server-side code only: a key\n * shipped inside a browser or app bundle is not a secret. Browser clients stay public.\n */\n apiKey?: string | undefined;\n}\n\n/** The channels of the realtime stream. */\nexport type GdexChannel = 'pool' | 'balance' | 'poolCreated' | 'swap' | 'liquidity' | 'blocks';\n\n/** A pool named by its two token class keys (pipe form) and fee tier. */\nexport interface GdexPoolKey {\n token0ClassKey: string;\n token1ClassKey: string;\n fee: number;\n}\n\n/** A pool named either by its key or by its hash (`v2:<poolRef>` for a v2 pool). */\nexport type GdexPoolSelector = { pool: GdexPoolKey } | { poolHash: string };\n\n/** Options common to every subscription. */\nexport interface GdexSubscribeOptions {\n /** Send the current state right after the subscribe response. */\n snapshot?: boolean | undefined;\n /** Trim each event to these fields; identity and envelope fields always stay. */\n fields?: string[] | undefined;\n}\n\n/** Filters for {@link GdexStreamService.subscribeLiquidity}; all optional. */\nexport interface GdexLiquidityFilter {\n /** Only this pool, named by its key. */\n pool?: GdexPoolKey | undefined;\n /** Only this pool, named by its hash (`v2:<poolRef>` for a v2 pool). */\n poolHash?: string | undefined;\n /** Only events for this LP wallet (the position's owner). */\n owner?: string | undefined;\n /** Only this transaction. */\n transactionId?: string | undefined;\n /** Contract version filter. */\n version?: 'v1' | 'v2' | 'all' | undefined;\n}\n\n/** One committed add, remove or collect, as the `liquidity` channel reports it. */\nexport interface GdexLiquidityEvent {\n version: 'v1' | 'v2';\n pool: GdexPoolKey;\n poolHash: string;\n transactionId: string;\n /** `add`, `remove` or `collect`. */\n action: 'add' | 'remove' | 'collect';\n /** The position's owner (the LP wallet). */\n owner: string;\n /** v1: the position id. v2: the chain position key `<pool>|<tickLow>|<tickHigh>|<owner>`. */\n positionId?: string;\n tickLower?: number;\n tickUpper?: number;\n /** v2 only: the position's liquidity after the operation; `\"0\"` means it is closed. */\n liquidityAfter?: string;\n /** Principal moved: deposited by an add, withdrawn by a remove, `\"0\"` for a collect. */\n amount0: string;\n amount1: string;\n /** Fees paid out. v2: always present (`\"0\"` for an add). v1: present on a collect only. */\n fees0?: string;\n fees1?: string;\n /** v2 only. */\n token0Symbol?: string;\n token1Symbol?: string;\n blockNumber: number;\n timestamp: string;\n}\n\nconst LIQUIDITY_ACTIONS: readonly unknown[] = ['add', 'remove', 'collect'];\n\n/** Whether a stream payload carries every field of a {@link GdexLiquidityEvent}. */\nexport function isGdexLiquidityEvent(\n value: Record<string, unknown>,\n): value is Record<string, unknown> & GdexLiquidityEvent {\n const { pool } = value;\n return (\n (value['version'] === 'v1' || value['version'] === 'v2') &&\n typeof pool === 'object' &&\n pool !== null &&\n typeof value['poolHash'] === 'string' &&\n typeof value['transactionId'] === 'string' &&\n LIQUIDITY_ACTIONS.includes(value['action']) &&\n typeof value['owner'] === 'string' &&\n typeof value['amount0'] === 'string' &&\n typeof value['amount1'] === 'string' &&\n typeof value['blockNumber'] === 'number' &&\n typeof value['timestamp'] === 'string'\n );\n}\n\n/** A live subscription. */\nexport interface GdexSubscription {\n subscriptionId: string;\n unsubscribe(): Promise<void>;\n}\n\n/** A JSON-RPC error answered by the stream. */\nexport class GdexStreamError extends Error {\n readonly code: number;\n readonly data?: unknown;\n\n constructor(code: number, message: string, data?: unknown) {\n super(message);\n this.name = 'GdexStreamError';\n this.code = code;\n if (data !== undefined) this.data = data;\n }\n}\n\ninterface WebSocketLike {\n readonly readyState: number;\n send(data: string): void;\n close(code?: number, reason?: string): void;\n onopen: ((event: unknown) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onclose: ((event: { code?: number; reason?: string }) => void) | null;\n onerror: ((event: unknown) => void) | null;\n}\n\ninterface WebSocketConstructor {\n new (\n url: string,\n protocols?: string | string[],\n options?: { headers: Record<string, string> },\n ): WebSocketLike;\n}\n\ninterface PendingRequest {\n resolve(value: unknown): void;\n reject(error: Error): void;\n timeout: ReturnType<typeof setTimeout>;\n /**\n * Runs SYNCHRONOUSLY when the response frame is handled, before any frame that follows it in\n * the same read. Subscriptions register here: the server writes a snapshot right after the\n * subscribe response, and a runtime that delivers both frames without yielding to microtasks\n * (Node's `ws` does, for frames in one chunk) would otherwise drop the snapshot because the\n * awaiting caller has not registered the subscription yet.\n */\n onResult?: ((value: unknown) => void) | undefined;\n}\n\ntype EventCallback = (event: Record<string, unknown>) => void;\n\ninterface ActiveSubscription {\n serverId: string;\n readonly params: Record<string, unknown>;\n readonly callback: EventCallback;\n readonly handle: MutableGdexSubscription;\n active: boolean;\n}\n\ninterface MutableGdexSubscription extends GdexSubscription {\n subscriptionId: string;\n}\n\nfunction readSubscriptionId(value: unknown): string {\n const id =\n typeof value === 'object' && value !== null\n ? (value as { subscriptionId?: unknown }).subscriptionId\n : undefined;\n if (typeof id !== 'string') {\n throw new GdexStreamError(-32603, 'GDEX subscribe response is missing its subscriptionId');\n }\n return id;\n}\n\ninterface JsonRpcResponse {\n id?: unknown;\n method?: unknown;\n result?: unknown;\n error?: { code?: unknown; message?: unknown; data?: unknown };\n params?: unknown;\n}\n\n/**\n * Client for the gSwap realtime stream (gdex WebSocket Protocol v1): JSON-RPC 2.0 over one raw\n * WebSocket, with automatic reconnect and resubscribe.\n *\n * @example\n * ```typescript\n * const stream = new GdexStreamService();\n * await stream.connect();\n * await stream.subscribeLiquidity(event => console.log(event.action, event.owner), {\n * owner: 'client|618ae395c1c653111d3315be',\n * });\n * ```\n */\nexport class GdexStreamService {\n private readonly url: string;\n private readonly requestTimeoutMs: number;\n private readonly apiKey: string | undefined;\n private readonly webSocketConstructor: WebSocketConstructor;\n private readonly backoff: ReconnectionBackoff;\n private socket: WebSocketLike | undefined;\n private connectPromise: Promise<void> | undefined;\n private nextRequestId = 0;\n private readonly pending = new Map<number, PendingRequest>();\n private readonly subscriptionsByServerId = new Map<string, ActiveSubscription>();\n private readonly activeSubscriptions = new Set<ActiveSubscription>();\n private intentionalClose = false;\n private reconnecting = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private reconnectDelayResolve: (() => void) | undefined;\n\n constructor(config: GdexStreamConfig = {}) {\n this.url = config.url ?? GSWAP_ENVIRONMENTS.prod.dexBackendWsUrl;\n this.requestTimeoutMs = config.requestTimeoutMs ?? 15_000;\n this.backoff = new ReconnectionBackoff({\n maxAttempts: config.reconnectAttempts ?? 5,\n baseDelayMs: config.reconnectDelayMs ?? 2_000,\n });\n\n const implementation =\n config.webSocketImpl ?? (globalThis as { WebSocket?: unknown }).WebSocket;\n if (typeof implementation !== 'function') {\n throw new GSwapSDKError('STREAM_WEBSOCKET_UNAVAILABLE', {});\n }\n this.webSocketConstructor = implementation as WebSocketConstructor;\n if (config.apiKey !== undefined) {\n if (config.apiKey === '' || config.webSocketImpl === undefined) {\n throw new GSwapSDKError('STREAM_API_KEY_UNUSABLE', {});\n }\n this.apiKey = config.apiKey;\n }\n }\n\n /** Open the connection. Resolves at once when already connected. */\n connect(): Promise<void> {\n if (this.isConnected()) return Promise.resolve();\n if (this.connectPromise) return this.connectPromise;\n this.intentionalClose = false;\n this.clearReconnectTimer();\n this.connectPromise = this.openSocket();\n return this.connectPromise;\n }\n\n /** Close the connection and stop reconnecting. */\n disconnect(): void {\n this.intentionalClose = true;\n this.reconnecting = false;\n this.clearReconnectTimer();\n this.rejectPending(new GSwapSDKError('STREAM_DISCONNECTED', {}));\n const socket = this.socket;\n this.socket = undefined;\n this.connectPromise = undefined;\n socket?.close(1000, 'client disconnect');\n }\n\n isConnected(): boolean {\n return this.socket?.readyState === WEBSOCKET_OPEN;\n }\n\n /** Raw JSON-RPC escape hatch. */\n request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T> {\n return this.send<T>(method, params);\n }\n\n private send<T>(\n method: string,\n params: Record<string, unknown> | undefined,\n onResult?: (value: unknown) => void,\n ): Promise<T> {\n if (!this.isConnected() || !this.socket) {\n return Promise.reject(new GSwapSDKError('STREAM_NOT_CONNECTED', {}));\n }\n\n const id = ++this.nextRequestId;\n const frame: Record<string, unknown> = { jsonrpc: '2.0', id, method };\n if (params !== undefined) frame['params'] = params;\n\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(\n new GSwapSDKError('STREAM_REQUEST_TIMEOUT', { method, timeoutMs: this.requestTimeoutMs }),\n );\n }, this.requestTimeoutMs);\n this.pending.set(id, { resolve: (value) => resolve(value as T), reject, timeout, onResult });\n\n try {\n this.socket?.send(JSON.stringify(frame));\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(id);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n serverInfo(): Promise<Record<string, unknown>> {\n return this.request('gdex_serverInfo');\n }\n\n ping(): Promise<{ pong: boolean; serverTime: string }> {\n return this.request('gdex_ping');\n }\n\n getPool(selector: GdexPoolSelector): Promise<Record<string, unknown>> {\n return this.request('gdex_getPool', selector);\n }\n\n getBalance(owner: string, tokenClassKey?: string): Promise<Record<string, unknown>> {\n return this.request(\n 'gdex_getBalance',\n tokenClassKey === undefined ? { owner } : { owner, tokenClassKey },\n );\n }\n\n getPositions(opts: {\n owner: string;\n pool?: GdexPoolKey;\n poolHash?: string;\n limit?: number;\n bookmark?: string;\n }): Promise<{ positions: Record<string, unknown>[]; bookmark: string }> {\n return this.request('gdex_getPositions', opts);\n }\n\n getBlockHeight(): Promise<{ blockNumber: number; timestamp: string }> {\n return this.request('gdex_getBlockHeight');\n }\n\n quote(params: {\n tokenIn: string;\n tokenOut: string;\n fee?: number;\n amountIn?: string;\n amountOut?: string;\n }): Promise<Record<string, unknown>> {\n return this.request('gdex_quote', params);\n }\n\n getToken(tokenClassKey: string): Promise<Record<string, unknown>> {\n return this.request('gdex_getToken', { tokenClassKey });\n }\n\n /** One event per committed swap. Omit the pool to receive every pool's swaps. */\n subscribeSwaps(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & {\n pool?: GdexPoolKey;\n poolHash?: string;\n transactionId?: string;\n } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('swap', cb, opts);\n }\n\n /**\n * State changes of one pool (price, tick, reserves, liquidity). These events carry no acting wallet:\n * on v2 `creator` is whoever created the pool, not whoever just traded or added liquidity. For\n * \"who did it\", use {@link subscribeLiquidity} (`owner`) or {@link subscribeSwaps} (`sender`).\n */\n subscribePool(\n selector: GdexPoolSelector,\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('pool', cb, { ...selector, ...opts });\n }\n\n /** Balance changes of one wallet. */\n subscribeBalances(\n owner: string,\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & { tokenClassKey?: string } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('balance', cb, { owner, ...opts });\n }\n\n /** Each newly created pool. */\n subscribePoolCreated(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & { tokenClassKey?: string } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('poolCreated', cb, opts);\n }\n\n /**\n * One event per committed AddLiquidity, RemoveLiquidity and CollectPositionFees, on both contract\n * versions. Every filter is optional; with none, every liquidity event arrives. These events never\n * appear on {@link subscribeSwaps}. There is no snapshot: read positions with {@link getPositions}.\n * Deduplicate by `transactionId` plus `positionId`: a v1 BatchSubmit can hold several operations\n * under one transaction id.\n */\n subscribeLiquidity(\n cb: (event: GdexLiquidityEvent) => void,\n opts: GdexSubscribeOptions & GdexLiquidityFilter = {},\n ): Promise<GdexSubscription> {\n return this.subscribe(\n 'liquidity',\n (event) => {\n if (isGdexLiquidityEvent(event)) cb(event);\n else debugLog('Ignoring a malformed liquidity event from the GDEX stream');\n },\n opts,\n );\n }\n\n /** Each block-height advance. */\n subscribeBlocks(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('blocks', cb, opts);\n }\n\n private openSocket(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let opened = false;\n const socket =\n this.apiKey === undefined\n ? new this.webSocketConstructor(this.url, GDEX_SUBPROTOCOL)\n : new this.webSocketConstructor(this.url, GDEX_SUBPROTOCOL, {\n headers: { 'x-api-key': this.apiKey },\n });\n this.socket = socket;\n\n socket.onopen = () => {\n if (this.socket !== socket) return;\n opened = true;\n this.connectPromise = undefined;\n if (!this.reconnecting) this.backoff.reset();\n debugLog('Connected to GDEX stream');\n resolve();\n };\n socket.onmessage = (event) => this.handleMessage(event.data);\n socket.onerror = () => {\n if (!opened) reject(new GSwapSDKError('STREAM_CONNECT_FAILED', { url: this.url }));\n };\n socket.onclose = (event) => {\n if (this.socket !== socket) return;\n this.socket = undefined;\n this.connectPromise = undefined;\n if (!opened) {\n reject(new GSwapSDKError('STREAM_CLOSED_BEFORE_CONNECT', { closeCode: event.code ?? 0 }));\n }\n this.rejectPending(\n new GSwapSDKError('STREAM_CONNECTION_CLOSED', { closeCode: event.code ?? 0 }),\n );\n if (!this.intentionalClose && !this.reconnecting) this.startReconnectLoop();\n };\n });\n }\n\n private handleMessage(data: unknown): void {\n if (typeof data !== 'string') {\n debugLog('Ignoring non-text GDEX WebSocket frame');\n return;\n }\n\n let message: JsonRpcResponse;\n try {\n message = JSON.parse(data) as JsonRpcResponse;\n } catch {\n debugLog('Ignoring invalid JSON from GDEX stream');\n return;\n }\n\n if (typeof message.id === 'number') {\n const pending = this.pending.get(message.id);\n if (!pending) return;\n clearTimeout(pending.timeout);\n this.pending.delete(message.id);\n if (message.error) {\n const code = typeof message.error.code === 'number' ? message.error.code : -32603;\n const errorMessage =\n typeof message.error.message === 'string' ? message.error.message : 'GDEX request failed';\n pending.reject(new GdexStreamError(code, errorMessage, message.error.data));\n } else {\n try {\n pending.onResult?.(message.result);\n } catch (error) {\n pending.reject(error instanceof Error ? error : new Error(String(error)));\n return;\n }\n pending.resolve(message.result);\n }\n return;\n }\n\n if (message.method !== 'gdex_subscription' || !this.isRecord(message.params)) return;\n const subscriptionId = message.params['subscription'];\n const result = message.params['result'];\n if (typeof subscriptionId !== 'string' || !this.isRecord(result)) return;\n const subscription = this.subscriptionsByServerId.get(subscriptionId);\n if (!subscription?.active) return;\n try {\n subscription.callback(result);\n } catch (error) {\n debugLog('GDEX subscription callback failed', error);\n }\n }\n\n private async subscribe(\n channel: GdexChannel,\n callback: EventCallback,\n options: object,\n ): Promise<GdexSubscription> {\n const params: Record<string, unknown> = { channel, ...options };\n const handle: MutableGdexSubscription = {\n subscriptionId: '',\n unsubscribe: async () => this.unsubscribe(subscription),\n };\n const subscription: ActiveSubscription = {\n serverId: '',\n params,\n callback,\n handle,\n active: true,\n };\n // Registered inside the response handler, not after the await: see PendingRequest.onResult.\n await this.send('gdex_subscribe', params, (value) => {\n const serverId = readSubscriptionId(value);\n subscription.serverId = serverId;\n handle.subscriptionId = serverId;\n this.activeSubscriptions.add(subscription);\n this.subscriptionsByServerId.set(serverId, subscription);\n });\n return handle;\n }\n\n private async unsubscribe(subscription: ActiveSubscription): Promise<void> {\n if (!subscription.active) return;\n subscription.active = false;\n this.activeSubscriptions.delete(subscription);\n this.subscriptionsByServerId.delete(subscription.serverId);\n if (this.isConnected()) {\n await this.request('gdex_unsubscribe', { subscriptionId: subscription.serverId });\n }\n }\n\n private startReconnectLoop(): void {\n if (this.reconnecting || this.intentionalClose) return;\n this.reconnecting = true;\n void this.reconnectLoop();\n }\n\n private async reconnectLoop(): Promise<void> {\n while (!this.intentionalClose && this.backoff.shouldRetry()) {\n const delay = this.backoff.nextDelayMs();\n this.backoff.recordAttempt();\n debugLog(\n `GDEX reconnect attempt ${this.backoff.attemptCount}/${this.backoff.maxAttempts} in ${delay}ms`,\n );\n await this.waitForReconnectDelay(delay);\n // `disconnect()` can run while the asynchronous delay is pending.\n if (this.intentionalClose) break;\n\n try {\n await this.openSocket();\n await this.resubscribeAll();\n this.backoff.reset();\n this.reconnecting = false;\n return;\n } catch (error) {\n debugLog(\n `GDEX reconnect failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n this.reconnecting = false;\n if (!this.intentionalClose) debugLog('GDEX reconnection attempts exhausted');\n }\n\n private async resubscribeAll(): Promise<void> {\n this.subscriptionsByServerId.clear();\n for (const subscription of this.activeSubscriptions) {\n if (!subscription.active) continue;\n const params = { ...subscription.params, snapshot: true };\n const result = await this.resubscribeWithRateLimitRetry(params, (value) => {\n const serverId = readSubscriptionId(value);\n // The consumer can unsubscribe while the asynchronous subscribe request is pending.\n if (!subscription.active) return;\n subscription.serverId = serverId;\n subscription.handle.subscriptionId = serverId;\n this.subscriptionsByServerId.set(serverId, subscription);\n });\n if (!subscription.active) {\n await this.request('gdex_unsubscribe', { subscriptionId: result.subscriptionId });\n }\n }\n }\n\n private async resubscribeWithRateLimitRetry(\n params: Record<string, unknown>,\n onResult: (value: unknown) => void,\n ): Promise<{ subscriptionId: string }> {\n for (let attempt = 0; ; attempt++) {\n try {\n return await this.send('gdex_subscribe', params, onResult);\n } catch (error) {\n if (\n !(error instanceof GdexStreamError) ||\n error.code !== RATE_LIMITED ||\n attempt >= MAX_RESUBSCRIBE_RATE_RETRIES\n ) {\n throw error;\n }\n const retryAfterMs = this.readRetryAfterMs(error.data);\n debugLog(`GDEX resubscribe rate limited; retrying in ${retryAfterMs}ms`);\n await new Promise<void>((resolve) => setTimeout(resolve, retryAfterMs));\n }\n }\n }\n\n private waitForReconnectDelay(delay: number): Promise<void> {\n return new Promise((resolve) => {\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n this.reconnectDelayResolve = undefined;\n resolve();\n }, delay);\n this.reconnectDelayResolve = resolve;\n });\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer !== undefined) clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n const resolve = this.reconnectDelayResolve;\n this.reconnectDelayResolve = undefined;\n resolve?.();\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n pending.reject(error);\n }\n this.pending.clear();\n }\n\n private readRetryAfterMs(data: unknown): number {\n if (\n !this.isRecord(data) ||\n typeof data['retryAfterMs'] !== 'number' ||\n data['retryAfterMs'] < 0\n )\n return 1_000;\n return data['retryAfterMs'];\n }\n\n private isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n}\n","import type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { debugLog } from '../utils/debug.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport {\n buildQueryString,\n buildRequestHeaders,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n} from '../utils/transport.js';\n\nexport class HttpClient {\n /**\n * Create an HTTP client around fetch or an injected requestor. `wire` selects the query\n * encoding and the `User-Agent` (see {@link WireOptions}).\n */\n constructor(\n private readonly httpRequestor: HttpRequestor = fetchRequestor,\n private readonly timeoutMs = 30_000,\n private readonly wire: WireOptions = {},\n ) {}\n\n private async sendRequest<TReturnType>(\n method: 'POST' | 'GET',\n baseUrl: string,\n basePath: string,\n endpoint: string,\n body?: unknown,\n options?: Pick<RequestInit, 'signal'>,\n ): Promise<TReturnType> {\n const url = `${baseUrl}${basePath}${endpoint}`;\n debugLog(`Sending request to ${url} with body:`, body);\n\n const hasBody = Boolean(body);\n const response = await requestWithTimeout(\n this.httpRequestor,\n url,\n {\n method,\n // Content-Type describes a body, so a GET carries none: it also keeps a browser's\n // cross-origin GET a simple request instead of forcing a CORS preflight.\n headers: buildRequestHeaders(this.wire, { json: hasBody }),\n ...(hasBody ? { body: JSON.stringify(body) } : {}),\n ...(options?.signal === undefined ? {} : { signal: options.signal }),\n },\n this.timeoutMs,\n );\n\n if (!response.ok) {\n throw await GSwapSDKError.fromErrorResponse(url, response);\n }\n\n const json = await readResponseBody(response);\n debugLog(`Response from ${baseUrl}${basePath}${endpoint}:`, json);\n\n return json as TReturnType;\n }\n\n /** Send a JSON POST request and decode its response. */\n async sendPostRequest<TReturnType>(\n baseUrl: string,\n basePath: string,\n endpoint: string,\n body: unknown,\n ): Promise<TReturnType> {\n return this.sendRequest('POST', baseUrl, basePath, endpoint, body);\n }\n\n /** Send a GET request with URL-encoded query parameters and decode its response. */\n async sendGetRequest<TReturnType>(\n baseUrl: string,\n basePath: string,\n endpoint: string,\n params?: Record<string, string>,\n options?: Pick<RequestInit, 'signal'>,\n ): Promise<TReturnType> {\n const endpointWithParams = params\n ? `${endpoint}?${buildQueryString(params, this.wire.queryEncoding)}`\n : endpoint;\n\n return this.sendRequest('GET', baseUrl, basePath, endpointWithParams, undefined, options);\n }\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** One row of a list answer that the SDK skipped because it was not usable. */\nexport interface InvalidEntry {\n /** Which read the row came from. */\n source: 'pools' | 'symbols' | 'positions';\n /** Position of the row in the answer's array. */\n index: number;\n /** The row exactly as the backend sent it. */\n entry: unknown;\n /** Why it was skipped, in words. */\n reason: string;\n}\n\n/**\n * Called once per skipped row, in order, before the read resolves. It is a diagnostics hook: what it\n * does, or throws, never changes the result of the read.\n */\nexport type InvalidEntryHandler = (invalid: InvalidEntry) => void;\n\n/** The outcome of reading one row. */\nexport type EntryParse<T> = { ok: true; value: T } | { ok: false; reason: string };\n\n/** A usable row. */\nexport function entryOk<T>(value: T): EntryParse<T> {\n return { ok: true, value };\n}\n\n/** An unusable row, with the reason it is reported under. */\nexport function entryRejected<T>(reason: string): EntryParse<T> {\n return { ok: false, reason };\n}\n\n/**\n * Reads a list answer row by row: a row that cannot be used is skipped and reported, instead of\n * rejecting the whole list because of one bad row. An answer that is not a list at all is still\n * `INVALID_CHAIN_RESPONSE`: nothing in it can be trusted.\n */\nexport function readEntries<T>(\n source: InvalidEntry['source'],\n data: unknown,\n parse: (entry: unknown) => EntryParse<T>,\n onInvalidEntry?: InvalidEntryHandler,\n): T[] {\n if (!Array.isArray(data)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: `${source} list` },\n { body: data },\n );\n }\n const rows: T[] = [];\n (data as unknown[]).forEach((entry, index) => {\n const parsed = parse(entry);\n if (parsed.ok) {\n rows.push(parsed.value);\n return;\n }\n try {\n onInvalidEntry?.({ source, index, entry, reason: parsed.reason });\n } catch {\n // A diagnostics hook must not turn a lenient read into a failed one.\n }\n });\n return rows;\n}\n\n/** A plain JSON object (not null, not an array). */\nexport function asEntryRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** A finite number, or a non-empty numeric string, as a number; otherwise `undefined`. */\nexport function finiteNumberOf(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined;\n if (typeof value === 'string' && value.trim() !== '') {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { GalaChainTokenClassKey } from '../types/token.js';\n\n/** A symbol or a GalaChain token class key accepted by v2 operations. */\nexport type TokenRef = string | GalaChainTokenClassKey;\n\n/** Return two trading symbols in the contract's plain-string order. */\nexport function orderSymbols(a: string, b: string): [string, string] {\n return a < b ? [a, b] : [b, a];\n}\n\n/** Read an ordered symbol pair from a tuple or object returned by a boundary helper.\n *\n * @example\n * ```ts\n * const pair = readOrderedSymbols(['GALA', 'GUSDC']);\n * console.log(pair.token0);\n * ```\n */\nexport function readOrderedSymbols(value: unknown): { token0: string; token1: string } {\n if (Array.isArray(value) && value.length >= 2) {\n const token0 = (value as unknown[])[0];\n const token1 = (value as unknown[])[1];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n if (typeof value === 'object' && value !== null) {\n const record = value as Record<string, unknown>;\n const token0 = record['token0'];\n const token1 = record['token1'];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n throw new GSwapSDKError('UNORDERABLE_SYMBOLS', {\n received: Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value,\n });\n}\n\n/** Return the `$`-joined composite key used by GalaChain object identities. */\nexport function compositeKeyOf(token: GalaChainTokenClassKey): string {\n return [token.collection, token.category, token.type, token.additionalKey].join('$');\n}\n\n/**\n * Parse a pipe- or dollar-separated token class key.\n *\n * The LAST three segments are always `category`, `type` and `additionalKey`; everything before\n * them is the `collection`. Parsing from the right is required because real collections contain\n * the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`\n * shifts every field. Nothing here says anything about the token's symbol: a class key carries\n * no symbol, which must come from the token class or trading-symbol registry.\n *\n * @example\n * ```ts\n * parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'\n * ```\n */\nexport function parseTokenClassKey(tokenClassKey: TokenRef): GalaChainTokenClassKey {\n if (typeof tokenClassKey === 'object') {\n return {\n collection: tokenClassKey.collection,\n category: tokenClassKey.category,\n type: tokenClassKey.type,\n additionalKey: tokenClassKey.additionalKey,\n };\n }\n\n const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes('|') ? '|' : '$');\n if (parsed === undefined) throw new GSwapSDKError('INVALID_TOKEN_CLASS_KEY', { tokenClassKey });\n return parsed;\n}\n\n/**\n * Splits `collection<d>category<d>type<d>additionalKey` from the right, or `undefined` when there\n * are fewer than four segments or any of the four is empty. The one place the split is written.\n */\nfunction splitClassKey(key: string, delimiter: '|' | '$'): GalaChainTokenClassKey | undefined {\n const segments = key.split(delimiter);\n const tail = segments.slice(-3);\n const collection = segments.slice(0, -3).join(delimiter);\n if (segments.length < 4 || collection.length === 0 || tail.some((part) => part.length === 0)) {\n return undefined;\n }\n const [category, type, additionalKey] = tail;\n return {\n collection,\n category: category as string,\n type: type as string,\n additionalKey: additionalKey as string,\n };\n}\n\n/**\n * The non-throwing {@link parseTokenClassKey}: the class key, or `undefined` when `value` is not\n * one. A string is split exactly as `parseTokenClassKey` splits it (`|` form when it contains a\n * `|`, else `$`, from the right, all four parts non-empty). Unlike `parseTokenClassKey`, an\n * object is VALIDATED, not just copied: all four fields must be non-empty strings. Anything else\n * (`undefined`, `null`, a number, an array) is `undefined`, so it is safe on untrusted input (a\n * stored token, a URL parameter, a wallet row) without a `try`/`catch`.\n *\n * Use {@link tryParseCompositeKey} instead when only the `$` form is valid input.\n *\n * @example\n * ```ts\n * const key = tryParseTokenClassKey(row.compositeKey);\n * if (key === undefined) return failClosed(); // no class is known: never invent one from a symbol\n * ```\n */\nexport function tryParseTokenClassKey(value: unknown): GalaChainTokenClassKey | undefined {\n if (typeof value === 'string') return splitClassKey(value, value.includes('|') ? '|' : '$');\n if (typeof value !== 'object' || value === null) return undefined;\n try {\n const { collection, category, type, additionalKey } = value as Record<string, unknown>;\n if (\n typeof collection !== 'string' ||\n typeof category !== 'string' ||\n typeof type !== 'string' ||\n typeof additionalKey !== 'string' ||\n collection === '' ||\n category === '' ||\n type === '' ||\n additionalKey === ''\n ) {\n return undefined;\n }\n return { collection, category, type, additionalKey };\n } catch {\n // A getter or proxy that throws is not a token class key.\n return undefined;\n }\n}\n\n/**\n * Parses a `$`-joined composite key (`Collection$Category$Type$AdditionalKey`, what\n * {@link compositeKeyOf} writes) and nothing else, or `undefined`. It is {@link tryParseTokenClassKey}\n * for a string that may ONLY be in the `$` form: a key that contains `|` is NOT read as the pipe\n * form here (it stays part of a segment), and only a string is accepted. The split is from the\n * right, so a collection that itself contains `$` (production's `$GMUSIC`, stage's\n * `$GMUSIC_TEST1`) stays whole; `'GALA'`, `'GALA$Unit$none'`, `'ETIME$$$'`, `'GALA$Unit$none$'` and\n * `'$$$$'` are `undefined`.\n *\n * It replaces an app's own `parseCompositeKey(key): Components | null` (`?? null`), which had\n * exactly these semantics.\n *\n * @example\n * ```ts\n * tryParseCompositeKey('$GMUSIC_TEST1$Unit$none$none')?.collection; // '$GMUSIC_TEST1'\n * tryParseCompositeKey('GALA$Unit$none'); // undefined\n * ```\n */\nexport function tryParseCompositeKey(value: unknown): GalaChainTokenClassKey | undefined {\n return typeof value === 'string' ? splitClassKey(value, '$') : undefined;\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { TradingSymbol } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport type { TokenRef } from '../utils/ordering.js';\nimport { compositeKeyOf, orderSymbols, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend } from '../utils/pre_send.js';\nimport { isProposableTradingSymbol } from '../utils/validation.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { ChainGateway } from './gateway.js';\nimport { HttpClient } from './http_client.js';\n\nconst SYMBOL_CACHE_TTL_MS = 60_000;\n\n/** Symbol registry client for the current GalaChainDex contract. */\nexport class Symbols {\n private cachedSymbols: TradingSymbol[] | undefined;\n private cachedAt = 0;\n private refreshInFlight: Promise<TradingSymbol[]> | undefined;\n\n private readonly http: HttpClient;\n\n /**\n * Create a symbol service backed by the swap backend. `onInvalidEntry` is told about every\n * registry row that was skipped as unusable (see {@link InvalidEntryHandler}).\n */\n constructor(\n private readonly gateway: Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n },\n private readonly options: { onInvalidEntry?: InvalidEntryHandler | undefined } = {},\n ) {\n this.http = new HttpClient(gateway.httpRequestor, gateway.requestTimeoutMs, gateway.wire);\n }\n\n /**\n * List all registered GalaChainDex trading symbols, cached for 60 seconds. A registry row that\n * is not a usable symbol is skipped (and reported to `onInvalidEntry`) instead of failing the\n * whole list.\n */\n public async list(): Promise<TradingSymbol[]> {\n if (this.cachedSymbols !== undefined && Date.now() - this.cachedAt < SYMBOL_CACHE_TTL_MS) {\n return this.cachedSymbols;\n }\n if (this.refreshInFlight !== undefined) return this.refreshInFlight;\n this.refreshInFlight = this.http\n .sendGetRequest<{ data: unknown }>(this.gateway.dexBackendBaseUrl, '/v2/trade', '/symbols')\n .then((response) =>\n readEntries('symbols', response.data, parseTradingSymbol, this.options.onInvalidEntry),\n )\n .then((symbols) => {\n this.cachedSymbols = symbols;\n this.cachedAt = Date.now();\n return symbols;\n })\n .finally(() => {\n this.refreshInFlight = undefined;\n });\n return this.refreshInFlight;\n }\n\n /** Invalidate the cached symbol registry after a write changes registration state.\n *\n * @example\n * ```ts\n * gSwap.symbols.invalidate();\n * ```\n */\n public invalidate(): void {\n this.cachedSymbols = undefined;\n this.cachedAt = 0;\n }\n\n /** Force one registry refresh, bypassing the cache.\n *\n * @example\n * ```ts\n * const symbols = await gSwap.symbols.refresh();\n * ```\n */\n public async refresh(): Promise<TradingSymbol[]> {\n this.invalidate();\n // list() would otherwise return an ALREADY in-flight refresh that started before this\n // call (built from pre-invalidation state) — bypassing it too is what makes this\n // actually force a fresh fetch, not just satisfy the cache-freshness check.\n this.refreshInFlight = undefined;\n return this.list();\n }\n\n /** Resolve a symbol or token class key to its registered symbol metadata. */\n public async resolve(ref: TokenRef): Promise<TradingSymbol> {\n let symbols = await this.list();\n const composite =\n typeof ref === 'string'\n ? isCompositeKey(ref)\n ? compositeKeyOf(parseTokenClassKey(ref))\n : undefined\n : compositeKeyOf(ref);\n const resolved = symbols.find(\n (entry) =>\n entry.symbol === ref || (composite !== undefined && compositeKeyOf(entry) === composite),\n );\n if (resolved === undefined) {\n symbols = await this.refresh();\n const refreshed = symbols.find(\n (entry) =>\n entry.symbol === ref || (composite !== undefined && compositeKeyOf(entry) === composite),\n );\n if (refreshed === undefined) throw GSwapSDKError.unknownTokenError(ref);\n return refreshed;\n }\n return resolved;\n }\n\n /**\n * The trading symbol to put in a token's first CreatePool.\n *\n * 1. The symbol ALREADY registered for exactly this class key, if any: proposing another one\n * fails the gateway's registry-conflict check.\n * 2. Otherwise `displaySymbol` (the token's curated symbol), when it is proposable\n * ({@link isProposableTradingSymbol}).\n * 3. Otherwise a `NO_VALID_TRADING_SYMBOL` error: a symbol is never derived from the key (BNB's collection is\n * `GBNB`, a launchpad token's is the reserved word `Token`).\n *\n * `registryFailure: 'ignore'` treats an unreachable registry as an empty one and falls through\n * to step 2 (the gateway still rejects a conflicting symbol); the default `'throw'` propagates\n * the failure.\n *\n * @example\n * ```ts\n * const symbol = await gSwap.symbols.proposeSymbol(\n * { collection: 'GALA_TEST1', category: 'Unit', type: 'none', additionalKey: 'none' },\n * 'GALATEST',\n * );\n * ```\n */\n public async proposeSymbol(\n classKey: GalaChainTokenClassKey,\n displaySymbol: string,\n options: { registryFailure?: 'throw' | 'ignore' | undefined } = {},\n ): Promise<string> {\n let registry: TradingSymbol[] = [];\n try {\n registry = await this.list();\n } catch (error: unknown) {\n if (options.registryFailure !== 'ignore') throw error;\n }\n const wanted = compositeKeyOf(classKey);\n const registered = registry.find(\n (entry) =>\n entry.collection === classKey.collection &&\n entry.category === classKey.category &&\n entry.type === classKey.type &&\n entry.additionalKey === classKey.additionalKey,\n );\n if (registered !== undefined) return registered.symbol;\n if (isProposableTradingSymbol(displaySymbol)) return displaySymbol;\n throw new GSwapSDKError('NO_VALID_TRADING_SYMBOL', { classKey: wanted, displaySymbol });\n }\n\n /** Resolve and put two token references in canonical trading-symbol order. */\n public async orderPair(\n a: TokenRef,\n b: TokenRef,\n ): Promise<{\n token0: TradingSymbol;\n token1: TradingSymbol;\n flipped: boolean;\n }> {\n const [resolvedA, resolvedB] = await Promise.all([this.resolve(a), this.resolve(b)]);\n const [token0Symbol, token1Symbol] = orderSymbols(resolvedA.symbol, resolvedB.symbol);\n return {\n token0: token0Symbol === resolvedA.symbol ? resolvedA : resolvedB,\n token1: token1Symbol === resolvedB.symbol ? resolvedB : resolvedA,\n flipped: token0Symbol !== resolvedA.symbol,\n };\n }\n}\n\n/** Reads one registry row: all four class-key parts, a symbol and non-negative integer decimals. */\nfunction parseTradingSymbol(value: unknown): EntryParse<TradingSymbol> {\n const entry = asEntryRecord(value);\n if (entry === undefined) return entryRejected('the row is not an object');\n const { symbol, collection, category, type, additionalKey, decimals } = entry;\n if (typeof symbol !== 'string') return entryRejected('symbol is not a string');\n if (symbol.length === 0) return entryRejected('symbol is empty');\n if (typeof collection !== 'string') return entryRejected('collection is not a string');\n if (typeof category !== 'string') return entryRejected('category is not a string');\n if (typeof type !== 'string') return entryRejected('type is not a string');\n if (typeof additionalKey !== 'string') return entryRejected('additionalKey is not a string');\n if (typeof decimals !== 'number' || !Number.isInteger(decimals) || decimals < 0) {\n return entryRejected('decimals is not a non-negative integer');\n }\n return entryOk({ symbol, collection, category, type, additionalKey, decimals });\n}\n\nfunction isCompositeKey(ref: string): boolean {\n return ref.includes('|') || ref.includes('$');\n}\n\n/** Alias exported for callers that use the contract's shorter type name. */\nexport type TokenClassKey = GalaChainTokenClassKey;\n\n/**\n * What the services need from a token resolver: how a token reference becomes a trading symbol,\n * and whether requests carry the caller's references untouched. {@link Symbols} is the registry\n * resolver (one `GET /v2/trade/symbols`, cached); {@link CanonicalSymbols} is the offline one.\n */\nexport interface TokenResolver {\n resolve(ref: TokenRef): Promise<TradingSymbol>;\n /**\n * True when reads send the caller's token references verbatim (a symbol, or a composite key as\n * the caller wrote it) and let the backend resolve and orient the pair — no registry request\n * and no client-side ordering or tick flip.\n */\n readonly passthrough?: boolean | undefined;\n}\n\n/** A token reference as the caller wrote it: a string verbatim, a class key as its `$` composite. */\nexport function rawTokenOf(ref: TokenRef): string {\n return typeof ref === 'string' ? ref : compositeKeyOf(ref);\n}\n\n/** The trading symbol of a reference, or `SYMBOL_NOT_FOUND` when the resolver has none. */\nexport async function tradingSymbolOf(resolver: TokenResolver, ref: TokenRef): Promise<string> {\n const resolved = await resolvePreSend(rawTokenOf(ref), () => resolver.resolve(ref));\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('SYMBOL_NOT_FOUND', { token: rawTokenOf(ref) });\n}\n\n/** What a read request names a token by: the reference itself in pass-through mode, else its symbol. */\nexport async function queryTokenOf(resolver: TokenResolver, ref: TokenRef): Promise<string> {\n return resolver.passthrough === true ? rawTokenOf(ref) : tradingSymbolOf(resolver, ref);\n}\n\n/**\n * The offline resolver for apps that already hold the backend's canonical trading symbols (from\n * `/quote`, `/add-liq-estimate`, a position row) and must not make a registry request of their own.\n *\n * - `resolve` accepts a bare trading symbol and returns it as is; a class key (object, `$` or `|`\n * form) is not a symbol and is refused as `UNKNOWN_TOKEN`. `createPool` relies on that refusal to\n * fall back to the symbols its caller supplies.\n * - `orderPair` orders two symbols by plain string comparison, as the contract does.\n * - Reads are pass-through (see {@link TokenResolver.passthrough}): the caller's references go on\n * the wire verbatim, composite keys included, and the backend orients the pair.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, new CanonicalSymbols(), signer, walletAddress);\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '10' });\n * ```\n */\nexport class CanonicalSymbols implements TokenResolver {\n public readonly passthrough = true;\n\n /** Resolve a bare trading symbol to itself. */\n public resolve(ref: TokenRef): Promise<TradingSymbol> {\n if (typeof ref === 'string' && !isCompositeKey(ref)) {\n return Promise.resolve({\n symbol: ref,\n collection: '',\n category: '',\n type: '',\n additionalKey: '',\n decimals: 0,\n });\n }\n return Promise.reject(GSwapSDKError.unknownTokenError(ref));\n }\n\n /** Put two symbols in canonical (string) order. */\n public async orderPair(\n a: TokenRef,\n b: TokenRef,\n ): Promise<{ token0: TradingSymbol; token1: TradingSymbol; flipped: boolean }> {\n const [resolvedA, resolvedB] = await Promise.all([this.resolve(a), this.resolve(b)]);\n const [first] = orderSymbols(resolvedA.symbol, resolvedB.symbol);\n const flipped = first !== resolvedA.symbol;\n return {\n token0: flipped ? resolvedB : resolvedA,\n token1: flipped ? resolvedA : resolvedB,\n flipped,\n };\n }\n\n /** There is no registry state to drop. */\n public invalidate(): void {\n // Nothing is cached: every answer is derived from the reference itself.\n }\n}\n","import type { FEE_TIER } from '../types/fees.js';\nimport type { CompositePool, PoolInfo, PoolListInfo, Slot0 } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n finiteNumberOf,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport type { ChainGateway } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, rawTokenOf, tradingSymbolOf, type TokenResolver } from './symbols.js';\nimport { validateFee } from '../utils/validation.js';\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\ntype PoolGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** The sort keys of `GET /v2/trade/pools`. */\nexport type PoolSortBy = 'tvl' | 'volume1d' | 'volume30d';\n\n/** Options of {@link Pools.getPools}. Omit all of `search`, `sortBy`, `sortOrder`, `page`, `limit` for the full, unsorted list. */\nexport interface PoolListOptions {\n signal?: AbortSignal | undefined;\n /** Case-insensitive match on the pair's symbols; `A/B` or `A B` matches either order. At most 64 characters. */\n search?: string | undefined;\n sortBy?: PoolSortBy | undefined;\n sortOrder?: 'asc' | 'desc' | undefined;\n /** 1-based page number; only meaningful together with `limit`. */\n page?: number | undefined;\n /** Rows per page, 1-1000; omitted returns every row. */\n limit?: number | undefined;\n /** Overrides the service-level handler for this call. */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n}\n\n/** Read-only pool and current-price access for the current GalaChainDex contract. */\nexport class Pools {\n /**\n * Creates a pool service. `options.onInvalidEntry` is told about every pool row that was\n * skipped as unusable (see {@link InvalidEntryHandler}).\n *\n * @example\n * ```ts\n * const pools = new Pools(gateway, symbols);\n * ```\n */\n constructor(\n private readonly gateway: PoolGateway,\n private readonly symbols: TokenResolver,\n private readonly options: { onInvalidEntry?: InvalidEntryHandler | undefined } = {},\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Fetches current-contract pools from the swap backend, optionally searched, sorted and paged\n * by the backend. A row that is not a usable pool is skipped and reported to `onInvalidEntry`\n * instead of failing the whole list; an answer that is not a list at all is\n * `INVALID_CHAIN_RESPONSE`.\n *\n * @example\n * ```ts\n * const top = await service.getPools({ sortBy: 'tvl', sortOrder: 'desc', page: 1, limit: 8 });\n * console.log(top.length);\n * ```\n */\n public async getPools(options?: PoolListOptions): Promise<PoolListInfo[]> {\n const response = await this.http.sendGetRequest<BackendEnvelope<unknown>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/pools',\n poolListParams(options),\n options?.signal === undefined ? undefined : { signal: options.signal },\n );\n return readEntries(\n 'pools',\n response.data,\n parsePoolListInfo,\n options?.onInvalidEntry ?? this.options.onInvalidEntry,\n );\n }\n\n /**\n * Fetches one pool from the backend, preserving whether the request order was flipped.\n *\n * @example\n * ```ts\n * const pool = await service.getPool('GUSDC', 'GALA', 3000);\n * console.log(pool.flippedFromRequest);\n * ```\n */\n public async getPool(token0: TokenRef, token1: TokenRef, fee: FEE_TIER): Promise<PoolInfo> {\n validateFee(fee);\n return this.getBackend<PoolInfo>('/pool', await this.backendParams(token0, token1, fee));\n }\n\n /**\n * Fetches the current sqrt price, price, and tick for one pool.\n *\n * @example\n * ```ts\n * const slot0 = await service.getSlot0('GALA', 'GUSDC', 3000);\n * console.log(slot0.tick);\n * ```\n */\n public async getSlot0(token0: TokenRef, token1: TokenRef, fee: FEE_TIER): Promise<Slot0> {\n validateFee(fee);\n return this.getBackend<Slot0>('/slot0', await this.backendParams(token0, token1, fee));\n }\n\n /**\n * Fetches the complete chain composite pool snapshot, in canonical symbol order.\n *\n * @example\n * ```ts\n * const composite = await service.getCompositePool('GALA', 'GUSDC', 3000);\n * console.log(composite.positions?.length ?? 0);\n * ```\n */\n public async getCompositePool(\n token0: TokenRef,\n token1: TokenRef,\n fee: FEE_TIER,\n ): Promise<CompositePool> {\n validateFee(fee);\n if (this.symbols.passthrough === true) {\n return this.getBackend<CompositePool>('/composite-pool', {\n token0: rawTokenOf(token0),\n token1: rawTokenOf(token1),\n fee: String(fee),\n });\n }\n const first = await tradingSymbolOf(this.symbols, token0);\n const second = await tradingSymbolOf(this.symbols, token1);\n const ordered = readOrderedSymbols(orderSymbols(first, second));\n return this.getBackend<CompositePool>('/composite-pool', {\n token0: ordered.token0,\n token1: ordered.token1,\n fee: String(fee),\n });\n }\n\n private async backendParams(\n token0: TokenRef,\n token1: TokenRef,\n fee: FEE_TIER,\n ): Promise<Record<string, string>> {\n return {\n token0: await queryTokenOf(this.symbols, token0),\n token1: await queryTokenOf(this.symbols, token1),\n fee: String(fee),\n };\n }\n\n private async getBackend<T>(endpoint: string, params: Record<string, string>): Promise<T> {\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<T>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n );\n return response.data;\n } catch (error: unknown) {\n if (error instanceof GSwapSDKError) throw error;\n throw new GSwapSDKError('REQUEST_FAILED', { operation: 'pool' }, { cause: error });\n }\n }\n}\n\nconst SORT_KEYS: readonly string[] = ['tvl', 'volume1d', 'volume30d'];\nconst MAX_SEARCH_LENGTH = 64;\nconst MAX_PAGE_SIZE = 1000;\n\n/** The pool-list query, in the order the apps write it: search, sortBy, sortOrder, page, limit. */\nfunction poolListParams(options: PoolListOptions | undefined): Record<string, string> | undefined {\n if (options === undefined) return undefined;\n const params: Record<string, string> = {};\n if (options.search !== undefined) {\n if (options.search.length > MAX_SEARCH_LENGTH) {\n throw new GSwapSDKError('SEARCH_TOO_LONG', {\n length: options.search.length,\n maxLength: MAX_SEARCH_LENGTH,\n });\n }\n params['search'] = options.search;\n }\n if (options.sortBy !== undefined) {\n if (!SORT_KEYS.includes(options.sortBy)) {\n throw new GSwapSDKError('INVALID_SORT_BY', {\n value: String(options.sortBy),\n allowed: SORT_KEYS.join(','),\n });\n }\n params['sortBy'] = options.sortBy;\n }\n if (options.sortOrder !== undefined) {\n if (options.sortOrder !== 'asc' && options.sortOrder !== 'desc') {\n throw new GSwapSDKError('INVALID_SORT_ORDER', { value: String(options.sortOrder) });\n }\n params['sortOrder'] = options.sortOrder;\n }\n if (options.page !== undefined) {\n if (!Number.isInteger(options.page) || options.page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: options.page });\n }\n params['page'] = String(options.page);\n }\n if (options.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > MAX_PAGE_SIZE) {\n throw new GSwapSDKError('INVALID_LIMIT', {\n value: options.limit,\n min: 1,\n max: MAX_PAGE_SIZE,\n });\n }\n params['limit'] = String(options.limit);\n }\n return Object.keys(params).length === 0 ? undefined : params;\n}\n\nconst OPTIONAL_POOL_STRINGS = [\n 'poolName',\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'creator',\n 'price',\n 'sqrtPrice',\n 'token0Tvl',\n 'token1Tvl',\n] as const;\n\nconst OPTIONAL_POOL_NUMBERS = [\n 'tickSpacing',\n 'protocolFees',\n 'tradingFees',\n 'tick',\n 'volume1d',\n 'volume7d',\n 'volume30d',\n 'trades1d',\n 'fee24h',\n 'token0Price',\n 'token1Price',\n] as const;\n\n/** Fields the apps accept as a number or a numeric string (the wallet does `Number(row.x)`). */\nconst NUMERIC_POOL_FIELDS = ['fee', 'tvlUsd', 'apr1d'] as const;\n\n/**\n * Reads one pool-list row the way the apps do: the identity (`token0`, `token1`, `poolRef`) and\n * `fee` must be usable, every other field is optional but, when present, must have its type.\n * `fee`, `tvlUsd` and `apr1d` may arrive as numeric strings and are returned as numbers. Fields\n * the SDK does not know are kept.\n */\nfunction parsePoolListInfo(entry: unknown): EntryParse<PoolListInfo> {\n const row = asEntryRecord(entry);\n if (row === undefined) return entryRejected('the row is not an object');\n for (const key of ['token0', 'token1', 'poolRef'] as const) {\n if (typeof row[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n if (row['contractVersion'] !== undefined && row['contractVersion'] !== 'v2') {\n return entryRejected('contractVersion is not v2');\n }\n const normalized: Record<string, unknown> = { ...row };\n for (const key of NUMERIC_POOL_FIELDS) {\n const raw = row[key];\n if (raw === undefined && key !== 'fee') continue;\n const value = finiteNumberOf(raw);\n if (value === undefined) return entryRejected(`${key} is not a number`);\n normalized[key] = value;\n }\n for (const key of OPTIONAL_POOL_STRINGS) {\n if (row[key] !== undefined && typeof row[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n for (const key of OPTIONAL_POOL_NUMBERS) {\n const value = row[key];\n if (value !== undefined && (typeof value !== 'number' || !Number.isFinite(value))) {\n return entryRejected(`${key} is not a number`);\n }\n }\n return entryOk(normalized as unknown as PoolListInfo);\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { isValidUniqueKey } from './unique_key_syntax.js';\n\n/**\n * The `uniqueKey` prefix frontend_v2 and wallet_extension have always sent\n * (`galaswap-operation-<uuid>`). defi-backend does not depend on it: the chain-write verifier\n * only requires a non-empty key of at most 256 characters, and apply-results accepts\n * `[A-Za-z0-9._:-]{1,128}`; the only code that mints a prefixed key itself is the server-side v1\n * trade builder, which nothing reads back by prefix.\n */\nexport const DEFAULT_UNIQUE_KEY_PREFIX = 'galaswap-operation-';\n\n/** Options shared by the services that mint `uniqueKey`s for writes. */\nexport interface UniqueKeyOptions {\n /**\n * Prefix of every minted `uniqueKey` (`<prefix><uuid>`). Defaults to\n * `DEFAULT_UNIQUE_KEY_PREFIX` (`galaswap-operation-`).\n */\n uniqueKeyPrefix?: string | undefined;\n}\n\n/** A canonical UUID is 36 characters; the apply-results key limit is 128. */\nconst MAX_UNIQUE_KEY_PREFIX_LENGTH = 128 - 36;\nconst UNIQUE_KEY_PREFIX_PATTERN = /^[A-Za-z0-9._:-]*$/u;\n\n/**\n * Validates a caller-supplied `uniqueKey` prefix. The whole key (`<prefix><uuid>`) must stay a\n * valid apply-results key, otherwise `confirm()` could never read the outcome of the write.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY_PREFIX` when the prefix has characters outside\n * `A-Za-z0-9._:-` or is longer than 92 characters.\n */\nexport function resolveUniqueKeyPrefix(prefix: string | undefined): string {\n if (prefix === undefined) return DEFAULT_UNIQUE_KEY_PREFIX;\n if (!UNIQUE_KEY_PREFIX_PATTERN.test(prefix) || prefix.length > MAX_UNIQUE_KEY_PREFIX_LENGTH) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY_PREFIX', {\n uniqueKeyPrefix: prefix,\n maxLength: MAX_UNIQUE_KEY_PREFIX_LENGTH,\n });\n }\n return prefix;\n}\n\n/**\n * Validates a caller-supplied write `uniqueKey`: 1 to 128 characters of `A-Za-z0-9._:-`, the\n * shape the apply-results route accepts, so the write's outcome can always be read back with\n * `confirm()`. A key is one attempt's identity: reuse it only to retry that same attempt.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY` otherwise.\n */\nexport function assertUniqueKey(uniqueKey: string): void {\n if (!isValidUniqueKey(uniqueKey)) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY', { uniqueKey: String(uniqueKey) });\n }\n}\n\n/** A fresh per-attempt key: `<prefix><random UUID>`. */\nexport function createUniqueKey(prefix: string): string {\n return `${prefix}${globalThis.crypto.randomUUID()}`;\n}\n","import BigNumber from 'bignumber.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount, SwapAmount } from '../types/amounts.js';\nimport type {\n AddLiquidityDTO,\n CollectPositionFeesDTO,\n CreatePoolDTO,\n RemoveLiquidityDTO,\n RequestTradeDTO,\n} from '../types/v2_dtos.js';\nimport type { GalaChainTokenClassKey } from '../types/token.js';\nimport { assertTickRange } from './ticks.js';\nimport { assertUniqueKey } from './unique_key.js';\nimport {\n assertCanonicalPair,\n isProposableTradingSymbol,\n validateFee,\n validateNumericAmount,\n} from './validation.js';\n\n// The pure builders of every v2 write DTO. They validate, canonicalize decimals\n// (`BigNumber#toFixed`) and fix the key order, and nothing else: no network, no signer, no\n// clock, no randomness — the `uniqueKey` is an input. The `Swaps` and `Positions` services call\n// exactly these functions, so a DTO an app builds here (to show in an approval popup, to sign on\n// another device, to submit later) is the DTO the services would have built.\n//\n// Inputs are already CANONICAL: `token0 < token1` by plain string comparison, ticks and prices in\n// that orientation. Orienting a caller's pair (and inverting its ticks and price) is the\n// services' job; a reversed pair is refused (`NON_CANONICAL_PAIR`) rather than silently signed.\n\nconst decimalString = (amount: NumericAmount): string => new BigNumber(amount).toFixed();\n\n/** The pool a RequestTrade trades in, its fee tier, the `uniqueKey` and what is traded. */\nexport type RequestTradeInput = {\n /** Canonical pool symbols: `token0 < token1`. Take them from a quote verbatim. */\n token0: string;\n token1: string;\n fee: number;\n /** Which side of the pool is sold: `true` when the input token is `token0`. */\n tokenInIsToken0: boolean;\n uniqueKey: string;\n} & SwapAmount;\n\n/**\n * Builds the RequestTrade DTO: `exactIn` sells that much of the input token (`sell0Qty` or\n * `sell1Qty`), `exactOut` buys that much of the output token (`buy1Qty` or `buy0Qty`), plus the\n * side's slippage bound and an optional `priceLimit`. Key order: `token0, token1, fee, uniqueKey,\n * <quantity>, amountOutMinimum | amountInMaximum, priceLimit`.\n *\n * @example\n * ```ts\n * const dto = buildRequestTradeDto({\n * token0: quote.token0Symbol, token1: quote.token1Symbol,\n * tokenInIsToken0: quote.tokenInIsToken0, fee: quote.fee,\n * uniqueKey: createUniqueKey('galaswap-operation-'),\n * exactIn: '100', amountOutMinimum: '14',\n * });\n * ```\n */\nexport function buildRequestTradeDto(input: RequestTradeInput): RequestTradeDTO {\n validateFee(input.fee);\n assertCanonicalPair(input.token0, input.token1);\n assertUniqueKey(input.uniqueKey);\n const dto: Record<string, unknown> = {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n uniqueKey: input.uniqueKey,\n };\n if ('exactIn' in input) {\n const exactIn = input.exactIn;\n if (exactIn === undefined) {\n throw new GSwapSDKError('EXACT_AMOUNT_REQUIRED', { field: 'exactIn' });\n }\n validateNumericAmount(exactIn, 'exactIn');\n dto[input.tokenInIsToken0 ? 'sell0Qty' : 'sell1Qty'] = decimalString(exactIn);\n if (input.amountOutMinimum !== undefined) {\n validateNumericAmount(input.amountOutMinimum, 'amountOutMinimum', true);\n dto['amountOutMinimum'] = decimalString(input.amountOutMinimum);\n }\n } else {\n const exactOut = input.exactOut;\n if (exactOut === undefined) {\n throw new GSwapSDKError('EXACT_AMOUNT_REQUIRED', { field: 'exactOut' });\n }\n validateNumericAmount(exactOut, 'exactOut');\n dto[input.tokenInIsToken0 ? 'buy1Qty' : 'buy0Qty'] = decimalString(exactOut);\n if (input.amountInMaximum !== undefined) {\n validateNumericAmount(input.amountInMaximum, 'amountInMaximum', true);\n dto['amountInMaximum'] = decimalString(input.amountInMaximum);\n }\n }\n if (input.priceLimit !== undefined) {\n validateNumericAmount(input.priceLimit, 'priceLimit');\n dto['priceLimit'] = decimalString(input.priceLimit);\n }\n return dto as unknown as RequestTradeDTO;\n}\n\n/** A canonical pool position: the pair, fee tier, tick range and the attempt's `uniqueKey`. */\nexport interface PoolPositionInput {\n token0: string;\n token1: string;\n fee: number;\n tickLower: number;\n tickUpper: number;\n uniqueKey: string;\n}\n\nfunction assertPoolPosition(input: PoolPositionInput): void {\n validateFee(input.fee);\n assertCanonicalPair(input.token0, input.token1);\n assertTickRange(input.tickLower, input.tickUpper, input.fee);\n assertUniqueKey(input.uniqueKey);\n}\n\n/** Exactly one canonical deposit side. */\nexport type AddLiquidityInput = PoolPositionInput &\n (\n | { depositQuantityToken0: NumericAmount; depositQuantityToken1?: undefined }\n | { depositQuantityToken0?: undefined; depositQuantityToken1: NumericAmount }\n );\n\n/**\n * Builds the AddLiquidity DTO: exactly one of `depositQuantityToken0` / `depositQuantityToken1`\n * (the other side is derived on chain). Key order: `token0, token1, fee, tickLower, tickUpper,\n * uniqueKey, <deposit>`.\n */\nexport function buildAddLiquidityDto(input: AddLiquidityInput): AddLiquidityDTO {\n assertPoolPosition(input);\n const side = onlyOne(\n input.depositQuantityToken0,\n input.depositQuantityToken1,\n 'depositQuantityToken0',\n 'depositQuantityToken1',\n );\n if (side === undefined) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'depositQuantityToken0',\n second: 'depositQuantityToken1',\n });\n }\n validateNumericAmount(side.amount, side.name);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n [side.name]: decimalString(side.amount),\n } as AddLiquidityDTO;\n}\n\n/** At most one canonical withdrawal side; neither closes the position. */\nexport type RemoveLiquidityInput = PoolPositionInput & {\n withdrawalQuantityToken0?: NumericAmount | undefined;\n withdrawalQuantityToken1?: NumericAmount | undefined;\n};\n\n/**\n * Builds the RemoveLiquidity DTO: at most one of `withdrawalQuantityToken0` /\n * `withdrawalQuantityToken1`; omitting both closes the position and sweeps its fees.\n */\nexport function buildRemoveLiquidityDto(input: RemoveLiquidityInput): RemoveLiquidityDTO {\n assertPoolPosition(input);\n const side = onlyOne(\n input.withdrawalQuantityToken0,\n input.withdrawalQuantityToken1,\n 'withdrawalQuantityToken0',\n 'withdrawalQuantityToken1',\n true,\n );\n if (side !== undefined) validateNumericAmount(side.amount, side.name);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n ...(side === undefined ? {} : { [side.name]: decimalString(side.amount) }),\n };\n}\n\n/** Builds the CollectPositionFees DTO (the contract sweeps all of a position's fees). */\nexport function buildCollectPositionFeesDto(input: PoolPositionInput): CollectPositionFeesDTO {\n assertPoolPosition(input);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n };\n}\n\n/** A CreatePool in canonical orientation, with exactly one starting price. */\nexport type CreatePoolInput = {\n token0Key: GalaChainTokenClassKey;\n token1Key: GalaChainTokenClassKey;\n /** The symbols to register; `token0Symbol < token1Symbol` and both proposable. */\n token0Symbol: string;\n token1Symbol: string;\n fee: number;\n /** Optional display name; omitted when undefined or empty. */\n name?: string | undefined;\n isPrivate?: boolean | undefined;\n privateAccess?: string[] | undefined;\n uniqueKey: string;\n} & (\n | { startingPrice: NumericAmount; startingSqrtPrice?: undefined }\n | { startingPrice?: undefined; startingSqrtPrice: NumericAmount }\n);\n\n/**\n * Builds the CreatePool DTO. Key order: `token0Key, token1Key, fee, startingPrice |\n * startingSqrtPrice, token0Symbol, token1Symbol, uniqueKey, name, isPrivate, privateAccess`.\n * Prices are those of the canonical pair (token1 per token0); a price quoted the other way round\n * is inverted by the caller before it gets here.\n */\nexport function buildCreatePoolDto(input: CreatePoolInput): CreatePoolDTO {\n validateFee(input.fee);\n assertUniqueKey(input.uniqueKey);\n assertCanonicalPair(input.token0Symbol, input.token1Symbol);\n for (const symbol of [input.token0Symbol, input.token1Symbol]) {\n if (!isProposableTradingSymbol(symbol)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol });\n }\n }\n for (const key of [input.token0Key, input.token1Key]) assertClassKey(key);\n const price = onlyOne(\n input.startingPrice,\n input.startingSqrtPrice,\n 'startingPrice',\n 'startingSqrtPrice',\n );\n if (price === undefined) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n if (typeof price.amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: price.name });\n }\n const parsed = new BigNumber(price.amount);\n if (!parsed.isFinite() || parsed.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(price.amount) });\n }\n return {\n token0Key: input.token0Key,\n token1Key: input.token1Key,\n fee: input.fee,\n [price.name]: parsed.toFixed(),\n token0Symbol: input.token0Symbol,\n token1Symbol: input.token1Symbol,\n uniqueKey: input.uniqueKey,\n // An empty name is \"no name\", as in frontend_v2's builder (its form yields '').\n ...(input.name === undefined || input.name === '' ? {} : { name: input.name }),\n ...(input.isPrivate === undefined ? {} : { isPrivate: input.isPrivate }),\n ...(input.privateAccess === undefined ? {} : { privateAccess: input.privateAccess }),\n } as CreatePoolDTO;\n}\n\nfunction assertClassKey(key: GalaChainTokenClassKey): void {\n for (const part of ['collection', 'category', 'type', 'additionalKey'] as const) {\n if (typeof key[part] !== 'string' || key[part].length === 0) {\n throw new GSwapSDKError('INCOMPLETE_TOKEN_CLASS_KEY', {\n compositeKey: [key.collection, key.category, key.type, key.additionalKey].join('$'),\n part,\n });\n }\n }\n}\n\n/**\n * Of two mutually exclusive fields, the one that is set (`undefined` when neither is);\n * both set is an error (`AT_MOST_ONE_OF_ALLOWED` or `EXACTLY_ONE_OF_REQUIRED`), and so is\n * neither unless `allowNeither`.\n */\nfunction onlyOne<T>(\n first: T | undefined,\n second: T | undefined,\n firstName: string,\n secondName: string,\n allowNeither = false,\n): { name: string; amount: T } | undefined {\n if (first !== undefined && second !== undefined) {\n throw allowNeither\n ? new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: firstName, second: secondName })\n : new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', { first: firstName, second: secondName });\n }\n if (first !== undefined) return { name: firstName, amount: first };\n if (second !== undefined) return { name: secondName, amount: second };\n return undefined;\n}\n\n/** The methods whose DTOs the builders produce. */\nexport type V2WriteMethod =\n 'RequestTrade' | 'AddLiquidity' | 'RemoveLiquidity' | 'CollectPositionFees' | 'CreatePool';\n\ntype DtoExpectation =\n 'string' | 'number' | 'boolean' | 'class_key' | 'string_array' | 'exactly_once';\n\nfunction invalidDto(\n method: string,\n field: string,\n expected: DtoExpectation,\n): GSwapSDKError<'INVALID_DTO'> {\n return new GSwapSDKError('INVALID_DTO', { method, field, expected });\n}\n\n/**\n * Rebuilds a DTO from its own fields with the builder of its method: the canonical form of the\n * DTO, with the same validation. Key order and decimal text are the builder's.\n */\nfunction rebuildV2Dto(\n method: V2WriteMethod,\n dto: Record<string, unknown>,\n): Record<string, unknown> {\n const text = (field: string): string => {\n const value = dto[field];\n if (typeof value !== 'string') throw invalidDto(method, field, 'string');\n return value;\n };\n const integer = (field: string): number => {\n const value = dto[field];\n if (typeof value !== 'number') throw invalidDto(method, field, 'number');\n return value;\n };\n const optionalText = (field: string): string | undefined =>\n dto[field] === undefined ? undefined : text(field);\n const classKey = (field: string): GalaChainTokenClassKey => {\n const value = dto[field];\n if (typeof value !== 'object' || value === null) throw invalidDto(method, field, 'class_key');\n const key = value as Record<string, unknown>;\n const part = (name: string): string => {\n if (typeof key[name] !== 'string') throw invalidDto(method, `${field}.${name}`, 'string');\n return key[name];\n };\n return {\n collection: part('collection'),\n category: part('category'),\n type: part('type'),\n additionalKey: part('additionalKey'),\n };\n };\n // The pool pair is not a field of CreatePool, so these are read per method, not up front.\n const base = () => ({ token0: text('token0'), token1: text('token1'), fee: integer('fee') });\n const uniqueKey = text('uniqueKey');\n const position = () => ({\n ...base(),\n uniqueKey,\n tickLower: integer('tickLower'),\n tickUpper: integer('tickUpper'),\n });\n switch (method) {\n case 'RequestTrade': {\n const qty = ['sell0Qty', 'sell1Qty', 'buy0Qty', 'buy1Qty'].filter(\n (f) => dto[f] !== undefined,\n );\n const [field] = qty;\n if (qty.length !== 1 || field === undefined) {\n throw invalidDto(method, 'sell0Qty|sell1Qty|buy0Qty|buy1Qty', 'exactly_once');\n }\n const tokenInIsToken0 = field === 'sell0Qty' || field === 'buy1Qty';\n const shared = { ...base(), uniqueKey, tokenInIsToken0 };\n const priceLimit = optionalText('priceLimit');\n return field.startsWith('sell')\n ? buildRequestTradeDto({\n ...shared,\n exactIn: text(field),\n amountOutMinimum: optionalText('amountOutMinimum'),\n priceLimit,\n })\n : buildRequestTradeDto({\n ...shared,\n exactOut: text(field),\n amountInMaximum: optionalText('amountInMaximum'),\n priceLimit,\n });\n }\n case 'AddLiquidity': {\n const token0Side = optionalText('depositQuantityToken0');\n const token1Side = optionalText('depositQuantityToken1');\n return buildAddLiquidityDto({\n ...position(),\n ...(token0Side === undefined\n ? { depositQuantityToken1: token1Side as string }\n : { depositQuantityToken0: token0Side }),\n });\n }\n case 'RemoveLiquidity':\n return buildRemoveLiquidityDto({\n ...position(),\n withdrawalQuantityToken0: optionalText('withdrawalQuantityToken0'),\n withdrawalQuantityToken1: optionalText('withdrawalQuantityToken1'),\n });\n case 'CollectPositionFees':\n return buildCollectPositionFeesDto(position());\n case 'CreatePool': {\n const price = optionalText('startingPrice');\n const sqrtPrice = optionalText('startingSqrtPrice');\n const privateAccess = dto['privateAccess'];\n if (\n privateAccess !== undefined &&\n (!Array.isArray(privateAccess) || privateAccess.some((entry) => typeof entry !== 'string'))\n ) {\n throw invalidDto(method, 'privateAccess', 'string_array');\n }\n if (dto['isPrivate'] !== undefined && typeof dto['isPrivate'] !== 'boolean') {\n throw invalidDto(method, 'isPrivate', 'boolean');\n }\n return buildCreatePoolDto({\n token0Key: classKey('token0Key'),\n token1Key: classKey('token1Key'),\n token0Symbol: text('token0Symbol'),\n token1Symbol: text('token1Symbol'),\n fee: integer('fee'),\n uniqueKey,\n name: optionalText('name'),\n isPrivate: dto['isPrivate'],\n privateAccess: privateAccess as string[] | undefined,\n ...(price === undefined\n ? { startingSqrtPrice: sqrtPrice as string }\n : { startingPrice: price }),\n });\n }\n }\n}\n\n/**\n * Asserts that `dto` is EXACTLY what the builder of `method` produces for its own fields — the\n * same fields, canonical decimal text, builder key order, nothing extra (no `signature`). The\n * `submit*` methods use it so that what an app showed a user (a DTO it built) is byte for byte\n * what gets signed; a DTO edited by hand, or built elsewhere, is refused rather than signed.\n *\n * @throws GSwapSDKError `INVALID_DTO` or `DTO_NOT_CANONICAL`.\n */\nexport function assertCanonicalV2Dto(method: V2WriteMethod, dto: Record<string, unknown>): void {\n const rebuilt = rebuildV2Dto(method, dto);\n if (JSON.stringify(rebuilt) !== JSON.stringify(dto)) {\n throw new GSwapSDKError('DTO_NOT_CANONICAL', { method });\n }\n}\n","import BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './error_catalog.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport type { ChainGateway, ChainSubmitOptions } from './gateway.js';\nimport type { PositionConfirmationResult, SubmittedTransaction } from './submitted_transaction.js';\nimport { HttpClient } from './http_client.js';\nimport type { GalaChainSigner } from './signers.js';\nimport { rawTokenOf, type Symbols, type TokenResolver } from './symbols.js';\nimport type { NumericAmount, PriceIn } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\nimport type {\n AddLiquidityDTO,\n CollectPositionFeesDTO,\n CreatePoolDTO,\n RemoveLiquidityDTO,\n} from '../types/v2_dtos.js';\nimport type {\n AddLiquidityEstimate,\n Position,\n RemoveLiquidityEstimate,\n} from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { type TokenRef, compositeKeyOf, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend, signPreSend } from '../utils/pre_send.js';\nimport {\n isProposableTradingSymbol,\n validateFee,\n validateNumericAmount,\n} from '../utils/validation.js';\nimport { alignTickDown, alignTickUp, assertTickRange, tickFromPrice } from '../utils/ticks.js';\nimport {\n assertCanonicalV2Dto,\n buildAddLiquidityDto,\n buildCollectPositionFeesDto,\n buildCreatePoolDto,\n buildRemoveLiquidityDto,\n} from '../utils/dto_builders.js';\nimport {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n type UniqueKeyOptions,\n} from '../utils/unique_key.js';\n\ntype PositionGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n submit: (\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<Position | null>>;\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\ntype PositionSymbols = TokenResolver & Pick<Symbols, 'orderPair'> & { invalidate?: () => void };\n\n/** Options of {@link Positions}: the `uniqueKey` prefix and a handler for skipped list rows. */\nexport interface PositionsOptions extends UniqueKeyOptions {\n /** Told about every position row of a list that was skipped as unusable. */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n}\n\n/** A write's optional attempt identity. */\ninterface UniqueKeyArg {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing, or to retry the SAME\n * attempt after a lost response; never reuse it for another write.\n */\n uniqueKey?: string | undefined;\n}\n\n/** Arguments of {@link Positions.addLiquidityByTicks} and {@link Positions.buildAddLiquidity}. */\nexport interface AddLiquidityArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n /** Whether `amount` is of `token0` as the caller passed it (not of the canonical token0). */\n amountIsToken0: boolean;\n}\n\n/** Arguments of {@link Positions.removeLiquidity} and {@link Positions.buildRemoveLiquidity}. */\nexport interface RemoveLiquidityArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n /** Withdraw this much of the caller's `token0`; give at most one of `amount0` / `amount1`. */\n amount0?: NumericAmount | undefined;\n amount1?: NumericAmount | undefined;\n}\n\n/** Arguments of {@link Positions.collectPositionFees} and {@link Positions.buildCollectPositionFees}. */\nexport interface CollectPositionFeesArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n}\n\n/** Arguments of {@link Positions.createPool} and {@link Positions.buildCreatePool}. */\nexport interface CreatePoolArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n token0Symbol?: string | undefined;\n token1Symbol?: string | undefined;\n fee: FEE_TIER;\n startingPrice?: NumericAmount | undefined;\n startingSqrtPrice?: NumericAmount | undefined;\n /** Optional pool display name, sent as the DTO's `name`; omitted when undefined or empty. */\n name?: string | undefined;\n isPrivate?: boolean | undefined;\n privateAccess?: string[] | undefined;\n}\n\n/** The pool position a liquidity DTO names, as its confirmation needs it. */\nfunction identityOf(\n dto: Pick<CollectPositionFeesDTO, 'token0' | 'token1' | 'fee' | 'tickLower' | 'tickUpper'>,\n): PositionIdentity {\n return {\n token0: dto.token0,\n token1: dto.token1,\n fee: dto.fee,\n tickLower: dto.tickLower,\n tickUpper: dto.tickUpper,\n };\n}\n\n/**\n * The outcome of {@link Positions.readPosition}. Only `not_found` is chain-confirmed absence (the\n * backend answers HTTP 404 only when the chain itself found no such position); `unknown` is \"no\n * evidence either way\" — a transport failure, a gateway timeout, any other error status or an\n * answer that is not a position — and must never be read as a removal.\n */\nexport type PositionRead =\n | { kind: 'found'; data: Position }\n | { kind: 'not_found' }\n | { kind: 'unknown'; error: GSwapSDKError };\n\ninterface BackendEnvelope<TData> {\n data: TData;\n}\n\ninterface AddLiquidityEstimateWire {\n amount0: string;\n amount1: string;\n liquidity: string;\n token0Symbol: string;\n token1Symbol: string;\n tickLower: number;\n tickUpper: number;\n amountIsCanonicalToken0: boolean;\n}\n\ninterface RemoveLiquidityEstimateWire {\n amount0: string;\n amount1: string;\n}\n\ninterface ResolvedCreateToken {\n symbol: string;\n classKey: ReturnType<typeof parseTokenClassKey>;\n}\n\ninterface PositionIdentity {\n token0: string;\n token1: string;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n}\n\n/** Tells `submit()` how to prove a write's own effect for `SubmittedTransaction.confirm()`. */\ntype PositionSubmitConfirmation =\n | { kind: 'add' | 'removePartial' | 'removeFull' | 'collect'; identity: PositionIdentity }\n | { kind: 'createPool'; token0: string; token1: string; fee: FEE_TIER };\n\n/**\n * Manages current-contract concentrated-liquidity positions.\n *\n * @example\n * ```typescript\n * const positions = gSwap.positions;\n * const mine = await positions.getUserPositions('client|012345678901234567890123');\n * console.log(mine.length);\n * ```\n */\nexport class Positions {\n constructor(\n private readonly gateway: PositionGateway,\n private readonly symbols: PositionSymbols,\n private readonly signer?: GalaChainSigner,\n private readonly walletAddress?: string,\n options: PositionsOptions = {},\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\n this.onInvalidEntry = options.onInvalidEntry;\n }\n\n private readonly http: HttpClient;\n private readonly uniqueKeyPrefix: string;\n private readonly onInvalidEntry: InvalidEntryHandler | undefined;\n\n /**\n * Gets all current-contract positions owned by an address.\n *\n * @param owner - GalaChain owner identity.\n * @returns Enriched positions from the v2 trade backend, token images included. A row that is\n * not a usable position is skipped and reported to `onInvalidEntry`.\n * @example\n * ```typescript\n * const positions = await gSwap.positions.getUserPositions('client|012345678901234567890123');\n * ```\n */\n async getUserPositions(owner: string): Promise<Position[]> {\n const response = await this.get<unknown>('/positions', { user: owner });\n return readEntries('positions', response.data, parsePosition, this.onInvalidEntry);\n }\n\n /**\n * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.\n * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.\n *\n * @param args - Pair, owner, fee, and position tick range.\n * @returns The position, or `null` when the backend returns 404.\n * @example\n * ```typescript\n * const position = await gSwap.positions.getPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async getPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<Position | null> {\n const response = await this.getNullable<unknown>(\n '/position',\n await this.positionParams(args),\n signal,\n );\n return response === null ? null : readPositionBody(response.data);\n }\n\n /**\n * Reads one position and classifies the outcome instead of throwing: `found` with the position\n * (fees included), `not_found` (the backend's HTTP 404, which it sends only when the chain\n * itself has no such position) or `unknown` (any other failure, carried as `error`). Use it\n * to confirm a write: `unknown` is \"no evidence either way\", never a confirmed absence.\n *\n * Only the caller's own abort rethrows. With a pass-through resolver ({@link CanonicalSymbols})\n * the pair and ticks go to the backend exactly as given and the backend orients them.\n *\n * @example\n * ```typescript\n * const read = await gSwap.positions.readPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * if (read.kind === 'found') console.log(read.data.fees0);\n * ```\n */\n async readPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<PositionRead> {\n try {\n const position = await this.getPosition(args, signal);\n return position === null ? { kind: 'not_found' } : { kind: 'found', data: position };\n } catch (error: unknown) {\n if (signal?.aborted === true) throw error;\n return {\n kind: 'unknown',\n error: isGSwapError(error)\n ? error\n : new GSwapSDKError('REQUEST_FAILED', { operation: 'position' }, { cause: error }),\n };\n }\n }\n\n /**\n * The `/position` query: canonical symbols and canonical ticks after a client-side flip, or,\n * for a pass-through resolver, the caller's references and ticks untouched.\n */\n private async positionParams(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n }): Promise<Record<string, string>> {\n if (this.symbols.passthrough === true) {\n return {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n owner: args.owner,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n };\n }\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n return {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: `${args.fee}`,\n owner: args.owner,\n tickLower: `${ticks.tickLower}`,\n tickUpper: `${ticks.tickUpper}`,\n };\n }\n\n /**\n * Estimates the other token amount and resulting liquidity for a deposit.\n *\n * @param args - Pair, tick range, deposit amount, and the amount's caller-side token index.\n * @returns Backend liquidity estimate.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async estimateAddLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n amountIsToken0: boolean;\n }): Promise<AddLiquidityEstimate> {\n validateNumericAmount(args.amount, 'amount');\n const response = await this.get<AddLiquidityEstimateWire>('/add-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n amount: new BigNumber(args.amount).toFixed(),\n amountIsToken0: String(args.amountIsToken0),\n });\n return response.data;\n }\n\n /**\n * Estimates token amounts released by burning liquidity.\n *\n * @param args - Pair, tick range, fee tier, and liquidity quantity.\n * @returns Estimated token0 and token1 quantities.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateRemoveLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, liquidity: '1000',\n * });\n * ```\n */\n async estimateRemoveLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n liquidity: NumericAmount;\n }): Promise<RemoveLiquidityEstimate> {\n validateNumericAmount(args.liquidity, 'liquidity');\n const response = await this.get<RemoveLiquidityEstimateWire>('/remove-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n liquidity: new BigNumber(args.liquidity).toFixed(),\n });\n return response.data;\n }\n\n /**\n * Adds liquidity using an explicit tick range. Exactly one canonical deposit field is emitted.\n *\n * @param args - Pair, fee, range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByTicks({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * await tx.confirm();\n * ```\n */\n async addLiquidityByTicks(args: AddLiquidityArgs) {\n return this.submitAddLiquidity(await this.buildAddLiquidity(args));\n }\n\n /**\n * Builds the AddLiquidity DTO that {@link addLiquidityByTicks} would sign, without signing or\n * sending it: to show in an approval popup, or to sign elsewhere. Submit exactly this DTO with\n * {@link submitAddLiquidity}. The pure counterpart, with canonical inputs and no resolution,\n * is `buildAddLiquidityDto`.\n *\n * @example\n * ```typescript\n * const dto = await gSwap.positions.buildAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async buildAddLiquidity(args: AddLiquidityArgs): Promise<AddLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n // Caller-facing checks first, so a refusal names the caller's own argument (`amount`).\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n validateNumericAmount(args.amount, 'amount');\n const base = {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n };\n return pair.flipped !== args.amountIsToken0\n ? buildAddLiquidityDto({ ...base, depositQuantityToken0: args.amount })\n : buildAddLiquidityDto({ ...base, depositQuantityToken1: args.amount });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildAddLiquidity} or `buildAddLiquidityDto`; it must\n * be exactly what the builder produces. The returned transaction confirms by proving the\n * position's liquidity grew.\n */\n async submitAddLiquidity(dto: AddLiquidityDTO) {\n assertCanonicalV2Dto('AddLiquidity', dto);\n return this.submit('AddLiquidity', dto, { kind: 'add', identity: identityOf(dto) });\n }\n\n /**\n * Adds liquidity from prices, flooring the lower tick and ceiling the upper tick to fee spacing.\n * The resulting range is therefore no narrower than the requested price interval.\n *\n * @param args - Pair, fee, price range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByPrice({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * minPrice: '0.14', maxPrice: '0.16', amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async addLiquidityByPrice(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n minPrice: PriceIn;\n maxPrice: PriceIn;\n amount: NumericAmount;\n amountIsToken0: boolean;\n /** The attempt's `uniqueKey`; default a fresh one (see {@link AddLiquidityArgs.uniqueKey}). */\n uniqueKey?: string | undefined;\n }) {\n validateFee(args.fee);\n this.rejectNumber(args.minPrice, 'minPrice');\n this.rejectNumber(args.maxPrice, 'maxPrice');\n const minPrice = new BigNumber(args.minPrice);\n const maxPrice = new BigNumber(args.maxPrice);\n if (\n !minPrice.isFinite() ||\n !maxPrice.isFinite() ||\n minPrice.isLessThanOrEqualTo(0) ||\n maxPrice.isLessThanOrEqualTo(0)\n ) {\n throw new GSwapSDKError('INVALID_PRICE_BOUNDS', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError('PRICE_BOUNDS_ORDER', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n const spacing = this.tickSpacing(args.fee);\n const tickLower = alignTickDown(tickFromPrice(minPrice), spacing);\n const tickUpper = alignTickUp(tickFromPrice(maxPrice), spacing);\n return this.addLiquidityByTicks({\n token0: args.token0,\n token1: args.token1,\n fee: args.fee,\n tickLower,\n tickUpper,\n amount: args.amount,\n amountIsToken0: args.amountIsToken0,\n uniqueKey: args.uniqueKey,\n });\n }\n\n /**\n * Removes liquidity by withdrawing at most one canonical token quantity.\n * Omitting both amounts closes the position and sweeps all accrued fees.\n *\n * @param args - Pair, fee, range, and optional caller-side withdrawal amount.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.removeLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async removeLiquidity(args: RemoveLiquidityArgs) {\n return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(args));\n }\n\n /**\n * Builds the RemoveLiquidity DTO that {@link removeLiquidity} would sign, without signing or\n * sending it. Submit exactly this DTO with {@link submitRemoveLiquidity}. The pure counterpart\n * is `buildRemoveLiquidityDto`.\n */\n async buildRemoveLiquidity(args: RemoveLiquidityArgs): Promise<RemoveLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n if (args.amount0 !== undefined && args.amount1 !== undefined) {\n throw new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: 'amount0', second: 'amount1' });\n }\n if (args.amount0 !== undefined) validateNumericAmount(args.amount0, 'amount0');\n if (args.amount1 !== undefined) validateNumericAmount(args.amount1, 'amount1');\n // The caller's amount0 / amount1 follow the caller's pair; the DTO's follow the canonical one.\n const [canonical0, canonical1] = pair.flipped\n ? [args.amount1, args.amount0]\n : [args.amount0, args.amount1];\n return buildRemoveLiquidityDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n withdrawalQuantityToken0: canonical0,\n withdrawalQuantityToken1: canonical1,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildRemoveLiquidity} or `buildRemoveLiquidityDto`;\n * it must be exactly what the builder produces. A DTO with no withdrawal quantity closes the\n * position, and the returned transaction then confirms by proving the position is gone.\n */\n async submitRemoveLiquidity(dto: RemoveLiquidityDTO) {\n assertCanonicalV2Dto('RemoveLiquidity', dto);\n const isFullClose =\n dto.withdrawalQuantityToken0 === undefined && dto.withdrawalQuantityToken1 === undefined;\n return this.submit('RemoveLiquidity', dto, {\n kind: isFullClose ? 'removeFull' : 'removePartial',\n identity: identityOf(dto),\n });\n }\n\n /**\n * Collects all accrued fees for a position; the contract does not support partial collection.\n *\n * @param args - Pair, fee, and tick range identifying the position.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.collectPositionFees({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async collectPositionFees(args: CollectPositionFeesArgs) {\n return this.submitCollectPositionFees(await this.buildCollectPositionFees(args));\n }\n\n /**\n * Builds the CollectPositionFees DTO that {@link collectPositionFees} would sign, without\n * signing or sending it. Submit exactly this DTO with {@link submitCollectPositionFees}. The\n * pure counterpart is `buildCollectPositionFeesDto`.\n */\n async buildCollectPositionFees(args: CollectPositionFeesArgs): Promise<CollectPositionFeesDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n return buildCollectPositionFeesDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCollectPositionFees} or\n * `buildCollectPositionFeesDto`; it must be exactly what the builder produces.\n */\n async submitCollectPositionFees(dto: CollectPositionFeesDTO) {\n assertCanonicalV2Dto('CollectPositionFees', dto);\n return this.submit('CollectPositionFees', dto, { kind: 'collect', identity: identityOf(dto) });\n }\n\n /**\n * Creates a pool, resolving registered trading symbols.\n * Reversed symbol order inverts the supplied starting price or square-root price.\n *\n * A token class key carries no symbol, so for a token being proposed into the v2\n * trading-symbol registry for the first time (no existing pool has registered it yet) the\n * caller MUST pass `token0Symbol`/`token1Symbol` (the token class's symbol, from the token\n * list or FetchTokenClasses). The SDK never derives a symbol from the key, and throws a\n * TOKEN_SYMBOL_NOT_REGISTERED error when an unregistered token has none. For an already-registered token a\n * supplied symbol must match the registered one.\n *\n * @param args - Token class keys or references, fee, exactly one starting price field, and privacy options.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.createPool({\n * token0: 'GALA|Unit|none|none', token1: 'GUSDC|Unit|none|none', fee: 3000,\n * startingPrice: '0.15',\n * });\n * ```\n */\n async createPool(args: CreatePoolArgs) {\n return this.submitCreatePool(await this.buildCreatePool(args));\n }\n\n /**\n * Builds the CreatePool DTO that {@link createPool} would sign, without signing or sending it:\n * symbols resolved or proposed, the pair put in canonical order and the price inverted when it\n * was reversed. Submit exactly this DTO with {@link submitCreatePool}. The pure counterpart,\n * with canonical inputs, is `buildCreatePoolDto`.\n */\n async buildCreatePool(args: CreatePoolArgs): Promise<CreatePoolDTO> {\n const hasPrice = args.startingPrice !== undefined;\n const hasSqrtPrice = args.startingSqrtPrice !== undefined;\n if (hasPrice === hasSqrtPrice) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n validateFee(args.fee);\n const [tokenA, tokenB] = await Promise.all([\n this.resolveCreateToken(args.token0, args.token0Symbol),\n this.resolveCreateToken(args.token1, args.token1Symbol),\n ]);\n const flipped = tokenA.symbol > tokenB.symbol;\n const [token0, token1] = flipped ? [tokenB, tokenA] : [tokenA, tokenB];\n const sourcePriceInput = hasPrice\n ? (args.startingPrice as NumericAmount)\n : (args.startingSqrtPrice as NumericAmount);\n this.rejectNumber(sourcePriceInput, hasPrice ? 'startingPrice' : 'startingSqrtPrice');\n const sourcePrice = new BigNumber(sourcePriceInput);\n if (!sourcePrice.isFinite() || sourcePrice.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(sourcePriceInput) });\n }\n const canonicalPrice = flipped ? new BigNumber(1).dividedBy(sourcePrice) : sourcePrice;\n const shared = {\n token0Key: token0.classKey,\n token1Key: token1.classKey,\n token0Symbol: token0.symbol,\n token1Symbol: token1.symbol,\n fee: args.fee,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n name: args.name,\n isPrivate: args.isPrivate,\n privateAccess: args.privateAccess,\n };\n return hasPrice\n ? buildCreatePoolDto({ ...shared, startingPrice: canonicalPrice })\n : buildCreatePoolDto({ ...shared, startingSqrtPrice: canonicalPrice });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCreatePool} or `buildCreatePoolDto`; it must be\n * exactly what the builder produces. The returned transaction confirms by the pool existing, and\n * the cached symbol registry is dropped, since the pool may have registered new symbols.\n */\n async submitCreatePool(dto: CreatePoolDTO) {\n assertCanonicalV2Dto('CreatePool', dto);\n const transaction = await this.submit('CreatePool', dto, {\n kind: 'createPool',\n token0: dto.token0Symbol,\n token1: dto.token1Symbol,\n fee: dto.fee,\n });\n this.symbols.invalidate?.();\n return transaction;\n }\n\n private async submit(\n method: string,\n dto: Record<string, unknown>,\n confirmation?: PositionSubmitConfirmation,\n ) {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const signed = await signPreSend(this.signer, method, dto);\n const submitOptions =\n this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n const owner = this.walletAddress;\n const positionConfirmation = this.buildPositionConfirmation(confirmation, owner);\n const options: ChainSubmitOptions = {\n ...submitOptions,\n ...(positionConfirmation === undefined ? {} : { positionConfirmation }),\n };\n return this.gateway.submit(method, signed, options);\n }\n\n /**\n * Builds a confirmation closure that proves the write's own effect, not just that a\n * position row exists (true before most of these writes run too, for any operation on a\n * pre-existing position — existence alone would false-confirm before the write executes,\n * and would never confirm a full close, whose whole point is that the position stops\n * existing).\n *\n * The \"before\" state is captured lazily, on the confirmation closure's own first poll —\n * not eagerly here in `submit()` — so confirming a write never adds an extra round-trip to\n * the write itself; the cost of establishing the baseline is paid by `confirm()`, only if\n * and when the caller actually asks to confirm.\n */\n private buildPositionConfirmation(\n confirmation: PositionSubmitConfirmation | undefined,\n owner: string | undefined,\n ): ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined {\n if (confirmation === undefined) return undefined;\n\n if (confirmation.kind === 'createPool') {\n const { token0, token1, fee } = confirmation;\n return async (signal) => {\n const pool = await this.getNullable<unknown>(\n '/pool',\n { token0, token1, fee: `${fee}` },\n signal,\n );\n return pool === null ? { confirmed: false } : { confirmed: true, position: null };\n };\n }\n\n if (owner === undefined) return undefined;\n const { kind, identity } = confirmation;\n let baseline: { liquidity: BigNumber; fees: BigNumber } | undefined;\n\n return async (signal) => {\n const current = await this.getPosition({ ...identity, owner }, signal);\n\n if (baseline === undefined) {\n // First poll only establishes the baseline to compare future polls against — it can\n // never itself be the confirmed outcome (nothing has been observed to change yet).\n baseline = {\n liquidity: new BigNumber(current?.liquidity ?? 0),\n fees: new BigNumber(current?.fees0 ?? 0).plus(new BigNumber(current?.fees1 ?? 0)),\n };\n // A full close starting from \"already gone\" (e.g. a retried confirm after the position\n // was already swept) is confirmed immediately rather than waiting for a change that\n // already happened.\n return kind === 'removeFull' && current === null\n ? { confirmed: true, position: null }\n : { confirmed: false };\n }\n\n switch (kind) {\n case 'add':\n return current !== null &&\n new BigNumber(current.liquidity).isGreaterThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removePartial':\n return current !== null && new BigNumber(current.liquidity).isLessThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removeFull':\n return current === null ? { confirmed: true, position: null } : { confirmed: false };\n case 'collect': {\n if (current === null) return { confirmed: false };\n const currentFees = new BigNumber(current.fees0 ?? 0).plus(\n new BigNumber(current.fees1 ?? 0),\n );\n if (currentFees.isLessThan(baseline.fees)) return { confirmed: true, position: current };\n // Nothing to sweep in the first place — a legitimate no-op collect never moves\n // fees, so \"still zero\" is the confirmed outcome, not an unconfirmed one.\n if (baseline.fees.isZero() && currentFees.isZero())\n return { confirmed: true, position: current };\n return { confirmed: false };\n }\n }\n };\n }\n\n private async get<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData>> {\n return this.http.sendGetRequest<BackendEnvelope<TData>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n signal === undefined ? undefined : { signal },\n );\n }\n\n private async getNullable<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData> | null> {\n try {\n return await this.get<TData>(endpoint, params, signal);\n } catch (error: unknown) {\n if (this.isNotFound(error)) return null;\n throw error;\n }\n }\n\n private isNotFound(error: unknown): boolean {\n return error instanceof GSwapSDKError && error.status === 404;\n }\n\n private canonicalTicks(tickLower: number, tickUpper: number, flipped: boolean) {\n return flipped ? { tickLower: -tickUpper, tickUpper: -tickLower } : { tickLower, tickUpper };\n }\n\n private tickSpacing(fee: number): number {\n const spacing = (TICK_SPACING_BY_FEE as Record<number, number>)[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n }\n\n /** The caller's `uniqueKey` (validated), else a fresh one. */\n private uniqueKeyFor(supplied: string | undefined): string {\n if (supplied === undefined) return createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(supplied);\n return supplied;\n }\n\n /**\n * The pair in canonical order. A resolver failure that is not an SDK error (an app's own\n * resolver, an app requestor's rejection during the registry read) is `TOKEN_RESOLUTION_FAILED`.\n */\n private orderPair(a: TokenRef, b: TokenRef) {\n return resolvePreSend(`${rawTokenOf(a)}/${rawTokenOf(b)}`, () => this.symbols.orderPair(a, b));\n }\n\n private async resolveCreateToken(\n ref: TokenRef,\n symbolOverride?: string,\n ): Promise<ResolvedCreateToken> {\n try {\n const lookupRef = typeof ref === 'object' ? compositeKeyOf(ref) : ref;\n const resolved = await resolvePreSend(rawTokenOf(ref), () => this.symbols.resolve(lookupRef));\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError('SYMBOL_DISAGREES_WITH_REGISTRY', {\n token: rawTokenOf(ref),\n suppliedSymbol: symbolOverride,\n registeredSymbol: resolved.symbol,\n });\n }\n const suppliedClassKey = this.tryParseClassKey(ref);\n if (suppliedClassKey === undefined && resolved.collection === '') {\n // An offline resolver knows a bare symbol but not its class key; a pool needs the key.\n throw new GSwapSDKError('CREATE_POOL_NEEDS_CLASS_KEY', { token: rawTokenOf(ref) });\n }\n return {\n symbol: resolved.symbol,\n classKey:\n suppliedClassKey ??\n parseTokenClassKey({\n collection: resolved.collection,\n category: resolved.category,\n type: resolved.type,\n additionalKey: resolved.additionalKey,\n }),\n };\n } catch (error: unknown) {\n if (!(error instanceof GSwapSDKError) || error.code !== 'UNKNOWN_TOKEN') {\n throw error;\n }\n let classKey: ReturnType<typeof parseTokenClassKey>;\n try {\n classKey = parseTokenClassKey(ref);\n } catch {\n throw error;\n }\n // First-time registration: a class key carries NO symbol (collection and symbol disagree\n // for many tokens, launchpad tokens all share collection `Token`, and some collections\n // contain `$`), so the symbol to propose must be supplied by the caller from the token\n // class / registry. Never derive it from the key.\n if (symbolOverride === undefined || symbolOverride === '') {\n throw new GSwapSDKError('TOKEN_SYMBOL_NOT_REGISTERED', { token: rawTokenOf(ref) });\n }\n if (!isProposableTradingSymbol(symbolOverride)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol: symbolOverride });\n }\n return { symbol: symbolOverride, classKey };\n }\n }\n\n private tryParseClassKey(ref: TokenRef): ReturnType<typeof parseTokenClassKey> | undefined {\n try {\n return parseTokenClassKey(ref);\n } catch {\n return undefined;\n }\n }\n}\n\nconst REQUIRED_POSITION_STRINGS = [\n 'token0Symbol',\n 'token1Symbol',\n 'owner',\n 'liquidity',\n 'amount0',\n 'amount1',\n] as const;\nconst REQUIRED_POSITION_NUMBERS = ['fee', 'tickLower', 'tickUpper'] as const;\nconst OPTIONAL_POSITION_STRINGS = [\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'sqrtPrice',\n 'fees0',\n 'fees1',\n] as const;\n\n/**\n * Reads one position row of `/positions` or `/position`: the pair, owner, range, liquidity and\n * amounts must be usable; the composite keys, token images, current tick and price, and the\n * escrowed fees are carried when present. `pool` is the pool reference (`poolRef` wins over\n * `pool`; `''` when the row names neither).\n */\nfunction parsePosition(value: unknown): EntryParse<Position> {\n const wire = asEntryRecord(value);\n if (wire === undefined) return entryRejected('the row is not an object');\n for (const key of REQUIRED_POSITION_STRINGS) {\n if (typeof wire[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n for (const key of REQUIRED_POSITION_NUMBERS) {\n const number = wire[key];\n if (typeof number !== 'number' || !Number.isFinite(number)) {\n return entryRejected(`${key} is not a number`);\n }\n }\n if (typeof wire['inRange'] !== 'boolean') return entryRejected('inRange is not a boolean');\n for (const key of OPTIONAL_POSITION_STRINGS) {\n if (wire[key] !== undefined && typeof wire[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n const currentTick = wire['currentTick'];\n if (\n currentTick !== undefined &&\n (typeof currentTick !== 'number' || !Number.isFinite(currentTick))\n ) {\n return entryRejected('currentTick is not a number');\n }\n const pool = wire['poolRef'] ?? wire['pool'] ?? '';\n if (typeof pool !== 'string') return entryRejected('pool is not a string');\n const optional = Object.fromEntries(\n [...OPTIONAL_POSITION_STRINGS, 'currentTick' as const].flatMap((key) =>\n wire[key] === undefined ? [] : [[key, wire[key]]],\n ),\n );\n return entryOk({\n token0Symbol: wire['token0Symbol'] as string,\n token1Symbol: wire['token1Symbol'] as string,\n fee: wire['fee'] as number,\n tickLower: wire['tickLower'] as number,\n tickUpper: wire['tickUpper'] as number,\n liquidity: wire['liquidity'] as string,\n amount0: wire['amount0'] as string,\n amount1: wire['amount1'] as string,\n inRange: wire['inRange'],\n pool,\n owner: wire['owner'] as string,\n ...optional,\n });\n}\n\n/** The position inside a `/position` answer, or `INVALID_CHAIN_RESPONSE` when it is not one. */\nfunction readPositionBody(data: unknown): Position {\n const parsed = parsePosition(data);\n if (parsed.ok) return parsed.value;\n throw new GSwapSDKError('INVALID_POSITION_RESPONSE', { reason: parsed.reason }, { body: data });\n}\n","import BigNumber from 'bignumber.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport type { QuoteResult } from '../types/v2_results.js';\nimport type { TokenRef } from '../utils/ordering.js';\nimport { validateNumericAmount } from '../utils/validation.js';\nimport type { WireOptions } from '../types/wire.js';\nimport type { ChainGateway } from './gateway.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './error_catalog.js';\nimport { readServerMessage } from '../utils/server_message.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, type TokenResolver } from './symbols.js';\n\ninterface QuoteWire {\n contractVersion: 'v2';\n fee: number;\n amountIn: string;\n amountOut: string;\n currentSqrtPrice?: string;\n newSqrtPrice?: string;\n currentPrice?: string;\n newPrice?: string;\n newTick: number;\n tradingFees: string;\n protocolFees: string;\n totalFees: string;\n feeTokenSymbol: string;\n token0Symbol: string;\n token1Symbol: string;\n tokenInIsToken0: boolean;\n}\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\n/** The transport a quote service reads through: the same shape `Pools` and `Symbols` take. */\ntype QuoteGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** Read-only quote service backed by the v2 offline quote engine. */\nexport class Quoting {\n /**\n * Creates a quote service.\n *\n * @example\n * ```ts\n * const quoting = new Quoting(gateway, symbols); // a ChainGateway, or any { dexBackendBaseUrl, httpRequestor }\n * ```\n */\n constructor(\n private readonly gateway: QuoteGateway,\n private readonly symbols: TokenResolver,\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Quotes the output for a positive exact-input amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactInput('GALA', 'GUSDC', '100');\n * console.log(quote.amountOut);\n * ```\n */\n public async quoteExactInput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountIn: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountIn, 'amountIn');\n return this.quote(tokenIn, tokenOut, { amountIn: toDecimalString(amountIn) }, fee);\n }\n\n /**\n * Quotes the input for a positive exact-output amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactOutput('GALA', 'GUSDC', '10', 3000);\n * console.log(quote.amountIn);\n * ```\n */\n public async quoteExactOutput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountOut: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountOut, 'amountOut');\n return this.quote(tokenIn, tokenOut, { amountOut: toDecimalString(amountOut) }, fee);\n }\n\n private async quote(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amount: { amountIn: string } | { amountOut: string },\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateOptionalFee(fee);\n\n const params: Record<string, string> = {\n tokenIn: await queryTokenOf(this.symbols, tokenIn),\n tokenOut: await queryTokenOf(this.symbols, tokenOut),\n ...amount,\n };\n if (fee !== undefined) params['fee'] = String(fee);\n\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<QuoteWire>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/quote',\n params,\n );\n return mapQuote(response.data);\n } catch (error: unknown) {\n throw mapQuoteError(error, tokenIn, tokenOut, fee, {\n tokenIn: params['tokenIn'] ?? '',\n tokenOut: params['tokenOut'] ?? '',\n });\n }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError('INVALID_CHAIN_RESPONSE', { resource: 'quote' }, { body: value });\n }\n const wire = value;\n const currentPrice =\n wire.currentPrice !== undefined\n ? new BigNumber(wire.currentPrice)\n : orientPrice(wire.currentSqrtPrice!, wire.tokenInIsToken0);\n const newPrice =\n wire.newPrice !== undefined\n ? new BigNumber(wire.newPrice)\n : orientPrice(wire.newSqrtPrice!, wire.tokenInIsToken0);\n const priceImpact = newPrice.minus(currentPrice).dividedBy(currentPrice);\n\n return {\n contractVersion: wire.contractVersion,\n fee: wire.fee,\n amountIn: wire.amountIn,\n amountOut: wire.amountOut,\n ...(wire.currentSqrtPrice === undefined ? {} : { currentSqrtPrice: wire.currentSqrtPrice }),\n ...(wire.newSqrtPrice === undefined ? {} : { newSqrtPrice: wire.newSqrtPrice }),\n feeTier: wire.fee,\n newTick: wire.newTick,\n tradingFees: wire.tradingFees,\n protocolFees: wire.protocolFees,\n totalFees: wire.totalFees,\n feeTokenSymbol: wire.feeTokenSymbol,\n token0Symbol: wire.token0Symbol,\n token1Symbol: wire.token1Symbol,\n tokenInIsToken0: wire.tokenInIsToken0,\n currentPrice,\n newPrice,\n priceImpact,\n };\n}\n\n// The default BigNumber.DECIMAL_PLACES (20) underflows 1/poolPrice to exactly 0 for a\n// pool price above ~1e20 (a real, in-range price for a low-unit-value token quoted\n// against a high-value one) — 60dp matches the precision ticks.ts's DexMath already\n// uses for this same class of division.\nconst HighPrecision = BigNumber.clone({ DECIMAL_PLACES: 60 });\n\nfunction orientPrice(sqrtPrice: string, tokenInIsToken0: boolean): BigNumber {\n const poolPrice = new HighPrecision(sqrtPrice).pow(2);\n return tokenInIsToken0 ? poolPrice : new HighPrecision(1).dividedBy(poolPrice);\n}\n\nfunction isQuoteWire(value: unknown): value is QuoteWire {\n if (typeof value !== 'object' || value === null) return false;\n const wire = value as Record<string, unknown>;\n const requiredStrings = [\n 'amountIn',\n 'amountOut',\n 'tradingFees',\n 'protocolFees',\n 'totalFees',\n 'feeTokenSymbol',\n 'token0Symbol',\n 'token1Symbol',\n ];\n return (\n wire['contractVersion'] === 'v2' &&\n typeof wire['fee'] === 'number' &&\n Number.isFinite(wire['fee']) &&\n requiredStrings.every((key) => typeof wire[key] === 'string') &&\n typeof wire['newTick'] === 'number' &&\n Number.isInteger(wire['newTick']) &&\n typeof wire['tokenInIsToken0'] === 'boolean' &&\n optionalPositiveDecimal(wire['currentSqrtPrice']) &&\n optionalPositiveDecimal(wire['newSqrtPrice']) &&\n optionalPositiveDecimal(wire['currentPrice']) &&\n optionalPositiveDecimal(wire['newPrice']) &&\n (wire['currentSqrtPrice'] !== undefined || wire['currentPrice'] !== undefined) &&\n (wire['newSqrtPrice'] !== undefined || wire['newPrice'] !== undefined)\n );\n}\n\nfunction optionalPositiveDecimal(value: unknown): boolean {\n if (value === undefined) return true;\n if (typeof value !== 'string') return false;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this validates an untrusted backend field, so an unparseable value\n // must fail validation cleanly (INVALID_CHAIN_RESPONSE), not throw raw.\n const decimal = new BigNumber(value);\n return decimal.isFinite() && decimal.isGreaterThan(0);\n } catch {\n return false;\n }\n}\n\n/**\n * The ways the backend says a pair has no market at all: no pool at ANY fee tier (\"No pools found\n * with sufficient liquidity\") or a missing pool (\"Pool does not exist on the new DEX contract\").\n * A pool that exists but is too thin says \"Insufficient liquidity: ...\" instead.\n */\nconst NO_MARKET_MESSAGE = /no pool|no pools|pool does not exist/iu;\n\n/**\n * A token the DEX contract never registered: the backend's symbol registry answers\n * `Token <token> has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`\n * with an HTTP 400, naming the token exactly as the quote request sent it. That is a different\n * fact from \"no pool for this pair\" (the token itself is unknown), so it is `UNKNOWN_TOKEN` with\n * the token, not `NO_POOL_AVAILABLE`. Token class keys and symbols contain no whitespace.\n */\nconst NO_SYMBOL_MESSAGE = /Token (\\S+) has no trading symbol on the new DEX contract/u;\n\n/** The token the quote request named in the form the caller gave it, else as the backend echoed it. */\nfunction unknownTokenOf(\n echoed: string,\n queried: { tokenIn: string; tokenOut: string },\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n): TokenRef {\n if (echoed === queried.tokenIn) return tokenIn;\n if (echoed === queried.tokenOut) return tokenOut;\n return echoed;\n}\n\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n queried: { tokenIn: string; tokenOut: string },\n): GSwapSDKError {\n if (isGSwapError(error)) {\n // The backend's own English is read ONLY to classify its answer; it is never surfaced. The\n // SDK's generated `message` is never matched: its templates are not a contract.\n const message = readServerMessage(error) ?? '';\n const unregistered = NO_SYMBOL_MESSAGE.exec(message)?.[1];\n if (unregistered !== undefined) {\n return GSwapSDKError.unknownTokenError(\n unknownTokenOf(unregistered, queried, tokenIn, tokenOut),\n error,\n );\n }\n if (error.status === 404 || NO_MARKET_MESSAGE.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee, error);\n }\n if (error.status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee, error);\n }\n return error;\n }\n return new GSwapSDKError('REQUEST_FAILED', { operation: 'quote' }, { cause: error });\n}\n\nfunction validateOptionalFee(fee: FEE_TIER | undefined): void {\n if (fee !== undefined && !ALL_FEE_TIERS.some((tier) => Number(tier) === Number(fee))) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: Number(fee),\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n","import { getStringProperty, GSwapSDKError } from './gswap_sdk_error.js';\n\n/** The raw answer to a shadow (dark) write: every HTTP status resolves. */\nexport interface ShadowSubmitResult {\n httpStatus: number;\n /** Parsed JSON body, or the raw text when the body was not JSON. */\n body: unknown;\n}\n\n/**\n * Machine-readable codes defi-backend returns in a shadow failure body (`{ code, message }`, with\n * no `statusCode`; the HTTP status carries the number).\n *\n * - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back\n * silently to a public swap.\n * - `SHADOW_DISABLED` (400): the feature is off for this environment.\n * - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.\n * - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;\n * `message` is the gateway's verbatim string.\n */\nexport const SHADOW_SUBMIT_CODES = [\n 'SHADOW_UNAVAILABLE',\n 'SHADOW_DISABLED',\n 'SHADOW_UNSUPPORTED_TYPE',\n 'SHADOW_RELAY_REJECTED',\n] as const;\n\n/** One member of {@link SHADOW_SUBMIT_CODES}. */\nexport type ShadowSubmitCode = (typeof SHADOW_SUBMIT_CODES)[number];\n\n/**\n * Every `kind` of a failed {@link ShadowSubmitOutcome}, for an app that maps each to its own text\n * (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled`, `rejected` (carries\n * the gateway's `message`) and `unknown`.\n */\nexport const SHADOW_FAILURE_KINDS = ['unavailable', 'disabled', 'rejected', 'unknown'] as const;\n\n/** One member of {@link SHADOW_FAILURE_KINDS}. */\nexport type ShadowFailureKind = (typeof SHADOW_FAILURE_KINDS)[number];\n\n/** A RequestTrade the gateway queued: the handle to confirm it with `confirmAppliedTrade`. */\nexport interface ShadowQueuedRequest {\n uniqueKey: string;\n requestTransactionId: string | null;\n}\n\n/** A shadow write the gateway refused or did not answer: `kind` says why (see {@link SHADOW_FAILURE_KINDS}). */\nexport type ShadowSubmitFailure =\n | { ok: false; kind: 'unavailable'; retryable: true }\n | { ok: false; kind: 'disabled'; retryable: false }\n | { ok: false; kind: 'rejected'; retryable: false; message: string }\n | { ok: false; kind: 'unknown'; retryable: false };\n\n/**\n * The normalized outcome of a shadow RequestTrade (a dark swap). A success (`ok: true`) ALWAYS\n * carries `queued`, the exact key the gateway acknowledged: a RequestTrade answer that does not\n * queue the signed key is not an outcome but a thrown `SHADOW_NOT_QUEUED`. So after `if (outcome.ok)`\n * the app reads `outcome.queued` with no `undefined` branch.\n */\nexport type ShadowSubmitOutcome =\n | {\n ok: true;\n /** The request transaction id (`''` when the gateway gave none). */\n bundleId: string;\n /** Confirm with `confirmAppliedTrade`. */\n queued: ShadowQueuedRequest;\n }\n | ShadowSubmitFailure;\n\n/**\n * The success of a shadow write that is NOT a RequestTrade and executed synchronously\n * (`mode: 'sync'`, a liquidity write): there is nothing queued to confirm, so `queued` is absent.\n */\nexport interface ShadowSyncSuccess {\n ok: true;\n /** The transaction id (`''` when the gateway gave none). */\n bundleId: string;\n queued?: undefined;\n}\n\n/** Maps an HTTP status to a failure kind: 503 retryable, 400 disabled, anything else unknown. */\nexport function classifyShadowSubmitStatus(status: number): ShadowFailureKind {\n if (status === 503) return 'unavailable';\n if (status === 400) return 'disabled';\n return 'unknown';\n}\n\n/**\n * Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.\n * `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway\n * rejection; the two other 400 codes and any unknown 400 map to \"disabled\".\n */\nexport function classifyShadowSubmitError(status: number, code?: string): ShadowFailureKind {\n if (code === 'SHADOW_UNAVAILABLE') return 'unavailable';\n if (code === 'SHADOW_RELAY_REJECTED') return 'rejected';\n if (code === 'SHADOW_DISABLED' || code === 'SHADOW_UNSUPPORTED_TYPE') return 'disabled';\n return classifyShadowSubmitStatus(status);\n}\n\n/**\n * Normalizes a shadow write's raw answer. For `'RequestTrade'` the result is a\n * {@link ShadowSubmitOutcome}, whose success always has `queued`; any other method may also be a\n * {@link ShadowSyncSuccess} (no `queued`).\n *\n * A 2xx envelope with `error === false` is a success when it is a queued RequestTrade that\n * acknowledges the EXACT signed `uniqueKey`, or a synchronous (`mode: 'sync'`) liquidity write.\n * Everything else is classified as a failure from the status and the body's `code`.\n *\n * @throws GSwapSDKError SHADOW_NOT_QUEUED when a RequestTrade success does not queue the\n * signed `uniqueKey` (a synchronous or mismatched answer must never be accepted as a swap).\n */\nexport function readShadowSubmitOutcome(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess {\n const { httpStatus, body } = result;\n const envelope = asRecord(body);\n if (httpStatus >= 200 && httpStatus < 300 && envelope?.['error'] === false) {\n const data = asRecord(envelope['data']);\n const rawTransactionId =\n typeof data?.['transactionId'] === 'string' ? data['transactionId'] : undefined;\n if (method === 'RequestTrade') {\n const requestedKey = signedBody['uniqueKey'];\n if (\n data?.['mode'] !== 'queued' ||\n typeof requestedKey !== 'string' ||\n data['uniqueKey'] !== requestedKey\n ) {\n throw new GSwapSDKError(\n 'SHADOW_NOT_QUEUED',\n {},\n {\n status: httpStatus,\n body,\n shadow: true,\n ...(typeof requestedKey === 'string' ? { uniqueKey: requestedKey } : {}),\n },\n );\n }\n return {\n ok: true,\n bundleId: rawTransactionId ?? '',\n queued: { uniqueKey: requestedKey, requestTransactionId: rawTransactionId ?? null },\n };\n }\n if (data?.['mode'] === 'sync') return { ok: true, bundleId: rawTransactionId ?? '' };\n }\n\n const kind = classifyShadowSubmitError(httpStatus, getStringProperty(body, 'code'));\n if (kind === 'rejected') {\n return {\n ok: false,\n kind: 'rejected',\n retryable: false,\n message: getStringProperty(body, 'message') ?? '',\n };\n }\n return kind === 'unavailable'\n ? { ok: false, kind, retryable: true }\n : { ok: false, kind, retryable: false };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","import type { SwapAmount } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport { assertCanonicalV2Dto, buildRequestTradeDto } from '../utils/dto_builders.js';\nimport { signPreSend } from '../utils/pre_send.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport { assertCanonicalPair, validateFee } from '../utils/validation.js';\nimport type { ChainSubmitOptions } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { GalaChainSigner } from './signers.js';\nimport {\n readShadowSubmitOutcome,\n type ShadowSubmitOutcome,\n type ShadowSubmitResult,\n} from './shadow_submit.js';\nimport { SubmittedTransaction } from './submitted_transaction.js';\nimport type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { RequestTradeDTO } from '../types/v2_dtos.js';\nimport type { AppliedTrade, QuoteResult } from '../types/v2_results.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { tradingSymbolOf, type TokenResolver } from './symbols.js';\nimport {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n type UniqueKeyOptions,\n} from '../utils/unique_key.js';\n\ninterface SwapGateway {\n submit: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<AppliedTrade>>;\n submitShadow: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<ShadowSubmitResult>;\n readonly dexBackendBaseUrl: string;\n readonly httpRequestor: HttpRequestor;\n readonly requestTimeoutMs: number;\n readonly wire?: WireOptions | undefined;\n}\n\n/** The canonical pool a swap trades in, as a quote names it. */\nexport interface SwapPool {\n token0: string;\n token1: string;\n}\n\n/** Options of a swap. */\nexport interface SwapOptions {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing (to remember it, to\n * show it), or to retry the SAME attempt after a lost response; never reuse it for another trade.\n */\n uniqueKey?: string | undefined;\n /**\n * Pin the pool: take `token0` / `token1` verbatim from the quote the user saw, instead of\n * ordering `tokenIn` / `tokenOut` by string comparison. `tokenIn` and `tokenOut` must be exactly\n * these two symbols, and `token0` must sort before `token1`. See {@link swapRouteFromQuote}.\n */\n pool?: SwapPool | undefined;\n}\n\n/** Everything {@link Swaps.swap} needs to trade in the pool a quote priced. */\nexport interface SwapRoute {\n tokenIn: string;\n tokenOut: string;\n fee: FEE_TIER;\n pool: SwapPool;\n}\n\n/**\n * The route of a quote: its fee tier and pool, with `tokenIn` / `tokenOut` taken from\n * `tokenInIsToken0`, nothing re-derived. Use it to swap in exactly the pool a quote priced:\n *\n * @example\n * ```ts\n * const route = swapRouteFromQuote(quote);\n * await swaps.swap(route.tokenIn, route.tokenOut, route.fee, { exactIn: '100' }, { pool: route.pool });\n * ```\n */\nexport function swapRouteFromQuote(\n quote: Pick<QuoteResult, 'token0Symbol' | 'token1Symbol' | 'tokenInIsToken0' | 'fee'>,\n): SwapRoute {\n validateFee(quote.fee);\n assertCanonicalPair(quote.token0Symbol, quote.token1Symbol);\n const [tokenIn, tokenOut] = quote.tokenInIsToken0\n ? [quote.token0Symbol, quote.token1Symbol]\n : [quote.token1Symbol, quote.token0Symbol];\n return {\n tokenIn,\n tokenOut,\n fee: quote.fee,\n pool: { token0: quote.token0Symbol, token1: quote.token1Symbol },\n };\n}\n\n/** Executes queued current-contract RequestTrade operations through the Chain Gateway. */\nexport class Swaps {\n /**\n * Creates a swap service.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, symbols, signer, 'client|alice');\n * ```\n */\n constructor(\n private readonly gateway: SwapGateway,\n private readonly symbols: TokenResolver,\n private readonly signer?: GalaChainSigner,\n private readonly walletAddress?: string,\n options: UniqueKeyOptions = {},\n ) {\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\n }\n\n private readonly uniqueKeyPrefix: string;\n\n /**\n * Signs and submits an exact-input or exact-output RequestTrade DTO. The returned transaction\n * is QUEUED; call `await tx.confirm()` to obtain the executed trade or chain rejection.\n *\n * @example\n * ```ts\n * const submitted = await swaps.swap('GALA', 'GUSDC', 3000, {\n * exactIn: '100',\n * amountOutMinimum: '14',\n * });\n * ```\n */\n public async swap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>> {\n return this.submitSwap(await this.buildSwap(tokenIn, tokenOut, fee, amount, options));\n }\n\n /**\n * Signs and submits a SHADOW (dark) swap: the same RequestTrade as {@link swap}, relayed with\n * `X-Shadow: true` so defi-backend marks it private before it reaches the contract. Requires a\n * `walletAddress`. Resolves the normalized outcome instead of throwing on a gateway refusal:\n * `ok: false` carries `unavailable` (retryable), `disabled`, `rejected` (with the gateway's\n * message) or `unknown`. A success carries `queued`, to be confirmed with\n * `confirmSwap(queued.uniqueKey)`; never fall back to a public swap on failure. Whatever this\n * THROWS (a validation error, the signer, a lost connection, `SHADOW_NOT_QUEUED`) has\n * `error.shadow === true` (`isShadowError`), so an app can apply its dark-swap policy to it.\n *\n * @example\n * ```ts\n * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * if (outcome.ok) await swaps.confirmSwap(outcome.queued.uniqueKey);\n * ```\n */\n public async swapShadow(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () =>\n this.submitSwapShadow(await this.buildSwap(tokenIn, tokenOut, fee, amount, options)),\n );\n }\n\n /**\n * Builds the RequestTrade DTO that {@link swap} would sign, without signing or sending it: to\n * show in an approval popup, to remember its `uniqueKey`, or to sign elsewhere. Submit exactly\n * this DTO with {@link submitSwap}. The pure counterpart, with canonical inputs and no\n * resolution, is `buildRequestTradeDto`.\n *\n * @example\n * ```ts\n * const dto = await swaps.buildSwap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * showApproval(dto);\n * const submitted = await swaps.submitSwap(dto);\n * ```\n */\n public async buildSwap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<RequestTradeDTO> {\n validateFee(fee);\n const uniqueKey = options?.uniqueKey ?? createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(uniqueKey);\n const tokenInSymbol = await tradingSymbolOf(this.symbols, tokenIn);\n const tokenOutSymbol = await tradingSymbolOf(this.symbols, tokenOut);\n const ordered = this.orientPool(tokenInSymbol, tokenOutSymbol, options?.pool);\n return buildRequestTradeDto({\n token0: ordered.token0,\n token1: ordered.token1,\n fee,\n tokenInIsToken0: tokenInSymbol === ordered.token0,\n uniqueKey,\n ...amount,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildSwap} or `buildRequestTradeDto`. The DTO must be\n * exactly what the builder produces (no signature, canonical decimals, builder key order), so\n * what an app showed is what gets signed.\n *\n * @example\n * ```ts\n * const submitted = await swaps.submitSwap(dto);\n * const applied = await submitted.confirm();\n * ```\n */\n public async submitSwap(dto: RequestTradeDTO): Promise<SubmittedTransaction<AppliedTrade>> {\n const signed = await this.signRequestTrade(dto);\n return this.gateway.submit('RequestTrade', signed, this.submitOptions());\n }\n\n /** Signs and shadow-submits a DTO built by {@link buildSwap}; see {@link swapShadow}. */\n public async submitSwapShadow(dto: RequestTradeDTO): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () => {\n const signed = await this.signRequestTrade(dto);\n const result = await this.gateway.submitShadow('RequestTrade', signed, this.submitOptions());\n return readShadowSubmitOutcome('RequestTrade', signed, result);\n });\n }\n\n private submitOptions(): ChainSubmitOptions {\n return this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n }\n\n private async signRequestTrade(dto: RequestTradeDTO): Promise<Record<string, unknown>> {\n assertCanonicalV2Dto('RequestTrade', dto);\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n return signPreSend(this.signer, 'RequestTrade', dto);\n }\n\n /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */\n private orientPool(\n tokenInSymbol: string,\n tokenOutSymbol: string,\n pool: SwapPool | undefined,\n ): SwapPool {\n if (pool === undefined) {\n return readOrderedSymbols(orderSymbols(tokenInSymbol, tokenOutSymbol));\n }\n const sameSet =\n (tokenInSymbol === pool.token0 && tokenOutSymbol === pool.token1) ||\n (tokenInSymbol === pool.token1 && tokenOutSymbol === pool.token0);\n if (!sameSet) {\n throw new GSwapSDKError('POOL_MISMATCH', {\n tokenIn: tokenInSymbol,\n tokenOut: tokenOutSymbol,\n poolToken0: pool.token0,\n poolToken1: pool.token1,\n });\n }\n return { token0: pool.token0, token1: pool.token1 };\n }\n\n /**\n * Confirm a swap by its durable `uniqueKey` without resubmitting it. This is the recovery\n * path after a `CONFIRMATION_TIMEOUT`, a `SUBMISSION_OUTCOME_UNKNOWN`, a `409` replay\n * conflict, or a process restart: it reads the same apply-results record that\n * `SubmittedTransaction.confirm()` reads (retained for 7 days) and resolves the applied trade\n * or throws the chain's rejection. The first read happens immediately unless\n * `initialDelayMs` is given.\n *\n * @example\n * ```ts\n * const applied = await swaps.confirmSwap('galaswap-operation-2f1c…');\n * ```\n */\n public async confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade> {\n assertUniqueKey(uniqueKey);\n const transaction = new SubmittedTransaction<AppliedTrade>({\n method: 'RequestTrade',\n uniqueKey,\n transactionId: null,\n mode: 'queued',\n result: undefined,\n dexBackendBaseUrl: this.gateway.dexBackendBaseUrl,\n httpRequestor: this.gateway.httpRequestor,\n requestTimeoutMs: this.gateway.requestTimeoutMs,\n wire: this.gateway.wire,\n });\n return transaction.confirm({ initialDelayMs: 0, ...options });\n }\n}\n","import { Assets } from './assets.js';\nimport { DexFees } from './dex_fees.js';\nimport { ChainGateway } from './gateway.js';\nimport { GdexStreamService } from './gdex_stream.js';\nimport { HttpClient } from './http_client.js';\nimport { Pools } from './pools.js';\nimport { Positions } from './positions.js';\nimport { Quoting } from './quoting.js';\nimport type { GalaChainSigner } from './signers.js';\nimport { CanonicalSymbols, Symbols } from './symbols.js';\nimport type { InvalidEntryHandler } from '../utils/lenient.js';\nimport { Swaps } from './swaps.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { GSwapEnv } from '../types/env.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { GSWAP_ENVIRONMENTS } from '../types/env.js';\n\n/** Options for constructing a backend-routed SDK client. */\nexport interface GSwapOptions {\n signer?: GalaChainSigner | undefined;\n walletAddress?: string | undefined;\n env?: GSwapEnv | undefined;\n dexBackendBaseUrl?: string | undefined;\n httpRequestor?: HttpRequestor | undefined;\n /** Request timeout in milliseconds (default 30 000); `Infinity` arms no timer. */\n chainCallTimeoutMs?: number | undefined;\n /** Query encoding and `User-Agent` of the read requests (see {@link WireOptions}). */\n wire?: WireOptions | undefined;\n /**\n * How tokens are turned into trading symbols. `'registry'` (default) reads the symbol registry\n * once (`GET /v2/trade/symbols`, cached) and accepts symbols or class keys. `'canonical'` makes\n * no registry request: the caller passes the backend's canonical trading symbols (from a quote,\n * an estimate or a position), reads send tokens and ticks exactly as given (composite keys\n * included) and the backend orients the pair; see {@link CanonicalSymbols}.\n */\n symbolResolution?: 'registry' | 'canonical' | undefined;\n /**\n * Told about every row of a pool, symbol or position list that was skipped as unusable (see\n * {@link InvalidEntryHandler}); without it such rows are skipped silently.\n */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n /** Realtime stream endpoint. Defaults to the environment's, or is derived from `dexBackendBaseUrl`. */\n dexBackendWsUrl?: string | undefined;\n /** WebSocket constructor for the realtime stream; required on Node.js older than 22. */\n webSocketImpl?: unknown;\n /**\n * `x-api-key` for the privileged stream view; server-side only, and it requires `webSocketImpl`\n * (see `GdexStreamConfig.apiKey`).\n */\n streamApiKey?: string | undefined;\n /**\n * Prefix of every write's `uniqueKey` (`<prefix><uuid>`). Defaults to `galaswap-operation-`,\n * what frontend_v2 and wallet_extension send; defi-backend does not depend on it.\n */\n uniqueKeyPrefix?: string | undefined;\n}\n\n/** Main entry point for the current GalaChainDex SDK. */\nexport class GSwap {\n public readonly dexBackendBaseUrl: string;\n public readonly chainCallTimeoutMs: number;\n public readonly signer: GalaChainSigner | undefined;\n public readonly walletAddress: string | undefined;\n public readonly gateway: ChainGateway;\n public readonly symbols: Symbols;\n public readonly quoting: Quoting;\n public readonly pools: Pools;\n public readonly positions: Positions;\n public readonly swaps: Swaps;\n public readonly assets: Assets;\n /** Network-fee quotes (DryRun) signed with this client's signer. */\n public readonly fees: DexFees;\n public readonly dexBackendWsUrl: string;\n private readonly webSocketImpl: unknown;\n private readonly streamApiKey: string | undefined;\n private streamClient: GdexStreamService | undefined;\n\n /**\n * Create an SDK client for prod or stage.\n *\n * @example\n * ```typescript\n * const gSwap = new GSwap({ env: 'stage' });\n * const symbols = await gSwap.symbols.list();\n * ```\n */\n constructor(options?: GSwapOptions) {\n const environment = GSWAP_ENVIRONMENTS[options?.env ?? 'prod'];\n this.dexBackendBaseUrl = trimTrailingSlash(\n options?.dexBackendBaseUrl ?? environment.dexBackendBaseUrl,\n );\n this.chainCallTimeoutMs = options?.chainCallTimeoutMs ?? 30_000;\n this.signer = options?.signer;\n this.walletAddress = options?.walletAddress;\n\n const httpClient = new HttpClient(\n options?.httpRequestor,\n this.chainCallTimeoutMs,\n options?.wire,\n );\n this.gateway = new ChainGateway({\n dexBackendBaseUrl: this.dexBackendBaseUrl,\n chainCallTimeoutMs: this.chainCallTimeoutMs,\n ...(options?.wire === undefined ? {} : { wire: options.wire }),\n ...(options?.httpRequestor === undefined ? {} : { httpRequestor: options.httpRequestor }),\n ...(this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress }),\n });\n const lenient = { onInvalidEntry: options?.onInvalidEntry };\n this.symbols = new Symbols(this.gateway, lenient);\n // The services resolve tokens through the registry by default; the offline resolver sends the\n // caller's canonical symbols and keys as they are and never reads the registry.\n const resolver =\n options?.symbolResolution === 'canonical' ? new CanonicalSymbols() : this.symbols;\n this.quoting = new Quoting(this.gateway, resolver);\n this.pools = new Pools(this.gateway, resolver, lenient);\n const keyOptions = { uniqueKeyPrefix: options?.uniqueKeyPrefix, ...lenient };\n this.positions = new Positions(\n this.gateway,\n resolver,\n this.signer,\n this.walletAddress,\n keyOptions,\n );\n this.swaps = new Swaps(this.gateway, resolver, this.signer, this.walletAddress, keyOptions);\n this.assets = new Assets(this.dexBackendBaseUrl, httpClient);\n this.fees = new DexFees(this.gateway, this.signer);\n this.dexBackendWsUrl =\n options?.dexBackendWsUrl ??\n (options?.dexBackendBaseUrl === undefined\n ? environment.dexBackendWsUrl\n : `${this.dexBackendBaseUrl.replace(/^http/u, 'ws')}/ws`);\n this.webSocketImpl = options?.webSocketImpl;\n this.streamApiKey = options?.streamApiKey;\n }\n\n /**\n * The realtime stream client for this environment (created on first use, not connected until you\n * call `connect()`).\n *\n * @example\n * ```typescript\n * const gSwap = new GSwap({ env: 'stage' });\n * await gSwap.stream.connect();\n * await gSwap.stream.subscribeLiquidity((event) => console.log(event.action, event.amount0));\n * ```\n */\n get stream(): GdexStreamService {\n this.streamClient ??= new GdexStreamService({\n url: this.dexBackendWsUrl,\n ...(this.webSocketImpl === undefined ? {} : { webSocketImpl: this.webSocketImpl }),\n ...(this.streamApiKey === undefined ? {} : { apiKey: this.streamApiKey }),\n });\n return this.streamClient;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/u, '');\n}\n","import type { GSWAP_ERROR_CATALOG, GSwapErrorCode } from '../classes/error_catalog.js';\nimport type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { isCatalogCode } from '../classes/error_phase_table.js';\nimport type { FailureOutcome } from './failure_outcomes.js';\nimport { isWriteView, numberParamOf, stringParamOf, toFailureView } from './failure_view.js';\nimport type { FailureView } from './failure_view.js';\n\n/** The result of {@link classifyFailure}. */\nexport interface FailureClassification {\n readonly outcome: FailureOutcome;\n /**\n * May the app offer the user Retry: repeat the operation as a NEW request (a fresh key for a\n * write) without any risk of applying it twice? Always `false` for `unknown` (confirm the same\n * key instead) and `invalid_input` (the same call fails again). It says a repeat is SAFE, not\n * that it will succeed, and it is the SDK's floor: an app may still withhold Retry (the\n * wallet and frontend_v2 do after a Dark swap: see `isShadowError`).\n */\n readonly retryable: boolean;\n}\n\n/**\n * The SDK's default Retry answer for each outcome. A decision that departs from it (a refusal the\n * gateway will repeat, `SHADOW_NOT_QUEUED`) is written out in the table below.\n */\nconst DEFAULT_RETRYABLE = {\n rejected: true,\n unknown: false,\n not_queued: true,\n not_sent: true,\n invalid_input: false,\n transient: true,\n} as const satisfies Record<FailureOutcome, boolean>;\n\n/**\n * Builds the classification the SDK itself gives an outcome, so an app that classifies a step of\n * its OWN (one that is not an SDK call) uses the SDK's type and its values instead of a\n * hard-coded `{ outcome, retryable }` literal. `retryable` is the SDK's default for that outcome\n * (`false` for `unknown` and `invalid_input`, `true` for the rest). Each call returns a new\n * object, safe to mutate or freeze.\n *\n * `options.retryable: false` WITHHOLDS Retry from an outcome that would otherwise allow it: the\n * SDK's own `not_queued` for a refusal the gateway will repeat is `classification('not_queued',\n * { retryable: false })` (also exported, frozen, as {@link NOT_QUEUED_FINAL}). An app may take\n * Retry away from an outcome but never grant it to one that cannot have it, so only `false` is\n * accepted.\n *\n * @example\n * ```ts\n * // The app refreshes a quote before it asks the SDK to sign; the refresh failed.\n * throw new AppSwapError(text, classification('not_sent'));\n * // The app refuses a request for a reason a repeat cannot fix.\n * throw new AppSwapError(text, classification('not_queued', { retryable: false }));\n * ```\n */\nexport function classification(\n outcome: FailureOutcome,\n options: { readonly retryable?: false } = {},\n): FailureClassification {\n return { outcome, retryable: options.retryable === false ? false : DEFAULT_RETRYABLE[outcome] };\n}\n\n/**\n * `classification('not_queued', { retryable: false })`: the gateway refused the write before\n * queueing it AND will refuse a repeat the same way (the version wall, a dark swap that did not\n * queue, an HTTP 4xx). Nothing is pending and Retry is not offered. It is frozen: use it as it is\n * (`classification: NOT_QUEUED_FINAL`) instead of spreading `classification('not_queued')` and\n * overriding `retryable`; `{ ...NOT_QUEUED_FINAL }` is a mutable copy.\n */\nexport const NOT_QUEUED_FINAL: Readonly<FailureClassification> = Object.freeze(\n classification('not_queued', { retryable: false }),\n);\n\n/**\n * `classification('not_sent')`: a step of the app's own failed before anything was signed or\n * sent (a quote refresh, a balance read), so nothing is pending and a repeat is safe.\n */\nexport function notSentClassification(): FailureClassification {\n return classification('not_sent');\n}\n\nconst REJECTED: FailureClassification = classification('rejected');\nconst UNKNOWN: FailureClassification = classification('unknown');\nconst NOT_QUEUED: FailureClassification = classification('not_queued');\nconst NOT_SENT: FailureClassification = classification('not_sent');\nconst INVALID_INPUT: FailureClassification = classification('invalid_input');\nconst TRANSIENT: FailureClassification = classification('transient');\n\n/**\n * The classification of every code whose meaning does not depend on the failing answer. A code\n * missing here is a compile error (unless it is `pre_send`, see {@link CodeTable}), so adding a\n * catalog code forces a decision.\n */\nconst BY_CODE = {\n // ----------------------------------------------------------------------------------- transport\n REQUEST_TIMEOUT: TRANSIENT,\n TRANSPORT_ERROR: TRANSIENT,\n REQUEST_FAILED: TRANSIENT,\n\n // ------------------------------------------------------------------------------- write: unknown\n // No answer was read, or a 2xx answer that does not prove the write was queued under the signed\n // key: it may have been applied.\n SUBMISSION_OUTCOME_UNKNOWN: UNKNOWN,\n GATEWAY_REPORTED_ERROR: UNKNOWN,\n GATEWAY_DATA_MISSING: UNKNOWN,\n GATEWAY_MODE_INVALID: UNKNOWN,\n GATEWAY_SYNC_REQUEST_TRADE: UNKNOWN,\n MISSING_UNIQUE_KEY: UNKNOWN,\n UNIQUE_KEY_MISMATCH: UNKNOWN,\n\n // --------------------------------------------------------------------- write: refused, not queued\n SHADOW_NOT_QUEUED: NOT_QUEUED_FINAL,\n METHOD_NOT_ALLOWED: NOT_QUEUED,\n SIGNATURE_INVALID: NOT_QUEUED,\n SIGNER_MISMATCH: NOT_QUEUED,\n DTO_INVALID: NOT_QUEUED,\n BOUNDS_VIOLATION: NOT_QUEUED,\n SYMBOL_CONFLICT: NOT_QUEUED,\n RATE_LIMITED: NOT_QUEUED,\n GATEWAY_REJECTED: NOT_QUEUED,\n\n // ----------------------------------------------------------------------- the chain's own verdict\n CHAIN_REJECTED: REJECTED,\n\n // ----------------------------------------------------------------------- reads of backend data\n INVALID_CHAIN_RESPONSE: TRANSIENT,\n INVALID_POSITION_RESPONSE: TRANSIENT,\n\n // -------------------------------------------------------------------------------- confirmation\n CONFIRMATION_TIMEOUT: UNKNOWN,\n CONFIRMATION_ABORTED: UNKNOWN,\n CONFIRMATION_FAILED: UNKNOWN,\n CONFIRMATION_MALFORMED: UNKNOWN,\n CONFIRMATION_KEY_MISMATCH: UNKNOWN,\n\n // ------------------------------------------------------------------------------ the realtime stream\n STREAM_DISCONNECTED: TRANSIENT,\n STREAM_REQUEST_TIMEOUT: TRANSIENT,\n STREAM_CONNECT_FAILED: TRANSIENT,\n STREAM_CLOSED_BEFORE_CONNECT: TRANSIENT,\n STREAM_CONNECTION_CLOSED: TRANSIENT,\n\n // ----------------------------------------------- pre-send: an app-supplied callback failed\n // The signer, the key provider or the token resolver threw before anything was transmitted. The\n // original error is `cause`. A repeat cannot apply anything twice.\n SIGNING_FAILED: NOT_SENT,\n KEY_PROVIDER_FAILED: NOT_SENT,\n TOKEN_RESOLUTION_FAILED: NOT_SENT,\n\n // ------------------------------------------- the call cannot work as written, found AFTER an answer\n // (a pre_send code needs no row: it is `invalid_input` by default, see `CodeTable`)\n NO_WALLET_ADDRESS: INVALID_INPUT,\n NO_POOL_AVAILABLE: INVALID_INPUT,\n INSUFFICIENT_LIQUIDITY: INVALID_INPUT,\n} as const satisfies CodeTable;\n\n/** A code whose catalog phase is `pre_send`. */\ntype PreSendCode = {\n [C in GSwapErrorCode]: (typeof GSWAP_ERROR_CATALOG)[C]['phase'] extends 'pre_send' ? C : never;\n}[GSwapErrorCode];\n\n/** The codes whose classification depends on the failing answer, not on a table row. */\ntype AnswerDependentCode =\n 'HTTP_ERROR' | 'UPDATE_REQUIRED' | 'CHAIN_DISPATCH_FAILED' | 'INVALID_PRIVATE_KEY';\n\n/**\n * Every code that is NOT `pre_send` needs a row (a new one is a compile error until it has one);\n * a `pre_send` code may have one (`SIGNING_FAILED` is `not_sent`). A `pre_send` code without a row\n * is `invalid_input`: nothing was transmitted, so it cannot be `unknown`, and it is not a\n * condition a repeat clears. That keeps the 90-odd validation codes out of the table, which is\n * what keeps `classifyFailure` small enough for an app shell.\n */\ntype CodeTable = {\n readonly [C in Exclude<GSwapErrorCode, PreSendCode | AnswerDependentCode>]: FailureClassification;\n} & {\n readonly [C in Exclude<PreSendCode, AnswerDependentCode>]?: FailureClassification;\n};\n\n/**\n * A key that is not valid is the input's fault (`invalid_input`), except `no_key_provided`: the\n * provider had nothing to give right now (a locked wallet, an empty slot). That is the same\n * situation as a provider that throws (`KEY_PROVIDER_FAILED`), and it clears once a key exists, so\n * it is `not_sent` and Retry is safe.\n */\nfunction classifyInvalidPrivateKey(view: FailureView): FailureClassification {\n return stringParamOf(view, 'reason') === 'no_key_provided' ? NOT_SENT : INVALID_INPUT;\n}\n\n/** The status of an HTTP failure: the one it carries, else its `status` param. */\nfunction statusOfView(view: FailureView): number | undefined {\n return view.status ?? numberParamOf(view, 'status');\n}\n\n/**\n * An HTTP failure with no gateway or chain code: its meaning depends on the status and on read vs\n * write. A view that states no status at all cannot be judged: `unknown`.\n */\nfunction classifyHttpError(view: FailureView): FailureClassification {\n const status = statusOfView(view);\n if (status === undefined) return UNKNOWN;\n if (isWriteView(view)) {\n // A gateway that answered 5xx or 408 may still have queued the write; 429 and 4xx did not.\n if (status === 429) return NOT_QUEUED;\n if (status === 408 || status >= 500) return UNKNOWN;\n return NOT_QUEUED_FINAL;\n }\n return status === 408 || status === 429 || status >= 500 ? TRANSIENT : INVALID_INPUT;\n}\n\n/**\n * The version wall (HTTP 426). On a write the gateway refused it before queueing anything, and a\n * repeat of the same app version is refused the same way, so it is `not_queued` with no Retry. On a\n * read nothing changed either, and only an update helps: `invalid_input`, no Retry. Both say \"show\n * the update screen\", not \"try again\".\n */\nfunction classifyUpdateRequired(view: FailureView): FailureClassification {\n return isWriteView(view) ? NOT_QUEUED_FINAL : INVALID_INPUT;\n}\n\n/**\n * The chain dispatch failed. The gateway echoes the upstream status: 409 is \"this uniqueKey was\n * already consumed\" (the first attempt may be applied), 422 is the chain evaluating the write and\n * refusing it (definite), another 5xx is an upstream outage after which the write may have landed,\n * and a 4xx is a refusal before anything was queued.\n */\nfunction classifyChainDispatchFailed(view: FailureView): FailureClassification {\n const status = view.status;\n if (status === undefined || status === 409 || status >= 500) return UNKNOWN;\n return status === 422 ? REJECTED : NOT_QUEUED;\n}\n\n/**\n * True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a\n * `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied\n * (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting\n * again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&\n * error.status === 409` and the regex on \"already saved\". Accepts an SDK error or a plain-object\n * view ({@link FailureView}: `code` and `status`); every other value is `false`.\n *\n * @example\n * ```ts\n * if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);\n * ```\n */\nexport function isUniqueKeyConsumed(error: unknown): boolean {\n const view = toFailureView(error);\n return view?.code === 'CHAIN_DISPATCH_FAILED' && view.status === 409;\n}\n\nconst UNPROVEN_ACKNOWLEDGEMENT_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_DATA_MISSING',\n 'GATEWAY_MODE_INVALID',\n 'GATEWAY_SYNC_REQUEST_TRADE',\n 'MISSING_UNIQUE_KEY',\n 'UNIQUE_KEY_MISMATCH',\n];\n\n/**\n * True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no\n * `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.\n * The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an\n * app shows is one line for all five (\"the backend did not confirm it queued the request\"), so\n * the app asks this instead of keeping its own list of the codes. A gateway that says\n * `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.\n *\n * @example\n * ```ts\n * if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);\n * ```\n */\nexport function isUnprovenAcknowledgement(error: unknown): boolean {\n return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);\n}\n\n/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */\nfunction isCodeIn(code: string, codes: readonly GSwapErrorCode[]): boolean {\n return codes.some((known) => known === code);\n}\n\n/**\n * True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose\n * `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet\n * error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.\n */\nfunction hasCodeIn(error: unknown, codes: readonly GSwapErrorCode[]): boolean {\n const view = toFailureView(error);\n // `codes` holds catalog codes only, so membership already means \"a catalog code\": no table needed.\n return view !== undefined && isCodeIn(view.code, codes);\n}\n\n/**\n * The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app\n * may show as it is (and falls back to its own line when it is empty): a refusal the gateway made\n * (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the\n * SDK knows, and `GATEWAY_REJECTED` for one it does not).\n */\nconst RELAYABLE_REFUSAL_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_REPORTED_ERROR',\n 'METHOD_NOT_ALLOWED',\n 'SIGNATURE_INVALID',\n 'SIGNER_MISMATCH',\n 'DTO_INVALID',\n 'BOUNDS_VIOLATION',\n 'SYMBOL_CONFLICT',\n 'RATE_LIMITED',\n 'CHAIN_DISPATCH_FAILED',\n 'GATEWAY_REJECTED',\n];\n\n/**\n * True when the error is a gateway refusal whose `params.serverMessage` an app may relay to the\n * person as the gateway sent it: `GATEWAY_REPORTED_ERROR`, the gateway bounces (`METHOD_NOT_ALLOWED`,\n * `SIGNATURE_INVALID`, `SIGNER_MISMATCH`, `DTO_INVALID`, `BOUNDS_VIOLATION`, `SYMBOL_CONFLICT`,\n * `RATE_LIMITED`, `GATEWAY_REJECTED`) and `CHAIN_DISPATCH_FAILED`. The app shows `serverMessage` when\n * it is not empty and its own line when it is; the SDK's English `message` is never what to show.\n *\n * It accepts a plain-object view of an SDK error too ({@link FailureView}: an app's wrapper with a\n * `code`), and decides from the code in the same way. It narrows to `GSwapSDKError<...>` ONLY when\n * called with an SDK error; with an `unknown` or a view it answers `boolean` (narrow with\n * `isGSwapError` first, or read the view's own `params`).\n *\n * It is a test on the code alone, so it also holds for `CHAIN_DISPATCH_FAILED` with HTTP 409\n * (the `uniqueKey` was already consumed; `classifyFailure` says `unknown`): an app that words that\n * case itself (\"already submitted\", then confirm the key) checks `error.status === 409` BEFORE\n * relaying. It is false for `CHAIN_REJECTED` (the chain's verdict, worded by where it is shown: the\n * submit and confirm screens differ), for `HTTP_ERROR` (a proxy's page, not an answer to this\n * write) and for the five unproven acknowledgements (`isUnprovenAcknowledgement`: they carry no\n * server text).\n *\n * @example\n * ```ts\n * if (isRelayableRefusal(error)) show(error.params.serverMessage || t('swap.requestFailed'));\n * ```\n */\nexport function isRelayableRefusal(error: GSwapSDKError): error is GSwapSDKError<RelayableCode>;\nexport function isRelayableRefusal(error: unknown): boolean;\nexport function isRelayableRefusal(error: unknown): boolean {\n return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);\n}\n\n/** The codes {@link isRelayableRefusal} is true for. */\nexport type RelayableCode =\n | 'GATEWAY_REPORTED_ERROR'\n | 'METHOD_NOT_ALLOWED'\n | 'SIGNATURE_INVALID'\n | 'SIGNER_MISMATCH'\n | 'DTO_INVALID'\n | 'BOUNDS_VIOLATION'\n | 'SYMBOL_CONFLICT'\n | 'RATE_LIMITED'\n | 'CHAIN_DISPATCH_FAILED'\n | 'GATEWAY_REJECTED';\n\n/**\n * True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in\n * `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements\n * (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).\n * The outcome is `unknown` for all six. It replaces the app's own\n * `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.\n */\nexport function isUninterpretedAnswer(error: unknown): boolean {\n return isUnprovenAcknowledgement(error) || hasCodeIn(error, ['GATEWAY_REPORTED_ERROR']);\n}\n\n/**\n * Classifies any thrown value from its code (and, for two codes, its HTTP status), never from\n * message text, so an app does not have to re-derive \"may I offer Retry?\" and \"is the outcome\n * unknown?\" for every code. The decision for each code is in this module's table; a new catalog\n * code cannot be added without one.\n *\n * A failure BEFORE the request left (`error.phase === 'pre_send'`, `isPreSendError`) can never be\n * `unknown` or `rejected`: it is `invalid_input` (the input has to change) or `not_sent` (nothing\n * was transmitted; a repeat is safe). Every app-supplied callback the SDK calls before it sends\n * (the signer, the key provider, a token resolver) has its failure wrapped into such an error\n * (`SIGNING_FAILED`, `KEY_PROVIDER_FAILED`, `TOKEN_RESOLUTION_FAILED`, the original as `cause`),\n * so an app NEVER needs an error class of its own to say \"nothing was sent\": a locked wallet,\n * a declined signature and a failed lookup all arrive as `not_sent`, retryable.\n *\n * It accepts a `GSwapSDKError` or a plain-object VIEW of one ({@link FailureView}: `{ code,\n * params?, status?, uniqueKey?, ... }`, the shape of the wrapper an app builds from an SDK error;\n * `toFailureView` reads any value), and decides from the same fields, so an app does not need to\n * keep the original error to ask. `{ afterQueued: true }` says the write is already queued (the\n * step being classified is a confirmation): `retryable` is then always `false`.\n *\n * Anything that is not an SDK error or such a view, or a view whose `code` the catalog does not\n * define, is `{ outcome: 'unknown', retryable: false }`: the SDK\n * cannot say what happened, and refusing Retry is the safe answer. That is only what escapes AFTER\n * the request left (an app requestor that rejects with its own error, a callback of yours that\n * throws once bytes were sent). An error your own code raises BEFORE it calls the SDK says so\n * itself: give it a code of its own and `outcome` (`{ code: 'POSITION_STALE', outcome: 'not_sent'\n * }`), and the SDK answers with that outcome's classification and `mayHaveBeenQueued` is `false`.\n * The declared `outcome` is read only for a code the catalog does not define.\n *\n * A failure is a WRITE's unless it states `write: false` (`GSwapSDKError.write`, set for every\n * SDK read): see {@link FailureView}. A view that lost its `uniqueKey` is therefore still judged as\n * a write (a 5xx stays `unknown`), never as a retryable read.\n *\n * To learn that a failure came from the dark (shadow) path, read `error.shadow` (a typed field of\n * every `GSwapSDKError`) or call `isShadowError(error)`, which also covers a non-SDK object that\n * escaped `swapShadow` / `submitSwapShadow` / `ChainGateway.submitShadow`. The classification is\n * the same as on the public path; an app that withholds Retry or a public fallback after a dark\n * swap applies that policy on top of `retryable`.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { outcome, retryable } = classifyFailure(error);\n * if (outcome === 'unknown') keepPendingAndConfirm(error); // never a second swap\n * else if (retryable) offerRetry(); // a new request under a fresh key\n * }\n * ```\n */\nexport function classifyFailure(\n error: unknown,\n options: ClassifyFailureOptions = {},\n): FailureClassification {\n const result = classifyView(toFailureView(error));\n // A `rejected` outcome is the chain's definite no: the queued write was evaluated and NOT\n // applied, so a new request under a fresh key cannot double-apply it and Retry stays as it is.\n return options.afterQueued === true && result.outcome !== 'rejected'\n ? { ...result, retryable: false }\n : result;\n}\n\n/** Options of {@link classifyFailure}. */\nexport interface ClassifyFailureOptions {\n /**\n * The write is ALREADY queued (the gateway acknowledged it with this `uniqueKey`), and what is\n * being classified is a later step: confirming it, reading its apply result. Whatever the\n * outcome, `retryable` is then `false`: a NEW request would be a second trade, so the app\n * confirms the same key (or forgets it) and never offers \"Try again\". `outcome` is unchanged.\n *\n * The one exception is `rejected`: the chain evaluated the queued write and refused it (an\n * apply result of `Status: 0`, `CHAIN_REJECTED`; a 422 dispatch). That PROVES it was not\n * applied, so a new request under a fresh key cannot make a second trade, and `retryable`\n * keeps the answer it has without this option (`true`). Every outcome that does not prove\n * \"not applied\" (`unknown`, `transient`, `not_queued`, ...) is `false`.\n */\n afterQueued?: boolean | undefined;\n}\n\n/**\n * The classification of a failure view: the table decision for its code, the status-dependent\n * decision for the four codes whose meaning needs it, and for a code the catalog does not define\n * (a wallet error, an ethers `ACTION_REJECTED`, a typo, an app's own error): `unknown` unless the\n * view DECLARES its `outcome` (an app's error, `{ code: 'POSITION_STALE', outcome: 'not_sent' }`),\n * then the SDK's own classification of that outcome. A value with no view is `unknown`.\n */\nfunction classifyView(view: FailureView | undefined): FailureClassification {\n if (view === undefined) return { ...UNKNOWN };\n if (!isCatalogCode(view.code)) {\n if (view.outcome === undefined) return { ...UNKNOWN };\n // Withhold-only: `retryable: false` removes Retry from the declared outcome, never adds it.\n return view.retryable === false\n ? classification(view.outcome, { retryable: false })\n : classification(view.outcome);\n }\n const { code } = view;\n if (code === 'HTTP_ERROR') return { ...classifyHttpError(view) };\n if (code === 'UPDATE_REQUIRED') return { ...classifyUpdateRequired(view) };\n if (code === 'CHAIN_DISPATCH_FAILED') return { ...classifyChainDispatchFailed(view) };\n if (code === 'INVALID_PRIVATE_KEY') return { ...classifyInvalidPrivateKey(view) };\n const row: FailureClassification | undefined = (\n BY_CODE as Readonly<Partial<Record<GSwapErrorCode, FailureClassification>>>\n )[code];\n return { ...(row ?? INVALID_INPUT) };\n}\n\n/** Codes that mean \"there is no market for this\" however the app reached them. */\nconst NO_MARKET_CODES: readonly GSwapErrorCode[] = [\n 'NO_POOL_AVAILABLE',\n 'INSUFFICIENT_LIQUIDITY',\n 'UNKNOWN_TOKEN',\n];\n\n/**\n * True when a failure means \"there is no market to trade this pair\": `NO_POOL_AVAILABLE` (no pool\n * at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX\n * has no trading symbol for the token), or a READ that was answered 404 (a quote the backend\n * cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||\n * notFound` list, so the empty-state (\"No market for this pair\") has one definition.\n *\n * A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing\n * market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every\n * other value is `false`.\n *\n * @example\n * ```ts\n * if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);\n * ```\n */\nexport function isNoMarket(error: unknown): boolean {\n const view = toFailureView(error);\n if (view === undefined) return false;\n if (isCodeIn(view.code, NO_MARKET_CODES)) return true;\n return !isWriteView(view) && (view.notFound === true || view.status === 404);\n}\n\n/**\n * True when the failed call was a WRITE that may nevertheless have been queued: its outcome is\n * `unknown` (`classifyFailure(error).outcome === 'unknown'`: a timeout or broken connection after\n * the request left, an acknowledgement that proves nothing, a gateway 409 or 5xx, a failed\n * confirmation). The app must keep `error.uniqueKey` and confirm it, and must NOT submit again\n * under a fresh key. Every other outcome (`rejected`, `not_queued`, `not_sent`, `invalid_input`,\n * `transient`) proves the write is not pending.\n *\n * A value the SDK cannot judge (an app requestor's own rejection after the request left) is\n * `unknown` too, so it is `true`; handle errors your own code raised BEFORE calling the SDK first.\n * Meant for the catch of a write; a read never has a pending key to keep.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * if (mayHaveBeenQueued(error)) keepPendingAndConfirm(error);\n * }\n * ```\n */\nexport function mayHaveBeenQueued(error: unknown): boolean {\n return classifyFailure(error).outcome === 'unknown';\n}\n","import { classifyFailure } from '../utils/failure_classification.js';\nimport type { FailureOutcome } from '../utils/failure_outcomes.js';\nimport { isValidUniqueKey } from '../utils/unique_key_syntax.js';\n\n/** Key the wallet_extension has always used; its storage value is a plain array of entries. */\nexport const PENDING_SWAPS_STORAGE_KEY = 'pendingSwaps.v1';\n\n/** Entries older than this are dropped the next time a wallet's swaps are listed. */\nexport const PENDING_SWAP_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000;\n\n/**\n * Async key/value storage the pending-swap store persists through. It stores STRUCTURED VALUES\n * (the store never serializes), so each platform decides how a value lands on disk:\n *\n * - `chrome.storage.local`: `get: async (k) => (await chrome.storage.local.get(k))[k]`,\n * `set: (k, v) => chrome.storage.local.set({ [k]: v })`. This is the wallet's stored shape.\n * - `localStorage` (frontend_v2): `get: async (k) => { const raw = localStorage.getItem(k);\n * if (raw === null) return undefined; try { return JSON.parse(raw); } catch { return raw; } }`,\n * `set: async (k, v) => localStorage.setItem(k, JSON.stringify(v))`. Corrupt JSON MUST come back\n * as a value (here the raw string), not as a rejection: a value that is not an array reads as\n * \"no entries\" and the next write repairs it, whereas a `get` that rejects forever makes every\n * `remember` a no-op.\n * - React Native: AsyncStorage with the same JSON wrapping and the same corrupt-JSON rule.\n *\n * `get` resolves `undefined` for a missing key. Either method may reject; the store treats that\n * as \"storage unavailable\" and never lets it surface (see {@link PendingSwapStore}).\n */\nexport interface StorageAdapter {\n get(key: string): Promise<unknown>;\n set(key: string, value: unknown): Promise<void>;\n}\n\n/**\n * The part of a `chrome.storage` area ({@link storageAdapterFromChromeStorage}) the adapter uses,\n * written structurally so the SDK needs no `chrome` types: `chrome.storage.local`,\n * `chrome.storage.session`, `browser.storage.local` (webextension-polyfill) and any object with\n * these two promise-returning methods satisfy it. It is the Manifest V3 promise form: the methods\n * are called WITHOUT a callback.\n */\nexport interface ChromeStorageAreaLike {\n get(key: string): Promise<Record<string, unknown>>;\n set(items: Record<string, unknown>): Promise<void>;\n}\n\n/**\n * A {@link StorageAdapter} over a `chrome.storage` area, the shape the wallet stores pending swaps\n * in: the value lands under the key as the structured value it is (the browser clones it; nothing\n * is serialized here). A missing key resolves `undefined`; a rejection of the area reaches the\n * store, which treats it as \"storage unavailable\".\n *\n * Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is\n * built: a module that is imported where `chrome` does not exist yet (a test, a closing extension\n * context) then fails only when the store touches storage, and that failure (a throw inside the\n * function) is the same \"storage unavailable\" rejection.\n *\n * @example\n * ```ts\n * const store = new PendingSwapStore(storageAdapterFromChromeStorage(chrome.storage.local));\n * const lazy = new PendingSwapStore(storageAdapterFromChromeStorage(() => chrome.storage.local));\n * ```\n */\nexport function storageAdapterFromChromeStorage(\n area: ChromeStorageAreaLike | (() => ChromeStorageAreaLike),\n): StorageAdapter {\n const areaNow = (): ChromeStorageAreaLike => (typeof area === 'function' ? area() : area);\n return {\n async get(key) {\n const items = await areaNow().get(key);\n return Object.hasOwn(items, key) ? items[key] : undefined;\n },\n async set(key, value) {\n await areaNow().set({ [key]: value });\n },\n };\n}\n\n/** A RequestTrade that was accepted by the gateway but whose outcome has not been read yet. */\nexport interface PendingSwap {\n uniqueKey: string;\n requestTransactionId: string | null;\n /** The wallet (account) that submitted the swap; `list` filters by it. */\n wallet: string;\n token0Symbol: string;\n token1Symbol: string;\n /** Whether the swap was a shadow (\"dark\") swap. */\n isDarkSwap: boolean;\n /** Epoch milliseconds when the swap was queued. */\n createdAt: number;\n}\n\n/**\n * Why the store dropped a pending swap (the `reason` of {@link PrunedPendingSwap}).\n *\n * - `expired`: older than {@link PENDING_SWAP_EXPIRY_MS}.\n * - `invalid_unique_key`: its `uniqueKey` is not a valid apply-results key (1 to 128 characters\n * of `A-Za-z0-9._:-`). `confirmAppliedTrade` refuses such a key with `INVALID_UNIQUE_KEY`\n * before reading anything and always will, so keeping the entry would retry it forever. The\n * SDK never signs such a key; an entry like this is corrupt or foreign.\n * - `chain_rejected`: {@link PendingSwapStore.settle} dropped it because a confirmation proved the\n * chain REFUSED the trade (`pendingSwapFateFor` is `forget`): it did not happen.\n * - `unconfirmable`: {@link PendingSwapStore.settle} dropped it because a confirmation failed in a\n * way that never changes (`forget_quietly`: the key itself is refused): nothing can be learned.\n */\nexport const PENDING_SWAP_PRUNE_REASONS = [\n 'expired',\n 'invalid_unique_key',\n 'chain_rejected',\n 'unconfirmable',\n] as const;\n\n/** One member of {@link PENDING_SWAP_PRUNE_REASONS}. */\nexport type PendingSwapPruneReason = (typeof PENDING_SWAP_PRUNE_REASONS)[number];\n\n/**\n * What to do with a pending swap after confirming it failed (the answer of\n * {@link pendingSwapFateFor}).\n *\n * - `forget`: the chain REFUSED the trade, so it did not happen. Drop it AND tell the user.\n * - `forget_quietly`: the confirmation can never succeed (the key is refused: `invalid_input`).\n * Drop it without claiming anything about the trade.\n * - `keep`: the trade may still have been applied (a timeout, a broken connection, a gateway\n * hiccup, anything not proven). Leave it pending and look again later.\n */\nexport const PENDING_SWAP_FATES = ['forget', 'forget_quietly', 'keep'] as const;\n\n/** One member of {@link PENDING_SWAP_FATES}. */\nexport type PendingSwapFate = (typeof PENDING_SWAP_FATES)[number];\n\n/**\n * The fate of a pending swap for each failure OUTCOME. Only a chain rejection proves the trade did\n * not happen; an input that can never be confirmed is dropped quietly; every other outcome leaves\n * the trade possibly applied. Typed over `FailureOutcome`, so a new outcome does not compile until\n * it is decided here.\n */\nconst FATE_OF_OUTCOME = {\n rejected: 'forget',\n invalid_input: 'forget_quietly',\n unknown: 'keep',\n not_queued: 'keep',\n not_sent: 'keep',\n transient: 'keep',\n} as const satisfies Record<FailureOutcome, PendingSwapFate>;\n\n/**\n * {@link pendingSwapFateFor} from an outcome the app already holds (for example the\n * `classifyFailure(error).outcome` it stored on its own failure wrapper). An outcome this SDK\n * version does not know (a newer SDK at run time) is `keep`: never forget what may have happened.\n */\nexport function pendingSwapFateOfOutcome(outcome: FailureOutcome): PendingSwapFate {\n return Object.hasOwn(FATE_OF_OUTCOME, outcome) ? FATE_OF_OUTCOME[outcome] : 'keep';\n}\n\n/**\n * The fate of a queued swap whose confirmation (`confirmAppliedTrade`) just failed with `error`,\n * from the SDK's classification alone: `forget` for a chain rejection (`rejected`), `forget_quietly`\n * for a key that can never be confirmed (`invalid_input`), `keep` for every other outcome\n * (`unknown`, `not_queued`, `not_sent`, `transient`) and for any value the SDK cannot judge. It\n * accepts an SDK error or a plain-object view of one (see `FailureView`). It replaces the wallet's\n * `pendingSwapActionFor` and frontend_v2's `confirmationStanceOf`.\n *\n * @example\n * ```ts\n * try {\n * await confirmAppliedTrade(client, swap);\n * } catch (error) {\n * if ((await store.settle(swap.uniqueKey, error)) === 'forget') tellTheUserItFailed();\n * }\n * ```\n */\nexport function pendingSwapFateFor(error: unknown): PendingSwapFate {\n return pendingSwapFateOfOutcome(classifyFailure(error, { afterQueued: true }).outcome);\n}\n\n/** A pending swap the store dropped, and why. */\nexport interface PrunedPendingSwap {\n swap: PendingSwap;\n reason: PendingSwapPruneReason;\n}\n\n/** Options for {@link PendingSwapStore}. */\nexport interface PendingSwapStoreOptions {\n /**\n * Called once per dropped entry (after the drop is persisted, for `list`; at once for a\n * `remember` that refuses an invalid key), so the app can tell the user or log why a swap it\n * was tracking is gone. Diagnostics only: what it does, or throws, never changes the store.\n */\n onPrune?: ((pruned: PrunedPendingSwap) => void) | undefined;\n /** Storage key. Default {@link PENDING_SWAPS_STORAGE_KEY}. */\n storageKey?: string | undefined;\n /**\n * The stored name of the dark-swap flag. `isDarkSwap` (default) is wallet_extension's shape;\n * `shadow` is frontend_v2's. Entries are always exposed to callers as `isDarkSwap`.\n */\n darkFlagField?: 'isDarkSwap' | 'shadow' | undefined;\n /**\n * Where `remember` puts a new entry in the stored array: `end` (default, wallet_extension) or\n * `start` (frontend_v2).\n */\n insertAt?: 'end' | 'start' | undefined;\n /**\n * The order of `list`: `stored` (default, wallet_extension: oldest first for `insertAt: 'end'`)\n * or `newest-first` (frontend_v2).\n */\n listOrder?: 'stored' | 'newest-first' | undefined;\n /** Clock, in epoch milliseconds. Defaults to `Date.now`. */\n now?: (() => number) | undefined;\n}\n\n/**\n * Remembers queued swaps so their outcome can be confirmed after the UI, popup or service worker\n * that submitted them is gone (`confirmAppliedTrade` with the stored `uniqueKey`).\n *\n * Guarantees:\n * - Persistence is best effort and NEVER throws: a failing or missing storage must not turn an\n * accepted request into a client-side resubmission. `list` resolves `[]` when storage fails.\n * - Operations of one store instance are serialized, so concurrent `remember` / `forget` calls\n * cannot lose each other's write (read-modify-write over an async adapter). Two store instances\n * over the same storage (for example popup and service worker) are not coordinated.\n * - Entries that do not match the expected shape are ignored and dropped on the next write.\n * - Entries expire after seven days (an entry exactly seven days old is expired; frontend_v2\n * kept it for that one millisecond); `list` removes them from storage, which frontend_v2 never\n * did on read.\n * - An entry whose `uniqueKey` is not a valid apply-results key is terminal, not pending:\n * `confirmAppliedTrade` fails it with `INVALID_UNIQUE_KEY` every time, so a resume loop would\n * retry it forever. `list` prunes it like an expired one, and `remember` refuses to save it;\n * both tell `onPrune` the reason (`PENDING_SWAP_PRUNE_REASONS`).\n * - New entries go to the end (or `insertAt: 'start'`); `list` returns the wallet's entries in\n * stored order (or `listOrder: 'newest-first'`).\n * - The stored shape is wallet_extension's by default; `storageKey`, `darkFlagField`, `insertAt`\n * and `listOrder` reproduce frontend_v2's. JSON key order inside an entry is not preserved.\n *\n * Passing no `storage` yields a store that remembers nothing.\n *\n * @example\n * ```ts\n * const store = new PendingSwapStore({\n * get: async (key) => (await chrome.storage.local.get(key))[key],\n * set: (key, value) => chrome.storage.local.set({ [key]: value }),\n * });\n * await store.remember({ uniqueKey, requestTransactionId, wallet, token0Symbol: 'GALA',\n * token1Symbol: 'GUSDC', isDarkSwap: false, createdAt: Date.now() });\n * for (const swap of await store.list(wallet)) await confirmAppliedTrade(client, swap);\n * ```\n */\nexport class PendingSwapStore {\n private readonly storageKey: string;\n private readonly darkFlagField: 'isDarkSwap' | 'shadow';\n private readonly insertAt: 'end' | 'start';\n private readonly listOrder: 'stored' | 'newest-first';\n private readonly now: () => number;\n private readonly onPrune: ((pruned: PrunedPendingSwap) => void) | undefined;\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(\n private readonly storage: StorageAdapter | undefined,\n options: PendingSwapStoreOptions = {},\n ) {\n this.storageKey = options.storageKey ?? PENDING_SWAPS_STORAGE_KEY;\n this.darkFlagField = options.darkFlagField ?? 'isDarkSwap';\n this.insertAt = options.insertAt ?? 'end';\n this.listOrder = options.listOrder ?? 'stored';\n this.now = options.now ?? Date.now;\n this.onPrune = options.onPrune;\n }\n\n /**\n * Saves (or replaces, by `uniqueKey`) a pending swap. A swap whose `uniqueKey` is not a valid\n * apply-results key is not saved (it could never be confirmed); it is reported to `onPrune` as\n * `invalid_unique_key`.\n */\n public remember(swap: PendingSwap): Promise<void> {\n if (!isValidUniqueKey(swap.uniqueKey)) {\n this.report([{ swap, reason: 'invalid_unique_key' }]);\n return Promise.resolve();\n }\n return this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const others = current\n .filter((entry) => entry.uniqueKey !== swap.uniqueKey)\n .map(this.toStored);\n const stored = this.toStored(swap);\n await storage.set(\n this.storageKey,\n this.insertAt === 'end' ? [...others, stored] : [stored, ...others],\n );\n });\n }\n\n /** Removes a pending swap once its outcome is known. */\n public forget(uniqueKey: string): Promise<void> {\n return this.enqueue(async (storage) => {\n const current = await this.read(storage);\n await storage.set(\n this.storageKey,\n current.filter((entry) => entry.uniqueKey !== uniqueKey).map(this.toStored),\n );\n });\n }\n\n /**\n * Applies {@link pendingSwapFateFor} to a swap whose confirmation failed with `error`, and\n * returns the fate so the app can word it (tell the user on `forget`, say nothing on\n * `forget_quietly`, keep polling on `keep`):\n *\n * - `forget`: the entry is removed and `onPrune` hears `chain_rejected`.\n * - `forget_quietly`: the entry is removed and `onPrune` hears `unconfirmable`.\n * - `keep`: nothing changes and `onPrune` is not called.\n *\n * Like every store operation it is serialized and best effort: if storage fails the entry stays\n * (a later `settle` or `list` handles it) and the fate is still returned. A key that is not\n * stored (already forgotten) is not an error and `onPrune` is not called for it.\n */\n public async settle(uniqueKey: string, error: unknown): Promise<PendingSwapFate> {\n const fate = pendingSwapFateFor(error);\n if (fate === 'keep') return fate;\n const removed = await this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const swap = current.find((entry) => entry.uniqueKey === uniqueKey);\n if (swap === undefined) return undefined;\n await storage.set(\n this.storageKey,\n current.filter((entry) => entry.uniqueKey !== uniqueKey).map(this.toStored),\n );\n return swap;\n });\n if (removed !== undefined) {\n this.report([\n { swap: removed, reason: fate === 'forget' ? 'chain_rejected' : 'unconfirmable' },\n ]);\n }\n return fate;\n }\n\n /**\n * The wallet's pending swaps that can still be confirmed (see `listOrder`). Entries that never\n * can be are pruned from storage, for every wallet, and reported to `onPrune`: expired ones\n * (`expired`) and ones whose `uniqueKey` is not a valid apply-results key\n * (`invalid_unique_key`: `confirmAppliedTrade` would fail `INVALID_UNIQUE_KEY` on it forever).\n */\n public async list(wallet: string): Promise<PendingSwap[]> {\n const result = await this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const now = this.now();\n const pruned: PrunedPendingSwap[] = [];\n const kept: PendingSwap[] = [];\n for (const entry of current) {\n const reason = this.pruneReasonOf(entry, now);\n if (reason === undefined) kept.push(entry);\n else pruned.push({ swap: entry, reason });\n }\n if (pruned.length > 0) {\n await storage.set(this.storageKey, kept.map(this.toStored));\n this.report(pruned);\n }\n const mine = kept.filter((entry) => entry.wallet === wallet);\n return this.listOrder === 'newest-first'\n ? mine.sort((left, right) => right.createdAt - left.createdAt)\n : mine;\n });\n return result ?? [];\n }\n\n private pruneReasonOf(entry: PendingSwap, now: number): PendingSwapPruneReason | undefined {\n if (!isValidUniqueKey(entry.uniqueKey)) return 'invalid_unique_key';\n return now - entry.createdAt < PENDING_SWAP_EXPIRY_MS ? undefined : 'expired';\n }\n\n /** Tells `onPrune` about each dropped entry; the hook is diagnostics and cannot break the store. */\n private report(pruned: readonly PrunedPendingSwap[]): void {\n for (const entry of pruned) {\n try {\n this.onPrune?.(entry);\n } catch {\n // A diagnostics hook must not turn a store operation into a failure.\n }\n }\n }\n\n private enqueue<T>(operation: (storage: StorageAdapter) => Promise<T>): Promise<T | undefined> {\n const storage = this.storage;\n if (storage === undefined) return Promise.resolve(undefined);\n const run = this.queue.then(async () => {\n try {\n return await operation(storage);\n } catch {\n // Storage can be missing, full, or disappear while a context is closing. Persistence is\n // best effort by contract.\n return undefined;\n }\n });\n this.queue = run;\n return run;\n }\n\n private async read(storage: StorageAdapter): Promise<PendingSwap[]> {\n const value = await storage.get(this.storageKey);\n if (!Array.isArray(value)) return [];\n const entries: PendingSwap[] = [];\n for (const item of value as unknown[]) {\n const entry = this.fromStored(item);\n if (entry !== undefined) entries.push(entry);\n }\n return entries;\n }\n\n private readonly toStored = (swap: PendingSwap): Record<string, unknown> => ({\n uniqueKey: swap.uniqueKey,\n requestTransactionId: swap.requestTransactionId,\n wallet: swap.wallet,\n token0Symbol: swap.token0Symbol,\n token1Symbol: swap.token1Symbol,\n [this.darkFlagField]: swap.isDarkSwap,\n createdAt: swap.createdAt,\n });\n\n private fromStored(value: unknown): PendingSwap | undefined {\n if (value === null || typeof value !== 'object') return undefined;\n const entry = value as Record<string, unknown>;\n const flag = entry[this.darkFlagField];\n const { uniqueKey, requestTransactionId, wallet, token0Symbol, token1Symbol, createdAt } =\n entry;\n if (\n typeof uniqueKey !== 'string' ||\n !(typeof requestTransactionId === 'string' || requestTransactionId === null) ||\n typeof wallet !== 'string' ||\n typeof token0Symbol !== 'string' ||\n typeof token1Symbol !== 'string' ||\n typeof flag !== 'boolean' ||\n typeof createdAt !== 'number' ||\n !Number.isFinite(createdAt)\n ) {\n return undefined;\n }\n return {\n uniqueKey,\n requestTransactionId,\n wallet,\n token0Symbol,\n token1Symbol,\n isDarkSwap: flag,\n createdAt,\n };\n }\n}\n","/**\n * Genuine EIP-712 typed-data signing for the four v2 dex-contract operations proven (2026-09-16,\n * live bisection against stage — see defi-backend's `chain-findings-artifact` memory /\n * https://claude.ai/artifact/3N9MevSjoQdU7gqnVB3dfU) to recover the `client|` identity correctly\n * via `eth_signTypedData_v4`, unlike `personal_sign` (which only ever resolves the bare `eth|`\n * form — see `BrowserWalletSigner`'s own doc comment). Mirrors frontend_v2's\n * `src/Services/eip712Types.ts` + `readWriteUtilsV2.ts`'s `EIP712_FIELD_COMPLETERS` exactly —\n * ported here rather than shared as a package because gswap-sdk has no frontend_v2 dependency\n * and should not gain one for four small functions.\n */\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nexport type EIP712Types = Record<string, Array<{ name: string; type: string }>>;\n\n/**\n * Derives the EIP-712 `types` for a DTO from its runtime shape.\n *\n * The generated `types` travel with the signed payload and are what BOTH sides hash, so they\n * must enumerate EVERY field the chain-side DTO will carry. GalaChain refuses any signature\n * whose `types` leave a DTO field uncovered (`assertNoUnsignedFields`, the fix for the\n * 2026-08-18 unsigned-field-injection drain); when that happens signature recovery fails\n * outright and the chain reports \"Missing signerPublicKey or signerAddress field in dto\".\n */\nexport function generateEIP712Types(\n typeName: string,\n params: Record<string, unknown>,\n): EIP712Types {\n const types: EIP712Types = {};\n types[typeName] = [];\n\n // Every `name` this is ever called with (the top-level `typeName`, or a nested struct's own\n // name) is unconditionally assigned `types[name] = []` on the line immediately before any\n // recursive call that could reach here; TypeScript still types `types[name]` as\n // possibly-undefined (index-signature access), so the guard below stays for real type safety\n // even though no current call path can actually trigger it.\n function fieldsFor(name: string): Array<{ name: string; type: string }> {\n const fields = types[name];\n /* c8 ignore next */\n if (!fields) throw new Error(`Missing EIP-712 type definition for ${name}`);\n return fields;\n }\n\n function addField(\n name: string,\n fieldValue: unknown,\n parentTypeName: string,\n onlyGetType = false,\n ): string | undefined {\n if (Array.isArray(fieldValue)) {\n const type =\n fieldValue.length > 0 ? addField(name, fieldValue[0], parentTypeName, true) : 'string';\n if (!onlyGetType) fieldsFor(parentTypeName).push({ name, type: (type ?? name) + '[]' });\n } else if (typeof fieldValue === 'object' && fieldValue !== null) {\n if (types[name]) {\n throw new GSwapSDKError('EIP712_NAME_COLLISION', { name });\n }\n types[name] = [];\n Object.entries(fieldValue).forEach(([key, value]) => {\n addField(key, value, name);\n });\n if (!onlyGetType) fieldsFor(parentTypeName).push({ name, type: name });\n } else {\n let eipType: string;\n switch (typeof fieldValue) {\n case 'string':\n eipType = 'string';\n break;\n case 'number':\n eipType = 'int256';\n break;\n case 'boolean':\n eipType = 'bool';\n break;\n case 'bigint':\n case 'symbol':\n case 'undefined':\n case 'function':\n case 'object':\n throw new GSwapSDKError('EIP712_UNSUPPORTED_VALUE', { valueType: typeof fieldValue });\n }\n if (onlyGetType) {\n return eipType;\n }\n fieldsFor(parentTypeName).push({ name, type: eipType });\n }\n return undefined;\n }\n\n Object.entries(params).forEach(([key, value]) => {\n addField(key, value, typeName);\n });\n\n return types;\n}\n\n/** The EIP-712 domain carried by a signed payload: GalaChain only uses `name` and `chainId`. */\nexport interface EIP712DomainValue {\n name: string;\n chainId: number;\n}\n\n/**\n * Builds the EIP-712 domain from the wallet's LIVE `eth_chainId` result, exactly like frontend_v2\n * (DEFI-1895): a wallet hashes whatever domain it is handed, and MetaMask refuses a `chainId` that\n * differs from its active network, so a hardcoded `1` breaks every wallet that is not on Mainnet.\n * defi-backend recovers the signer from the `domain` the payload carries (live-proven for chain\n * ids 1, 56 and 11155111), so following the wallet is correct on every network.\n *\n * @param chainId - The raw `eth_chainId` result: a `0x` hex string (the JSON-RPC form) or an integer.\n * @throws GSwapSDKError (`INVALID_CHAIN_ID`) when the wallet answers with anything else.\n */\nexport function eip712DomainFor(chainId: unknown): EIP712DomainValue {\n const parsed =\n typeof chainId === 'string' && /^0x[0-9a-fA-F]+$/u.test(chainId)\n ? Number(chainId)\n : typeof chainId === 'number'\n ? chainId\n : Number.NaN;\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new GSwapSDKError('INVALID_CHAIN_ID', {\n chainId:\n typeof chainId === 'string' || typeof chainId === 'number'\n ? String(chainId)\n : typeof chainId,\n });\n }\n return { name: 'ethereum', chainId: parsed };\n}\n\n/**\n * The four v2 operations proven to recover the signer correctly via genuine EIP-712: `RequestTrade`\n * never had the problem (one numeric field). `AddLiquidity`/`RemoveLiquidity`/\n * `CollectPositionFees` each need their `types` completed with a handful of fields their real\n * server-side DTO always carries — see the `complete*Fields` functions below. `CreatePool` is a\n * genuinely different, unsolved problem (nested `TokenClassKey` structs, not a flat\n * missing-field gap) and is NOT in this set — callers must keep using `personal-sign` for it.\n */\nexport const EIP712_CAPABLE_METHODS: ReadonlySet<string> = new Set([\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n]);\n\n/**\n * Every `complete*Fields` function below shares the same two live-proven rules:\n * 1. Numeric completeness fields MUST be JS `number`, never numeric strings —\n * `generateEIP712Types` infers a field's Solidity type from `typeof`, and declaring one as\n * EIP-712 `string` instead of `int256` breaks recovery identically to omitting the field\n * entirely (verified live on AddLiquidity: `amount0Min: '0'` fails with the exact same\n * \"Missing signerPublicKey\" error as `amount0Min` being absent; `amount0Min: 0` succeeds).\n * 2. `positionId` has no such constraint — an empty string works, and does not target an\n * existing position (`positionId: ''` created a fresh position on AddLiquidity, not an add\n * to position id `''`; on RemoveLiquidity/CollectPositionFees the real position is still\n * resolved from `token0`/`token1`/`fee`/`tickLower`/`tickUpper`, not from this field).\n */\nfunction numericOr0(dto: Record<string, unknown>, field: string): number {\n return typeof dto[field] === 'number' ? dto[field] : 0;\n}\n\n/**\n * `AddLiquidity`'s real server-side DTO always carries `amount0Desired`/`amount0Min`/\n * `amount1Desired`/`amount1Min`/`positionId` once reconstructed, regardless of which deposit\n * convention the caller used (`Positions.addLiquidityByTicks` only ever sends\n * `depositQuantityToken0`/`depositQuantityToken1`). Proven empirically by bisection: none of the\n * five alone fixes recovery, all five together does (live 201, tx `407d9b24...`, block\n * `2429022`).\n */\nfunction completeAddLiquidityFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount0Desired: numericOr0(dto, 'amount0Desired'),\n amount0Min: numericOr0(dto, 'amount0Min'),\n amount1Desired: numericOr0(dto, 'amount1Desired'),\n amount1Min: numericOr0(dto, 'amount1Min'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\n/**\n * `RemoveLiquidity`'s real server-side DTO always carries `amount`/`amount0Min`/`amount1Min`/\n * `positionId` — `Positions.removeLiquidity` only ever sends a `withdrawalQuantityTokenX` (or\n * neither, for a full close). Proven empirically: every subset of these four fails, all four\n * together succeeds (live, random-signer probe — recovery confirmed by the response moving from\n * \"Missing signerPublicKey\" to a genuine position-not-found 404).\n */\nfunction completeRemoveLiquidityFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount: numericOr0(dto, 'amount'),\n amount0Min: numericOr0(dto, 'amount0Min'),\n amount1Min: numericOr0(dto, 'amount1Min'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\n/**\n * `CollectPositionFees`'s real server-side DTO always carries `amount0Requested`/\n * `amount1Requested`/`positionId` — `Positions.collectPositionFees` sends only the five identity\n * fields. Proven empirically the same way as `completeRemoveLiquidityFields`.\n */\nfunction completeCollectPositionFeesFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount0Requested: numericOr0(dto, 'amount0Requested'),\n amount1Requested: numericOr0(dto, 'amount1Requested'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\nexport const EIP712_FIELD_COMPLETERS: Readonly<\n Record<string, (dto: Record<string, unknown>) => Record<string, unknown>>\n> = {\n AddLiquidity: completeAddLiquidityFields,\n RemoveLiquidity: completeRemoveLiquidityFields,\n CollectPositionFees: completeCollectPositionFeesFields,\n};\n\n/**\n * Completes a DTO's fields for EIP-712 signing (a no-op for methods with no known gap, e.g.\n * `RequestTrade`) and derives its `types`. Exported separately from the signing call itself so tests\n * can assert on the exact payload without needing a live provider.\n */\nexport function buildEIP712Payload(\n methodName: string,\n dto: Record<string, unknown>,\n): { completedDto: Record<string, unknown>; types: EIP712Types } {\n const completer = EIP712_FIELD_COMPLETERS[methodName];\n const completedDto = completer ? completer(dto) : dto;\n const types = generateEIP712Types(methodName, completedDto);\n return { completedDto, types };\n}\n","/**\n * SDK-owned signing primitives.\n *\n * Everything the SDK needs to produce a GalaChain signature lives here, with no dependency on\n * `@gala-chain/api` (which drags `secp256k1` native bindings, `reflect-metadata`, `class-validator`\n * and its own `bignumber.js` major into every consumer). The only runtime dependencies are the\n * audited, pure-JS `@noble/curves` (secp256k1) and `@noble/hashes` (keccak256), which run\n * unchanged in browsers, MV3 service workers, Node and React Native/Hermes.\n *\n * Every function here is pinned byte-for-byte to the signatures produced by `@gala-chain/api`\n * (`serialize`, `signatures.getSignature`), `@gala-chain/connect`, the Gala Wallet extension and\n * frontend_v2 by the golden-vector suite in `tests/signing-golden.test.ts`.\n */\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { bytesToHex } from '@noble/hashes/utils';\nimport type { InvalidPrivateKeyReason } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nconst textEncoder = new TextEncoder();\n\nfunction toDeterministicNode(node: unknown): unknown {\n if (node === null || node === undefined) return node;\n if (node instanceof RegExp) return node.toString();\n const candidate = node as { toJSON?: unknown };\n return typeof candidate.toJSON === 'function'\n ? (Reflect.apply(candidate.toJSON, node, []) as unknown)\n : node;\n}\n\nfunction deterministicNode(rawNode: unknown): string | undefined {\n const node = toDeterministicNode(rawNode);\n if (node === undefined) return undefined;\n if (typeof node !== 'object' || node === null) return JSON.stringify(node);\n\n if (Array.isArray(node)) {\n const items = (node as unknown[]).map((item) => deterministicNode(item) ?? 'null');\n return `[${items.join(',')}]`;\n }\n\n const record = node as Record<string, unknown>;\n const members: string[] = [];\n for (const key of Object.keys(record).sort()) {\n const value = deterministicNode(record[key]);\n if (value === undefined) continue;\n members.push(`${JSON.stringify(key)}:${value}`);\n }\n return `{${members.join(',')}}`;\n}\n\n/**\n * GalaChain's deterministic JSON: object keys sorted (UTF-16 code-unit order) at every depth, no\n * whitespace, `undefined`/function members dropped, `toJSON()` honored. Byte-identical to\n * `serialize` from `@gala-chain/api` / `json-stringify-deterministic` for every JSON-shaped\n * value, which is all a DTO ever is.\n *\n * @throws TypeError for circular structures and BigInt values (as `JSON.stringify` does) and\n * when the value itself has no JSON representation (`undefined`, a function, a symbol).\n */\nexport function serialize(value: unknown): string {\n // Same cycle/BigInt guard json-stringify-deterministic runs before walking the value.\n JSON.stringify(value);\n const result = deterministicNode(value);\n if (result === undefined) {\n throw new TypeError('Cannot serialize a value with no JSON representation.');\n }\n return result;\n}\n\n/**\n * The exact string GalaChain hashes for a DTO: the (optional, string) `prefix` field PREPENDED to\n * the deterministic serialization of the DTO WITHOUT `signature`, `multisig`, `trace` and `prefix`.\n * Equivalent to `@gala-chain/api` 3.x `getPayloadToSign` for every non-EIP-712 DTO.\n */\nexport function getPayloadToSign(dto: Record<string, unknown>): string {\n const { prefix, ...rest } = dto;\n delete rest['signature'];\n delete rest['multisig'];\n delete rest['trace'];\n const head = typeof prefix === 'string' ? prefix : '';\n return head + serialize(rest);\n}\n\n// Built via String.fromCharCode rather than a literal escape ON PURPOSE: a literal control byte in\n// source is invisible and fragile under editors/diffs/copy-paste; this keeps the source ordinary.\nconst ETHEREUM_SIGNED_MESSAGE = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\n\n/**\n * The EIP-191 header for `message`: `\"\\x19Ethereum Signed Message:\\n\"` + the message's UTF-8 BYTE\n * length. This is what a wallet's `personal_sign` prepends, and what the chain recomputes when it\n * recovers a personal-signed DTO.\n */\nexport function calculatePersonalSignPrefix(message: string): string {\n return ETHEREUM_SIGNED_MESSAGE + String(textEncoder.encode(message).length);\n}\n\n/**\n * The EIP-191 header for `serialize(dto)` (any `prefix` already on the DTO is ignored). This is\n * deliberately the same string the signers hand a wallet to sign, so the header's length can never\n * disagree with the signed message. Wallet-neutral: it is the value both a browser wallet's\n * `personal_sign` and Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepend.\n */\nexport function personalSignPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n return calculatePersonalSignPrefix(serialize(withoutPrefix));\n}\n\n/**\n * The `@gala-chain/connect`-style prefix frontend_v2 puts in the body of an EIP-712 write: the\n * EIP-191 header whose number counts the prefix string ITSELF plus the body (the UTF-8 length of\n * `getPayloadToSign({ ...dto, prefix })`), found by fixpoint because adding the prefix changes the\n * length (a body of 99 bytes settles on 101).\n *\n * It is NOT a personal-sign prefix (a personal-sign write with this value recovers a phantom\n * signer; use `personalSignPrefixFor`). Under EIP-712 the field is an untyped extra that the\n * typed-data hash ignores and defi-backend recomputes, so it only exists to keep the submitted\n * body byte-identical to what frontend_v2 has always sent.\n */\nexport function fixpointPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n let payloadLength = textEncoder.encode(getPayloadToSign(withoutPrefix)).length;\n let prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n let previousLength = -1;\n while (payloadLength !== previousLength) {\n previousLength = payloadLength;\n prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n payloadLength = textEncoder.encode(getPayloadToSign({ ...withoutPrefix, prefix })).length;\n }\n return prefix;\n}\n\nfunction invalidPrivateKey(reason: InvalidPrivateKeyReason): GSwapSDKError<'INVALID_PRIVATE_KEY'> {\n return new GSwapSDKError('INVALID_PRIVATE_KEY', { reason });\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction decodeBase64(input: string): Uint8Array | undefined {\n if (!/^[A-Za-z0-9+/]+={0,2}$/u.test(input) || input.length % 4 !== 0) return undefined;\n const unpadded = input.replace(/=+$/u, '');\n const bytes: number[] = [];\n let buffer = 0;\n let bits = 0;\n for (const char of unpadded) {\n buffer = (buffer << 6) | BASE64_ALPHABET.indexOf(char);\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n bytes.push((buffer >> bits) & 0xff);\n }\n }\n return Uint8Array.from(bytes);\n}\n\nfunction decodeHex(input: string): Uint8Array {\n const bytes = new Uint8Array(input.length / 2);\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = parseInt(input.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Normalizes a secp256k1 private key to a fresh 32-byte array (the caller may zero it). Also\n * accepts 32 raw bytes, which are validated and copied. For strings it accepts what `@gala-chain/api`'s\n * `normalizePrivateKey` accepted for a usable key: 64 hex characters (optionally `0x`-prefixed;\n * a 63-character hex key is left-padded with a zero) or a 44-character base64 string.\n *\n * @throws GSwapSDKError (`INVALID_PRIVATE_KEY`; `params.reason` is one of\n * `INVALID_PRIVATE_KEY_REASONS`: `wrong_length` for raw bytes that are not 32 long,\n * `bad_encoding` for any other string shape, `not_on_curve` for an out-of-range scalar).\n */\nexport function normalizePrivateKey(input: string | Uint8Array): Uint8Array {\n if (typeof input !== 'string') {\n // Raw bytes: validated, then COPIED, so zeroing the result never touches the caller's array.\n if (!(input instanceof Uint8Array) || input.length !== 32) {\n throw invalidPrivateKey('wrong_length');\n }\n if (!secp256k1.utils.isValidSecretKey(input)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return Uint8Array.from(input);\n }\n const withoutPrefix = input.startsWith('0x') ? input.slice(2) : input;\n let key: Uint8Array | undefined;\n if (/^[0-9a-fA-F]{63,64}$/u.test(withoutPrefix)) {\n key = decodeHex(withoutPrefix.length === 63 ? `0${withoutPrefix}` : withoutPrefix);\n } else if (withoutPrefix.length === 44) {\n key = decodeBase64(withoutPrefix);\n }\n if (key?.length !== 32) {\n throw invalidPrivateKey('bad_encoding');\n }\n if (!secp256k1.utils.isValidSecretKey(key)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return key;\n}\n\n/**\n * Signs a 32-byte keccak256 hash and returns GalaChain's recoverable signature: 64 hex `r` +\n * 64 hex `s` + `1b`/`1c` (`v`), lowercase, no `0x`. Deterministic (RFC 6979) and low-S, exactly\n * what `@gala-chain/api` and the Gala Wallet produce. A DER signature carries no recovery byte\n * and cannot be used: the chain RECOVERS the signer from the signature.\n */\nexport function signHash(privateKey: Uint8Array, hash: Uint8Array): string {\n if (hash.length !== 32) {\n throw new GSwapSDKError('INVALID_SIGNING_HASH_LENGTH', { length: hash.length });\n }\n const signature = secp256k1.sign(hash, privateKey, { prehash: false, lowS: true });\n // compact raw bytes are r (32) || s (32); the recovery id becomes v.\n return bytesToHex(signature.toBytes('compact')) + (signature.recovery === 1 ? '1c' : '1b');\n}\n\n/**\n * The lowercase `0x` Ethereum address (last 20 bytes of keccak256 of the uncompressed public key)\n * of a normalized private key. The Gala `eth|` identity of a key is this address.\n */\nexport function ethAddressOfPrivateKey(privateKey: Uint8Array): string {\n const publicKey = secp256k1.getPublicKey(privateKey, false);\n return `0x${bytesToHex(keccak_256(publicKey.slice(1)).slice(-20))}`;\n}\n\n/** keccak256 of a string's UTF-8 bytes. */\nexport function keccak256Utf8(data: string): Uint8Array {\n return keccak_256(textEncoder.encode(data));\n}\n\n/**\n * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes, with no\n * prefix and no signature envelope. The caller owns serialization, so the bytes shown to a user\n * and the bytes signed can never diverge.\n */\nexport function signSerializedNative(privateKey: Uint8Array, serializedDto: string): string {\n return signHash(privateKey, keccak256Utf8(serializedDto));\n}\n\n/**\n * GalaChain NATIVE signature for a DTO: keccak256 of `getPayloadToSign(dto)`, signed with\n * secp256k1. Byte-identical to `signatures.getSignature` from `@gala-chain/api`.\n */\nexport function signNative(privateKey: Uint8Array, dto: Record<string, unknown>): string {\n return signSerializedNative(privateKey, getPayloadToSign(dto));\n}\n\n/**\n * Personal-sign hash and signature: keccak256(`prefix` + `message`), both hashed VERBATIM with no\n * further EIP-191 wrapping. Passing `prefix = calculatePersonalSignPrefix(message)` reproduces a\n * wallet's `personal_sign` of `message`. Gala Wallet's `gala_signChainDto` (personal-sign\n * scheme) hashes `prefix` + the exact string it is handed, which can differ from the bare message\n * (see the `signatureOverPrefixlessBody` vectors); that quirk is why the two inputs stay separate.\n */\nexport function signPersonalMessage(\n privateKey: Uint8Array,\n prefix: string,\n message: string,\n): string {\n return signHash(privateKey, keccak256Utf8(prefix + message));\n}\n","import { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport {\n buildEIP712Payload,\n EIP712_CAPABLE_METHODS,\n eip712DomainFor,\n type EIP712DomainValue,\n type EIP712Types,\n} from '../utils/eip712.js';\nimport {\n ethAddressOfPrivateKey,\n fixpointPrefixFor,\n normalizePrivateKey,\n personalSignPrefixFor,\n serialize,\n signNative,\n} from '../utils/signing.js';\n\n// Personal-sign prefix, computed the way THE CHAIN verifies it.\n//\n// GalaChain (SDK 3.x) recovers a personal-signed DTO from\n// keccak256(<prefix field> + <canonical JSON of the DTO WITHOUT the prefix field>)\n// and a browser wallet's `personal_sign` (EIP-191) hashes\n// \"\\u0019Ethereum Signed Message:\\n\" + <byte length of message> + <message>.\n// They agree exactly when the wallet signs the bare canonical DTO and `prefix` is the EIP-191\n// header for that message's UTF-8 BYTE length. Any other message still yields a valid-looking\n// signature — it just recovers to an address nobody holds. This SDK used to embed `prefix` in\n// the signed message (the SDK 1.10 client recipe): observed on stage 2026-09-23, such a\n// MetaMask-signed CreatePool executed on chain under a phantom creator, and defi-backend's\n// bouncer now rejects that shape outright.\n//\n// `@gala-chain/connect`'s prefix helper must NOT be used for wallet `personal_sign`: its\n// fixpoint counts the prefix itself and targets the SDK's raw-payload signer. The same header\n// is also what Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepends before hashing,\n// so one value serves both paths.\n//\n// The header itself is computed by `personalSignPrefixFor` in ../utils/signing.ts.\n\n/** The signing schemes supported by the Gala Wallet signer. */\nexport type GalaWalletScheme = 'native' | 'personal-sign';\n\n/** The request surface used by an EIP-1193 browser wallet. */\nexport interface BrowserWalletProvider {\n request(args: { method: string; params?: unknown[] }): Promise<unknown>;\n}\n\ninterface GalaWalletProvider {\n request(args: { method: string; params?: unknown[] }): Promise<unknown>;\n /** Gala Wallet's \"act as this account\" switch; absent on other providers. */\n setAddress?: (address: string) => Promise<void>;\n}\n\ninterface WindowWithGala {\n gala?: GalaWalletProvider;\n}\n\ninterface GlobalWithWindow {\n window?: WindowWithGala;\n}\n\n/** A DTO together with the signature that belongs in the gateway request body. */\nexport type SignedDto<T extends Record<string, unknown>> = T & { signature: string };\n\n/**\n * A signer for complete GalaChain write bodies.\n *\n * Implementations return the DTO fields together with the signature that belongs in the\n * gateway request body. Signer identity is recovered from that signature; implementations do\n * not add signer hints, typed-data metadata, or a domain.\n */\nexport interface GalaChainSigner {\n /**\n * Signs a DTO for a named GalaChain contract method.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n */\n signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;\n}\n\nfunction getWalletProvider(): GalaWalletProvider {\n const globalObject = globalThis as GlobalWithWindow;\n const wallet = globalObject.window?.gala;\n if (!wallet) {\n throw new GSwapSDKError('GALA_WALLET_NOT_AVAILABLE', {});\n }\n return wallet;\n}\n\nfunction getNativeSignature(value: unknown): string {\n if (typeof value !== 'string') {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'native' });\n }\n // 130 hex digits (r || s || v), bare as Gala Wallet returns it or `0x`-prefixed; passed on\n // verbatim, because the backend recovers the signer from either spelling.\n if (!/^(?:0x)?[0-9a-fA-F]{130}$/u.test(value)) {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'native' });\n }\n return value;\n}\n\nfunction getPersonalSignature(value: unknown): string {\n if (typeof value !== 'string' || !/^(?:0x)?[0-9a-fA-F]{130}$/u.test(value)) {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'personal-sign' });\n }\n return value;\n}\n\n/**\n * The `0x`-prefixed Ethereum address a Gala account is signed by, or `undefined` when the account\n * names no key (a `client|` alias or a bare GalaChain id is not derivable from a key). Accepts\n * `0x` plus 40 hex digits and `eth|` plus 40 hex digits, with or without `0x`; the caller's casing\n * is kept. For {@link LazyPrivateKeySignerOptions.expectedAddress}, which should only be set for\n * an account whose key can be checked.\n *\n * @example\n * ```ts\n * createLazyPrivateKeySigner(getKey, { expectedAddress: ethereumAddressOfAccount(account) });\n * ```\n */\nexport function ethereumAddressOfAccount(account: string): string | undefined {\n const match = /^(?:eth\\|(?:0x)?|0x)([0-9a-fA-F]{40})$/u.exec(account);\n return match?.[1] === undefined ? undefined : `0x${match[1]}`;\n}\n\nfunction normalizeEthereumAccount(address: string, allowGalaPrefix: boolean): string {\n const normalized = allowGalaPrefix ? (ethereumAddressOfAccount(address) ?? address) : address;\n if (!/^0x[0-9a-fA-F]{40}$/u.test(normalized)) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'walletAddress', value: address });\n }\n // The caller's casing is kept on purpose: frontend_v2 and the wallet hand the wallet the\n // checksummed account, and EIP-1193 / Gala Wallet accept any case, so passing the value through\n // unchanged is the only choice that cannot differ from what they send.\n return normalized;\n}\n\n/**\n * The account handed to Gala Wallet as the signer address. An Ethereum account is held to the\n * same strict check as ever (`0x` plus 40 hex digits; `eth|` plus 40 hex digits, with or without\n * `0x`, is normalized to it). A GalaChain id the wallet can also be asked to sign for is passed\n * through verbatim: `client|` plus 24 hex digits, or the bare 24 hex digits that frontend_v2 keeps\n * in `state.user.wallet` after a direct `client|` login. Nothing else is accepted.\n */\nfunction normalizeGalaWalletAccount(address: string): string {\n const eth = /^eth\\|(?:0x)?([0-9a-fA-F]{40})$/u.exec(address);\n if (eth?.[1] !== undefined) return `0x${eth[1]}`;\n if (/^0x[0-9a-fA-F]{40}$/u.test(address) || /^(?:client\\|)?[0-9a-fA-F]{24}$/u.test(address)) {\n return address;\n }\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'walletAddress', value: address });\n}\n\n/** An identity Gala Wallet can act as: an account form above, any `eth|`/`client|` alias, verbatim. */\nfunction assertWalletIdentity(identity: string): void {\n if (\n !/^(?:eth\\|(?:0x)?[0-9a-fA-F]{40}|0x[0-9a-fA-F]{40}|(?:client\\|)?[0-9a-fA-F]{24})$/u.test(\n identity,\n )\n ) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'selectAddress', value: identity });\n }\n}\n\n/** Provider-wide queue: `setAddress` + the signature request must not interleave across signers. */\nconst walletIdentityQueue = new WeakMap<object, Promise<unknown>>();\n\n/**\n * Runs `signWith` with `identity` selected on a Gala Wallet that supports `setAddress`. Gala\n * Wallet holds ONE current account, so two signatures for different identities in flight at once\n * would sign as whichever selection came last; the pair (select, sign) is therefore serialized\n * per provider. A failed selection fails the signature (nothing is requested).\n */\nfunction withSelectedIdentity<T>(\n wallet: GalaWalletProvider,\n identity: string | undefined,\n signWith: () => Promise<T>,\n): Promise<T> {\n const { setAddress } = wallet;\n if (identity === undefined || typeof setAddress !== 'function') return signWith();\n const previous = walletIdentityQueue.get(wallet) ?? Promise.resolve();\n const run = previous\n .catch(() => undefined)\n .then(async () => {\n await setAddress.call(wallet, identity);\n return signWith();\n });\n walletIdentityQueue.set(wallet, run);\n return run;\n}\n\nfunction personalSign<T extends Record<string, unknown>>(\n provider: GalaWalletProvider | BrowserWalletProvider,\n dto: T,\n walletAddress: string,\n methodName?: string,\n): Promise<T & { prefix: string; signature: string }> {\n const prefix = personalSignPrefixFor(dto);\n const payload = { ...dto, prefix };\n // A browser wallet's `personal_sign` applies the EIP-191 header ITSELF, so it must sign the\n // bare DTO; Gala Wallet's `gala_signChainDto` (personal-sign scheme) instead extracts the\n // `prefix` field from what it is handed and prepends it before hashing, so it is handed the\n // prefixed payload. Both submit `{ ...dto, prefix, signature }`.\n const params =\n methodName !== undefined\n ? [serialize(payload), walletAddress, methodName]\n : [serialize(dto), walletAddress];\n\n return provider\n .request({ method: methodName !== undefined ? 'gala_signChainDto' : 'personal_sign', params })\n .then((value) => ({ ...payload, signature: getPersonalSignature(value) }));\n}\n\n/**\n * Signs a DTO via genuine EIP-712 (`eth_signTypedData_v4`) — correctly resolves the `client|`\n * identity, unlike `personal_sign`, for the operations in `EIP712_CAPABLE_METHODS`.\n *\n * Constructs the raw JSON-RPC payload by hand (`{domain, types: {...types, EIP712Domain},\n * primaryType, message}`) rather than depending on ethers.js, matching exactly what\n * `ethers.TypedDataEncoder.getPayload`/`Wallet.signTypedData` produce internally — verified\n * byte-for-byte equivalent (same recovered address from the same signature against both\n * constructions) before this shipped, since gswap-sdk deliberately has no ethers dependency.\n */\nasync function signEIP712<T extends Record<string, unknown>>(\n provider: BrowserWalletProvider,\n methodName: string,\n dto: T,\n walletAddress: string,\n): Promise<T & { types: EIP712Types; domain: EIP712DomainValue; signature: string }> {\n const { completedDto, types } = buildEIP712Payload(methodName, dto);\n // The wallet's LIVE chain id, read on every signature: a user can switch networks after\n // connecting, and a cached or hardcoded id would sign a domain MetaMask itself rejects.\n const domain = eip712DomainFor(await provider.request({ method: 'eth_chainId', params: [] }));\n // The body `prefix` is not part of the EIP-712 `types`, so it is never hashed; it carries the\n // connect-style fixpoint value only to keep the submitted body byte-identical to frontend_v2's.\n const prefix = fixpointPrefixFor(completedDto);\n const message = { ...completedDto, prefix };\n const eip712Domain = [\n { name: 'name', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n ];\n const payload = {\n domain,\n types: { ...types, EIP712Domain: eip712Domain },\n primaryType: methodName,\n message,\n };\n\n const value = await provider.request({\n method: 'eth_signTypedData_v4',\n params: [walletAddress, JSON.stringify(payload)],\n });\n // Key order matches frontend_v2's submitted body: ..., prefix, signature, types, domain.\n return {\n ...(message as T & { prefix: string }),\n signature: getPersonalSignature(value),\n types,\n domain,\n };\n}\n\n/**\n * A GalaChain native signer backed by a secp256k1 private key.\n *\n * Native signing produces the bare GalaChain signature format, without a personal-sign prefix\n * or EIP-712 metadata. The private-key identity is recovered by the chain.\n */\nexport class PrivateKeySigner implements GalaChainSigner {\n private readonly privateKey: Uint8Array;\n\n /**\n * Creates a native signer from a hex or base64 secp256k1 private key.\n *\n * @example\n * ```typescript\n * const signer = new PrivateKeySigner('1'.padStart(64, '0'));\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n */\n constructor(privateKey: string) {\n this.privateKey = normalizePrivateKey(privateKey);\n }\n\n /**\n * Signs the DTO with GalaChain native signing.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * fee: 3000,\n * });\n * ```\n */\n public signObject<T extends Record<string, unknown>>(\n _methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const signature = signNative(this.privateKey, dto);\n return Promise.resolve({ ...dto, signature });\n }\n}\n\n/** Supplies a private key at sign time: a hex/base64 string, possibly fetched asynchronously. */\nexport type PrivateKeyProvider = () => Promise<string> | string;\n\n/** Options for {@link createLazyPrivateKeySigner}. */\nexport interface LazyPrivateKeySignerOptions {\n /**\n * When set, every signature first checks that the fetched key belongs to this account (`0x...`\n * or the Gala `eth|0x...` / `eth|<40 hex>` form, case-insensitive) and refuses to sign otherwise\n * (`SIGNER_ADDRESS_MISMATCH`). Use it when the key lives in a slot another surface can switch\n * between the moment a request was approved and the moment it is signed.\n */\n expectedAddress?: string | undefined;\n}\n\n/**\n * Calls the app's key provider. Whatever it throws or rejects with is the app's own failure to\n * produce a key before anything was signed or sent, so it becomes `KEY_PROVIDER_FAILED` (the\n * original is `cause`); an SDK error is already catalogued and passes through.\n */\nasync function keyFrom(getPrivateKey: PrivateKeyProvider): Promise<unknown> {\n try {\n return await getPrivateKey();\n } catch (cause: unknown) {\n throw isGSwapError(cause) ? cause : new GSwapSDKError('KEY_PROVIDER_FAILED', {}, { cause });\n }\n}\n\n/**\n * Creates the native-signing equivalent of {@link PrivateKeySigner} for apps that must not hold a\n * key in a long-lived object (an extension that reads its session key at sign time).\n *\n * `getPrivateKey` is called once per `signObject` call, never cached, never shared between calls\n * (concurrent signatures each fetch their own key), and the normalized key bytes are zeroed\n * before `signObject` settles, also on failure. A rejection or exception from `getPrivateKey` (the\n * app's \"wallet is locked\", a storage read that failed) is a `KEY_PROVIDER_FAILED` error with the\n * original error as `cause`: nothing has been sent, so `classifyFailure` says `not_sent` and Retry\n * is safe, and the app needs no error class of its own to tell this apart. A provider that returns\n * no usable string (`''`, `undefined`) is `INVALID_PRIVATE_KEY` with `reason: 'no_key_provided'`,\n * classified the same way; any other key that is not a valid secp256k1 key string is an\n * `INVALID_PRIVATE_KEY` error. An SDK error the provider throws itself is passed through.\n * Signatures are byte-identical to `new PrivateKeySigner(key).signObject(...)`.\n *\n * A JavaScript string cannot be wiped; the provider owns the lifetime of the string it returns.\n *\n * @example\n * ```typescript\n * const signer = createLazyPrivateKeySigner(\n * () => SecurityHelper.getSessionSecret(SecurityHelper.SESSION_PRIVATE_KEY_KEY),\n * { expectedAddress: account.address },\n * );\n * const gswap = new GSwap({ signer });\n * ```\n */\nexport function createLazyPrivateKeySigner(\n getPrivateKey: PrivateKeyProvider,\n options: LazyPrivateKeySignerOptions = {},\n): GalaChainSigner {\n const expected = options.expectedAddress;\n const expectedLower =\n expected === undefined ? undefined : normalizeEthereumAccount(expected, true).toLowerCase();\n\n return {\n async signObject<T extends Record<string, unknown>>(\n _methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const provided: unknown = await keyFrom(getPrivateKey);\n if (typeof provided !== 'string' || provided === '') {\n throw new GSwapSDKError('INVALID_PRIVATE_KEY', { reason: 'no_key_provided' });\n }\n const key = normalizePrivateKey(provided);\n try {\n if (expectedLower !== undefined && ethAddressOfPrivateKey(key) !== expectedLower) {\n throw new GSwapSDKError('SIGNER_ADDRESS_MISMATCH', {});\n }\n return { ...dto, signature: signNative(key, dto) };\n } finally {\n key.fill(0);\n }\n },\n };\n}\n\n/**\n * A Gala Wallet signer using native GalaChain signing, with an opt-in personal-sign mode.\n *\n * The selected Ethereum account is passed to Gala Wallet. There is NO automatic fallback: a\n * wallet that rejects `native` surfaces its error to the caller, because the only alternative,\n * `personal-sign`, silently recovers a phantom signer on every released Gala Wallet.\n *\n * `scheme: 'personal-sign'` calls\n * `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])` and REQUIRES\n * a wallet build that contains wallet_extension commit 3ad7ae6 (strips the embedded `prefix`\n * field and hashes `prefix` + the prefix-less canonical body, the chain's scheme). Wallets\n * released before that fix hash the string with the `prefix` field still inside it and the\n * signature recovers to an address nobody holds, so only opt in once the fixed wallet is\n * released. See SIGNING-PARITY.md.\n */\nexport class GalaWalletSigner implements GalaChainSigner {\n /** The wallet address supplied to Gala Wallet for each signing request. */\n public readonly walletAddress: string;\n\n /** The signing scheme used for every request; it never changes after construction. */\n public readonly scheme: GalaWalletScheme;\n\n /**\n * Creates a Gala Wallet signer.\n *\n * @example\n * ```typescript\n * const signer = new GalaWalletSigner('0x0123456789012345678901234567890123456789');\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n *\n * @param walletAddress - The account passed to Gala Wallet as the signer address. An Ethereum\n * account is `0x` plus 40 hex digits (Gala Wallet's `eth|...` form is normalized to it and held\n * to the same check); a GalaChain id is `client|` plus 24 hex digits, or the bare 24 hex digits\n * frontend_v2 keeps for a direct `client|` login, and is passed through unchanged.\n * @param options - Select native signing (default) or personal-sign explicitly.\n * `'personal-sign'` requires a Gala Wallet build with wallet_extension commit 3ad7ae6.\n * `selectAddress` is the identity (`client|...` / `eth|...`) Gala Wallet is switched to with\n * `window.gala.setAddress` before every signature, when the wallet offers it.\n */\n constructor(\n walletAddress: string,\n options: { scheme?: GalaWalletScheme | undefined; selectAddress?: string | undefined } = {},\n ) {\n this.walletAddress = normalizeGalaWalletAccount(walletAddress);\n this.scheme = options.scheme ?? 'native';\n if (options.selectAddress !== undefined) assertWalletIdentity(options.selectAddress);\n this.selectAddress = options.selectAddress;\n }\n\n /** The identity Gala Wallet is switched to before each signature, if one was given. */\n public readonly selectAddress: string | undefined;\n\n /**\n * Signs a DTO through `gala_signChainDto`.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('AddLiquidity', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * tickLower: -60,\n * tickUpper: 60,\n * });\n * ```\n */\n public async signObject<T extends Record<string, unknown>>(\n methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const wallet = getWalletProvider();\n\n return withSelectedIdentity(wallet, this.selectAddress, async () => {\n if (this.scheme === 'personal-sign') {\n return personalSign(wallet, dto, this.walletAddress, methodName);\n }\n const signature = await wallet.request({\n method: 'gala_signChainDto',\n params: [serialize(dto), this.walletAddress, methodName, 'native'],\n });\n return { ...dto, signature: getNativeSignature(signature) };\n });\n }\n}\n\n/**\n * A personal-sign signer for MetaMask and other EIP-1193 browser wallets.\n *\n * The chain recovers this signature using the EIP-191 wrap applied by the wallet to\n * `personal_sign`. This is the browser-wallet path used by the v2 frontend and resolves the\n * bare `eth|` identity.\n */\nexport class BrowserWalletSigner implements GalaChainSigner {\n /**\n * Creates a browser-wallet signer.\n *\n * Defaults to `personal_sign` — unchanged from every existing integration, since it only ever\n * resolves the bare `eth|` identity and changing that silently would be a real behavior\n * break for anyone already depending on it. Pass `{ scheme: 'eip712' }` to correctly resolve\n * a registered `client|` alias instead, for `RequestTrade`/`AddLiquidity`/`RemoveLiquidity`/\n * `CollectPositionFees` (`EIP712_CAPABLE_METHODS`) — `CreatePool` and any other method still\n * falls back to `personal_sign` even in `'eip712'` mode, since its EIP-712 signing is a\n * separate, unsolved chain-side problem.\n *\n * @example\n * ```typescript\n * const signer = new BrowserWalletSigner(window.ethereum, '0x0123456789012345678901234567890123456789');\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n * @example\n * ```typescript\n * // Correctly resolves a registered client| alias instead of the bare eth| address.\n * const signer = new BrowserWalletSigner(window.ethereum, walletAddress, { scheme: 'eip712' });\n * ```\n */\n constructor(\n private readonly provider: BrowserWalletProvider,\n walletAddress: string,\n options: { scheme?: 'personal-sign' | 'eip712' } = {},\n ) {\n this.walletAddress = normalizeEthereumAccount(walletAddress, false);\n this.scheme = options.scheme ?? 'personal-sign';\n }\n\n public readonly walletAddress: string;\n private readonly scheme: 'personal-sign' | 'eip712';\n\n /**\n * Signs the DTO with `eth_signTypedData_v4` (when constructed with `{ scheme: 'eip712' }` and\n * `methodName` is in `EIP712_CAPABLE_METHODS`) or the EIP-1193 `personal_sign` method\n * (otherwise — the default).\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * fee: 3000,\n * });\n * ```\n */\n public signObject<T extends Record<string, unknown>>(\n methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n if (this.scheme === 'eip712' && EIP712_CAPABLE_METHODS.has(methodName)) {\n return signEIP712(this.provider, methodName, dto, this.walletAddress);\n }\n return personalSign(this.provider, dto, this.walletAddress);\n }\n}\n","/**\n * String-key signing entry points for apps that hold a private key only briefly (the Gala Wallet\n * extension reads its session key at sign time and must not keep it in a long-lived object).\n *\n * These are thin, byte-exact ports of the functions the wallet shipped in\n * `wallet_extension/src/helpers/wallet/signing.ts` (including the fail-closed personal-sign\n * payload resolver from its commit 3ad7ae6), re-expressed over the SDK's own primitives. Every\n * function takes the key as a string (`0x`-optional hex, or base64) or as bytes, normalizes it per\n * call, and zeroes the normalized copy before returning, so nothing in this module retains a key.\n * A JavaScript string cannot be wiped; the caller owns the lifetime of the string it passes in.\n */\nimport BigNumber from 'bignumber.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport {\n normalizePrivateKey,\n serialize,\n signPersonalMessage,\n signSerializedNative,\n} from './signing.js';\n\n/** A secp256k1 private key as a hex/base64 string or as raw 32 bytes. */\nexport type PrivateKeyInput = string | Uint8Array;\n\n/**\n * Runs `action` with a private normalized copy of the key, zeroed afterwards (also when `action`\n * throws). Bytes given by the caller are copied, never modified: the caller owns them.\n */\nexport function withPrivateKey<T>(privateKey: PrivateKeyInput, action: (key: Uint8Array) => T): T {\n const key = normalizePrivateKey(privateKey);\n try {\n return action(key);\n } finally {\n key.fill(0);\n }\n}\n\n/**\n * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes with no\n * prefix and no envelope (wallet `signChainDtoNative`). The caller owns serialization, so the\n * bytes a user reviewed and the bytes signed cannot diverge.\n *\n * @returns 130 lowercase hex characters, `r || s || v` with `v` = `1b`/`1c`, no `0x`.\n */\nexport function signChainDtoNative(privateKey: PrivateKeyInput, serializedDto: string): string {\n return withPrivateKey(privateKey, (key) => signSerializedNative(key, serializedDto));\n}\n\n/**\n * The personal-sign hash primitive (wallet `signChainDtoHash`): keccak256(`prefix` + `message`),\n * both verbatim, with no further EIP-191 wrap. `message` must be the DTO's serialization WITHOUT\n * its `prefix` field; callers holding a dApp-supplied string go through `signChainDtoPersonalSign`,\n * which derives both inputs from it.\n */\nexport function signChainDtoHash(\n privateKey: PrivateKeyInput,\n prefix: string,\n message: string,\n): string {\n return withPrivateKey(privateKey, (key) => signPersonalMessage(key, prefix, message));\n}\n\nconst PERSONAL_SIGN_HEADER = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\nconst PERSONAL_SIGN_LENGTH_PATTERN = /^(?:0|[1-9][0-9]*)$/u;\n\n// A header with a body starting `{` can never collide with another EIP-191 message's hash, and\n// anything that is not a header (arbitrary bytes the user cannot see on an approval card) is\n// refused. The number is NOT required to equal the byte length: the chain hashes whatever prefix\n// the submitted DTO carries, and defi-backend's bouncer rejects a mismatched header loudly.\nfunction isPersonalSignHeader(prefix: string): boolean {\n return (\n prefix.startsWith(PERSONAL_SIGN_HEADER) &&\n PERSONAL_SIGN_LENGTH_PATTERN.test(prefix.slice(PERSONAL_SIGN_HEADER.length))\n );\n}\n\n/**\n * Top-level fields that would make the chain (`getPayloadToSign`) or defi-backend's personal-sign\n * verifier hash something other than `prefix + serialize(dto minus prefix)`. An unsigned DTO from\n * a dApp never legitimately carries any of them, so they fail closed. Order is part of the error\n * message the wallet shows its user.\n */\nconst PERSONAL_SIGN_FORBIDDEN_FIELDS = [\n 'signature',\n 'multisig',\n 'trace',\n 'types',\n 'domain',\n 'stringsInstructions',\n] as const;\n\n/** What a `gala_signChainDto` personal-sign request hashes. */\nexport interface PersonalSignChainDtoPayload {\n /** The `prefix` the chain prepends: the DTO's own `prefix` field, or `''` when it has none. */\n prefix: string;\n /** The exact message hashed after `prefix`. */\n message: string;\n}\n\n/**\n * Derives what to hash for a `gala_signChainDto` personal-sign request from the exact string the\n * dApp sent (and the approval card displayed): wallet `resolvePersonalSignChainDtoPayload`.\n *\n * The dApp submits `{ ...dto, prefix, signature }`, which the chain recovers from\n * `keccak256(prefix + serialize(dto WITHOUT prefix))`. So when the string embeds a `prefix`\n * field, that field is removed and the remainder re-serialized; the prefix used is the dApp's own\n * value byte for byte. A string with no `prefix` field is hashed verbatim with an empty prefix\n * (chain-equivalent to a native signature of that exact string).\n *\n * Fails closed (throws `GSwapSDKError` `PERSONAL_SIGN_NOT_JSON`, `PERSONAL_SIGN_NOT_OBJECT`,\n * `PERSONAL_SIGN_BAD_PREFIX`, `PERSONAL_SIGN_ENVELOPE_FIELDS` or `PERSONAL_SIGN_NOT_CANONICAL`) on:\n * malformed JSON; JSON that is not a plain object; a `prefix` that is not an EIP-191\n * \"Ethereum Signed Message\" header; any signing-envelope field (`signature`, `multisig`, `trace`,\n * `types`, `domain`, `stringsInstructions`); and a string that is not already the canonical\n * serialization of what it parses to (duplicate keys, lossy numbers, key-order tricks the card\n * would render differently). Stripping `prefix` is therefore the ONLY byte change between the\n * reviewed string and the signed message.\n */\nexport function resolvePersonalSignChainDtoPayload(data: string): PersonalSignChainDtoPayload {\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_JSON', {});\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_OBJECT', {});\n }\n const dto = parsed as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(dto, 'prefix')) {\n return { prefix: '', message: data };\n }\n\n const { prefix, ...withoutPrefix } = dto;\n if (typeof prefix !== 'string' || !isPersonalSignHeader(prefix)) {\n throw new GSwapSDKError('PERSONAL_SIGN_BAD_PREFIX', {});\n }\n const forbidden = PERSONAL_SIGN_FORBIDDEN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(withoutPrefix, field),\n );\n if (forbidden.length > 0) {\n throw new GSwapSDKError('PERSONAL_SIGN_ENVELOPE_FIELDS', { fields: forbidden.join(', ') });\n }\n if (serialize(dto) !== data) {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_CANONICAL', {});\n }\n return { prefix, message: serialize(withoutPrefix) };\n}\n\n/**\n * Signs a GalaChain personal-sign scheme DTO from the exact string a dApp sent through\n * `gala_signChainDto` (wallet `signChainDtoPersonalSign`). See\n * `resolvePersonalSignChainDtoPayload` for what is signed and what is refused; the signature\n * recovers, under the chain's `getPayloadToSign`, to this key for the DTO the dApp submits with\n * its `prefix`, and equals a `personal_sign` of the bare body when that prefix is the EIP-191\n * header of the bare body's byte length.\n *\n * @throws GSwapSDKError (`PERSONAL_SIGN_*`, see `resolvePersonalSignChainDtoPayload`) before any\n * signing when the input is refused.\n */\nexport function signChainDtoPersonalSign(privateKey: PrivateKeyInput, data: string): string {\n const { prefix, message } = resolvePersonalSignChainDtoPayload(data);\n return signChainDtoHash(privateKey, prefix, message);\n}\n\n/**\n * Raw object signing (wallet `signObject`), used for transfers, bridge and fee-dry-run DTOs the\n * wallet signs itself. Removes ONLY `signature`, signs `keccak256(serialize(rest))` natively\n * (no `prefix` handling, and `trace` / `multisig` stay in the signed bytes, unlike\n * `signNative`), and returns `{ signature, ...rest }` with the signature as the FIRST key, exactly\n * like the wallet. Callers that must not sign extra fields strip them first.\n */\nexport function signRawObject(\n privateKey: PrivateKeyInput,\n obj: Record<string, unknown>,\n): { signature: string } & Record<string, unknown> {\n const rest = { ...obj };\n delete rest['signature'];\n return {\n signature: signChainDtoNative(privateKey, serialize(rest)),\n ...rest,\n };\n}\n\n/**\n * Drops the `EIP712Domain` entry from a dApp-supplied types map (a typed-data encoder derives the\n * domain type itself and rejects an explicit one). The order of the remaining types is preserved.\n */\nexport function stripEip712DomainType<T>(types: Record<string, T>): Record<string, T> {\n const stripped: Record<string, T> = {};\n for (const typeName of Object.keys(types)) {\n if (typeName !== 'EIP712Domain') stripped[typeName] = types[typeName] as T;\n }\n return stripped;\n}\n\n/**\n * `collection$category$type$additionalKey` for a token-class object (wallet `decodeTokenData`).\n * Lenient on purpose: any missing or non-string part becomes `''`, so a display layer never\n * throws on odd input.\n */\nexport function tokenClassDollarKey(token: Record<string, unknown> | null | undefined): string {\n const part = (field: string): string => {\n const value = token?.[field];\n return typeof value === 'string' ? value : '';\n };\n return `${part('collection')}$${part('category')}$${part('type')}$${part('additionalKey')}`;\n}\n\n/**\n * A quantity in the form GalaChain's `IsBigNumber` validator accepts: FIXED notation, no leading\n * zeros, no trailing decimal zeros (`BigNumber#toFixed()`; never `toString()`, which turns\n * `0.00000001` into `1e-8`, and never a JS number in between).\n *\n * @throws GSwapSDKError (`INVALID_DECIMAL`) for a value that is not a finite number. The wallet's\n * `cleanNumber` returned the string `'NaN'` there; signing that text can only fail on chain.\n */\nexport function canonicalDecimalString(value: string | number): string {\n let parsed = new BigNumber(Number.NaN);\n try {\n parsed = new BigNumber(value);\n } catch {\n // BigNumber throws instead of returning NaN when its DEBUG flag is on; both mean \"invalid\".\n }\n if (!parsed.isFinite()) {\n throw new GSwapSDKError('INVALID_DECIMAL', { value: String(value) });\n }\n return parsed.toFixed();\n}\n","/**\n * EIP-712 (`eth_signTypedData_v4`) hashing and signing for ARBITRARY dApp typed data, built on the\n * SDK's own primitives (`@noble/curves`, `@noble/hashes`) so a wallet can sign a dApp's typed-data\n * approval without ethers. It replaces the wallet's `new ethers.Wallet(key).signTypedData(...)`\n * and is pinned to it: the golden suite reproduces every fixture signature exactly and a seeded\n * differential fuzz compares the digest and signature with ethers for every supported type.\n *\n * Compared with ethers this encoder is deliberately STRICTER (it fails closed rather than coerce):\n * `bool` accepts only a boolean, numbers accept only safe integers / decimal or `0x` strings,\n * strings must be well-formed UTF-16, struct values must be objects whose fields are their own\n * properties, and every struct, field and type name must be a plain identifier. Anything ethers\n * accepts that is NOT in that set is refused here instead of being signed in a different shape\n * from what a user reviewed.\n */\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { signHash } from './signing.js';\nimport { withPrivateKey, type PrivateKeyInput } from './chain_dto_signing.js';\n\n/** A typed-data payload as `eth_signTypedData_v4` carries it, minus `primaryType` (it is inferred). */\nexport interface TypedDataPayload {\n domain: Record<string, unknown>;\n /** Struct definitions WITHOUT `EIP712Domain` (see `stripEip712DomainType`). */\n types: Record<string, readonly unknown[]>;\n message: Record<string, unknown>;\n}\n\ninterface TypedField {\n name: string;\n type: string;\n}\n\nconst textEncoder = new TextEncoder();\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;\nconst TYPE_SYNTAX = /^([A-Za-z_$][A-Za-z0-9_$]*)((?:\\[(?:0|[1-9][0-9]*)?\\])*)$/u;\nconst BIGINT_DECIMAL = /^-?[0-9]+$/u;\nconst BIGINT_HEX = /^-?0x[0-9a-fA-F]+$/u;\n\n/** The EIP-712 domain members and their types, in the order ethers (and the spec) hash them. */\nconst DOMAIN_FIELDS: readonly TypedField[] = [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n { name: 'salt', type: 'bytes32' },\n];\n\nfunction concat(parts: readonly Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((total, part) => total + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\nfunction bigintToWord(value: bigint): Uint8Array {\n const word = new Uint8Array(32);\n // Every caller has bounds-checked `value` against its Solidity type, so it fits in 256 bits.\n let rest = value < 0n ? value + (1n << 256n) : value;\n for (let index = 31; index >= 0; index -= 1) {\n word[index] = Number(rest & 0xffn);\n rest >>= 8n;\n }\n return word;\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const body = hex.slice(2);\n const out = new Uint8Array(body.length / 2);\n for (let index = 0; index < out.length; index += 1) {\n out[index] = parseInt(body.slice(index * 2, index * 2 + 2), 16);\n }\n return out;\n}\n\nfunction toBytes(value: unknown, what: string): Uint8Array {\n if (value instanceof Uint8Array) return value;\n if (typeof value === 'string' && /^0x(?:[0-9a-fA-F]{2})*$/u.test(value)) return hexToBytes(value);\n throw new GSwapSDKError('TYPED_DATA_NOT_HEX_BYTES', { what });\n}\n\nfunction toBigInt(value: unknown, what: string): bigint {\n if (typeof value === 'bigint') return value;\n if (typeof value === 'number') {\n if (!Number.isSafeInteger(value))\n throw new GSwapSDKError('TYPED_DATA_NOT_SAFE_INTEGER', { what });\n return BigInt(value);\n }\n if (typeof value === 'string') {\n if (BIGINT_DECIMAL.test(value)) return BigInt(value);\n if (BIGINT_HEX.test(value)) {\n return value.startsWith('-') ? -BigInt(value.slice(1)) : BigInt(value);\n }\n }\n throw new GSwapSDKError('TYPED_DATA_NOT_INTEGER', { what });\n}\n\nfunction utf8(value: unknown, what: string): Uint8Array {\n if (typeof value !== 'string') throw new GSwapSDKError('TYPED_DATA_NOT_STRING', { what });\n for (let index = 0; index < value.length; index += 1) {\n const unit = value.charCodeAt(index);\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (!(next >= 0xdc00 && next <= 0xdfff)) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n index += 1;\n } else if (unit >= 0xdc00 && unit <= 0xdfff) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n }\n return textEncoder.encode(value);\n}\n\n/** EIP-55: a mixed-case address must carry the right checksum; all-lower / all-upper is accepted. */\nfunction addressBytes(value: unknown): Uint8Array {\n if (typeof value !== 'string' || !/^0x[0-9a-fA-F]{40}$/u.test(value)) {\n throw new GSwapSDKError('TYPED_DATA_BAD_ADDRESS', {});\n }\n const digits = value.slice(2);\n if (/[A-F]/u.test(digits) && /[a-f]/u.test(digits)) {\n const hash = keccak_256(textEncoder.encode(digits.toLowerCase()));\n for (let index = 0; index < 40; index += 1) {\n const nibble = ((hash[index >> 1] as number) >> (index % 2 === 0 ? 4 : 0)) & 0xf;\n const char = digits.charAt(index);\n const expected = nibble >= 8 ? char.toUpperCase() : char.toLowerCase();\n if (char !== expected) throw new GSwapSDKError('TYPED_DATA_BAD_CHECKSUM', {});\n }\n }\n return hexToBytes(value);\n}\n\ntype LeafEncoder = (value: unknown) => Uint8Array;\n\n/** The encoder for a non-struct, non-array type, or undefined when `base` is not one. */\nfunction leafEncoder(base: string): LeafEncoder | undefined {\n if (base === 'string') return (value) => keccak_256(utf8(value, 'string'));\n if (base === 'bytes') return (value) => keccak_256(toBytes(value, 'bytes'));\n if (base === 'bool') {\n return (value) => {\n if (typeof value !== 'boolean') throw new GSwapSDKError('TYPED_DATA_NOT_BOOLEAN', {});\n return bigintToWord(value ? 1n : 0n);\n };\n }\n if (base === 'address') {\n return (value) => concat([new Uint8Array(12), addressBytes(value)]);\n }\n const fixed = /^bytes([1-9][0-9]?)$/u.exec(base);\n if (fixed !== null) {\n const width = Number(fixed[1]);\n if (width > 32 || String(width) !== fixed[1]) return undefined;\n return (value) => {\n const bytes = toBytes(value, base);\n if (bytes.length !== width) {\n throw new GSwapSDKError('TYPED_DATA_BYTES_LENGTH', { type: base, width });\n }\n return concat([bytes, new Uint8Array(32 - width)]);\n };\n }\n const integer = /^(u?)int([1-9][0-9]*)$/u.exec(base);\n if (integer !== null) {\n const width = Number(integer[2]);\n if (width % 8 !== 0 || width > 256 || String(width) !== integer[2]) return undefined;\n const signed = integer[1] === '';\n const lower = signed ? -(1n << BigInt(width - 1)) : 0n;\n const upper = signed ? (1n << BigInt(width - 1)) - 1n : (1n << BigInt(width)) - 1n;\n return (value) => {\n const number = toBigInt(value, base);\n if (number < lower || number > upper) {\n throw new GSwapSDKError('TYPED_DATA_OUT_OF_BOUNDS', { type: base });\n }\n return bigintToWord(number);\n };\n }\n return undefined;\n}\n\ninterface ParsedType {\n base: string;\n /** Array suffixes outermost-last, e.g. `uint256[2][]` is `[2, -1]` (-1 = dynamic). */\n dimensions: number[];\n}\n\nfunction parseType(type: string): ParsedType {\n const match = TYPE_SYNTAX.exec(type);\n if (match === null) throw new GSwapSDKError('TYPED_DATA_UNSUPPORTED_TYPE', { type });\n const dimensions = [...(match[2] ?? '').matchAll(/\\[([0-9]*)\\]/gu)].map((dimension) =>\n dimension[1] === '' ? -1 : Number(dimension[1]),\n );\n return { base: match[1] as string, dimensions };\n}\n\nfunction parseFields(typeName: string, rawFields: readonly unknown[]): TypedField[] {\n if (!Array.isArray(rawFields))\n throw new GSwapSDKError('TYPED_DATA_FIELDS_NOT_LIST', { typeName });\n const seen = new Set<string>();\n return rawFields.map((raw: unknown) => {\n const field = raw as { name?: unknown; type?: unknown } | null;\n if (typeof field?.name !== 'string' || typeof field.type !== 'string') {\n throw new GSwapSDKError('TYPED_DATA_FIELD_MALFORMED', { typeName });\n }\n if (!IDENTIFIER.test(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_FIELD_NAME', { name: field.name });\n }\n if (seen.has(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_DUPLICATE_FIELD', { name: field.name, typeName });\n }\n seen.add(field.name);\n // A bare `int` / `uint` is the 256-bit type and is hashed as `int256` / `uint256`, like ethers.\n const parsed = parseType(field.type);\n const base =\n parsed.base === 'uint' || parsed.base === 'int' ? `${parsed.base}256` : parsed.base;\n return { name: field.name, type: base + field.type.slice(parsed.base.length) };\n });\n}\n\ninterface StructEncoder {\n primaryType: string;\n hashStruct: (typeName: string, value: unknown) => Uint8Array;\n}\n\n/**\n * Builds the struct encoder for a set of type definitions: validates the type graph (unknown or\n * circular references, duplicate fields) and infers the primary type as the single type no other\n * type references, exactly like ethers' `TypedDataEncoder`.\n */\nfunction createStructEncoder(rawTypes: Record<string, readonly unknown[]>): StructEncoder {\n const names = Object.keys(rawTypes);\n const fields = new Map<string, TypedField[]>();\n for (const name of names) {\n if (!IDENTIFIER.test(name)) throw new GSwapSDKError('TYPED_DATA_INVALID_TYPE_NAME', { name });\n fields.set(name, parseFields(name, rawTypes[name] as readonly unknown[]));\n }\n\n const children = new Map<string, Set<string>>();\n const parents = new Map<string, Set<string>>();\n for (const name of names) {\n children.set(name, new Set());\n parents.set(name, new Set());\n }\n for (const [name, list] of fields) {\n for (const field of list) {\n const { base } = parseType(field.type);\n if (base === name) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (leafEncoder(base) !== undefined) continue;\n if (!fields.has(base)) {\n throw new GSwapSDKError('TYPED_DATA_UNKNOWN_FIELD_TYPE', { type: base, typeName: name });\n }\n children.get(name)?.add(base);\n parents.get(base)?.add(name);\n }\n }\n\n const roots = names.filter((name) => parents.get(name)?.size === 0);\n if (roots.length === 0) throw new GSwapSDKError('TYPED_DATA_NO_PRIMARY_TYPE', {});\n if (roots.length > 1) {\n throw new GSwapSDKError('TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE', { roots: roots.join(', ') });\n }\n const primaryType = roots[0] as string;\n\n const visiting = new Set<string>();\n const checked = new Set<string>();\n const checkCircular = (name: string): void => {\n if (visiting.has(name)) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (checked.has(name)) return;\n visiting.add(name);\n for (const child of children.get(name) ?? []) checkCircular(child);\n visiting.delete(name);\n checked.add(name);\n };\n checkCircular(primaryType);\n\n const dependencies = (name: string, found: Set<string>): Set<string> => {\n for (const child of children.get(name) ?? []) {\n if (!found.has(child)) {\n found.add(child);\n dependencies(child, found);\n }\n }\n return found;\n };\n const encodeOne = (name: string): string =>\n `${name}(${(fields.get(name) ?? []).map((field) => `${field.type} ${field.name}`).join(',')})`;\n const typeHashes = new Map<string, Uint8Array>();\n for (const name of names) {\n const sorted = [...dependencies(name, new Set())].filter((dep) => dep !== name).sort();\n typeHashes.set(name, keccak_256(textEncoder.encode([name, ...sorted].map(encodeOne).join(''))));\n }\n\n const encodeValue = (parsed: ParsedType, value: unknown, depth: number): Uint8Array => {\n // The LAST bracket written is the outermost array: `uint8[][2]` is two `uint8[]`.\n const dimension = parsed.dimensions[parsed.dimensions.length - 1 - depth];\n if (dimension !== undefined) {\n if (!Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_EXPECTED', { type: parsed.base });\n }\n if (dimension !== -1 && dimension !== value.length) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_LENGTH_MISMATCH', {});\n }\n return keccak_256(concat(value.map((item) => encodeValue(parsed, item, depth + 1))));\n }\n const leaf = leafEncoder(parsed.base);\n if (leaf !== undefined) return leaf(value);\n return hashStruct(parsed.base, value);\n };\n\n function hashStruct(typeName: string, value: unknown): Uint8Array {\n const list = fields.get(typeName);\n const typeHash = typeHashes.get(typeName);\n if (list === undefined || typeHash === undefined) {\n // createStructEncoder has already validated every struct name this is called with.\n throw new Error(`Internal error: no encoder for struct ${typeName}`);\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_STRUCT_NOT_OBJECT', { typeName });\n }\n const record = value as Record<string, unknown>;\n const words = list.map((field) => {\n if (!Object.prototype.hasOwnProperty.call(record, field.name)) {\n throw new GSwapSDKError('TYPED_DATA_MISSING_FIELD', { typeName, field: field.name });\n }\n // Struct-valued fields are encoded to their 32-byte struct hash by encodeValue.\n return encodeValue(parseType(field.type), record[field.name], 0);\n });\n return keccak_256(concat([typeHash, ...words]));\n }\n\n return { primaryType, hashStruct };\n}\n\nfunction hashDomain(domain: Record<string, unknown>): Uint8Array {\n if (domain === null || typeof domain !== 'object' || Array.isArray(domain)) {\n throw new GSwapSDKError('TYPED_DATA_DOMAIN_NOT_OBJECT', {});\n }\n for (const key of Object.keys(domain)) {\n if (!DOMAIN_FIELDS.some((field) => field.name === key)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_DOMAIN_KEY', { key: JSON.stringify(key) });\n }\n }\n const present = DOMAIN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(domain, field.name),\n );\n const encoder = createStructEncoder({ EIP712Domain: present });\n return encoder.hashStruct('EIP712Domain', domain);\n}\n\n/**\n * The EIP-712 digest `keccak256(0x1901 || domainSeparator || hashStruct(primaryType, message))`\n * that a wallet signs for `eth_signTypedData_v4`. The primary type is inferred, as ethers does.\n *\n * @throws GSwapSDKError (`TYPED_DATA_*`) for any type graph or value it cannot encode\n * exactly (see the module note on strictness).\n */\nexport function hashTypedData(payload: TypedDataPayload): Uint8Array {\n const domainHash = hashDomain(payload.domain);\n const encoder = createStructEncoder(payload.types);\n const structHash = encoder.hashStruct(encoder.primaryType, payload.message);\n return keccak_256(concat([Uint8Array.of(0x19, 0x01), domainHash, structHash]));\n}\n\n/**\n * Signs a dApp's EIP-712 typed-data approval (the wallet's `signTypedMessage` path), replacing\n * `new ethers.Wallet(key).signTypedData(domain, types, message)`. `types` must already have\n * `EIP712Domain` removed (`stripEip712DomainType`).\n *\n * @returns `0x` + r + s + v with `v` = `0x1b`/`0x1c` (27/28): ethers' serialized signature form,\n * recoverable with `verifyTypedData` / `eth_signTypedData_v4` verifiers. Rejects (never throws\n * synchronously) on invalid input.\n */\nexport async function signTypedDataPayload(\n privateKey: PrivateKeyInput,\n payload: TypedDataPayload,\n): Promise<string> {\n const digest = hashTypedData(payload);\n return withPrivateKey(privateKey, (key) => `0x${signHash(key, digest)}`);\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\n\n/** What the adapter reads of an axios response. */\nexport interface AxiosLikeResponse {\n status: number;\n data?: unknown;\n /** axios' `AxiosHeaders` (has `get`) or a plain header record. */\n headers?: unknown;\n}\n\n/** The request config the adapter hands to axios. */\nexport interface AxiosLikeConfig {\n headers: Record<string, string>;\n signal?: AbortSignal;\n validateStatus?: () => boolean;\n}\n\n/**\n * The part of an axios instance the adapter calls. Declared structurally, so the SDK takes no\n * dependency on axios and any axios instance (with its interceptors) satisfies it.\n */\nexport interface AxiosLikeInstance {\n get(url: string, config?: AxiosLikeConfig): Promise<unknown>;\n post(url: string, data?: unknown, config?: AxiosLikeConfig): Promise<unknown>;\n}\n\n/** Options of {@link httpRequestorFromAxios}. */\nexport interface AxiosRequestorOptions {\n /**\n * `true`: leave axios' default status validation alone, so a 4xx/5xx REJECTS through the\n * instance's own interceptors and the SDK rethrows what the app's error handling produced.\n * `false`: every HTTP status resolves, so the SDK classifies it itself (shadow submits,\n * apply-results reads); transport failures still reject.\n */\n rejectOnHttpError: boolean;\n /**\n * Request headers NOT to hand to axios, matched case-insensitively. Default `['content-type']`:\n * axios derives `Content-Type: application/json` from the object body it is given, and an\n * interceptor may set its own, so the SDK's copy would only be a second opinion.\n */\n omitHeaders?: readonly string[] | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * An axios interceptor may resolve something that is not a response at all (for example a string\n * for ECONNREFUSED). That is a transport failure, not an HTTP answer.\n */\nfunction isAxiosLikeResponse(value: unknown): value is AxiosLikeResponse {\n return isRecord(value) && typeof value['status'] === 'number';\n}\n\nfunction readAxiosHeader(headers: unknown, name: string): string | null {\n if (!isRecord(headers)) return null;\n const getter = headers['get'];\n if (typeof getter === 'function') {\n const value: unknown = getter.call(headers, name);\n return typeof value === 'string' ? value : null;\n }\n const match = Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase());\n return typeof match?.[1] === 'string' ? match[1] : null;\n}\n\nfunction toHttpResponse(answer: unknown, url: string): HTTPResponse {\n if (!isAxiosLikeResponse(answer)) {\n throw new GSwapSDKError('TRANSPORT_ERROR', { url }, { url });\n }\n const { status, data, headers } = answer;\n return {\n ok: status >= 200 && status < 300,\n status,\n json: () => Promise.resolve(data),\n text: () => Promise.resolve(typeof data === 'string' ? data : JSON.stringify(data)),\n headers: { get: (name: string) => readAxiosHeader(headers, name) },\n };\n}\n\nfunction headersFor(\n init: RequestInit | undefined,\n omit: readonly string[],\n): Record<string, string> {\n const omitted = new Set(omit.map((name) => name.toLowerCase()));\n const raw = init?.headers;\n const entries: Array<[string, string]> =\n raw === undefined\n ? []\n : raw instanceof Headers\n ? [...raw.entries()]\n : Array.isArray(raw)\n ? raw.map(([name, value]): [string, string] => [String(name), String(value)])\n : Object.entries(raw).map(([name, value]): [string, string] => [name, String(value)]);\n return Object.fromEntries(entries.filter(([name]) => !omitted.has(name.toLowerCase())));\n}\n\n/**\n * An SDK {@link HttpRequestor} over an axios instance, so the SDK's requests travel through the\n * app's own base URL, interceptors and error handling.\n *\n * A POST's string body is parsed back to the object the SDK serialized it from (axios serializes\n * again, and an interceptor may read the object); a GET goes through `instance.get`. The answer\n * is an HTTP response whose `json()`/`text()` read `response.data`. An answer that is not an\n * axios response is a `TRANSPORT_ERROR` rejection, and so is a rejection that means no HTTP\n * answer arrived (the original error is `cause`): any rejection with `rejectOnHttpError: false`\n * (every status resolves there), an axios error without a `response` with `true`. Any other\n * rejection (an interceptor's error for a 4xx, say) is rethrown unchanged, and so is an abort.\n *\n * Pair it with `ChainGateway`'s `dexBackendBaseUrl: ''` when the instance owns the base URL.\n *\n * @example\n * ```ts\n * const submitGateway = new ChainGateway({\n * dexBackendBaseUrl: '',\n * httpRequestor: httpRequestorFromAxios(chainGatewayInstance, { rejectOnHttpError: true }),\n * });\n * ```\n */\nexport function httpRequestorFromAxios(\n instance: AxiosLikeInstance,\n options: AxiosRequestorOptions,\n): HttpRequestor {\n const omit = options.omitHeaders ?? ['content-type'];\n return async (uri, init) => {\n const signal = init?.signal ?? undefined;\n const config: AxiosLikeConfig = {\n headers: headersFor(init, omit),\n ...(signal ? { signal } : {}),\n ...(options.rejectOnHttpError ? {} : { validateStatus: () => true }),\n };\n const isPost = (init?.method ?? 'GET').toUpperCase() === 'POST';\n const body: unknown =\n isPost && typeof init?.body === 'string' ? JSON.parse(init.body) : undefined;\n let answer: unknown;\n try {\n answer = await (isPost ? instance.post(uri, body, config) : instance.get(uri, config));\n } catch (error: unknown) {\n // An abort is the caller's or the SDK's timeout, and the request layer knows which.\n if (signal?.aborted === true || !isTransportRejection(error, options.rejectOnHttpError)) {\n throw error;\n }\n throw new GSwapSDKError('TRANSPORT_ERROR', { url: uri }, { url: uri, cause: error });\n }\n return toHttpResponse(answer, uri);\n };\n}\n\n/**\n * Whether an axios rejection means no HTTP answer arrived. With `rejectOnHttpError: false` every\n * status resolves, so any rejection is one. With `true`, a 4xx/5xx rejects too, so only an axios\n * error that carries no `response` is (an interceptor's own error is an app answer and passes\n * through; an app whose interceptors turn network errors into their own class names it in\n * `ChainGatewayOptions.isTransportFailure`).\n */\nfunction isTransportRejection(error: unknown, rejectOnHttpError: boolean): boolean {\n if (!rejectOnHttpError) return true;\n return isRecord(error) && error['isAxiosError'] === true && error['response'] === undefined;\n}\n","import type { BrowserWalletProvider } from '../classes/signers.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { stripEip712DomainType } from './chain_dto_signing.js';\n\n/**\n * The part of an ethers v6 signer (`JsonRpcSigner`, `Wallet`) the adapter calls. Declared\n * structurally, so the SDK takes no dependency on ethers and an ethers object satisfies it as is.\n */\nexport interface EthersLikeSigner {\n signTypedData(\n domain: Record<string, unknown>,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>,\n ): Promise<string>;\n signMessage(message: string): Promise<string>;\n}\n\n/** The part of an ethers v6 provider (`BrowserProvider`) the adapter calls. */\nexport interface EthersLikeProvider {\n getSigner(): Promise<EthersLikeSigner>;\n /** The raw JSON-RPC passthrough (`BrowserProvider.send`). */\n send(method: string, params: unknown[]): Promise<unknown>;\n}\n\n/** Options of {@link eip1193ProviderFromEthers}. */\nexport interface EthersEip1193Options {\n /**\n * Signs a `personal_sign` message when the provider cannot or should not: a wallet SDK that\n * signs through its own object (TrustWallet's `web3Wallet.signMessage`). When set it answers\n * every `personal_sign`, and the provider is not touched for it.\n */\n personalSign?: ((message: string) => Promise<string>) | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTypedDataTypes(\n value: unknown,\n): value is Record<string, Array<{ name: string; type: string }>> {\n return (\n isRecord(value) &&\n Object.values(value).every(\n (fields) =>\n Array.isArray(fields) &&\n fields.every(\n (field) =>\n isRecord(field) &&\n typeof field['name'] === 'string' &&\n typeof field['type'] === 'string',\n ),\n )\n );\n}\n\nfunction malformed(method: string): GSwapSDKError {\n return new GSwapSDKError('MALFORMED_WALLET_REQUEST', { method });\n}\n\n/** Splits `eth_signTypedData_v4` params (`[account, JSON payload]`) into what ethers' signer takes. */\nfunction readTypedDataRequest(params: unknown[] | undefined): {\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n message: Record<string, unknown>;\n} {\n const raw = params?.[1];\n let payload: unknown;\n try {\n payload = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n throw malformed('eth_signTypedData_v4');\n }\n if (!isRecord(payload)) throw malformed('eth_signTypedData_v4');\n const { domain, types, message } = payload;\n if (!isRecord(domain) || !isTypedDataTypes(types) || !isRecord(message)) {\n throw malformed('eth_signTypedData_v4');\n }\n // ethers refuses an explicit EIP712Domain type; the JSON-RPC form includes it.\n return { domain, types: stripEip712DomainType(types), message };\n}\n\n/**\n * An EIP-1193 provider over an ethers v6 provider, for {@link BrowserWalletSigner}: apps whose\n * wallet connection is an ethers `BrowserProvider` sign through the very ethers calls they always\n * made, with no hand-written shim.\n *\n * - `eth_chainId` is `provider.send('eth_chainId', [])`: the wallet's LIVE chain. Never\n * `provider.getNetwork()`, which ethers caches and does not invalidate on `chainChanged`, so a\n * user who switches networks after connecting would sign against a stale chainId.\n * - `eth_signTypedData_v4` parses the `[account, JSON]` params and calls\n * `signer.signTypedData(domain, types, message)` with `EIP712Domain` removed from `types`.\n * - `personal_sign` is `options.personalSign(message)` when given, else `signer.signMessage`.\n * - Anything else is `UNSUPPORTED_WALLET_METHOD`; a malformed request is\n * `MALFORMED_WALLET_REQUEST`; a missing provider is `WALLET_UNAVAILABLE`.\n *\n * `provider` may be `null`/`undefined` (nothing connected): a request that needs it then fails\n * with `WALLET_UNAVAILABLE` rather than at construction, so a signer can be built before the\n * connection state is known.\n *\n * @example\n * ```ts\n * const signer = new BrowserWalletSigner(eip1193ProviderFromEthers(browserProvider), account, {\n * scheme: 'eip712',\n * });\n * ```\n */\nexport function eip1193ProviderFromEthers(\n provider: EthersLikeProvider | null | undefined,\n options: EthersEip1193Options = {},\n): BrowserWalletProvider {\n const connected = (): EthersLikeProvider => {\n if (provider === null || provider === undefined) {\n throw new GSwapSDKError('WALLET_UNAVAILABLE', {});\n }\n return provider;\n };\n return {\n request: async ({ method, params }) => {\n switch (method) {\n case 'eth_chainId':\n return connected().send('eth_chainId', []);\n case 'eth_signTypedData_v4': {\n const wallet = connected();\n const { domain, types, message } = readTypedDataRequest(params);\n return (await wallet.getSigner()).signTypedData(domain, types, message);\n }\n case 'personal_sign': {\n const message = params?.[0];\n if (typeof message !== 'string') throw malformed('personal_sign');\n if (options.personalSign !== undefined) return options.personalSign(message);\n return (await connected().getSigner()).signMessage(message);\n }\n default:\n throw new GSwapSDKError('UNSUPPORTED_WALLET_METHOD', { method });\n }\n },\n };\n}\n","import type { GSwapErrorCode } from '../classes/error_catalog.js';\nimport { toFailureView } from './failure_view.js';\n\n/**\n * Where a failed CONFIRMATION of a queued write stopped, as a closed set a screen can switch on:\n *\n * - `aborted`: the caller's own `AbortSignal` ended the wait (`CONFIRMATION_ABORTED`). The person\n * or the screen gave up waiting; the write may still land, and its `uniqueKey` is still the handle.\n * - `timeout`: the wait ran out before an apply result arrived (`CONFIRMATION_TIMEOUT`). The write\n * is still pending as far as anyone knows.\n * - `failed`: the apply-results read itself failed or answered something unusable\n * (`CONFIRMATION_FAILED`, `CONFIRMATION_MALFORMED`, `CONFIRMATION_KEY_MISMATCH`).\n *\n * All three are `unknown` to `classifyFailure`: never submit again, confirm the same key.\n */\nexport type ConfirmationState = 'aborted' | 'timeout' | 'failed';\n\n/** The state of every confirmation code (a typo is caught by the all-codes test). */\nconst STATE_OF_CODE = {\n CONFIRMATION_ABORTED: 'aborted',\n CONFIRMATION_TIMEOUT: 'timeout',\n CONFIRMATION_FAILED: 'failed',\n CONFIRMATION_MALFORMED: 'failed',\n CONFIRMATION_KEY_MISMATCH: 'failed',\n} as const satisfies Partial<Record<GSwapErrorCode, ConfirmationState>>;\n\n/**\n * The {@link ConfirmationState} of a failure, or `undefined` when it is not a failed confirmation.\n * Accepts an SDK error or a plain-object view of one (an app's wrapper with a `code`), and decides\n * from the code alone, so a screen never matches `'CONFIRMATION_ABORTED'` itself.\n *\n * @example\n * ```ts\n * switch (confirmationStateOf(error)) {\n * case 'aborted': return; // the person closed the dialog\n * case 'timeout': return showStillPending(error.uniqueKey);\n * case 'failed': return showCouldNotCheck(error.uniqueKey);\n * case undefined: return showFailure(error);\n * }\n * ```\n */\nexport function confirmationStateOf(error: unknown): ConfirmationState | undefined {\n const code = toFailureView(error)?.code;\n if (code === undefined) return undefined;\n return Object.entries(STATE_OF_CODE).find(([known]) => known === code)?.[1];\n}\n\n/** True when the wait for the apply result was ended by the caller's `AbortSignal`. */\nexport function isConfirmationAborted(error: unknown): boolean {\n return confirmationStateOf(error) === 'aborted';\n}\n\n/** True when the wait for the apply result ran out of time (`CONFIRMATION_TIMEOUT`). */\nexport function isConfirmationTimeout(error: unknown): boolean {\n return confirmationStateOf(error) === 'timeout';\n}\n","/**\n * True when a rejection of a `fetch`-based requestor means NO HTTP ANSWER ARRIVED: the network\n * failed, the connection was reset, the host did not resolve, CORS blocked it. For a write that\n * is not a refusal (the request may have been queued), so this is the default\n * `ChainGatewayOptions.isTransportFailure` for a requestor that wraps `fetch` and rejects with\n * its own errors.\n *\n * - Yes: a `TypeError` (what `fetch` rejects with in every engine: `Failed to fetch`, `Load failed`,\n * `NetworkError when attempting to fetch resource`, undici's `fetch failed`), recognised by name\n * too so one from another realm (an extension page, an iframe) still counts, and a\n * `DOMException` named `NetworkError`.\n * - No: an abort (`AbortError`) or a timeout (`TimeoutError`). The SDK's own request layer knows\n * whether its timer or the caller's signal aborted, and reports those itself\n * (`REQUEST_TIMEOUT`, or the caller's own abort unchanged); claiming them here would turn the\n * caller's cancel into \"maybe queued\".\n * - No: anything else, including an SDK error and a value that is not an object.\n *\n * It never throws.\n *\n * @example\n * ```ts\n * new ChainGateway({ dexBackendBaseUrl, httpRequestor: galaFetch, isTransportFailure: isFetchTransportFailure });\n * ```\n */\nexport function isFetchTransportFailure(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false;\n try {\n const name: unknown = 'name' in error ? error.name : undefined;\n if (name === 'AbortError' || name === 'TimeoutError') return false;\n return error instanceof TypeError || name === 'TypeError' || name === 'NetworkError';\n } catch {\n // A hostile or revoked object (a Proxy that throws on property access) proves nothing.\n return false;\n }\n}\n","/**\n * What a write's gateway answer says about the write, as one vocabulary for every app.\n *\n * The gateway answers `{ status, message, error, data }`. `data.mode` is `'sync'` for a liquidity\n * write (its executed chain result is in `data.result`) and `'queued'` for a RequestTrade\n * acknowledgement (accepted, NOT executed: the outcome is read from apply-results with\n * `confirm()`). `error: true` is the gateway refusing the write.\n *\n * A {@link SubmittedTransaction} only exists for an answer the SDK accepted, so its\n * {@link SubmitStatus} is `'executed'` or `'queued'`; a refused answer is a thrown\n * {@link GSwapSDKError}. The predicates below classify a RAW envelope instead, for an app that\n * holds one (`SubmittedTransaction.envelope`, `GSwapSDKError.body`, a stored answer) and for the\n * answers that never became a transaction. They reproduce frontend_v2's `isV2SubmitSuccess` /\n * `isV2SubmitQueued` / `isV2SubmitRejected` exactly, so the app can delete its own copies.\n */\n\n/** The state of an accepted write: executed on chain (`mode: 'sync'`) or queued (`mode: 'queued'`). */\nexport type SubmitStatus = 'executed' | 'queued';\n\n/**\n * How a raw gateway envelope classifies:\n *\n * - `'executed'`: `error === false` and `data.mode === 'sync'` (the executed result came back).\n * - `'queued'`: `error === false`, `data.mode === 'queued'` and `data.uniqueKey` is a string.\n * - `'rejected'`: no envelope at all, or `error === true`: a DEFINITE failure.\n * - `'unconfirmed'`: anything else (`error: false` with another or no `mode`, a queued answer\n * with no `uniqueKey`, an envelope with no boolean `error`): accepted, outcome not known. It is\n * NOT a rejection and must not be shown as one.\n *\n * The four are mutually exclusive and exhaustive.\n */\nexport type SubmitClassification = SubmitStatus | 'rejected' | 'unconfirmed';\n\n/** The `mode` of `envelope.data`, or `undefined` when there is no such field. */\nfunction modeOf(envelope: Record<string, unknown>): unknown {\n const data = envelope['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)['mode']\n : undefined;\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** True when the envelope is a definite failure: absent, or `error === true`. */\nexport function isSubmitRejected(envelope: unknown): boolean {\n if (!envelope) return true;\n return recordOf(envelope)?.['error'] === true;\n}\n\n/**\n * True when the envelope carries an executed result: `error === false` and `data.mode === 'sync'`.\n * A queued RequestTrade acknowledgement is deliberately NOT executed: its outcome is not known\n * until apply-results resolves.\n */\nexport function isSubmitExecuted(envelope: unknown): boolean {\n const record = recordOf(envelope);\n return record?.['error'] === false && modeOf(record) === 'sync';\n}\n\n/** True when the envelope acknowledges a `uniqueKey` as queued (`data.mode === 'queued'`). */\nexport function isSubmitQueued(envelope: unknown): boolean {\n const record = recordOf(envelope);\n if (record?.['error'] !== false || modeOf(record) !== 'queued') return false;\n return typeof recordOf(record['data'])?.['uniqueKey'] === 'string';\n}\n\n/** Classifies a raw gateway envelope; see {@link SubmitClassification}. */\nexport function classifySubmitEnvelope(envelope: unknown): SubmitClassification {\n if (isSubmitRejected(envelope)) return 'rejected';\n if (isSubmitExecuted(envelope)) return 'executed';\n if (isSubmitQueued(envelope)) return 'queued';\n return 'unconfirmed';\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["isRecord","isRecord","asRecord","malformed","BigNumber","Decimal","BigNumber","isRecord","trimTrailingSlash","asRecord","BigNumber","BigNumber","BigNumber","textEncoder","secp256k1","bytesToHex","keccak_256","globalObject","BigNumber","keccak_256","isRecord"],"sources":["../src/utils/confirmation_schedule.ts","../src/utils/server_message.ts","../src/utils/unique_key_syntax.ts","../src/utils/error_brand.ts","../src/classes/error_phases.ts","../src/utils/failure_outcomes.ts","../src/utils/failure_view.ts","../src/classes/error_phase_table.ts","../src/classes/error_catalog.ts","../src/classes/gswap_sdk_error.ts","../src/version.ts","../src/utils/transport.ts","../src/classes/apply_results.ts","../src/types/fees.ts","../src/utils/tick_range.ts","../src/utils/tick_math.ts","../src/utils/validation.ts","../src/classes/assets.ts","../src/utils/wallet_rejection.ts","../src/utils/pre_send.ts","../src/classes/dex_fees.ts","../src/utils/shadow_errors.ts","../src/classes/submitted_transaction.ts","../src/classes/gateway.ts","../src/types/env.ts","../src/utils/debug.ts","../src/utils/reconnection.ts","../src/classes/gdex_stream.ts","../src/classes/http_client.ts","../src/utils/lenient.ts","../src/utils/class_key.ts","../src/utils/ordering.ts","../src/classes/symbols.ts","../src/classes/pools.ts","../src/utils/tick_align.ts","../src/utils/ticks.ts","../src/utils/unique_key.ts","../src/utils/dto_builders.ts","../src/classes/positions.ts","../src/classes/quoting.ts","../src/classes/shadow_submit.ts","../src/classes/swaps.ts","../src/classes/gswap.ts","../src/utils/classification.ts","../src/utils/failure_classification.ts","../src/classes/pending_swap_fate.ts","../src/classes/pending_swaps.ts","../src/utils/eip712.ts","../src/utils/signing.ts","../src/classes/signers.ts","../src/classes/storage_adapters.ts","../src/utils/chain_dto_signing.ts","../src/utils/typed_data.ts","../src/utils/axios_requestor.ts","../src/utils/ethers_provider.ts","../src/utils/confirmation_state.ts","../src/utils/fetch_failure.ts","../src/utils/failure_guards.ts","../src/utils/submit_state.ts"],"sourcesContent":["import type { ConfirmOptions } from '../types/confirm_options.js';\n\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst DEFAULT_POLL_INTERVAL_MS = 2_000;\nconst MIN_POLL_INTERVAL_MS = 500;\nconst MAX_BACKOFF_MS = 8_000;\n\n/** The pacing of confirmation reads: one initial delay, then jittered exponential backoff. */\nexport interface ConfirmationSchedule {\n /**\n * Waits for the next read. Resolves `true` when the caller should read, `false` when the\n * deadline leaves no room for another read. The very first call always resolves `true` (at\n * least one read is made, even when the deadline is already past). Rejects with the abort\n * error when the caller's signal aborts, before or during the wait.\n */\n waitForRead(retryAfterMs?: number): Promise<boolean>;\n}\n\n/**\n * Builds the schedule for one `confirm()` call. `abortError` creates the error thrown when\n * `options.signal` aborts, so each confirmation kind keeps its own error type and details.\n */\nexport function createConfirmationSchedule(\n options: ConfirmOptions | undefined,\n defaultInitialDelayMs: number,\n abortError: (cause?: unknown) => Error,\n): ConfirmationSchedule {\n const timeoutMs = Math.max(0, options?.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n const pollIntervalMs = Math.max(\n MIN_POLL_INTERVAL_MS,\n options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,\n );\n const initialDelayMs = Math.max(0, options?.initialDelayMs ?? defaultInitialDelayMs);\n const signal = options?.signal;\n const deadline = Date.now() + timeoutMs;\n let firstRead = true;\n let attempt = 0;\n return {\n async waitForRead(retryAfterMs?: number): Promise<boolean> {\n throwIfAborted(signal, abortError);\n if (firstRead) {\n firstRead = false;\n const remaining = Math.max(0, deadline - Date.now());\n await delay(Math.min(initialDelayMs, remaining), signal, abortError);\n return true;\n }\n const backoff = Math.min(MAX_BACKOFF_MS, pollIntervalMs * 2 ** Math.min(attempt, 5));\n attempt += 1;\n const waitMs = retryAfterMs === undefined ? jitter(backoff) : Math.max(0, retryAfterMs);\n if (Date.now() + waitMs > deadline) return false;\n await delay(waitMs, signal, abortError);\n return true;\n },\n };\n}\n\n/** Throws `abortError(signal.reason)` when the signal has aborted. */\nexport function throwIfAborted(\n signal: AbortSignal | undefined,\n abortError: (cause?: unknown) => Error,\n): void {\n if (signal?.aborted === true) throw abortError(signal.reason);\n}\n\nfunction delay(\n milliseconds: number,\n signal: AbortSignal | undefined,\n abortError: (cause?: unknown) => Error,\n): Promise<void> {\n if (signal?.aborted === true) return Promise.reject(abortError(signal.reason));\n return new Promise((resolve, reject) => {\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(abortError(signal?.reason));\n };\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, milliseconds);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nfunction jitter(milliseconds: number): number {\n return Math.max(0, Math.round(milliseconds * (0.9 + Math.random() * 0.2)));\n}\n","import type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nfunction nonEmptyString(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const field = (value as Record<string, unknown>)[property];\n return typeof field === 'string' && field !== '' ? field : undefined;\n}\n\n/**\n * The human message a failing JSON body carries, as the server wrote it: the first non-empty\n * string of `message`, `Message`, `error.message`, `error.Message` (NestJS, the gateway filter\n * and the chain each use one of these shapes), else `''`. A body that is not JSON (an HTML 502\n * page, an empty body), or whose `message` is not a string (a validation error's list), has no\n * message. This is the single reader behind every `serverMessage` param.\n *\n * The text is DATA from the server, not SDK text: it is English, unstable, and may be empty. The\n * SDK exposes it so an app can relay it or ignore it; it is never part of `error.message`.\n */\nexport function serverMessageOfBody(body: unknown): string {\n const nested =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)['error']\n : undefined;\n return (\n nonEmptyString(body, 'message') ??\n nonEmptyString(body, 'Message') ??\n nonEmptyString(nested, 'message') ??\n nonEmptyString(nested, 'Message') ??\n ''\n );\n}\n\n/**\n * The message the server put in a failing answer: the `serverMessage` param of a code that relays\n * it, else the message of the JSON body ({@link serverMessageOfBody}). Internal: the SDK reads it\n * ONLY to classify a failure (a quote that says \"no pools\"); it is English from the server, never\n * part of the SDK's own `message`, and not exported from the package.\n */\nexport function readServerMessage(error: GSwapSDKError): string | undefined {\n const params: Readonly<Record<string, string | number | boolean>> = error.params;\n const fromParams = params['serverMessage'];\n if (typeof fromParams === 'string' && fromParams !== '') return fromParams;\n const fromBody = serverMessageOfBody(error.body);\n return fromBody === '' ? undefined : fromBody;\n}\n","/**\n * The shape of a write `uniqueKey`, with NO imports: the pending-swap store and the failure guards\n * need only this check, and importing it from `unique_key.ts` would drag in `GSwapSDKError` and the\n * whole error catalog for it.\n */\n\n/** The swap backend's apply-results key constraint (`apply-results.dto.ts`). */\nconst UNIQUE_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/u;\n\n/**\n * True when `uniqueKey` is a usable write key: 1 to 128 characters of `A-Za-z0-9._:-`, the shape\n * the apply-results route accepts. The one definition behind `assertUniqueKey`, `confirm()` and\n * the pending-swap store, so they can never disagree about what a valid key is.\n */\nexport function isValidUniqueKey(uniqueKey: unknown): uniqueKey is string {\n return typeof uniqueKey === 'string' && UNIQUE_KEY_PATTERN.test(uniqueKey);\n}\n","/**\n * The brand every `GSwapSDKError` carries, and the duck-type check for the \"failure shape\". This\n * module has NO imports on purpose: it is part of the light `@gala-chain/gswap-sdk/wallet` entry,\n * which must never pull the error catalog or the main bundle in.\n */\n\n/**\n * The brand of an SDK error: `error[GSWAP_ERROR_BRAND] === true`. It is a registered symbol\n * (`Symbol.for`), so two copies of the SDK in one page (a wallet bundle and an app bundle) still\n * recognise each other's errors, which `instanceof` cannot do.\n */\nexport const GSWAP_ERROR_BRAND: unique symbol = Symbol.for('@gala-chain/gswap-sdk/error');\n\n/** The least an object must have to be read as an SDK error or its plain-object view. */\nexport interface GSwapErrorShape {\n readonly code: string;\n readonly params: Readonly<Record<string, unknown>>;\n}\n\nfunction isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** True when `value` carries the SDK error brand (a real `GSwapSDKError`, from any copy of the SDK). */\nexport function hasGSwapErrorBrand(value: unknown): boolean {\n return isRecord(value) && value[GSWAP_ERROR_BRAND] === true;\n}\n\n/**\n * True when `value` is an SDK error (it carries the brand) or a plain-object VIEW of one: a string\n * `code` and an object `params`, which is the shape of `GSwapSDKError` and of the wrapper objects\n * an app builds from one (`{ code, params, status?, phase?, ... }`). A wallet's own error (an\n * EIP-1193 numeric `code`, an ethers error with a string `code` and no `params`) is neither. It\n * says the value has the SDK's shape, not that `code` is a code the SDK knows.\n *\n * @example\n * ```ts\n * if (isGSwapErrorLike(error)) report(error.code, error.params); // no `instanceof`, no SDK import\n * ```\n */\nexport function isGSwapErrorLike(value: unknown): value is GSwapErrorShape {\n if (hasGSwapErrorBrand(value)) return true;\n return (\n isRecord(value) &&\n typeof value['code'] === 'string' &&\n isRecord(value['params']) &&\n !Array.isArray(value['params'])\n );\n}\n","/**\n * How far an operation had got when it failed, measured against the request it exists to send:\n * for a write, the POST that carries the signed DTO to the gateway; for a read, the GET.\n *\n * - `pre_send`: NOTHING was transmitted. Everything up to the request (validation, symbol\n * resolution, the signer, the wallet, a key provider) ran and failed, so no write can have been\n * queued. A write that failed `pre_send` is never \"maybe applied\".\n * - `in_flight`: the request left (or may have left) and no answer was read: a timeout, a broken\n * connection, a stream that dropped. For a write the outcome is unknown.\n * - `post_send`: an answer was read, or the write was already accepted: a refusal, an\n * acknowledgement that proves nothing, an unusable body, and every failure of a confirmation.\n *\n * Each catalog entry declares the phase its code is thrown in; a throw site where the same code\n * can occur in another phase overrides it (`GSwapErrorContext.phase`). It is a typed property of\n * every `GSwapSDKError` (`error.phase`) and `isPreSendError(error)` reads it.\n *\n * This module has no imports, on purpose: it is the closed set of phases, shared by the catalog,\n * the light phase table (`error_phase_table.ts`) and the failure view.\n */\nexport const GSWAP_ERROR_PHASES = ['pre_send', 'in_flight', 'post_send'] as const;\n\n/** One member of {@link GSWAP_ERROR_PHASES}. */\nexport type GSwapErrorPhase = (typeof GSWAP_ERROR_PHASES)[number];\n","/**\n * What a failure means for the operation that raised it, as one vocabulary for every app.\n *\n * - `rejected`: the CHAIN refused the request (a definite no). Nothing was applied, so a NEW\n * request is safe.\n * - `unknown`: the request MAY have been applied (a timeout, a broken connection, an\n * acknowledgement that proves nothing, a failed confirmation). Never submit again under a fresh\n * key: keep `error.uniqueKey` and confirm it.\n * - `not_queued`: the gateway refused the write before queueing it. Nothing is pending.\n * - `not_sent`: the request never left (`error.phase === 'pre_send'`) for a reason outside the\n * call itself: the signer or the wallet failed (locked, unreachable, the person declined), the\n * key provider or the token resolver failed, or no key was available yet. Nothing is pending and\n * nothing was transmitted, so repeating the call is safe and may succeed once the cause (an\n * unlocked wallet) is gone.\n * - `invalid_input`: the call itself cannot work (a bad argument, a missing signer or wallet, an\n * unknown token or pool, a corrupt stored key). Repeating the same call fails the same way.\n * Such an error is also pre-send (`isPreSendError`), but the input is what has to change.\n * - `transient`: a read or connection failed with no state change. Repeating the same call is safe\n * and may succeed.\n *\n * This module has no imports: the failure view (`FailureView.outcome`) and the classifier both\n * read the closed set from here.\n */\nexport const FAILURE_OUTCOMES = [\n 'rejected',\n 'unknown',\n 'not_queued',\n 'not_sent',\n 'invalid_input',\n 'transient',\n] as const;\n\n/** One member of {@link FAILURE_OUTCOMES}. */\nexport type FailureOutcome = (typeof FAILURE_OUTCOMES)[number];\n","import { GSWAP_ERROR_PHASES, type GSwapErrorPhase } from '../classes/error_phases.js';\nimport { FAILURE_OUTCOMES, type FailureOutcome } from './failure_outcomes.js';\n\n/**\n * A failure as a PLAIN OBJECT: the facts the SDK's guards and `classifyFailure` read, and nothing\n * else. A real `GSwapSDKError` is one (every field below is on it); so is the wrapper an app makes\n * from an SDK error to carry through its own layers (frontend_v2's `V2Failure`, the wallet's\n * `WalletSwapError` data), which has a `code` and `params` but is not an `instanceof` anything the\n * SDK owns. `classifyFailure`, `isRelayableRefusal`, `isUnprovenAcknowledgement`,\n * `isUninterpretedAnswer`, `isPreSendError`, `isShadowError`, `isNoMarket` and `mayHaveBeenQueued`\n * all accept such an object wherever they accept an SDK error, and decide from the SAME fields in\n * the same way, so an app never has to keep the original error just to ask.\n *\n * Only `code` is required. A field that is missing, or has the wrong type, reads as absent: a view\n * with no `status` is not a 404. Nothing here is text: the SDK never reads `message` of a view.\n *\n * READ OR WRITE: a view is a WRITE's unless it says it is a read. This fails CLOSED on purpose:\n * a 5xx on a write may have been queued (`unknown`, no retry) and the same 5xx on a read changed\n * nothing (`transient`, retry), so a wrapper that drops its `uniqueKey` must never turn the first\n * into the second. A view is a read ONLY when it states `write: false` and has no `uniqueKey`;\n * `GSwapSDKError.write` is already set that way for every SDK read. {@link isWriteView}\n * is the one definition.\n *\n * APP ERRORS: a code the SDK catalog does not define is `unknown` (the SDK cannot say what\n * happened, and a wrong \"failed\" invites a duplicate), unless the view declares `outcome`.\n */\nexport interface FailureView {\n /** The catalog code (`'HTTP_ERROR'`, `'CHAIN_REJECTED'`, ...). A string the SDK does not know classifies as `unknown`. */\n readonly code: string;\n /** The error's flat params (`status` of an `HTTP_ERROR`, `reason` of a `SIGNING_FAILED`, ...). */\n readonly params?: Readonly<Record<string, unknown>> | undefined;\n /** The HTTP status of the answer the failure was made from. */\n readonly status?: number | undefined;\n /** How far the request got; when absent, the catalog's phase for `code`. */\n readonly phase?: GSwapErrorPhase | undefined;\n /** The `uniqueKey` of the WRITE this is about; its presence makes the failure a write's. */\n readonly uniqueKey?: string | undefined;\n /**\n * `false` says the failed call was a READ (no `uniqueKey` to confirm, nothing pending). Anything\n * else, including absent, is a write: see the note on {@link FailureView}. With a `uniqueKey`\n * the failure is a write whatever this says.\n */\n readonly write?: boolean | undefined;\n /**\n * What an error the APP raised means, for a `code` the SDK catalog does not define (`'POSITION_STALE'`,\n * `'AMOUNT_SIDE'`): `not_sent` for a step that failed before anything was signed or sent, and so\n * on. The SDK honours it ONLY for such a code: for a catalog code the SDK's own table decides, so\n * an app cannot declare a refusal the SDK knows to be unknown as safe. A non-catalog code with no\n * `outcome` stays `unknown`, and `mayHaveBeenQueued` is then `true`.\n */\n readonly outcome?: FailureOutcome | undefined;\n /**\n * WITHHOLD-ONLY: `false` takes Retry away from the declared `outcome` (an app's `DID_NOT_QUEUE`\n * is `{ outcome: 'not_queued', retryable: false }`, the SDK's `NOT_QUEUED_FINAL`). Any other\n * value, `true` included, reads as absent: a view can never GRANT Retry to an outcome that does\n * not have it, and it is read only together with `outcome`, for a code the catalog does not\n * define.\n */\n readonly retryable?: false | undefined;\n /** True when the failure came from the shadow (dark) path. */\n readonly shadow?: boolean | undefined;\n /** True for \"that market does not exist\" (`GSwapSDKError.notFound`). */\n readonly notFound?: boolean | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * Reads the failure view of any value: a `GSwapSDKError`, or a plain object with a string `code`\n * (and, optionally, `params`, `status`, `phase`, `uniqueKey`, `shadow`, `notFound`). Anything else\n * (a string, a wallet error with a numeric `code`, `null`) has no view and is `undefined`.\n *\n * Having a view does not mean the SDK knows the code: an ethers error is `{ code:\n * 'ACTION_REJECTED' }` and has a view too. The SDK's guards compare the code with the catalog.\n *\n * @example\n * ```ts\n * const view = toFailureView(error); // an SDK error, or an app's `{ code, params, status }` wrapper\n * if (view?.code === 'CHAIN_REJECTED') showChainRejection(view.params);\n * ```\n */\nexport function toFailureView(value: unknown): FailureView | undefined {\n if (!isRecord(value)) return undefined;\n const { code, params, status, phase, uniqueKey, write, outcome, retryable, shadow, notFound } =\n value;\n if (typeof code !== 'string' || code === '') return undefined;\n return {\n code,\n params: isRecord(params) && !Array.isArray(params) ? params : undefined,\n status: typeof status === 'number' && Number.isFinite(status) ? status : undefined,\n phase: GSWAP_ERROR_PHASES.find((known) => known === phase),\n uniqueKey: typeof uniqueKey === 'string' && uniqueKey !== '' ? uniqueKey : undefined,\n write: typeof write === 'boolean' ? write : undefined,\n outcome: FAILURE_OUTCOMES.find((known) => known === outcome),\n retryable: retryable === false ? false : undefined,\n shadow: typeof shadow === 'boolean' ? shadow : undefined,\n notFound: typeof notFound === 'boolean' ? notFound : undefined,\n };\n}\n\n/**\n * True when a failure is a WRITE's: it names a `uniqueKey`, or it does not say `write: false`.\n * Fail-closed (see {@link FailureView}): only an explicit read is a read.\n */\nexport function isWriteView(view: FailureView): boolean {\n return view.uniqueKey !== undefined || view.write !== false;\n}\n\n/** A param of a view, when it is a string. */\nexport function stringParamOf(view: FailureView, name: string): string | undefined {\n const value = view.params?.[name];\n return typeof value === 'string' ? value : undefined;\n}\n\n/** A param of a view, when it is a finite number. */\nexport function numberParamOf(view: FailureView, name: string): number | undefined {\n const value = view.params?.[name];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n","import type { GSWAP_ERROR_CATALOG, GSwapErrorCode } from './error_catalog.js';\nimport type { GSwapErrorPhase } from './error_phases.js';\nimport type { FailureView } from '../utils/failure_view.js';\n\n/**\n * The phase of every catalog code, WITHOUT the catalog. The failure guards (`classifyFailure`,\n * `mayHaveBeenQueued`, ...) need only a code's phase, and the catalog's English templates are\n * ~20 kB: reading the phase from here keeps an app shell that imports a guard from loading them.\n * The catalog entry is still where a code is declared; this table is checked against it AT\n * COMPILE TIME, in both directions (a missing code, an extra code or a different phase is a type\n * error), so the two cannot drift.\n */\nexport const GSWAP_ERROR_PHASE_BY_CODE = {\n HTTP_ERROR: 'post_send',\n UPDATE_REQUIRED: 'post_send',\n REQUEST_TIMEOUT: 'in_flight',\n TRANSPORT_ERROR: 'in_flight',\n REQUEST_FAILED: 'in_flight',\n INVALID_TIMEOUT: 'pre_send',\n METHOD_NOT_SUPPORTED: 'pre_send',\n SUBMISSION_OUTCOME_UNKNOWN: 'in_flight',\n GATEWAY_REPORTED_ERROR: 'post_send',\n GATEWAY_DATA_MISSING: 'post_send',\n GATEWAY_MODE_INVALID: 'post_send',\n GATEWAY_SYNC_REQUEST_TRADE: 'post_send',\n MISSING_UNIQUE_KEY: 'post_send',\n UNIQUE_KEY_MISMATCH: 'post_send',\n SHADOW_NOT_QUEUED: 'post_send',\n SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS: 'pre_send',\n METHOD_NOT_ALLOWED: 'post_send',\n SIGNATURE_INVALID: 'post_send',\n SIGNER_MISMATCH: 'post_send',\n DTO_INVALID: 'post_send',\n BOUNDS_VIOLATION: 'post_send',\n SYMBOL_CONFLICT: 'post_send',\n RATE_LIMITED: 'post_send',\n CHAIN_DISPATCH_FAILED: 'post_send',\n GATEWAY_REJECTED: 'post_send',\n CHAIN_REJECTED: 'post_send',\n INVALID_CHAIN_RESPONSE: 'post_send',\n INVALID_POSITION_RESPONSE: 'post_send',\n CONFIRMATION_TIMEOUT: 'post_send',\n CONFIRMATION_ABORTED: 'post_send',\n CONFIRMATION_FAILED: 'post_send',\n CONFIRMATION_MALFORMED: 'post_send',\n CONFIRMATION_KEY_MISMATCH: 'post_send',\n NO_SIGNER: 'pre_send',\n NO_WALLET_ADDRESS: 'post_send',\n NO_POOL_AVAILABLE: 'post_send',\n INSUFFICIENT_LIQUIDITY: 'post_send',\n UNKNOWN_TOKEN: 'pre_send',\n SYMBOL_NOT_FOUND: 'pre_send',\n STREAM_API_KEY_UNUSABLE: 'pre_send',\n STREAM_WEBSOCKET_UNAVAILABLE: 'pre_send',\n STREAM_NOT_CONNECTED: 'pre_send',\n STREAM_DISCONNECTED: 'in_flight',\n STREAM_REQUEST_TIMEOUT: 'in_flight',\n STREAM_CONNECT_FAILED: 'in_flight',\n STREAM_CLOSED_BEFORE_CONNECT: 'in_flight',\n STREAM_CONNECTION_CLOSED: 'in_flight',\n GALA_WALLET_NOT_AVAILABLE: 'pre_send',\n WALLET_UNAVAILABLE: 'pre_send',\n MALFORMED_WALLET_REQUEST: 'pre_send',\n UNSUPPORTED_WALLET_METHOD: 'pre_send',\n INVALID_SIGNATURE: 'pre_send',\n INVALID_CHAIN_ID: 'pre_send',\n SIGNER_ADDRESS_MISMATCH: 'pre_send',\n INVALID_PRIVATE_KEY: 'pre_send',\n SIGNING_FAILED: 'pre_send',\n KEY_PROVIDER_FAILED: 'pre_send',\n TOKEN_RESOLUTION_FAILED: 'pre_send',\n INVALID_SIGNING_HASH_LENGTH: 'pre_send',\n MISSING_WALLET_ADDRESS: 'pre_send',\n INVALID_WALLET_ADDRESS: 'pre_send',\n INVALID_DECIMAL: 'pre_send',\n PERSONAL_SIGN_NOT_JSON: 'pre_send',\n PERSONAL_SIGN_NOT_OBJECT: 'pre_send',\n PERSONAL_SIGN_BAD_PREFIX: 'pre_send',\n PERSONAL_SIGN_ENVELOPE_FIELDS: 'pre_send',\n PERSONAL_SIGN_NOT_CANONICAL: 'pre_send',\n EIP712_NAME_COLLISION: 'pre_send',\n EIP712_UNSUPPORTED_VALUE: 'pre_send',\n TYPED_DATA_NOT_STRING: 'pre_send',\n TYPED_DATA_UNPAIRED_SURROGATE: 'pre_send',\n TYPED_DATA_NOT_HEX_BYTES: 'pre_send',\n TYPED_DATA_NOT_SAFE_INTEGER: 'pre_send',\n TYPED_DATA_NOT_INTEGER: 'pre_send',\n TYPED_DATA_NOT_BOOLEAN: 'pre_send',\n TYPED_DATA_BAD_ADDRESS: 'pre_send',\n TYPED_DATA_BAD_CHECKSUM: 'pre_send',\n TYPED_DATA_BYTES_LENGTH: 'pre_send',\n TYPED_DATA_OUT_OF_BOUNDS: 'pre_send',\n TYPED_DATA_UNSUPPORTED_TYPE: 'pre_send',\n TYPED_DATA_FIELDS_NOT_LIST: 'pre_send',\n TYPED_DATA_FIELD_MALFORMED: 'pre_send',\n TYPED_DATA_INVALID_FIELD_NAME: 'pre_send',\n TYPED_DATA_DUPLICATE_FIELD: 'pre_send',\n TYPED_DATA_INVALID_TYPE_NAME: 'pre_send',\n TYPED_DATA_CIRCULAR_TYPE: 'pre_send',\n TYPED_DATA_UNKNOWN_FIELD_TYPE: 'pre_send',\n TYPED_DATA_NO_PRIMARY_TYPE: 'pre_send',\n TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE: 'pre_send',\n TYPED_DATA_ARRAY_EXPECTED: 'pre_send',\n TYPED_DATA_ARRAY_LENGTH_MISMATCH: 'pre_send',\n TYPED_DATA_STRUCT_NOT_OBJECT: 'pre_send',\n TYPED_DATA_MISSING_FIELD: 'pre_send',\n TYPED_DATA_DOMAIN_NOT_OBJECT: 'pre_send',\n TYPED_DATA_INVALID_DOMAIN_KEY: 'pre_send',\n NON_CANONICAL_PAIR: 'pre_send',\n UNORDERABLE_SYMBOLS: 'pre_send',\n INVALID_TOKEN_CLASS_KEY: 'pre_send',\n INCOMPLETE_TOKEN_CLASS_KEY: 'pre_send',\n INVALID_TRADING_SYMBOL: 'pre_send',\n NO_VALID_TRADING_SYMBOL: 'pre_send',\n TOKEN_SYMBOL_NOT_REGISTERED: 'pre_send',\n SYMBOL_DISAGREES_WITH_REGISTRY: 'pre_send',\n CREATE_POOL_NEEDS_CLASS_KEY: 'pre_send',\n INVALID_UNIQUE_KEY: 'pre_send',\n INVALID_UNIQUE_KEY_PREFIX: 'pre_send',\n AMOUNT_IS_JS_NUMBER: 'pre_send',\n AMOUNT_NOT_FINITE: 'pre_send',\n AMOUNT_NOT_POSITIVE: 'pre_send',\n AMOUNT_NEGATIVE: 'pre_send',\n PRICE_VALUES_IS_JS_NUMBER: 'pre_send',\n INVALID_PRICE_VALUES: 'pre_send',\n INVALID_PRICE_RANGE: 'pre_send',\n INVALID_PRICE_BOUNDS: 'pre_send',\n PRICE_BOUNDS_ORDER: 'pre_send',\n INVALID_STARTING_PRICE: 'pre_send',\n INVALID_SQRT_PRICE: 'pre_send',\n INVALID_TOKEN_DECIMALS: 'pre_send',\n TICKS_NOT_INTEGERS: 'pre_send',\n INVALID_TICK_RANGE: 'pre_send',\n TICKS_OUT_OF_BOUNDS: 'pre_send',\n TICKS_NOT_ALIGNED: 'pre_send',\n INVALID_TICK_SPACING: 'pre_send',\n INVALID_FEE: 'pre_send',\n EXACT_AMOUNT_REQUIRED: 'pre_send',\n EXACTLY_ONE_OF_REQUIRED: 'pre_send',\n AT_MOST_ONE_OF_ALLOWED: 'pre_send',\n POOL_MISMATCH: 'pre_send',\n INVALID_DTO: 'pre_send',\n DTO_NOT_CANONICAL: 'pre_send',\n SEARCH_TOO_LONG: 'pre_send',\n INVALID_SORT_BY: 'pre_send',\n INVALID_SORT_ORDER: 'pre_send',\n INVALID_PAGE: 'pre_send',\n INVALID_LIMIT: 'pre_send',\n} as const satisfies {\n readonly [C in GSwapErrorCode]: (typeof GSWAP_ERROR_CATALOG)[C]['phase'];\n};\n\n/** True for a code the SDK catalog defines. */\nexport function isCatalogCode(code: string): code is GSwapErrorCode {\n return Object.hasOwn(GSWAP_ERROR_PHASE_BY_CODE, code);\n}\n\n/** The phase of a view: the one it states, else the catalog's phase for its code, else `undefined`. */\nexport function phaseOfView(view: FailureView): GSwapErrorPhase | undefined {\n if (view.phase !== undefined) return view.phase;\n return isCatalogCode(view.code) ? GSWAP_ERROR_PHASE_BY_CODE[view.code] : undefined;\n}\n","/**\n * The catalog of every error the SDK throws: the SINGLE source of truth for its `code`, the\n * named parameters it carries and the English template its `message` is generated from.\n *\n * - `code` is the only discriminator. It is stable: apps branch on it, never on message text.\n * - `params` are the named placeholders of the error: a flat object of primitives (string,\n * number, boolean) that an app feeds to its own localization (i18next, ICU, FormatJS).\n * Raw server payloads are never params (they are `error.body` / `error.bodyText`), and no\n * secret (private key, signature, raw DTO) ever is.\n * - `template` is English with `{placeholder}` markers. `error.message` is generated from it\n * and the params, so the two cannot drift. It is for logs and developers: it is not stable and\n * must not be shown to users or matched on.\n *\n * Every placeholder in a template is a declared param and every declared param is a placeholder,\n * except the few `unrendered` params that carry server text for the app and are kept out of\n * `message` on purpose (pinned by tests/error_catalog.test.ts). Facts that are not placeholders (HTTP status, URL,\n * `uniqueKey`, transaction ids, the raw body, the cause) are typed properties of the error, see\n * {@link GSwapErrorContext}.\n */\n\nimport type { GSwapErrorPhase } from './error_phases.js';\n\n/**\n * The kinds a param can have: a primitive, or a CLOSED set of string tokens (a readonly tuple).\n * A closed set is a documented union: an app maps each member to its own text and can check that\n * it covered all of them, and a new member is a compile error until it does.\n */\nexport type GSwapErrorParamKind = 'string' | 'number' | 'boolean' | readonly string[];\n\n/** One catalog entry. */\nexport interface GSwapErrorCatalogEntry {\n /** The phase this code is thrown in, unless a throw site says otherwise (see {@link GSwapErrorPhase}). */\n readonly phase: GSwapErrorPhase;\n /** English message template with `{placeholder}` markers. */\n readonly template: string;\n /** Param name to kind. Every param is required and appears in the template, except `unrendered`. */\n readonly params: Readonly<Record<string, GSwapErrorParamKind>>;\n /**\n * Params that are carried for the app but deliberately NOT placeholders of the template. Used\n * for `serverMessage` on the codes whose failing answer may be anything (a proxy's page, a\n * validation list): the server's text is data for the app to relay or ignore, and keeping it out\n * of `message` means it cannot reach a log line or a user interface by accident.\n */\n readonly unrendered?: readonly string[];\n}\n\n/**\n * Why a private key was refused (`INVALID_PRIVATE_KEY.params.reason`). A token for the app to map\n * to its own text, never English and never any part of the key.\n *\n * - `wrong_length`: raw bytes that are not 32 bytes long.\n * - `bad_encoding`: a string that is neither 64 hex characters (optionally `0x`-prefixed, 63 is\n * left-padded) nor a 44-character base64 string.\n * - `not_on_curve`: 32 bytes that are not a valid secp256k1 secret scalar.\n * - `no_key_provided`: a lazy key provider returned something that is not a string.\n */\nexport const INVALID_PRIVATE_KEY_REASONS = [\n 'wrong_length',\n 'bad_encoding',\n 'not_on_curve',\n 'no_key_provided',\n] as const;\n\n/** One member of {@link INVALID_PRIVATE_KEY_REASONS}. */\nexport type InvalidPrivateKeyReason = (typeof INVALID_PRIVATE_KEY_REASONS)[number];\n\n/**\n * Why the outcome of a write submission is unknown (`SUBMISSION_OUTCOME_UNKNOWN.params.reason`).\n * Both say the same thing about the swap (it MAY have been queued: never resubmit under a fresh\n * key, confirm `error.uniqueKey` instead) and differ only in what happened to the request.\n *\n * - `timeout`: the POST exceeded the gateway's timeout; the request may still be running.\n * - `transport`: the POST failed before an HTTP answer was read (offline, connection reset, DNS,\n * CORS, a body that broke off). The bytes may have reached the server and been queued, so this\n * does NOT prove the swap was not sent.\n */\nexport const SUBMISSION_OUTCOME_UNKNOWN_REASONS = ['timeout', 'transport'] as const;\n\n/** One member of {@link SUBMISSION_OUTCOME_UNKNOWN_REASONS}. */\nexport type SubmissionOutcomeUnknownReason = (typeof SUBMISSION_OUTCOME_UNKNOWN_REASONS)[number];\n\n/**\n * Why a signer could not produce a signature (`SIGNING_FAILED.params.reason`). A token for the\n * app to map to its own text.\n *\n * - `user_rejected`: the person declined in their wallet (an EIP-1193 `4001`, an ethers\n * `ACTION_REJECTED`, or a wallet that words it \"User rejected/denied ...\"). Nothing is wrong:\n * they may simply try again.\n * - `failed`: anything else the signer threw (a locked wallet, an unreachable extension, a wallet\n * that refused). The original error is `cause`.\n */\nexport const SIGNING_FAILURE_REASONS = ['user_rejected', 'failed'] as const;\n\n/** One member of {@link SIGNING_FAILURE_REASONS}. */\nexport type SigningFailureReason = (typeof SIGNING_FAILURE_REASONS)[number];\n\n/** The fee tiers as they appear in `INVALID_FEE.allowed`. */\nexport const ALLOWED_FEE_TIERS_TEXT = '0,500,3000,10000';\n\n/** The whole catalog. Add a code here before throwing it anywhere. */\nexport const GSWAP_ERROR_CATALOG = {\n // ---------------------------------------------------------------------------------- transport\n HTTP_ERROR: {\n phase: 'post_send',\n template: 'Unexpected HTTP error {status} from {url}.',\n params: { status: 'number', url: 'string', serverMessage: 'string' },\n unrendered: ['serverMessage'],\n },\n UPDATE_REQUIRED: {\n phase: 'post_send',\n template:\n 'The backend refused this app version and requires an update (HTTP {status}); nothing was queued.',\n params: { status: 'number' },\n },\n REQUEST_TIMEOUT: {\n phase: 'in_flight',\n template: 'Request to {url} timed out after {timeoutMs} ms.',\n params: { url: 'string', timeoutMs: 'number' },\n },\n TRANSPORT_ERROR: {\n phase: 'in_flight',\n template: 'The request to {url} failed before the server answered.',\n params: { url: 'string' },\n },\n REQUEST_FAILED: {\n phase: 'in_flight',\n template: 'The {operation} request failed.',\n params: { operation: 'string' },\n },\n INVALID_TIMEOUT: {\n phase: 'pre_send',\n template:\n '{field} must be a positive number of milliseconds, or Infinity for no timeout (got {value}).',\n params: { field: 'string', value: 'number' },\n },\n\n // ----------------------------------------------------------------------------------- gateway\n METHOD_NOT_SUPPORTED: {\n phase: 'pre_send',\n template: 'The method {method} is not supported; swaps are queued through RequestTrade.',\n params: { method: 'string' },\n },\n SUBMISSION_OUTCOME_UNKNOWN: {\n phase: 'in_flight',\n template:\n 'The submission outcome is unknown ({reason}): the request may have reached the gateway. Confirm before retrying.',\n params: { reason: SUBMISSION_OUTCOME_UNKNOWN_REASONS },\n },\n GATEWAY_REPORTED_ERROR: {\n phase: 'post_send',\n template: 'The gateway reported an error for this write: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n GATEWAY_DATA_MISSING: {\n phase: 'post_send',\n template: 'The gateway response is missing its data object.',\n params: {},\n },\n GATEWAY_MODE_INVALID: {\n phase: 'post_send',\n template:\n 'Gateway response must contain data.mode=\"sync\" with data.result, or data.mode=\"queued\".',\n params: {},\n },\n GATEWAY_SYNC_REQUEST_TRADE: {\n phase: 'post_send',\n template:\n 'The gateway executed RequestTrade synchronously, which this SDK refuses; RequestTrade must be queued.',\n params: {},\n },\n MISSING_UNIQUE_KEY: {\n phase: 'post_send',\n template:\n 'The gateway acknowledged RequestTrade without echoing its uniqueKey, so it cannot be tied to the signed request.',\n params: {},\n },\n UNIQUE_KEY_MISMATCH: {\n phase: 'post_send',\n template: 'Gateway response data.uniqueKey must match the signed RequestTrade uniqueKey.',\n params: {},\n },\n SHADOW_NOT_QUEUED: {\n phase: 'post_send',\n template: 'The swap backend did not queue the shadow request.',\n params: {},\n },\n SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS: {\n phase: 'pre_send',\n template:\n 'A shadow submission needs a walletAddress (the X-Wallet-Address header): pass one to the GSwap constructor or to this call.',\n params: {},\n },\n METHOD_NOT_ALLOWED: {\n phase: 'post_send',\n template: 'The gateway does not expose this contract method: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SIGNATURE_INVALID: {\n phase: 'post_send',\n template: 'The gateway could not verify the signature: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SIGNER_MISMATCH: {\n phase: 'post_send',\n template:\n 'The recovered signer does not match an actor named by the operation: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n DTO_INVALID: {\n phase: 'post_send',\n template: 'The gateway rejected the DTO shape: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n BOUNDS_VIOLATION: {\n phase: 'post_send',\n template: 'The gateway rejected a numeric, tick, symbol or range bound: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n SYMBOL_CONFLICT: {\n phase: 'post_send',\n template: 'The CreatePool symbol is already owned by another class: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n RATE_LIMITED: {\n phase: 'post_send',\n template: 'The gateway rate-limited this signer: {serverMessage}',\n params: { serverMessage: 'string' },\n },\n CHAIN_DISPATCH_FAILED: {\n phase: 'post_send',\n template: 'The chain dispatch failed (chain error key \"{errorKey}\"): {serverMessage}',\n params: { errorKey: 'string', serverMessage: 'string' },\n },\n GATEWAY_REJECTED: {\n phase: 'post_send',\n template: 'Gateway rejected {gatewayCode}: {serverMessage}',\n params: { gatewayCode: 'string', serverMessage: 'string' },\n },\n CHAIN_REJECTED: {\n phase: 'post_send',\n template: 'GalaChain error {errorKey}: {serverMessage}',\n params: { errorKey: 'string', serverMessage: 'string' },\n },\n INVALID_CHAIN_RESPONSE: {\n phase: 'post_send',\n template: 'Backend returned an invalid {resource}.',\n params: { resource: 'string' },\n },\n INVALID_POSITION_RESPONSE: {\n phase: 'post_send',\n template: 'Backend returned an invalid position ({reason}).',\n params: { reason: 'string' },\n },\n\n // -------------------------------------------------------------------------------- confirmation\n CONFIRMATION_TIMEOUT: {\n phase: 'post_send',\n template:\n 'Transaction confirmation timed out; the trade may still apply. Confirm the same uniqueKey again later instead of resubmitting.',\n params: {},\n },\n CONFIRMATION_ABORTED: {\n phase: 'post_send',\n template: 'Transaction confirmation was aborted.',\n params: {},\n },\n CONFIRMATION_FAILED: {\n phase: 'post_send',\n template: 'Transaction confirmation failed with HTTP {status}.',\n params: { status: 'number', serverMessage: 'string' },\n unrendered: ['serverMessage'],\n },\n CONFIRMATION_MALFORMED: {\n phase: 'post_send',\n template: 'Transaction confirmation returned a malformed body.',\n params: {},\n },\n CONFIRMATION_KEY_MISMATCH: {\n phase: 'post_send',\n template: 'Apply result key did not match the requested key.',\n params: {},\n },\n\n // ----------------------------------------------------------------------------------- services\n NO_SIGNER: {\n phase: 'pre_send',\n template: 'This method requires a signer. Please provide a signer to the GSwap constructor.',\n params: {},\n },\n NO_WALLET_ADDRESS: {\n phase: 'post_send',\n template:\n 'Cannot confirm this write: no walletAddress was provided to the GSwap constructor, so the resulting position cannot be looked up to confirm it landed on chain.',\n params: {},\n },\n NO_POOL_AVAILABLE: {\n phase: 'post_send',\n template: 'No pool is available for {tokenIn}/{tokenOut} (fee tier {fee}).',\n params: { tokenIn: 'string', tokenOut: 'string', fee: 'string' },\n },\n INSUFFICIENT_LIQUIDITY: {\n phase: 'post_send',\n template:\n 'The selected pool has insufficient liquidity for {tokenIn}/{tokenOut} (fee tier {fee}).',\n params: { tokenIn: 'string', tokenOut: 'string', fee: 'string' },\n },\n UNKNOWN_TOKEN: {\n phase: 'pre_send',\n template: 'Token {token} is not registered on the DEX contract: it has no trading symbol.',\n params: { token: 'string' },\n },\n SYMBOL_NOT_FOUND: {\n phase: 'pre_send',\n template: 'Token {token} could not be resolved to a trading symbol.',\n params: { token: 'string' },\n },\n STREAM_API_KEY_UNUSABLE: {\n phase: 'pre_send',\n template:\n 'GdexStreamConfig.apiKey needs a non-empty key and an explicit webSocketImpl that accepts upgrade headers as its third argument (the \"ws\" package, or React Native). A browser WebSocket cannot send x-api-key, so the key would be silently dropped.',\n params: {},\n },\n STREAM_WEBSOCKET_UNAVAILABLE: {\n phase: 'pre_send',\n template:\n 'GdexStreamService requires a standards-compatible WebSocket constructor. Node.js versions before 22 must provide one with config.webSocketImpl (for example, from the \"ws\" package).',\n params: {},\n },\n STREAM_NOT_CONNECTED: {\n phase: 'pre_send',\n template: 'GDEX stream is not connected. Call connect() first.',\n params: {},\n },\n STREAM_DISCONNECTED: {\n phase: 'in_flight',\n template: 'GDEX stream disconnected.',\n params: {},\n },\n STREAM_REQUEST_TIMEOUT: {\n phase: 'in_flight',\n template: 'GDEX request \"{method}\" timed out after {timeoutMs} ms.',\n params: { method: 'string', timeoutMs: 'number' },\n },\n STREAM_CONNECT_FAILED: {\n phase: 'in_flight',\n template: 'Failed to connect to GDEX stream at {url}.',\n params: { url: 'string' },\n },\n STREAM_CLOSED_BEFORE_CONNECT: {\n phase: 'in_flight',\n template: 'GDEX stream closed before connecting (code {closeCode}).',\n params: { closeCode: 'number' },\n },\n STREAM_CONNECTION_CLOSED: {\n phase: 'in_flight',\n template: 'GDEX stream connection closed (code {closeCode}).',\n params: { closeCode: 'number' },\n },\n\n // ------------------------------------------------------------------------------ wallet / keys\n GALA_WALLET_NOT_AVAILABLE: {\n phase: 'pre_send',\n template: 'Gala wallet is not available. Please ensure the Gala wallet is connected.',\n params: {},\n },\n WALLET_UNAVAILABLE: {\n phase: 'pre_send',\n template: 'No wallet is connected.',\n params: {},\n },\n MALFORMED_WALLET_REQUEST: {\n phase: 'pre_send',\n template: 'Wallet {method} request is malformed.',\n params: { method: 'string' },\n },\n UNSUPPORTED_WALLET_METHOD: {\n phase: 'pre_send',\n template: 'Unsupported wallet method {method}.',\n params: { method: 'string' },\n },\n INVALID_SIGNATURE: {\n phase: 'pre_send',\n template: 'Wallet returned an invalid {scheme} signature.',\n params: { scheme: 'string' },\n },\n INVALID_CHAIN_ID: {\n phase: 'pre_send',\n template: 'Wallet returned an invalid chain id ({chainId}).',\n params: { chainId: 'string' },\n },\n SIGNER_ADDRESS_MISMATCH: {\n phase: 'pre_send',\n template: 'The signing key does not belong to the expected account.',\n params: {},\n },\n INVALID_PRIVATE_KEY: {\n phase: 'pre_send',\n template: 'Invalid private key: {reason}.',\n params: { reason: INVALID_PRIVATE_KEY_REASONS },\n },\n SIGNING_FAILED: {\n phase: 'pre_send',\n template: 'Signing the {method} request failed ({reason}); nothing was sent.',\n params: { method: 'string', reason: SIGNING_FAILURE_REASONS },\n },\n KEY_PROVIDER_FAILED: {\n phase: 'pre_send',\n template: 'The signing key could not be fetched; nothing was sent.',\n params: {},\n },\n TOKEN_RESOLUTION_FAILED: {\n phase: 'pre_send',\n template: 'Token {token} could not be looked up; nothing was sent.',\n params: { token: 'string' },\n },\n INVALID_SIGNING_HASH_LENGTH: {\n phase: 'pre_send',\n template: 'secp256k1 can only sign a 32-byte hash (got {length}).',\n params: { length: 'number' },\n },\n MISSING_WALLET_ADDRESS: {\n phase: 'pre_send',\n template:\n 'Invalid wallet address: No wallet address provided. Either provide a wallet address to the function you are calling, or set one when instantiating GSwapSDK.',\n params: {},\n },\n INVALID_WALLET_ADDRESS: {\n phase: 'pre_send',\n template: 'Invalid {field}: \"{value}\" is not an accepted wallet address form.',\n params: { field: 'string', value: 'string' },\n },\n INVALID_DECIMAL: {\n phase: 'pre_send',\n template: 'Invalid decimal quantity: {value}',\n params: { value: 'string' },\n },\n\n // ------------------------------------------------------------------------- personal-sign DTOs\n PERSONAL_SIGN_NOT_JSON: {\n phase: 'pre_send',\n template: 'Personal-sign DTO is not valid JSON',\n params: {},\n },\n PERSONAL_SIGN_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Personal-sign DTO must be a JSON object',\n params: {},\n },\n PERSONAL_SIGN_BAD_PREFIX: {\n phase: 'pre_send',\n template: 'Personal-sign DTO prefix is not an EIP-191 \"Ethereum Signed Message\" header',\n params: {},\n },\n PERSONAL_SIGN_ENVELOPE_FIELDS: {\n phase: 'pre_send',\n template: 'Personal-sign DTO carries signing-envelope field(s): {fields}',\n params: { fields: 'string' },\n },\n PERSONAL_SIGN_NOT_CANONICAL: {\n phase: 'pre_send',\n template: 'Personal-sign DTO is not in canonical serialized form',\n params: {},\n },\n\n // ------------------------------------------------------------------ EIP-712 payload derivation\n EIP712_NAME_COLLISION: {\n phase: 'pre_send',\n template: 'Name collisions are not supported when deriving EIP-712 types ({name}).',\n params: { name: 'string' },\n },\n EIP712_UNSUPPORTED_VALUE: {\n phase: 'pre_send',\n template: 'Unsupported EIP-712 value of type {valueType}.',\n params: { valueType: 'string' },\n },\n\n // ----------------------------------------------------------------------------- EIP-712 typed data\n TYPED_DATA_NOT_STRING: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be a string',\n params: { what: 'string' },\n },\n TYPED_DATA_UNPAIRED_SURROGATE: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} has an unpaired surrogate',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_HEX_BYTES: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be an even-length 0x hex string',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_SAFE_INTEGER: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be a safe integer',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_INTEGER: {\n phase: 'pre_send',\n template: 'Invalid typed data: {what} must be an integer',\n params: { what: 'string' },\n },\n TYPED_DATA_NOT_BOOLEAN: {\n phase: 'pre_send',\n template: 'Invalid typed data: bool must be a boolean',\n params: {},\n },\n TYPED_DATA_BAD_ADDRESS: {\n phase: 'pre_send',\n template: 'Invalid typed data: address must be 0x followed by 40 hex digits',\n params: {},\n },\n TYPED_DATA_BAD_CHECKSUM: {\n phase: 'pre_send',\n template: 'Invalid typed data: address has a bad checksum',\n params: {},\n },\n TYPED_DATA_BYTES_LENGTH: {\n phase: 'pre_send',\n template: 'Invalid typed data: {type} must be exactly {width} bytes',\n params: { type: 'string', width: 'number' },\n },\n TYPED_DATA_OUT_OF_BOUNDS: {\n phase: 'pre_send',\n template: 'Invalid typed data: value out of bounds for {type}',\n params: { type: 'string' },\n },\n TYPED_DATA_UNSUPPORTED_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: unsupported type \"{type}\"',\n params: { type: 'string' },\n },\n TYPED_DATA_FIELDS_NOT_LIST: {\n phase: 'pre_send',\n template: 'Invalid typed data: type {typeName} must be a list of fields',\n params: { typeName: 'string' },\n },\n TYPED_DATA_FIELD_MALFORMED: {\n phase: 'pre_send',\n template: 'Invalid typed data: type {typeName} has a field without a string name and type',\n params: { typeName: 'string' },\n },\n TYPED_DATA_INVALID_FIELD_NAME: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid field name \"{name}\"',\n params: { name: 'string' },\n },\n TYPED_DATA_DUPLICATE_FIELD: {\n phase: 'pre_send',\n template: 'Invalid typed data: duplicate field \"{name}\" in {typeName}',\n params: { name: 'string', typeName: 'string' },\n },\n TYPED_DATA_INVALID_TYPE_NAME: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid type name \"{name}\"',\n params: { name: 'string' },\n },\n TYPED_DATA_CIRCULAR_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: circular type reference in {typeName}',\n params: { typeName: 'string' },\n },\n TYPED_DATA_UNKNOWN_FIELD_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: unknown type \"{type}\" in {typeName}',\n params: { type: 'string', typeName: 'string' },\n },\n TYPED_DATA_NO_PRIMARY_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: missing primary type',\n params: {},\n },\n TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE: {\n phase: 'pre_send',\n template: 'Invalid typed data: ambiguous primary types or unused types ({roots})',\n params: { roots: 'string' },\n },\n TYPED_DATA_ARRAY_EXPECTED: {\n phase: 'pre_send',\n template: 'Invalid typed data: {type} array value must be an array',\n params: { type: 'string' },\n },\n TYPED_DATA_ARRAY_LENGTH_MISMATCH: {\n phase: 'pre_send',\n template: 'Invalid typed data: array length mismatch',\n params: {},\n },\n TYPED_DATA_STRUCT_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Invalid typed data: {typeName} value must be an object',\n params: { typeName: 'string' },\n },\n TYPED_DATA_MISSING_FIELD: {\n phase: 'pre_send',\n template: 'Invalid typed data: {typeName} value is missing field \"{field}\"',\n params: { typeName: 'string', field: 'string' },\n },\n TYPED_DATA_DOMAIN_NOT_OBJECT: {\n phase: 'pre_send',\n template: 'Invalid typed data: domain must be an object',\n params: {},\n },\n TYPED_DATA_INVALID_DOMAIN_KEY: {\n phase: 'pre_send',\n template: 'Invalid typed data: invalid typed-data domain key {key}',\n params: { key: 'string' },\n },\n\n // ------------------------------------------------------------------------ input validation\n NON_CANONICAL_PAIR: {\n phase: 'pre_send',\n template:\n 'The pair {token0}/{token1} is not in canonical order: token0 must sort before token1.',\n params: { token0: 'string', token1: 'string' },\n },\n UNORDERABLE_SYMBOLS: {\n phase: 'pre_send',\n template: 'Unable to order trading symbols: expected a pair of symbols, got {received}.',\n params: { received: 'string' },\n },\n INVALID_TOKEN_CLASS_KEY: {\n phase: 'pre_send',\n template:\n 'Invalid token class key \"{tokenClassKey}\": expected a collection followed by category, type and additionalKey',\n params: { tokenClassKey: 'string' },\n },\n INCOMPLETE_TOKEN_CLASS_KEY: {\n phase: 'pre_send',\n template: 'Token class key \"{compositeKey}\" is missing {part}.',\n params: { compositeKey: 'string', part: 'string' },\n },\n INVALID_TRADING_SYMBOL: {\n phase: 'pre_send',\n template:\n 'Invalid trading symbol \"{symbol}\": must be 1-32 ASCII letters and digits and not a reserved word (Token, Unit, none).',\n params: { symbol: 'string' },\n },\n NO_VALID_TRADING_SYMBOL: {\n phase: 'pre_send',\n template:\n 'No valid trading symbol for token class {classKey}: \"{displaySymbol}\" is not an acceptable symbol and none is registered',\n params: { classKey: 'string', displaySymbol: 'string' },\n },\n TOKEN_SYMBOL_NOT_REGISTERED: {\n phase: 'pre_send',\n template:\n 'Token {token} is not registered in the trading-symbol registry yet; pass token0Symbol/token1Symbol (the token class symbol) to propose one. A symbol cannot be derived from a class key.',\n params: { token: 'string' },\n },\n SYMBOL_DISAGREES_WITH_REGISTRY: {\n phase: 'pre_send',\n template:\n 'Supplied symbol {suppliedSymbol} for {token} disagrees with the registered trading symbol {registeredSymbol}.',\n params: { token: 'string', suppliedSymbol: 'string', registeredSymbol: 'string' },\n },\n CREATE_POOL_NEEDS_CLASS_KEY: {\n phase: 'pre_send',\n template:\n 'createPool needs each token as a class key; {token} is a bare trading symbol, which does not carry one.',\n params: { token: 'string' },\n },\n INVALID_UNIQUE_KEY: {\n phase: 'pre_send',\n template:\n 'The uniqueKey \"{uniqueKey}\" must be 1-128 characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n params: { uniqueKey: 'string' },\n },\n INVALID_UNIQUE_KEY_PREFIX: {\n phase: 'pre_send',\n template:\n 'uniqueKeyPrefix \"{uniqueKeyPrefix}\" must be at most {maxLength} characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n params: { uniqueKeyPrefix: 'string', maxLength: 'number' },\n },\n AMOUNT_IS_JS_NUMBER: {\n phase: 'pre_send',\n template: 'Invalid {field}: use a decimal string or BigNumber, not a JavaScript number',\n params: { field: 'string' },\n },\n AMOUNT_NOT_FINITE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be a finite number (got {value})',\n params: { field: 'string', value: 'string' },\n },\n AMOUNT_NOT_POSITIVE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be positive (got {value})',\n params: { field: 'string', value: 'string' },\n },\n AMOUNT_NEGATIVE: {\n phase: 'pre_send',\n template: 'Invalid {field}: must not be negative (got {value})',\n params: { field: 'string', value: 'string' },\n },\n PRICE_VALUES_IS_JS_NUMBER: {\n phase: 'pre_send',\n template:\n 'Invalid price values: use decimal strings or BigNumber values, not JavaScript numbers',\n params: {},\n },\n INVALID_PRICE_VALUES: {\n phase: 'pre_send',\n template:\n 'Invalid price values: all prices must be finite and positive (spot {spotPrice}, lower {lowerPrice}, upper {upperPrice})',\n params: { spotPrice: 'string', lowerPrice: 'string', upperPrice: 'string' },\n },\n INVALID_PRICE_RANGE: {\n phase: 'pre_send',\n template:\n 'Invalid price range: lower price {lowerPrice} must be less than or equal to upper price {upperPrice}',\n params: { lowerPrice: 'string', upperPrice: 'string' },\n },\n INVALID_PRICE_BOUNDS: {\n phase: 'pre_send',\n template:\n 'Price bounds must be finite and positive (minPrice {minPrice}, maxPrice {maxPrice}).',\n params: { minPrice: 'string', maxPrice: 'string' },\n },\n PRICE_BOUNDS_ORDER: {\n phase: 'pre_send',\n template: 'minPrice {minPrice} must be less than or equal to maxPrice {maxPrice}.',\n params: { minPrice: 'string', maxPrice: 'string' },\n },\n INVALID_STARTING_PRICE: {\n phase: 'pre_send',\n template: 'Starting price must be finite and positive (got {value}).',\n params: { value: 'string' },\n },\n INVALID_SQRT_PRICE: {\n phase: 'pre_send',\n template: 'Cannot invert a non-positive sqrt price ({sqrtPrice}).',\n params: { sqrtPrice: 'string' },\n },\n INVALID_TOKEN_DECIMALS: {\n phase: 'pre_send',\n template: 'Invalid {field}: must be a non-negative integer (got {value})',\n params: { field: 'string', value: 'number' },\n },\n TICKS_NOT_INTEGERS: {\n phase: 'pre_send',\n template: 'Invalid tick values: ticks must be integers (got {tickLower} and {tickUpper})',\n params: { tickLower: 'number', tickUpper: 'number' },\n },\n INVALID_TICK_RANGE: {\n phase: 'pre_send',\n template: 'Invalid tick range: tickLower {tickLower} must be less than tickUpper {tickUpper}',\n params: { tickLower: 'number', tickUpper: 'number' },\n },\n TICKS_OUT_OF_BOUNDS: {\n phase: 'pre_send',\n template:\n 'Invalid tick range: ticks {tickLower} and {tickUpper} must be between {minTick} and {maxTick}',\n params: { tickLower: 'number', tickUpper: 'number', minTick: 'number', maxTick: 'number' },\n },\n TICKS_NOT_ALIGNED: {\n phase: 'pre_send',\n template: 'Ticks {tickLower} and {tickUpper} must be aligned to spacing {spacing}.',\n params: { tickLower: 'number', tickUpper: 'number', spacing: 'number' },\n },\n INVALID_TICK_SPACING: {\n phase: 'pre_send',\n template: 'Invalid tick spacing: must be a positive integer (got {value})',\n params: { value: 'number' },\n },\n INVALID_FEE: {\n phase: 'pre_send',\n template: 'Invalid {field}: {value} is not a supported fee tier; must be one of {allowed}.',\n params: { field: 'string', value: 'number', allowed: 'string' },\n },\n EXACT_AMOUNT_REQUIRED: {\n phase: 'pre_send',\n template: '{field} is required for this swap.',\n params: { field: 'string' },\n },\n EXACTLY_ONE_OF_REQUIRED: {\n phase: 'pre_send',\n template: 'Provide exactly one of {first} or {second}.',\n params: { first: 'string', second: 'string' },\n },\n AT_MOST_ONE_OF_ALLOWED: {\n phase: 'pre_send',\n template: 'Provide at most one of {first} or {second}.',\n params: { first: 'string', second: 'string' },\n },\n POOL_MISMATCH: {\n phase: 'pre_send',\n template:\n 'tokenIn {tokenIn} and tokenOut {tokenOut} must be the two tokens of the pinned pool {poolToken0}/{poolToken1}.',\n params: {\n tokenIn: 'string',\n tokenOut: 'string',\n poolToken0: 'string',\n poolToken1: 'string',\n },\n },\n INVALID_DTO: {\n phase: 'pre_send',\n template: '{method} DTO field {field} is invalid (expected {expected}).',\n params: { method: 'string', field: 'string', expected: 'string' },\n },\n DTO_NOT_CANONICAL: {\n phase: 'pre_send',\n template:\n 'The {method} DTO is not in the form the SDK builders produce; build it with the matching build function and submit that.',\n params: { method: 'string' },\n },\n SEARCH_TOO_LONG: {\n phase: 'pre_send',\n template: 'search must be at most {maxLength} characters (got {length}).',\n params: { length: 'number', maxLength: 'number' },\n },\n INVALID_SORT_BY: {\n phase: 'pre_send',\n template: 'sortBy \"{value}\" is not allowed; it must be one of {allowed}.',\n params: { value: 'string', allowed: 'string' },\n },\n INVALID_SORT_ORDER: {\n phase: 'pre_send',\n template: 'sortOrder \"{value}\" is not allowed; it must be asc or desc.',\n params: { value: 'string' },\n },\n INVALID_PAGE: {\n phase: 'pre_send',\n template: 'page must be an integer of at least 1 (got {value}).',\n params: { value: 'number' },\n },\n INVALID_LIMIT: {\n phase: 'pre_send',\n template: 'limit must be an integer from {min} to {max} (got {value}).',\n params: { value: 'number', min: 'number', max: 'number' },\n },\n} as const satisfies Record<string, GSwapErrorCatalogEntry>;\n\n/** Every error code the SDK can throw. */\nexport type GSwapErrorCode = keyof typeof GSWAP_ERROR_CATALOG;\n\ninterface KindToType {\n string: string;\n number: number;\n boolean: boolean;\n}\n\n/** The value type of a param kind: a primitive, or the union of a closed set's members. */\ntype ParamValue<K> = K extends readonly (infer Member)[]\n ? Member\n : K extends keyof KindToType\n ? KindToType[K]\n : never;\n\n/** The named params of one error code: a flat object of primitives (or closed string tokens). */\nexport type GSwapErrorParams<C extends GSwapErrorCode> = {\n readonly [P in keyof (typeof GSWAP_ERROR_CATALOG)[C]['params']]: ParamValue<\n (typeof GSWAP_ERROR_CATALOG)[C]['params'][P]\n >;\n};\n\n/**\n * The English template of every error code, `{placeholder}` markers included. An optional seed\n * or fallback for an app's own translations; the SDK's `message` is generated from it.\n */\nexport const gswapErrorTemplates: { readonly [C in GSwapErrorCode]: string } = Object.fromEntries(\n Object.entries(GSWAP_ERROR_CATALOG).map(([code, entry]) => [code, entry.template]),\n) as { readonly [C in GSwapErrorCode]: string };\n\nconst PLACEHOLDER = /\\{([A-Za-z0-9_]+)\\}/gu;\n\n/** Fills a template's `{placeholders}` from `params`; an unknown placeholder is left as written. */\nexport function renderGSwapErrorTemplate(\n template: string,\n params: Readonly<Record<string, unknown>>,\n): string {\n return template.replace(PLACEHOLDER, (whole, name: string) => {\n const value = params[name];\n return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean'\n ? String(value)\n : whole;\n });\n}\n\n/** The placeholder names a template uses, in order of first appearance. */\nexport function templatePlaceholders(template: string): string[] {\n return [...new Set([...template.matchAll(PLACEHOLDER)].map((match) => match[1] as string))];\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { HTTPResponse } from '../types/http_requestor.js';\nimport { GSWAP_ERROR_BRAND } from '../utils/error_brand.js';\nimport { toFailureView } from '../utils/failure_view.js';\nimport { phaseOfView } from './error_phase_table.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport {\n GSWAP_ERROR_CATALOG,\n renderGSwapErrorTemplate,\n type GSwapErrorCode,\n type GSwapErrorParams,\n} from './error_catalog.js';\nimport type { GSwapErrorPhase } from './error_phases.js';\n\n/**\n * The HTTP status of a version wall: the backend refuses an app version that is too old (HTTP 426\n * Upgrade Required). It is `UPDATE_REQUIRED` on every request the SDK sends, whatever else the body\n * says; a confirmation read keeps `CONFIRMATION_FAILED` because the write it confirms may be applied.\n */\nexport const UPDATE_REQUIRED_STATUS = 426;\n\n/**\n * The facts of an error that are not placeholders of its message: where it happened and what the\n * server said. All optional; none is localized text.\n */\nexport interface GSwapErrorContext {\n /** The HTTP status of the response that caused the error. */\n status?: number | undefined;\n /**\n * The response body: parsed JSON when the failing response had it, else the raw text (which\n * the error then exposes as {@link GSwapSDKError.bodyText}).\n */\n body?: unknown;\n /** The URL the failing request went to. */\n url?: string | undefined;\n /** The `uniqueKey` of the write this error is about: the handle for `confirm()` and recovery. */\n uniqueKey?: string | undefined;\n /** The transaction id of the queued request, `null` when unknown. */\n requestTransactionId?: string | null | undefined;\n /** The transaction id of the apply, `null` when unknown. */\n applyTransactionId?: string | null | undefined;\n /** The block the apply landed in, `null` when unknown. */\n blockNumber?: number | null | undefined;\n /** How long to wait before retrying, from the server's `Retry-After`. */\n retryAfterMs?: number | undefined;\n /** The error that caused this one (a transport failure, a wallet rejection). */\n cause?: unknown;\n /**\n * The phase of THIS occurrence when it differs from the code's catalog phase (see\n * {@link GSwapErrorPhase}): for example `UNKNOWN_TOKEN` is `pre_send` from the symbol registry\n * but `post_send` when it is derived from a quote answer.\n */\n phase?: GSwapErrorPhase | undefined;\n /** True when the failing operation was on the shadow (dark) path; see {@link GSwapSDKError.shadow}. */\n shadow?: boolean | undefined;\n /**\n * `false` for the failure of a READ (see {@link GSwapSDKError.write}); anything else, including\n * absent, is a write (fail-closed). Ignored when `uniqueKey` is set: that is a write.\n */\n write?: boolean | undefined;\n /** The wallet's own code on the error a signer threw; see {@link GSwapSDKError.walletCode}. */\n walletCode?: number | string | undefined;\n}\n\n/** What {@link GSwapSDKError.fromStatus} may be told about the HTTP answer. */\nexport interface GSwapStatusErrorOptions {\n /** The URL the request went to. */\n url?: string | undefined;\n /** The signed `uniqueKey` of the WRITE the answer is for; its presence makes this a write. */\n uniqueKey?: string | undefined;\n /** Say it outright: `true` for a write (needs `uniqueKey`), `false` for a read. */\n write?: boolean | undefined;\n /** The server's own text, for `HTTP_ERROR.params.serverMessage` (`''` when none). */\n serverMessage?: string | undefined;\n /** The response body, kept as `error.body` (or `bodyText` for a string). */\n body?: unknown;\n /** How long the server asked to wait (`Retry-After`), in milliseconds. */\n retryAfterMs?: number | undefined;\n}\n\n/**\n * Error raised by the SDK for validation, gateway, chain, or transaction failures.\n *\n * Branch on {@link code} (stable) and render {@link params} through your own localization.\n * {@link message} is English generated from the catalog template for logs and developers: it\n * is not stable and must never be shown to a user or matched on.\n */\nexport class GSwapSDKError<C extends GSwapErrorCode = GSwapErrorCode> extends Error {\n /** The stable, machine-readable code. */\n public readonly code: C;\n /** The named placeholders of the error: a flat object of primitives, safe to localize with. */\n public readonly params: GSwapErrorParams<C>;\n /** The server's `Retry-After` in milliseconds (a `RATE_LIMITED` answer), when it sent one. */\n public readonly retryAfterMs: number | undefined;\n /** The HTTP status of the response that caused this error, when there was one. */\n public readonly status: number | undefined;\n /**\n * The response body parsed as JSON, when the failing response had one; `undefined` for a body\n * that was not JSON (see {@link bodyText}). Never part of {@link message}.\n */\n public readonly body: unknown;\n /**\n * The raw text of a failing response whose body was NOT JSON (a proxy's HTML 502, a WAF page,\n * an empty body). It is kept here for diagnostics and is never copied into {@link message},\n * so it cannot reach a user interface by accident.\n */\n public readonly bodyText: string | undefined;\n /** The URL the failing request went to, when there was one. */\n public readonly url: string | undefined;\n /** The `uniqueKey` of the write this error is about, when there is one. */\n public readonly uniqueKey: string | undefined;\n /** The transaction id of the queued request, when known. */\n public readonly requestTransactionId: string | null | undefined;\n /** The transaction id of the apply, when known. */\n public readonly applyTransactionId: string | null | undefined;\n /** The block the apply landed in, when known. */\n public readonly blockNumber: number | null | undefined;\n /**\n * How far the operation had got when this was thrown, against the request it exists to send\n * (see {@link GSwapErrorPhase}): `pre_send` means NOTHING was transmitted, so a write that\n * failed this way cannot have been queued; `in_flight` means the request left and no answer was\n * read; `post_send` means an answer was read or the write was already accepted. Every catalog\n * code declares its phase, and a throw site can refine it. Read it with\n * {@link isPreSendError}; `classifyFailure` already folds it into `outcome` and `retryable`.\n */\n public readonly phase: GSwapErrorPhase;\n /**\n * True when this error came from the shadow (dark) path: `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`, whatever failed there (a validation error, the signer, the\n * transport, `SHADOW_NOT_QUEUED`). The classification is the same as on the public path; this\n * is how an app applies its own dark-swap policy (the wallet and frontend_v2 never offer a\n * public fallback or Retry after one). A shadow gateway refusal that RESOLVES (`{ ok: false }`)\n * is not an error and has no flag: the call itself says it was shadow.\n */\n public readonly shadow: boolean;\n /**\n * Whether this failure is a WRITE's, as the guards read it: `false` only for the failure of a\n * READ (a quote, a pool list, an apply-results read), which has no `uniqueKey` to confirm and\n * nothing pending, so a 5xx there is `transient` and retryable. It is `true` for everything else,\n * and always when {@link uniqueKey} is set. That is fail-closed: a failure that does not say it\n * is a read is judged a write, where a 5xx is `unknown` and never retried. Apps that carry an\n * error through their own wrapper copy this field next to `uniqueKey` (`FailureView.write`).\n */\n public readonly write: boolean;\n /**\n * On `SIGNING_FAILED`: the code the wallet put on the error its signer threw, when it set one: an\n * EIP-1193 / JSON-RPC number such as `4001` (the person declined) or `-32603`, or an ethers /\n * viem string such as `'ACTION_REJECTED'`. It is read from the `cause`'s own `code` and is\n * always a short primitive; `undefined` when the wallet sent none, and on every other code. It is\n * a typed field, not a param: it is data for an app's analytics or its own wallet-specific\n * wording, never part of `message`, and `params.reason` stays the stable thing to branch on.\n */\n public readonly walletCode: number | string | undefined;\n\n constructor(code: C, params: GSwapErrorParams<C>, context: GSwapErrorContext = {}) {\n super(\n renderGSwapErrorTemplate(GSWAP_ERROR_CATALOG[code].template, params),\n context.cause === undefined ? undefined : { cause: context.cause },\n );\n this.name = 'GSwapSDKError';\n this.code = code;\n this.params = params;\n this.retryAfterMs = context.retryAfterMs;\n this.status = context.status;\n this.body = typeof context.body === 'string' ? undefined : context.body;\n this.bodyText = typeof context.body === 'string' ? context.body : undefined;\n this.url = context.url;\n this.uniqueKey = context.uniqueKey;\n this.requestTransactionId = context.requestTransactionId;\n this.applyTransactionId = context.applyTransactionId;\n this.blockNumber = context.blockNumber;\n this.phase = context.phase ?? GSWAP_ERROR_CATALOG[code].phase;\n this.shadow = context.shadow ?? false;\n this.write =\n context.uniqueKey !== undefined && context.uniqueKey !== '' ? true : context.write !== false;\n this.walletCode = context.walletCode;\n }\n\n /**\n * The SDK error brand (`Symbol.for('@gala-chain/gswap-sdk/error')`), always `true`. The\n * dependency-free helpers (`isWalletUserRejection`, `isGSwapErrorLike`) recognise an SDK error\n * by it instead of `instanceof`, so they work across copies of the SDK and without importing\n * this class. It lives on the prototype: it is not an own property and is never copied or logged.\n */\n public get [GSWAP_ERROR_BRAND](): true {\n return true;\n }\n\n /**\n * True when the failure means \"that market, pool or position does not exist\" rather than\n * \"something went wrong\": an HTTP 404, a pair with no pool at any fee tier\n * (`NO_POOL_AVAILABLE`), or a token the DEX contract has no trading symbol for\n * (`UNKNOWN_TOKEN`). A pool that exists but is too thin (`INSUFFICIENT_LIQUIDITY`) is NOT\n * not-found.\n */\n public get notFound(): boolean {\n return (\n this.status === 404 || this.code === 'NO_POOL_AVAILABLE' || this.code === 'UNKNOWN_TOKEN'\n );\n }\n\n /** Create the standard missing-signer error. */\n public static noSignerError(): GSwapSDKError<'NO_SIGNER'> {\n return new GSwapSDKError('NO_SIGNER', {});\n }\n\n /** Create the error used when confirming a position write without a configured wallet address. */\n public static noWalletAddressError(): GSwapSDKError<'NO_WALLET_ADDRESS'> {\n return new GSwapSDKError('NO_WALLET_ADDRESS', {});\n }\n\n /**\n * Create the error used when no pool can quote the requested pair. `source` is the backend\n * answer that said so; its status and body are kept.\n */\n public static noPoolAvailableError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n source?: GSwapSDKError,\n ): GSwapSDKError<'NO_POOL_AVAILABLE'> {\n return new GSwapSDKError(\n 'NO_POOL_AVAILABLE',\n { tokenIn: tokenText(tokenIn), tokenOut: tokenText(tokenOut), fee: feeText(fee) },\n sourceContext(source),\n );\n }\n\n /** Create the error used when a pool lacks liquidity for a quote. `source` as for {@link noPoolAvailableError}. */\n public static insufficientLiquidityError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n source?: GSwapSDKError,\n ): GSwapSDKError<'INSUFFICIENT_LIQUIDITY'> {\n return new GSwapSDKError(\n 'INSUFFICIENT_LIQUIDITY',\n { tokenIn: tokenText(tokenIn), tokenOut: tokenText(tokenOut), fee: feeText(fee) },\n sourceContext(source),\n );\n }\n\n /**\n * Convert a chain-gateway bounce into a typed SDK error: the gateway's own code when the SDK\n * knows it, `GATEWAY_REJECTED` (with the code as `params.gatewayCode`) when it does not.\n * `serverMessage` is the gateway's English text: for logs, not for a user interface. For\n * `CHAIN_DISPATCH_FAILED`, `params.errorKey` is the chain's `ErrorKey` from the body's\n * top-level `errorKey` (`''` when the gateway sent none): map it, not the text.\n */\n public static fromGatewayBounce(\n gatewayCode: string,\n serverMessage: string,\n status: number,\n body: unknown,\n url: string,\n retryAfterMs?: number,\n uniqueKey?: string,\n ): GSwapSDKError {\n const context: GSwapErrorContext = { status, body, url, retryAfterMs, uniqueKey };\n const params = { serverMessage };\n switch (gatewayCode) {\n case 'METHOD_NOT_ALLOWED':\n return new GSwapSDKError('METHOD_NOT_ALLOWED', params, context);\n case 'SIGNATURE_INVALID':\n return new GSwapSDKError('SIGNATURE_INVALID', params, context);\n case 'SIGNER_MISMATCH':\n return new GSwapSDKError('SIGNER_MISMATCH', params, context);\n case 'DTO_INVALID':\n return new GSwapSDKError('DTO_INVALID', params, context);\n case 'BOUNDS_VIOLATION':\n return new GSwapSDKError('BOUNDS_VIOLATION', params, context);\n case 'SYMBOL_CONFLICT':\n return new GSwapSDKError('SYMBOL_CONFLICT', params, context);\n case 'RATE_LIMITED':\n return new GSwapSDKError('RATE_LIMITED', params, context);\n case 'CHAIN_DISPATCH_FAILED':\n // The gateway adds the chain's own machine-readable key as a top-level `errorKey`, only\n // when the chain supplied one; an older gateway sends none, which is the empty string.\n return new GSwapSDKError(\n 'CHAIN_DISPATCH_FAILED',\n { ...params, errorKey: getStringProperty(body, 'errorKey') ?? '' },\n context,\n );\n default:\n return new GSwapSDKError('GATEWAY_REJECTED', { gatewayCode, serverMessage }, context);\n }\n }\n\n /** Convert a GalaChain `Status: 0` response into a typed SDK error. */\n public static fromChainError(\n errorKey: string,\n serverMessage: string,\n context?: GSwapErrorContext,\n ): GSwapSDKError<'CHAIN_REJECTED'> {\n return new GSwapSDKError('CHAIN_REJECTED', { errorKey, serverMessage }, context);\n }\n\n /**\n * Create the error used when a token is not registered by the current DEX contract. `source` is\n * the backend answer that said so (a quote); its status, body and url are kept.\n */\n public static unknownTokenError(\n token: GalaChainTokenClassKey | string,\n source?: GSwapSDKError,\n ): GSwapSDKError<'UNKNOWN_TOKEN'> {\n return new GSwapSDKError('UNKNOWN_TOKEN', { token: tokenText(token) }, sourceContext(source));\n }\n\n /** Create the error used when apply-results confirmation does not arrive in time. */\n public static confirmationTimeoutError(\n uniqueKey: string,\n cause?: unknown,\n ): GSwapSDKError<'CONFIRMATION_TIMEOUT'> {\n return new GSwapSDKError('CONFIRMATION_TIMEOUT', {}, { uniqueKey, cause });\n }\n\n /**\n * Builds, synchronously, the error the SDK itself throws for an HTTP answer of this `status`\n * that has no gateway or chain code: `UPDATE_REQUIRED` for the version wall (426, whatever\n * else is true), `HTTP_ERROR` for every other status. It is for an app that holds a resolved\n * HTTP answer the SDK did not read (a v1 endpoint, an interceptor's rejection) and wants the\n * SDK's classification of it (`classifyFailure`) instead of building the error by hand.\n *\n * Reads and writes differ exactly as they do in the gateway (`classifyFailure`): a WRITE\n * carries the signed `uniqueKey` (the handle to confirm it), a READ carries none. Pass\n * `uniqueKey` for a write, or `write: true` with it; `write: false` builds a read and drops any\n * `uniqueKey`. `write: true` without a non-empty `uniqueKey` throws `INVALID_UNIQUE_KEY`: a\n * write error with no key would be classified as a read, which is a different answer. Either\n * way an answer was read, so the phase is `post_send`.\n *\n * @example\n * ```ts\n * const read = GSwapSDKError.fromStatus(503, { url });\n * classifyFailure(read); // { outcome: 'transient', retryable: true }\n * const write = GSwapSDKError.fromStatus(503, { url, uniqueKey });\n * classifyFailure(write); // { outcome: 'unknown', retryable: false }: it may have been queued\n * classifyFailure(GSwapSDKError.fromStatus(426)); // invalid_input: only an update helps\n * ```\n */\n public static fromStatus(\n status: number,\n options: GSwapStatusErrorOptions = {},\n ): GSwapSDKError<'UPDATE_REQUIRED' | 'HTTP_ERROR'> {\n const { url, uniqueKey, write, serverMessage, body, retryAfterMs } = options;\n const isWrite = write ?? (uniqueKey !== undefined && uniqueKey !== '');\n if (isWrite && (uniqueKey === undefined || uniqueKey === '')) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY', { uniqueKey: uniqueKey ?? '' });\n }\n const context: GSwapErrorContext = {\n status,\n body,\n url,\n retryAfterMs,\n uniqueKey: isWrite ? uniqueKey : undefined,\n write: isWrite,\n phase: 'post_send',\n };\n return status === UPDATE_REQUIRED_STATUS\n ? new GSwapSDKError('UPDATE_REQUIRED', { status }, context)\n : new GSwapSDKError(\n 'HTTP_ERROR',\n { status, url: url ?? '', serverMessage: serverMessage ?? '' },\n context,\n );\n }\n\n /** Convert an unexpected HTTP response into an SDK error. */\n public static async fromErrorResponse(\n url: string,\n response: HTTPResponse,\n ): Promise<GSwapSDKError> {\n const bodyText = await response.text();\n const bodyJson: unknown = parseJson(bodyText);\n const errorObject = getObjectProperty(bodyJson, 'error');\n const errorKey = getStringProperty(errorObject, 'ErrorKey');\n const message = getStringProperty(errorObject, 'Message');\n // Every request that goes through `HttpClient` is a READ (a quote, a list, an apply-results\n // GET); writes go through the gateway, which builds its own errors with the signed key.\n const context: GSwapErrorContext = {\n status: response.status,\n body: bodyJson ?? bodyText,\n url,\n write: false,\n };\n\n if (response.status === UPDATE_REQUIRED_STATUS) {\n return new GSwapSDKError('UPDATE_REQUIRED', { status: response.status }, context);\n }\n\n if (errorKey !== undefined && message !== undefined) {\n return new GSwapSDKError('CHAIN_REJECTED', { errorKey, serverMessage: message }, context);\n }\n\n return new GSwapSDKError(\n 'HTTP_ERROR',\n { status: response.status, url, serverMessage: serverMessageOfBody(bodyJson) },\n context,\n );\n }\n}\n\n/** A token as the text a param carries: a string as is, a class key as its `$` composite. */\nfunction tokenText(token: GalaChainTokenClassKey | string): string {\n return typeof token === 'string'\n ? token\n : [token.collection, token.category, token.type, token.additionalKey].join('$');\n}\n\nfunction feeText(fee: number | undefined): string {\n return fee === undefined ? 'any' : String(fee);\n}\n\n/**\n * The HTTP facts of the error a classified error was derived from. An error derived from a\n * backend answer is `post_send`: the answer was read.\n */\nfunction sourceContext(source: GSwapSDKError | undefined): GSwapErrorContext {\n if (source === undefined) return {};\n return {\n status: source.status,\n body: source.body ?? source.bodyText,\n url: source.url,\n phase: 'post_send',\n write: source.write,\n };\n}\n\n/** Any thrown value that is an SDK error, narrowed to the union of every code. */\nexport type AnyGSwapError = { [C in GSwapErrorCode]: GSwapSDKError<C> }[GSwapErrorCode];\n\n/**\n * True when `value` is an SDK error and, when `code` is given, carries exactly that code. With a\n * code, `error.params` narrows to that code's params.\n *\n * @example\n * ```ts\n * if (isGSwapError(error, 'NON_CANONICAL_PAIR')) {\n * t('errors.NON_CANONICAL_PAIR', error.params); // { token0, token1 }\n * }\n * ```\n */\nexport function isGSwapError(value: unknown): value is AnyGSwapError;\nexport function isGSwapError<C extends GSwapErrorCode>(\n value: unknown,\n code: C,\n): value is GSwapSDKError<C>;\nexport function isGSwapError(value: unknown, code?: GSwapErrorCode): boolean {\n return value instanceof GSwapSDKError && (code === undefined || value.code === code);\n}\n\n/**\n * True when `value` is an SDK error that was thrown BEFORE anything was transmitted\n * (`error.phase === 'pre_send'`): validation, symbol resolution, the signer, the wallet, a key\n * provider. A write that failed this way cannot have been queued, so the failure never calls for\n * \"confirm before you retry\". Every failure of an app-supplied callback that runs BEFORE the\n * request leaves reaches you as an SDK error of this kind (`SIGNING_FAILED`,\n * `KEY_PROVIDER_FAILED`, `TOKEN_RESOLUTION_FAILED`, the original error as `cause`), so an app\n * never needs an error class of its own to tell \"nothing was sent\" apart.\n *\n * Whether to offer Retry is `classifyFailure(error).retryable`, not this: a pre-send validation\n * error is pre-send too, and repeating the same call fails the same way.\n *\n * It also answers for a plain-object view of an SDK error (`{ code, phase? }`, see\n * `FailureView`): the view's own `phase`, else the catalog's phase for its `code`. It is a plain\n * `boolean`, not a type guard (a view is not a `GSwapSDKError`); use `isGSwapError` to narrow.\n *\n * @example\n * ```ts\n * if (isPreSendError(error)) markNothingSent(); // no pending swap to confirm\n * ```\n */\nexport function isPreSendError(value: unknown): boolean {\n const view = toFailureView(value);\n return view !== undefined && phaseOfView(view) === 'pre_send';\n}\n\n/** Narrow an object property without trusting a cast at a network boundary. */\nexport function getObjectProperty(\n value: unknown,\n property: string,\n): Record<string, unknown> | undefined {\n if (typeof value !== 'object' || value === null || !(property in value)) return undefined;\n const propertyValue = (value as Record<string, unknown>)[property];\n return typeof propertyValue === 'object' && propertyValue !== null\n ? (propertyValue as Record<string, unknown>)\n : undefined;\n}\n\n/** Read a string property from an unknown object. */\nexport function getStringProperty(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null || !(property in value)) return undefined;\n const propertyValue = (value as Record<string, unknown>)[property];\n return typeof propertyValue === 'string' ? propertyValue : undefined;\n}\n\n/** Parse a response body, preserving non-JSON text for error reporting. */\nexport function parseJson(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return undefined;\n }\n}\n","declare const __GSWAP_SDK_VERSION__: string | undefined;\n\n/** Package version embedded by the bundler, with a source-test fallback. */\nexport const SDK_VERSION =\n typeof __GSWAP_SDK_VERSION__ === 'string' ? __GSWAP_SDK_VERSION__ : '1.2.0';\n","import type { HTTPResponse, HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { GSwapSDKError, parseJson } from '../classes/gswap_sdk_error.js';\nimport { SDK_VERSION } from '../version.js';\n\n/**\n * Arms the abort timer for a request. `Infinity` means \"never time out\": `setTimeout` would turn\n * it into 1 ms, so no timer is armed at all. Returns a function that disarms it.\n */\nexport function armTimeout(controller: AbortController, timeoutMs: number): () => void {\n if (timeoutMs === Infinity) return () => undefined;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n return () => clearTimeout(timer);\n}\n\n/**\n * Validates a request timeout in milliseconds: a positive finite number, or `Infinity` for none.\n *\n * @throws GSwapSDKError `INVALID_TIMEOUT` (`params.field` = `name`) otherwise.\n */\nexport function validateTimeoutMs(timeoutMs: number, name: string): number {\n if (timeoutMs === Infinity || (Number.isFinite(timeoutMs) && timeoutMs > 0)) return timeoutMs;\n throw new GSwapSDKError('INVALID_TIMEOUT', { field: name, value: timeoutMs });\n}\n\nconst READABLE_QUERY_SAFE = /[A-Za-z0-9\\-._~!'()*$|:,]/u;\n\nfunction encodeReadable(text: string): string {\n let out = '';\n for (const char of text) {\n if (char === ' ') out += '+';\n else if (READABLE_QUERY_SAFE.test(char)) out += char;\n else out += encodeScalar(char);\n }\n return out;\n}\n\n/** Percent-encodes one code point; a lone surrogate becomes U+FFFD, as `URLSearchParams` does. */\nfunction encodeScalar(char: string): string {\n try {\n return encodeURIComponent(char);\n } catch {\n return '%EF%BF%BD';\n }\n}\n\n/** Serializes GET parameters, in insertion order, in the encoding the wire options select. */\nexport function buildQueryString(\n params: Record<string, string>,\n encoding: WireOptions['queryEncoding'] = 'standard',\n): string {\n if (encoding === 'readable') {\n return Object.entries(params)\n .map(([key, value]) => `${encodeReadable(key)}=${encodeReadable(value)}`)\n .join('&');\n }\n return new URLSearchParams(params).toString();\n}\n\n/** What an SDK request adds to the headers the wire options describe. */\nexport interface RequestHeaderParts {\n /** The request carries a JSON body: `Content-Type: application/json` unless `wire.headers` sets one. */\n json?: boolean | undefined;\n /** Headers the SDK sends unless `wire.headers` replaces them (for example `Accept`). */\n defaults?: Record<string, string> | undefined;\n /**\n * Headers that carry the request's meaning (`X-Wallet-Address`, `X-Shadow`). They come last and\n * replace a same-named `wire.headers` entry, so an app's static headers can never re-attribute\n * or un-shadow a write.\n */\n fixed?: Record<string, string> | undefined;\n}\n\n/**\n * The request headers for ANY SDK request, GET or POST, from one place so the wire options reach\n * every request alike. Order, which is the order the requestor sees them in: `User-Agent`\n * (`wire.userAgent`, default `GalaChain-SDK/<version>`, `false` omits it), `parts.defaults`,\n * `wire.headers`, `Content-Type` (JSON bodies only), `parts.fixed`. A later entry replaces an\n * earlier one of the same name regardless of case, so a header is never sent twice.\n */\nexport function buildRequestHeaders(\n wire: WireOptions | undefined,\n parts: RequestHeaderParts = {},\n): Record<string, string> {\n const entries = new Map<string, [name: string, value: string]>();\n const put = (headers: Record<string, string> | undefined, last = false): void => {\n for (const [name, value] of Object.entries(headers ?? {})) {\n // A fixed header leaves any earlier same-named entry behind, so it also keeps its place at the end.\n if (last) entries.delete(name.toLowerCase());\n entries.set(name.toLowerCase(), [name, value]);\n }\n };\n if (wire?.userAgent !== false) {\n put({ 'User-Agent': wire?.userAgent ?? `GalaChain-SDK/${SDK_VERSION}` });\n }\n put(parts.defaults);\n put(wire?.headers);\n if (parts.json === true && !entries.has('content-type')) {\n put({ 'Content-Type': 'application/json' });\n }\n put(parts.fixed, true);\n return Object.fromEntries(entries.values());\n}\n\n/**\n * The default requestor: the global `fetch`, with a failure before any answer (offline, DNS,\n * CORS) coded as `TRANSPORT_ERROR` and the original error kept as `cause`. An aborted request is\n * left to {@link requestWithTimeout}, which knows whether the timeout or the caller aborted it.\n * A requestor the app supplies is not wrapped: its rejection reaches the caller unchanged.\n */\nexport const fetchRequestor: HttpRequestor = async (url, init) => {\n try {\n return await fetch(url, init);\n } catch (error: unknown) {\n if (init?.signal?.aborted === true) throw error;\n throw new GSwapSDKError('TRANSPORT_ERROR', { url }, { url, cause: error });\n }\n};\n\nexport async function requestWithTimeout(\n requestor: HttpRequestor,\n url: string,\n options: RequestInit,\n timeoutMs: number,\n): Promise<HTTPResponse> {\n const controller = new AbortController();\n const disarm = armTimeout(controller, timeoutMs);\n const externalSignal = options.signal;\n const abortFromCaller = (): void => controller.abort();\n externalSignal?.addEventListener('abort', abortFromCaller, { once: true });\n try {\n return await requestor(url, { ...options, signal: controller.signal });\n } catch (error: unknown) {\n // The caller's own abort is theirs: it passes through as the abort it is, never as a timeout.\n if (externalSignal?.aborted === true) throw error;\n if (controller.signal.aborted) {\n throw new GSwapSDKError('REQUEST_TIMEOUT', { url, timeoutMs }, { url, cause: error });\n }\n // Anything else is the requestor's own rejection (an app's axios interceptor error, say):\n // rethrown as it is, because the app's error handling produced it.\n throw error;\n } finally {\n disarm();\n externalSignal?.removeEventListener('abort', abortFromCaller);\n }\n}\n\nexport async function readResponseBody(response: HTTPResponse): Promise<unknown> {\n const text = await response.text();\n return parseJson(text) ?? text;\n}\n\n/** Read a case-insensitive response header from either supported header shape. */\nexport function readHeader(response: HTTPResponse, name: string): string | undefined {\n const headers = response.headers;\n if (headers === undefined) return undefined;\n if (hasHeaderGetter(headers)) {\n const value = headers.get(name);\n return value === null || value === '' ? undefined : value;\n }\n const value = Object.entries(headers).find(\n ([key]) => key.toLowerCase() === name.toLowerCase(),\n )?.[1];\n return value === undefined || value === '' ? undefined : value;\n}\n\n/** Read a Retry-After header (delta-seconds or an HTTP date) as non-negative milliseconds. */\nexport function readRetryAfter(response: HTTPResponse): number | undefined {\n const raw = readHeader(response, 'retry-after');\n if (raw === undefined) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const timestamp = Date.parse(raw);\n return Number.isNaN(timestamp) ? undefined : Math.max(0, timestamp - Date.now());\n}\n\n/** Read a non-negative integer block number header. */\nexport function readBlockNumberHeader(\n response: HTTPResponse,\n headerName = 'x-block-number',\n): number | undefined {\n const raw = readHeader(response, headerName);\n if (raw === undefined) return undefined;\n const blockNumber = Number(raw);\n return Number.isInteger(blockNumber) && blockNumber >= 0 ? blockNumber : undefined;\n}\n\nfunction hasHeaderGetter(\n headers: NonNullable<HTTPResponse['headers']>,\n): headers is { get(name: string): string | null } {\n return 'get' in headers && typeof headers.get === 'function';\n}\n","import type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport type { AppliedTrade, TradeExecution } from '../types/v2_results.js';\nimport { createConfirmationSchedule, throwIfAborted } from '../utils/confirmation_schedule.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport { isValidUniqueKey } from '../utils/unique_key_syntax.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n} from '../utils/transport.js';\nimport type { GSwapErrorCode, GSwapErrorParams } from './error_catalog.js';\nimport { getStringProperty, GSwapSDKError, type GSwapErrorContext } from './gswap_sdk_error.js';\n\n/**\n * The AutoApplier waits at least 2 s before applying and the apply lands ~6-8 s after the\n * acknowledgement, so a read at t=0 is a guaranteed 404.\n */\nconst DEFAULT_INITIAL_DELAY_MS = 3_000;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 30_000;\n\n/**\n * The outcome of a queued RequestTrade that could not be delivered as an {@link AppliedTrade}.\n * `code` says why:\n *\n * - `CONFIRMATION_TIMEOUT`: no terminal result before the deadline. The trade may still apply;\n * confirm the same `uniqueKey` again later and never resubmit.\n * - `CONFIRMATION_ABORTED`: the caller's `signal` aborted. Nothing is known about the outcome.\n * - `CONFIRMATION_FAILED`: the apply-results read got a terminal HTTP status (`params.status`;\n * `params.serverMessage` is the failing body's own message, `''` when it had none: server\n * text is data, relay it or ignore it). The outcome is unknown.\n * - `CONFIRMATION_MALFORMED` / `CONFIRMATION_KEY_MISMATCH`: the apply result is not a usable\n * answer for this key. The outcome is unknown.\n * - `INVALID_UNIQUE_KEY`: the key is not a valid apply-results key; nothing was read. TERMINAL:\n * no retry can ever succeed (the SDK never signs such a key, so a stored one is corrupt), so a\n * resume loop must forget the swap. `PendingSwapStore.list` already prunes such entries.\n * - `CHAIN_REJECTED`: the chain REJECTED the trade; `params.errorKey` is the chain `ErrorKey` (or\n * `CHAIN_ERROR`) and `params.serverMessage` its English message.\n *\n * `uniqueKey` is always set and, where known, `requestTransactionId`, `applyTransactionId`,\n * `blockNumber`, `status`, `body`, `url` and the last transport `cause`.\n */\nexport class AppliedTradeError<C extends GSwapErrorCode = GSwapErrorCode> extends GSwapSDKError<C> {\n constructor(code: C, params: GSwapErrorParams<C>, context: GSwapErrorContext = {}) {\n super(code, params, context);\n this.name = 'AppliedTradeError';\n }\n}\n\n/** The transport and backend a confirmation reads from. */\nexport interface ApplyResultsClient {\n /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com` (no trailing path). */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-read timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /** Request headers of the poll (`userAgent`, `headers`); see {@link WireOptions}. */\n wire?: WireOptions | undefined;\n}\n\n/** What identifies the queued trade to confirm. */\nexport interface AppliedTradeInput {\n uniqueKey: string;\n /** The transaction id of the queued request, carried through to the result; `null` if unknown. */\n requestTransactionId: string | null;\n}\n\n/**\n * Polls `GET /v1/chain/apply-results/{uniqueKey}?channel=asset&contract=dex-contract` until the\n * queued RequestTrade reaches a terminal state.\n *\n * Pacing: wait `initialDelayMs` (default 3 s), then read; on 404, 429, 500, 502, 503, 504 or a\n * transport error wait with jittered exponential backoff (`pollIntervalMs` doubling to 8 s,\n * `Retry-After` honored as seconds or an HTTP date) until `timeoutMs`. Any other status is\n * terminal. At least one read is always made.\n *\n * @returns The applied trade.\n * @throws AppliedTradeError - see its documentation for every `code`.\n * @example\n * ```ts\n * const applied = await confirmAppliedTrade(\n * { dexBackendBaseUrl: 'https://dex-backend-prod1.defi.gala.com' },\n * { uniqueKey, requestTransactionId: null },\n * { initialDelayMs: 0, timeoutMs: 60_000, signal: controller.signal },\n * );\n * ```\n */\nexport async function confirmAppliedTrade(\n client: ApplyResultsClient,\n input: AppliedTradeInput,\n options?: ConfirmOptions,\n): Promise<AppliedTrade> {\n const { uniqueKey } = input;\n if (!isValidUniqueKey(uniqueKey)) {\n throw new AppliedTradeError(\n 'INVALID_UNIQUE_KEY',\n { uniqueKey: String(uniqueKey) },\n { uniqueKey },\n );\n }\n const requestor = client.httpRequestor ?? fetchRequestor;\n const requestTimeoutMs = client.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const signal = options?.signal;\n const abortError = (cause?: unknown): Error =>\n new AppliedTradeError('CONFIRMATION_ABORTED', {}, { uniqueKey, cause });\n const url = `${client.dexBackendBaseUrl.replace(/\\/$/u, '')}/v1/chain/apply-results/${encodeURIComponent(uniqueKey)}?channel=asset&contract=dex-contract`;\n\n const schedule = createConfirmationSchedule(options, DEFAULT_INITIAL_DELAY_MS, abortError);\n await schedule.waitForRead();\n let lastError: unknown;\n\n while (true) {\n throwIfAborted(signal, abortError);\n let response: HTTPResponse;\n let body: unknown;\n try {\n response = await requestWithTimeout(\n requestor,\n url,\n {\n method: 'GET',\n headers: buildRequestHeaders(client.wire),\n ...(signal === undefined ? {} : { signal }),\n },\n requestTimeoutMs,\n );\n body = await readResponseBody(response);\n } catch (error: unknown) {\n throwIfAborted(signal, abortError);\n lastError = error;\n if (!(await schedule.waitForRead())) break;\n continue;\n }\n throwIfAborted(signal, abortError);\n\n if (response.status === 200) return readAppliedResult(input, response, body, url);\n\n if (response.status === 404 || response.status === 429 || isTransient(response.status)) {\n const retryAfter = response.status === 429 ? readRetryAfter(response) : undefined;\n if (!(await schedule.waitForRead(retryAfter))) break;\n continue;\n }\n\n throw new AppliedTradeError(\n 'CONFIRMATION_FAILED',\n { status: response.status, serverMessage: serverMessageOfBody(body) },\n { uniqueKey, status: response.status, body, url },\n );\n }\n\n throw new AppliedTradeError(\n 'CONFIRMATION_TIMEOUT',\n {},\n { uniqueKey, requestTransactionId: input.requestTransactionId, url, cause: lastError },\n );\n}\n\nfunction readAppliedResult(\n input: AppliedTradeInput,\n response: HTTPResponse,\n body: unknown,\n url: string,\n): AppliedTrade {\n const { uniqueKey } = input;\n const record = asRecord(body);\n const responseKey = record?.['uniqueKey'] ?? record?.['UniqueKey'];\n if (typeof responseKey === 'string' && responseKey !== uniqueKey) {\n throw new AppliedTradeError(\n 'CONFIRMATION_KEY_MISMATCH',\n {},\n { uniqueKey, status: response.status, body, url },\n );\n }\n const status = record?.['Status'];\n const applyTransactionId = readHeader(response, 'x-apply-transaction-id') ?? null;\n const blockNumber = readBlockNumberHeader(response, 'x-apply-block-number') ?? null;\n if (status === 0) {\n const errorKey = getStringProperty(record, 'ErrorKey') ?? 'CHAIN_ERROR';\n const chainMessage = getStringProperty(record, 'Message') ?? '';\n throw new AppliedTradeError(\n 'CHAIN_REJECTED',\n { errorKey, serverMessage: chainMessage },\n {\n uniqueKey,\n requestTransactionId: input.requestTransactionId,\n applyTransactionId,\n blockNumber,\n status: response.status,\n body,\n url,\n },\n );\n }\n if (status !== 1) throw malformed(input, response, body, url);\n const result = parseTradeExecution(record?.['Data']);\n if (result === undefined) throw malformed(input, response, body, url);\n return {\n uniqueKey,\n transactionId: applyTransactionId,\n blockNumber,\n requestTransactionId: input.requestTransactionId,\n result,\n };\n}\n\nfunction malformed(\n input: AppliedTradeInput,\n response: HTTPResponse,\n body: unknown,\n url: string,\n): AppliedTradeError<'CONFIRMATION_MALFORMED'> {\n return new AppliedTradeError(\n 'CONFIRMATION_MALFORMED',\n {},\n { uniqueKey: input.uniqueKey, status: response.status, body, url },\n );\n}\n\nfunction parseTradeExecution(value: unknown): TradeExecution | undefined {\n const record = asRecord(value);\n if (\n record === undefined ||\n typeof record['token0'] !== 'string' ||\n typeof record['token1'] !== 'string' ||\n typeof record['fee'] !== 'number'\n ) {\n return undefined;\n }\n const optionalFields = [\n 'sell0Qty',\n 'sell1Qty',\n 'buy0Qty',\n 'buy1Qty',\n 'tradingFees',\n 'protocolFees',\n 'totalFees',\n ] as const;\n for (const field of optionalFields) {\n if (field in record && typeof record[field] !== 'string') return undefined;\n }\n return {\n token0: record['token0'],\n token1: record['token1'],\n fee: record['fee'],\n ...Object.fromEntries(\n optionalFields.flatMap((field) =>\n typeof record[field] === 'string' ? [[field, record[field]]] : [],\n ),\n ),\n };\n}\n\nfunction isTransient(status: number): boolean {\n return status === 500 || status === 502 || status === 503 || status === 504;\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","/**\n * Fee tiers for pools.\n */\nexport enum FEE_TIER {\n /** No trading fee. */\n PERCENT_00_00 = 0,\n /** 0.05% fee tier */\n PERCENT_00_05 = 500,\n /** 0.3% fee tier */\n PERCENT_00_30 = 3000,\n /** 1.0% fee tier */\n PERCENT_01_00 = 10000,\n}\n\n/** Tick spacing required by the current GalaChainDex contract for each fee tier. */\nexport const TICK_SPACING_BY_FEE: Readonly<Record<FEE_TIER, number>> = {\n [FEE_TIER.PERCENT_00_00]: 200,\n [FEE_TIER.PERCENT_00_05]: 10,\n [FEE_TIER.PERCENT_00_30]: 60,\n [FEE_TIER.PERCENT_01_00]: 200,\n};\n\n/** All fee tiers supported by the current GalaChainDex contract. */\nexport const ALL_FEE_TIERS: readonly FEE_TIER[] = [\n FEE_TIER.PERCENT_00_00,\n FEE_TIER.PERCENT_00_05,\n FEE_TIER.PERCENT_00_30,\n FEE_TIER.PERCENT_01_00,\n];\n","/**\n * Whether a pool's current tick lies inside a position's range, by the contract's own rule. This\n * module imports nothing, so an app shell (a position badge, a filter) pays for a few dozen bytes.\n */\n\n/** A tick as the chain and the backends write it: a number, or the decimal string of one. */\nexport type TickInput = number | string;\n\nfunction integerTickOf(tick: TickInput): number {\n if (typeof tick === 'string') return tick.trim() === '' ? Number.NaN : Number(tick);\n return tick;\n}\n\n/**\n * True when a position over `[tickLower, tickUpper)` is IN RANGE at `currentTick`: the lower tick\n * is INCLUSIVE and the upper tick is EXCLUSIVE. That is the GalaChainDex contract's rule\n * (`DexV3Pool`: `tickCurrent >= tickLower && tickCurrent < tickUpper` is the case in which a\n * position holds both tokens and earns fees). A pool whose tick equals `tickUpper` is already out\n * of range: the position is entirely token1 there, and a swap through the tick has crossed it.\n *\n * `currentTick` is the pool's tick (`slot0.tick`, the greatest tick whose price is no greater than\n * the pool's price), not a rounded display value. A tick may be a number or the decimal string a\n * backend returns. Anything that is not an integer (`NaN`, `undefined`-like, an empty string, a\n * fraction) makes the answer `false`: an app that must tell \"not loaded yet\" from \"out of range\"\n * checks for the missing value itself first.\n *\n * Do NOT decide range by comparing a price with a tick's price (`tickToPrice`) using `<=` on both\n * ends, or by mixing a square-root price with a price. A price exactly on a tick's boundary is\n * then in range at the upper edge (the contract says it is not), and two representations of the\n * same boundary can round to opposite sides. For a pool price use {@link isSqrtPriceInRange}, which\n * derives the tick the way the contract does and then applies this rule.\n *\n * @example\n * ```ts\n * isTickInRange(-60, -60, 60); // true: the lower tick is inclusive\n * isTickInRange(60, -60, 60); // false: the upper tick is exclusive\n * ```\n */\nexport function isTickInRange(\n currentTick: TickInput,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n const current = integerTickOf(currentTick);\n const lower = integerTickOf(tickLower);\n const upper = integerTickOf(tickUpper);\n if (!Number.isInteger(current) || !Number.isInteger(lower) || !Number.isInteger(upper)) {\n return false;\n }\n return current >= lower && current < upper;\n}\n","import BigNumber from 'bignumber.js';\nimport { Decimal } from 'decimal.js';\nimport { isTickInRange, type TickInput } from './tick_range.js';\n\n/**\n * Tick and price arithmetic that never throws an SDK error: the contract's tick bounds, the\n * conversions between ticks and prices, and nothing that validates a range. It imports only the\n * two number libraries it computes with, never the `GSwapSDKError` class or the error catalog\n * (functions that must throw, `alignTickDown` and `assertTickRange`, are in `ticks.ts`), so an\n * app shell that prices a tick pays for the libraries and these few functions, not for ~25 kB of\n * error templates. A value that cannot be computed is `NaN`, never an exception.\n */\n\n/** Minimum tick supported by GalaChainDex. */\nexport const GC_MIN_TICK = -887272;\n/** Maximum tick supported by GalaChainDex. */\nexport const GC_MAX_TICK = 887272;\n\nconst DexMath = BigNumber.clone({\n DECIMAL_PLACES: 60,\n ROUNDING_MODE: BigNumber.ROUND_DOWN,\n});\n/** `decimal.js` at the 60 significant digits the contract's price math is exact to. */\nexport const DexDecimal = Decimal.clone({ precision: 60 });\n\n/** Convert a tick to the corresponding square-root price. */\nexport function tickToSqrtPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick / 2).toString());\n}\n\n/** Return the greatest tick whose square-root price is no greater than the input. */\nexport function sqrtPriceToTick(sqrtPrice: BigNumber.Value): number {\n let value: BigNumber;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this function's contract is to signal an invalid input via NaN, not\n // to throw, so an unparseable value is just another case for the guard below.\n value = new DexMath(sqrtPrice);\n } catch {\n return Number.NaN;\n }\n if (!value.isFinite() || value.isLessThanOrEqualTo(0)) return Number.NaN;\n\n const approximate = Math.log(value.toNumber() ** 2) / Math.log(1.0001);\n if (!Number.isFinite(approximate)) return Number.NaN;\n // Clamp the seed before the correction loops below — an unclamped seed derived from an\n // out-of-range sqrtPrice (extreme but finite, e.g. 1e20) leaves the loops running past\n // GC_MIN_TICK/GC_MAX_TICK for a long time; an infinite (overflowed) seed would never\n // enter the increasing loop and never terminate the decreasing one.\n let tick = Math.min(GC_MAX_TICK, Math.max(GC_MIN_TICK, Math.floor(approximate)));\n while (tick < GC_MAX_TICK && tickToSqrtPrice(tick + 1).isLessThanOrEqualTo(value)) tick += 1;\n while (tick > GC_MIN_TICK && tickToSqrtPrice(tick).isGreaterThan(value)) tick -= 1;\n return tick;\n}\n\n/**\n * The token1/token0 price at `tick`: `1.0001 ** tick`, exact to 60 significant digits (the lower\n * edge of the tick's price range; `tickToSqrtPrice(tick) ** 2`). A tick outside the contract's\n * bounds is still computed; ask `assertTickRange` first when that matters. A non-integer tick is\n * computed as given.\n *\n * Use `.toNumber()` for a display value (it differs from `Math.exp(tick * Math.log(1.0001))` in\n * the last digits of a double: that expression multiplies in floating point first).\n */\nexport function tickToPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick).toString());\n}\n\n/**\n * {@link isTickInRange} for a pool's square-root price instead of its tick (a position row that\n * carries `sqrtPrice`, `tickLower` and `tickUpper`). The tick is derived from the price exactly as\n * the contract does (`sqrtPriceToTick`: the greatest tick whose square-root price is no greater\n * than the price, exact to 60 digits), then the contract's rule applies: lower tick inclusive,\n * upper tick exclusive. So a pool sitting exactly on `tickLower`'s price is in range, and exactly\n * on `tickUpper`'s price is not, and no float rounding can flip either.\n *\n * `false` for a price that is not positive and finite (not loaded, zero, `NaN`): it says nothing\n * about the position, so an app that must show a neutral state checks for the missing price\n * itself first. `tickLower` and `tickUpper` follow {@link isTickInRange}.\n *\n * @example\n * ```ts\n * const inRange = isSqrtPriceInRange(position.sqrtPrice, position.tickLower, position.tickUpper);\n * ```\n */\nexport function isSqrtPriceInRange(\n sqrtPrice: BigNumber.Value,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n return isTickInRange(sqrtPriceToTick(sqrtPrice), tickLower, tickUpper);\n}\n\n/** How {@link tickFromPrice} turns the exact logarithm into an integer tick. */\nexport interface TickFromPriceOptions {\n /**\n * `'floor'` (default): the greatest tick whose price is no greater than `price`, which is how\n * the contract places a price. `'nearest'`: the closest tick, a half rounding away from zero.\n * That is what a price INPUT wants (a person types a price, the field snaps to the nearest\n * tick), and it differs from `'floor'` for any price in the upper half of a tick's range.\n */\n rounding?: 'floor' | 'nearest' | undefined;\n}\n\n/**\n * Return the integer tick for a token1/token0 `price`: by default the greatest tick whose price\n * is no greater than `price`; `{ rounding: 'nearest' }` the closest tick. `NaN` for a price that\n * is not positive and finite.\n */\nexport function tickFromPrice(price: BigNumber.Value, options: TickFromPriceOptions = {}): number {\n const priceText =\n typeof price === 'string'\n ? price\n : typeof price === 'number'\n ? price.toString()\n : BigNumber.isBigNumber(price)\n ? price.toString()\n : 'NaN';\n const value = new DexDecimal(priceText);\n if (!value.isFinite() || value.lessThanOrEqualTo(0)) return Number.NaN;\n if (!Number.isFinite(value.toNumber())) return Number.NaN;\n const exact = value.ln().dividedBy(new DexDecimal(1.0001).ln());\n const tick = (options.rounding === 'nearest' ? exact.round() : exact.floor()).toNumber();\n return Number.isFinite(tick) ? tick : Number.NaN;\n}\n","import BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { GC_MAX_TICK, GC_MIN_TICK } from './tick_math.js';\n\n/**\n * Validates a decimal amount: a string or `BigNumber`, never a JavaScript number.\n *\n * @param amount - The amount to check.\n * @param parameterName - The field name reported in the error's `params.field`.\n * @param allowZero - Accept zero (default `false`).\n * @throws GSwapSDKError `AMOUNT_IS_JS_NUMBER`, `AMOUNT_NOT_FINITE`, `AMOUNT_NOT_POSITIVE` (zero\n * when `allowZero` is false) or `AMOUNT_NEGATIVE`.\n */\nexport function validateNumericAmount(\n amount: NumericAmount,\n parameterName: string,\n allowZero = false,\n): void {\n if (typeof amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite() check below still catches\n // it and raises the same typed error, instead of a raw exception escaping.\n let bnAmount: BigNumber;\n try {\n bnAmount = BigNumber(amount);\n } catch {\n bnAmount = BigNumber(NaN);\n }\n\n if (!bnAmount.isFinite()) {\n throw new GSwapSDKError('AMOUNT_NOT_FINITE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError('AMOUNT_NOT_POSITIVE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError('AMOUNT_NEGATIVE', { field: parameterName, value: String(amount) });\n }\n}\n\n/**\n * Validates a spot price and a lower/upper price range: none a JavaScript number, all positive and\n * finite (a non-finite upper bound counts as an unbounded `1e18`), and `lowerPrice <= upperPrice`.\n *\n * @throws GSwapSDKError `PRICE_VALUES_IS_JS_NUMBER`, `INVALID_PRICE_VALUES` or `INVALID_PRICE_RANGE`.\n */\nexport function validatePriceValues(\n spotPrice: NumericAmount,\n lowerPrice: NumericAmount,\n upperPrice: NumericAmount,\n): void {\n if ([spotPrice, lowerPrice, upperPrice].some((value) => typeof value === 'number')) {\n throw new GSwapSDKError('PRICE_VALUES_IS_JS_NUMBER', {});\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite()/isPositive() checks below\n // still catch it and raise the same typed error, instead of a raw exception escaping.\n const parse = (value: NumericAmount): BigNumber => {\n try {\n return BigNumber(value);\n } catch {\n return BigNumber(NaN);\n }\n };\n const bnSpotPrice = parse(spotPrice);\n const bnLowerPrice = parse(lowerPrice);\n let bnUpperPrice = parse(upperPrice);\n\n bnUpperPrice = bnUpperPrice.isFinite() ? bnUpperPrice : BigNumber(1e18);\n\n if (\n !bnSpotPrice.isFinite() ||\n !bnLowerPrice.isFinite() ||\n !bnUpperPrice.isFinite() ||\n !bnSpotPrice.isPositive() ||\n !bnLowerPrice.isPositive() ||\n !bnUpperPrice.isPositive()\n ) {\n throw new GSwapSDKError('INVALID_PRICE_VALUES', {\n spotPrice: String(spotPrice),\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError('INVALID_PRICE_RANGE', {\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n}\n\n/**\n * Validates a token's decimals: a non-negative integer.\n *\n * @throws GSwapSDKError `INVALID_TOKEN_DECIMALS` (`params.field` is `parameterName`).\n */\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError('INVALID_TOKEN_DECIMALS', { field: parameterName, value: decimals });\n }\n}\n\n/**\n * Validates a position's tick range: two integers with `tickLower < tickUpper`, both within\n * `GC_MIN_TICK`..`GC_MAX_TICK`. It does not check alignment to a fee tier's spacing (see\n * `assertTickRange`).\n *\n * @throws GSwapSDKError `TICKS_NOT_INTEGERS`, `INVALID_TICK_RANGE` or `TICKS_OUT_OF_BOUNDS`.\n */\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower, tickUpper });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower, tickUpper });\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n}\n\n/**\n * Asserts that `fee` is one of the fee tiers in `ALL_FEE_TIERS` (`0`, `500`, `3000`, `10000`).\n *\n * @throws GSwapSDKError `INVALID_FEE` (`params.field` `'fee'`, `params.allowed` the tiers).\n */\nexport function validateFee(fee: number): asserts fee is FEE_TIER {\n if (!ALL_FEE_TIERS.some((tier) => Number(tier) === fee)) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\n/**\n * Validates a tick spacing: a positive integer.\n *\n * @throws GSwapSDKError `INVALID_TICK_SPACING`.\n */\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: tickSpacing });\n }\n}\n\n/**\n * Asserts that a wallet address was given and is a non-blank string. It does not check the address\n * format.\n *\n * @throws GSwapSDKError `MISSING_WALLET_ADDRESS` (undefined) or `INVALID_WALLET_ADDRESS` (blank).\n */\nexport function validateWalletAddress(address?: string): asserts address is string {\n if (address === undefined) {\n throw new GSwapSDKError('MISSING_WALLET_ADDRESS', {});\n }\n\n if (!address || typeof address !== 'string' || address.trim().length === 0) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', {\n field: 'walletAddress',\n value: String(address),\n });\n }\n}\n\n/** Words the chain gateway refuses as a trading symbol. */\nconst RESERVED_TRADING_SYMBOLS = new Set(['Token', 'Unit', 'none']);\nconst TRADING_SYMBOL_PATTERN = /^[A-Za-z0-9]+$/u;\nconst MAX_TRADING_SYMBOL_LENGTH = 32;\n\n/**\n * True when `symbol` is acceptable to propose into the trading-symbol registry: ASCII letters and\n * digits only, 1 to 32 characters, and not a reserved word (`Token`, `Unit`, `none`) — the rules\n * the chain gateway enforces on a CreatePool symbol.\n */\nexport function isProposableTradingSymbol(symbol: string): boolean {\n return (\n TRADING_SYMBOL_PATTERN.test(symbol) &&\n symbol.length <= MAX_TRADING_SYMBOL_LENGTH &&\n !RESERVED_TRADING_SYMBOLS.has(symbol)\n );\n}\n\n/**\n * Asserts that a pair is in the contract's canonical order (`token0 < token1` by plain string\n * comparison), which every write DTO requires. A pair a caller took from a stale quote or\n * position can be reversed; signing it would sign something other than what was priced.\n *\n * @throws GSwapSDKError `NON_CANONICAL_PAIR` (`params.token0`, `params.token1`) otherwise.\n */\nexport function assertCanonicalPair(token0: string, token1: string): void {\n if (!(token0 < token1)) {\n throw new GSwapSDKError('NON_CANONICAL_PAIR', { token0, token1 });\n }\n}\n","import type { UserAsset, UserAssetsResult } from '../types/v2_results.js';\nimport { validateWalletAddress } from '../utils/validation.js';\nimport { getObjectProperty, GSwapSDKError } from './gswap_sdk_error.js';\nimport type { HttpClient } from './http_client.js';\n\n/**\n * Service for handling user asset operations.\n * Provides functionality to retrieve user token balances and asset information.\n */\nexport class Assets {\n constructor(\n private readonly dexBackendBaseUrl: string,\n private readonly httpClient: HttpClient,\n ) {}\n\n /**\n * Gets all token assets owned by a user with their balances.\n * @param ownerAddress - The wallet address to get assets for.\n * @param page - Page number for pagination (default: 1).\n * @param limit - Maximum number of assets to return per page (default: 10).\n * @returns User assets including token information and balances.\n * @example\n * ```typescript\n * const assets = await assetsService.getUserAssets('eth|123...abc', 1, 20);\n * console.log(`User has ${assets.count} different tokens`);\n * assets.tokens.forEach(token => {\n * console.log(`${token.symbol}: ${token.quantity}`);\n * });\n * ```\n */\n async getUserAssets(\n ownerAddress: string,\n page: number = 1,\n limit: number = 10,\n ): Promise<UserAssetsResult> {\n validateWalletAddress(ownerAddress);\n\n if (!Number.isInteger(page) || page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: page });\n }\n\n if (!Number.isInteger(limit) || limit < 1 || limit > 100) {\n throw new GSwapSDKError('INVALID_LIMIT', { value: limit, min: 1, max: 100 });\n }\n\n const json: unknown = await this.httpClient.sendGetRequest(\n this.dexBackendBaseUrl,\n '/user/assets',\n '',\n { address: ownerAddress, page: page.toString(), limit: limit.toString() },\n );\n return parseUserAssets(json);\n }\n}\n\nfunction parseUserAssets(value: unknown): UserAssetsResult {\n const data = getObjectProperty(value, 'data');\n // Not getObjectProperty — that's typed for object properties, and Array.isArray on its\n // Record<string, unknown> return type narrows to any[] instead of a real array type.\n const tokens: unknown = data?.['token'];\n if (!Array.isArray(tokens) || !tokens.every(isRawUserAsset)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: 'user assets response' },\n { body: value },\n );\n }\n const count = data?.['count'];\n return {\n tokens: tokens.map((token) => ({ ...token, decimals: parseInt(token.decimals, 10) })),\n count: typeof count === 'number' ? count : 0,\n };\n}\n\ntype RawUserAsset = Omit<UserAsset, 'decimals'> & { decimals: string };\n\nfunction isRawUserAsset(value: unknown): value is RawUserAsset {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n typeof entry['image'] === 'string' &&\n typeof entry['name'] === 'string' &&\n typeof entry['decimals'] === 'string' &&\n /^\\d+$/u.test(entry['decimals']) &&\n typeof entry['verify'] === 'boolean' &&\n typeof entry['symbol'] === 'string' &&\n typeof entry['quantity'] === 'string'\n );\n}\n","/**\n * What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet\n * code of the app's own): the code the wallet put on it, and whether it means the person declined.\n * Both read only the wallet's own error value; neither shows or forwards its text.\n */\n\nimport { hasGSwapErrorBrand, isGSwapErrorLike } from './error_brand.js';\n\n// This module is the whole of the light `@gala-chain/gswap-sdk/wallet` entry (and the main entry\n// re-exports it, so there is one implementation). It must stay dependency-free: it may import\n// only `./error_brand.js`, never the error catalog, `GSwapSDKError` or the main index.\n\n/** Codes the EIP-1193 / ethers / viem families use for \"the person declined in the wallet\". */\nconst REJECTION_CODES: readonly unknown[] = [4001, 'ACTION_REJECTED', 'USER_REJECTED'];\n\n/** The `name` viem / wagmi give the error of a declined request. */\nconst REJECTION_NAME = 'UserRejectedRequestError';\n\n/**\n * Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for\n * wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on\n * purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle\n * match an unrelated message that uses these words.\n */\nconst REJECTION_PHRASES: readonly string[] = [\n 'user rejected',\n 'user denied',\n 'user cancel',\n 'rejected the request',\n 'request rejected',\n 'rejected by user',\n 'action_rejected',\n 'cancelled',\n 'canceled',\n];\n\n/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */\nconst TEXT_KEYS: readonly string[] = [\n 'message',\n 'Message',\n 'shortMessage',\n 'details',\n 'errorDetails',\n 'reason',\n];\n\n/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */\nconst MAX_TEXT_DEPTH = 3;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction textsOf(value: unknown, depth = 0): string[] {\n if (typeof value === 'string') return [value];\n if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];\n return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));\n}\n\nfunction wordsADecline(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) ||\n (lower.includes('signature') && lower.includes('cancel'))\n );\n}\n\n/**\n * True when a wallet's error (or just its message text) says the person DECLINED the request in\n * their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===\n * 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a\n * v1 write path) so an app keeps no matcher of its own.\n *\n * It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`\n * (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are\n * absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,\n * `reason`, up to three levels deep, or a bare string): \"user rejected\", \"user denied\", \"user\n * cancelled\", \"request rejected\", \"rejected by user\", \"rejected the request\", \"cancelled\" /\n * \"canceled\", or a \"signature ... cancel\" sentence. The wording fallback is a last resort for\n * wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.\n *\n * An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its\n * `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a\n * plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape\n * of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with\n * the wallet code list above still honoured for a view that is not branded, and its English is\n * never read. This works without `instanceof`, so it is safe across two copies of the SDK.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (isWalletUserRejection(error)) return; // the person said no: not an error to report\n * report(error);\n * }\n * ```\n */\nexport function isWalletUserRejection(value: unknown): boolean {\n if (isGSwapErrorLike(value)) {\n if (value.code === 'SIGNING_FAILED') return value.params['reason'] === 'user_rejected';\n return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);\n }\n if (isRecord(value)) {\n if (REJECTION_CODES.includes(value['code']) || value['name'] === REJECTION_NAME) return true;\n }\n return textsOf(value).some(wordsADecline);\n}\n\n/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */\nconst MAX_WALLET_CODE_LENGTH = 64;\n\n/**\n * The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an\n * ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything\n * else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so\n * the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.\n *\n * @example\n * ```ts\n * walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001\n * walletDeclineCode(new Error('locked')); // undefined\n * ```\n */\nexport function walletDeclineCode(value: unknown): number | string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const { code } = value as { code?: unknown };\n if (typeof code === 'number') return Number.isFinite(code) ? code : undefined;\n if (typeof code === 'string' && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) {\n return code;\n }\n return undefined;\n}\n","import { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\nimport type { GalaChainSigner, SignedDto } from '../classes/signers.js';\nimport { isWalletUserRejection, walletDeclineCode } from './wallet_rejection.js';\n\n/**\n * The boundary of \"nothing was sent\". Every place where the SDK hands control to code the APP\n * supplied BEFORE the request leaves (the signer, the token resolver) goes through here, so a\n * failure of that code reaches the caller as a catalogued, pre-send SDK error with the original as\n * `cause`, never as a bare value the SDK cannot classify. An SDK error thrown by that code is\n * already catalogued and passes through untouched. Nothing here is used after the request has\n * been sent: an app's own rejection AFTER send stays what it is, because the SDK cannot know what\n * the server did with the write.\n */\n\n/**\n * Signs a DTO with the app's signer. Whatever the signer throws that is not already an SDK error\n * (a locked wallet, an unreachable extension, a wallet that declined) is `SIGNING_FAILED`\n * (`reason` `user_rejected` or `failed`, the original as `cause`), and a signer that returns\n * something other than an object is `SIGNING_FAILED` too: both are pre-send, so a retry is safe.\n *\n * @throws GSwapSDKError SIGNING_FAILED, or the SDK error the signer itself threw.\n */\nexport async function signPreSend<T extends Record<string, unknown>>(\n signer: GalaChainSigner,\n method: string,\n dto: T,\n): Promise<SignedDto<T>> {\n let signed: SignedDto<T>;\n try {\n signed = await signer.signObject(method, dto);\n } catch (cause: unknown) {\n if (isGSwapError(cause)) throw cause;\n const reason = isWalletUserRejection(cause) ? 'user_rejected' : 'failed';\n throw new GSwapSDKError(\n 'SIGNING_FAILED',\n { method, reason },\n { cause, walletCode: walletDeclineCode(cause) },\n );\n }\n if (typeof signed !== 'object' || signed === null) {\n throw new GSwapSDKError('SIGNING_FAILED', { method, reason: 'failed' }, { cause: signed });\n }\n return signed;\n}\n\n/**\n * Runs a token-resolution step (a resolver's `resolve` / `orderPair`, which may read the registry\n * through the app's HTTP stack). A failure that is not an SDK error is `TOKEN_RESOLUTION_FAILED`\n * (`token` names what was being resolved, the original is `cause`); an SDK error passes through.\n *\n * @throws GSwapSDKError TOKEN_RESOLUTION_FAILED, or the SDK error the step itself threw.\n */\nexport async function resolvePreSend<T>(token: string, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause: unknown) {\n throw isGSwapError(cause)\n ? cause\n : new GSwapSDKError('TOKEN_RESOLUTION_FAILED', { token }, { cause });\n }\n}\n","import type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n} from '../utils/transport.js';\nimport { signPreSend } from '../utils/pre_send.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { GalaChainSigner } from './signers.js';\n\n/** DEX methods the backend accepts a fee quote for (its allow-list enumerates the same six). */\nexport const DEX_FEE_METHODS = [\n 'Swap',\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n 'CreatePool',\n] as const;\n/** A chain method whose network fee `DexFees.quote` can price (see `isDexFeeMethod`). */\nexport type DexFeeMethod = (typeof DEX_FEE_METHODS)[number];\n\n/** Which pool contract the DTO being quoted targets: legacy (V3) or current (GalaChainDex). */\nexport type DexFeeContract = 'dexv3-contract' | 'dex-contract';\n\n/** The chain method name the signed DryRun wrapper is signed under. */\nexport const DRY_RUN_METHOD = 'DryRun';\n\n/** `uniqueKey` prefix of the DryRun WRAPPER (distinct from the inner DTO's key). */\nexport const DRY_RUN_UNIQUE_KEY_PREFIX = 'galaconnect-operation-';\n\n/** True when `method` is a DEX method a fee can be quoted for. */\nexport function isDexFeeMethod(method: unknown): method is DexFeeMethod {\n return typeof method === 'string' && (DEX_FEE_METHODS as readonly string[]).includes(method);\n}\n\n/** Current-contract typed DEX messages use trading symbols instead of TokenClassKey objects. */\nexport function isCurrentContractDexMessage(\n message: Record<string, unknown> | null | undefined,\n method: unknown,\n): boolean {\n return (\n isDexFeeMethod(method) &&\n typeof message?.['token0'] === 'string' &&\n typeof message['token1'] === 'string'\n );\n}\n\n/**\n * The backend's response. It ALWAYS carries a usable `fees[0].feeInGala`: the backend decides what\n * to serve when the chain cannot price the operation, so the client never invents a fee.\n *\n * `source` is informational: `'dry-run'` is simulated on chain and authoritative (possibly a\n * legitimate `'0'`), `'default'` means the chain could not price it and the platform default was\n * served.\n */\nexport interface DexFeeQuote {\n fees: Array<{ feeInGala: string }>;\n source: 'dry-run' | 'default';\n}\n\n/**\n * Reduces an EIP-712 approval `message` to the DTO the chain actually receives: drops the signing\n * envelope (`signature`, `prefix`, `types`, `domain`) and transport metadata (`trace`).\n */\nexport function toChainDto(message: Record<string, unknown>): Record<string, unknown> {\n const chainDto: Record<string, unknown> = { ...message };\n for (const field of ['signature', 'prefix', 'types', 'domain', 'trace']) {\n delete chainDto[field];\n }\n return chainDto;\n}\n\n/**\n * Signs the DryRun WRAPPER the gateway accepts for every contract:\n * `{ callerPublicKey, method, dto: <inner DTO object>, uniqueKey, signature }`. The inner DTO\n * travels unsigned and as an object; no `signerPublicKey` is sent because the signature already\n * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own\n * `uniqueKey`, distinct from the DTO's.\n */\nexport function buildDryRunWrapper(\n signer: GalaChainSigner,\n callerPublicKey: string,\n method: string,\n dto: Record<string, unknown>,\n uniqueKeyPrefix: string = DRY_RUN_UNIQUE_KEY_PREFIX,\n): Promise<Record<string, unknown>> {\n return signPreSend(signer, DRY_RUN_METHOD, {\n callerPublicKey,\n method,\n dto,\n uniqueKey: `${uniqueKeyPrefix}${globalThis.crypto.randomUUID()}`,\n });\n}\n\n/** The transport and backend a fee quote reads from. */\nexport interface DexFeesClient {\n /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com`. */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-request timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /**\n * Request headers of the fee POST (`userAgent`, `headers`); see {@link WireOptions}. The SDK's\n * `Accept: application/json` is a default that `wire.headers` may replace.\n */\n wire?: WireOptions | undefined;\n}\n\n/** Options for a single quote. */\nexport interface DexFeeQuoteOptions {\n /** GalaChain channel. Default `asset`. */\n channel?: string | undefined;\n /**\n * Contract the DTO targets. Default `dexv3-contract` (what every legacy caller quotes against);\n * a current-contract operation must pass `dex-contract` explicitly.\n */\n contract?: DexFeeContract | undefined;\n}\n\n/**\n * Network-fee quote for GalaChain DEX methods, derived from a server-side DryRun.\n *\n * The client only SIGNS the DryRun wrapper (with whatever {@link GalaChainSigner} it is given) and\n * the backend forwards it to the gateway, where the simulated writes carry the fee; the backend\n * never holds a key. Intended for wallets: the DTO quoted is the typed message a dApp handed over.\n *\n * @example\n * ```ts\n * const fees = new DexFees({ dexBackendBaseUrl }, new PrivateKeySigner(sessionKey));\n * const quote = await fees.quote(publicKey, 'RequestTrade', toChainDto(message), {\n * contract: 'dex-contract',\n * });\n * const feeInGala = quote?.fees[0]?.feeInGala;\n * ```\n */\nexport class DexFees {\n private readonly requestor: HttpRequestor;\n private readonly baseUrl: string;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n\n constructor(\n client: DexFeesClient,\n private readonly signer: GalaChainSigner | undefined,\n ) {\n this.requestor = client.httpRequestor ?? fetchRequestor;\n this.baseUrl = client.dexBackendBaseUrl.replace(/\\/$/u, '');\n this.requestTimeoutMs = client.requestTimeoutMs ?? 30_000;\n this.wire = client.wire;\n }\n\n /**\n * Quotes the network fee for `method` applied to `message`. The message is reduced with\n * {@link toChainDto} first, so an EIP-712 approval message can be passed as is.\n *\n * Resolves `null` when the BACKEND could not be reached or answered unusably (offline, 4xx/5xx,\n * malformed body): a transport outcome, not a fee. Deciding what to charge when the chain is\n * silent is the backend's job (it serves `source: 'default'`), so the client never substitutes\n * a fee of its own, with ONE exception that mirrors the wallet: a `dex-contract` quote answered\n * 403 or 404 means the contract has no fee route yet and resolves `{ source: 'default', '0' }`.\n * Never throws on transport, so a fee lookup cannot block or break a signing screen.\n *\n * @throws GSwapSDKError NO_SIGNER when constructed without a signer; `SIGNING_FAILED` or\n * `KEY_PROVIDER_FAILED` (a pre-send error, the original as `cause`) when the signer fails, for\n * example a locked wallet.\n */\n public async quote(\n callerPublicKey: string,\n method: DexFeeMethod,\n message: Record<string, unknown>,\n options: DexFeeQuoteOptions = {},\n ): Promise<DexFeeQuote | null> {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const channel = options.channel ?? 'asset';\n const contract = options.contract ?? 'dexv3-contract';\n const wrapper = await buildDryRunWrapper(\n this.signer,\n callerPublicKey,\n method,\n toChainDto(message),\n );\n const url = `${this.baseUrl}/wallet/connect/galachain/api/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;\n\n let status: number;\n let ok: boolean;\n let body: unknown;\n try {\n const response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers: buildRequestHeaders(this.wire, {\n json: true,\n defaults: { Accept: 'application/json' },\n }),\n body: JSON.stringify(wrapper),\n },\n this.requestTimeoutMs,\n );\n status = response.status;\n ok = response.ok;\n body = ok ? await readResponseBody(response) : undefined;\n } catch {\n return null;\n }\n\n if (!ok) {\n if (contract === 'dex-contract' && (status === 403 || status === 404)) {\n return { source: 'default', fees: [{ feeInGala: '0' }] };\n }\n return null;\n }\n // Accept whatever fee the backend served: 'default' is as usable as 'dry-run'. Only a body\n // missing the fee outright is unusable.\n return readQuote(body);\n }\n}\n\nfunction readQuote(body: unknown): DexFeeQuote | null {\n if (typeof body !== 'object' || body === null) return null;\n const fees = (body as { fees?: unknown }).fees;\n if (\n !Array.isArray(fees) ||\n typeof (fees[0] as { feeInGala?: unknown } | undefined)?.feeInGala !== 'string'\n ) {\n return null;\n }\n return body as DexFeeQuote;\n}\n","import { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\nimport { toFailureView } from './failure_view.js';\n\n/**\n * Failures of the shadow (dark) path carry that fact, so an app can apply its own policy (no\n * Retry, no public fallback) without tracking which call it made. An SDK error gets `shadow: true`;\n * a non-SDK object that escapes the path (an app requestor's own rejection) is remembered in a\n * WeakSet, which `isShadowError` reads. Nothing here changes what an error means, only where it\n * came from.\n */\nconst shadowRejections = new WeakSet<object>();\n\n/**\n * True when `value` is a failure of the shadow (dark) path: an SDK error with `shadow: true`, a\n * plain-object view of one (`{ code, shadow: true }`, see `FailureView`), or a non-SDK object (a requestor's own rejection) that escaped `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`. A primitive that was thrown (`throw 'x'`) cannot be remembered, so\n * it is never shadow; an app that cares tracks the call it made.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { retryable } = classifyFailure(error);\n * offerRetry(retryable && !isShadowError(error)); // never retry a dark swap in public\n * }\n * ```\n */\nexport function isShadowError(value: unknown): boolean {\n if (isGSwapError(value)) return value.shadow;\n if (toFailureView(value)?.shadow === true) return true;\n return typeof value === 'object' && value !== null && shadowRejections.has(value);\n}\n\n/**\n * The same failure, marked as shadow. An SDK error is COPIED (same code, params, status, body,\n * url, ids, cause, phase and stack), never mutated: one error object can be shared by several\n * callers (a registry read many swaps wait on), and only the shadow caller's copy is shadow.\n */\nfunction asShadowError(error: unknown): unknown {\n if (isGSwapError(error)) {\n if (error.shadow) return error;\n const copy = new GSwapSDKError(error.code, error.params, {\n status: error.status,\n body: error.body ?? error.bodyText,\n url: error.url,\n uniqueKey: error.uniqueKey,\n requestTransactionId: error.requestTransactionId,\n applyTransactionId: error.applyTransactionId,\n blockNumber: error.blockNumber,\n retryAfterMs: error.retryAfterMs,\n cause: error.cause,\n phase: error.phase,\n shadow: true,\n });\n if (error.stack !== undefined) copy.stack = error.stack;\n return copy;\n }\n if (typeof error === 'object' && error !== null) shadowRejections.add(error);\n return error;\n}\n\n/** Runs one shadow operation and marks whatever it throws as shadow (see {@link isShadowError}). */\nexport async function shadowFailures<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error: unknown) {\n throw asShadowError(error);\n }\n}\n","import type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { AppliedTrade, Position } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { createConfirmationSchedule, throwIfAborted } from '../utils/confirmation_schedule.js';\nimport type { SubmitStatus } from '../utils/submit_state.js';\nimport { armTimeout } from '../utils/transport.js';\nimport { confirmAppliedTrade } from './apply_results.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\n/** Result of one position-confirmation poll. */\nexport type PositionConfirmationResult =\n { confirmed: true; position: Position | null } | { confirmed: false; position?: Position | null };\n\n/** A submitted v2 transaction whose confirmation mode is explicit in the gateway response. */\nexport class SubmittedTransaction<TConfirmation = AppliedTrade | Position | null> {\n /** The chain method that was submitted (`RequestTrade`, `AddLiquidity`, ...). */\n public readonly method: string;\n /** The write's durable correlation key: persist it, and confirm from it alone later. */\n public readonly uniqueKey: string;\n /** The request transaction id the gateway reported, or `null` when it gave none. */\n public readonly transactionId: string | null;\n /** The block of the transaction, when the answer carried one; otherwise `null`. */\n public readonly blockNumber: number | null;\n /** The gateway's `data.mode`: `'sync'` (executed, `result` is the chain result) or `'queued'`. */\n public readonly mode: 'sync' | 'queued';\n /**\n * What the gateway's answer established: `'executed'` for `mode: 'sync'`, `'queued'` for\n * `mode: 'queued'` (accepted, NOT executed: `await confirm()` for the outcome). A refused answer\n * never becomes a transaction, so there is no `'rejected'` here; see {@link classifySubmitEnvelope}\n * for classifying a raw envelope.\n */\n public readonly status: SubmitStatus;\n /** The synchronous gateway result, or `undefined` when `mode === 'queued'`. */\n public readonly result: unknown;\n /**\n * The gateway's whole JSON answer as it came (`{ status, message, error, data }`), for an app\n * that hands the backend's own envelope to its callers; `undefined` for a transaction built from\n * a uniqueKey alone.\n */\n public readonly envelope: unknown;\n private readonly backendBaseUrl: string;\n private readonly requestor: HttpRequestor;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n private readonly positionConfirmation:\n ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n\n /** Construct a submitted transaction from a successful gateway response.\n *\n * @example\n * ```ts\n * const transaction = new SubmittedTransaction({\n * method: 'RequestTrade', mode: 'queued', uniqueKey: 'swap-1',\n * transactionId: 'request-tx', result: undefined,\n * dexBackendBaseUrl: 'https://dex.example', httpRequestor,\n * });\n * ```\n */\n constructor(options: {\n method: string;\n uniqueKey: string;\n transactionId: string | null;\n mode: 'sync' | 'queued';\n result: unknown;\n dexBackendBaseUrl: string;\n httpRequestor: HttpRequestor;\n blockNumber?: number | null | undefined;\n envelope?: unknown;\n requestTimeoutMs?: number | undefined;\n /** Wire options of the apply-results polls `confirm()` makes. */\n wire?: WireOptions | undefined;\n positionConfirmation?:\n ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n }) {\n this.method = options.method;\n this.uniqueKey = options.uniqueKey;\n this.transactionId = options.transactionId;\n this.blockNumber = options.blockNumber ?? null;\n this.mode = options.mode;\n this.status = options.mode === 'queued' ? 'queued' : 'executed';\n this.result = options.result;\n this.envelope = options.envelope;\n this.backendBaseUrl = options.dexBackendBaseUrl.replace(/\\/$/u, '');\n this.requestor = options.httpRequestor;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;\n this.wire = options.wire;\n this.positionConfirmation = options.positionConfirmation;\n }\n\n /** Confirm a queued RequestTrade or prove the affected position for a liquidity write.\n *\n * For RequestTrade, calling this method is required to learn the outcome: the queued\n * acknowledgement proves acceptance, not execution.\n *\n * @example\n * ```ts\n * const applied = await submitted.confirm({ initialDelayMs: 3_000 });\n * ```\n */\n public async confirm(options?: ConfirmOptions): Promise<TConfirmation> {\n if (this.method === 'RequestTrade') {\n return this.confirmApplied(options) as Promise<TConfirmation>;\n }\n return this.confirmPosition(options) as Promise<TConfirmation>;\n }\n\n private confirmApplied(options?: ConfirmOptions): Promise<AppliedTrade> {\n return confirmAppliedTrade(\n {\n dexBackendBaseUrl: this.backendBaseUrl,\n httpRequestor: this.requestor,\n requestTimeoutMs: this.requestTimeoutMs,\n wire: this.wire,\n },\n { uniqueKey: this.uniqueKey, requestTransactionId: this.transactionId },\n options,\n );\n }\n\n /** Confirm a liquidity write against the position's observable effect.\n *\n * @returns The position after the write, or `null` for a confirmed full close.\n * @example\n * ```ts\n * const position = await submitted.confirm({ timeoutMs: 60_000 });\n * ```\n */\n private async confirmPosition(options?: ConfirmOptions): Promise<Position | null> {\n if (this.positionConfirmation === undefined) throw GSwapSDKError.noWalletAddressError();\n // A liquidity write has already executed when the gateway answers, so the first re-read\n // happens immediately unless the caller asks for a delay.\n const callerSignal = options?.signal;\n const abortError = (cause?: unknown): Error =>\n new GSwapSDKError('CONFIRMATION_ABORTED', {}, { uniqueKey: this.uniqueKey, cause });\n const schedule = createConfirmationSchedule(options, 0, abortError);\n await schedule.waitForRead();\n while (true) {\n const controller = new AbortController();\n const disarm = armTimeout(controller, this.requestTimeoutMs);\n const forwardAbort = (): void => controller.abort();\n callerSignal?.addEventListener('abort', forwardAbort, { once: true });\n try {\n const result = await this.positionConfirmation(controller.signal);\n if (result.confirmed) return result.position;\n } catch (error: unknown) {\n throwIfAborted(callerSignal, abortError);\n throw error;\n } finally {\n disarm();\n callerSignal?.removeEventListener('abort', forwardAbort);\n }\n if (!(await schedule.waitForRead())) break;\n }\n throw GSwapSDKError.confirmationTimeoutError(this.uniqueKey);\n }\n}\n","import type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n getObjectProperty,\n getStringProperty,\n GSwapSDKError,\n isGSwapError,\n UPDATE_REQUIRED_STATUS,\n type GSwapErrorContext,\n} from './gswap_sdk_error.js';\nimport { serverMessageOfBody } from '../utils/server_message.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport type { SubmissionOutcomeUnknownReason } from './error_catalog.js';\nimport type { ShadowSubmitResult } from './shadow_submit.js';\nimport { SubmittedTransaction, type PositionConfirmationResult } from './submitted_transaction.js';\nimport {\n buildRequestHeaders,\n fetchRequestor,\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n validateTimeoutMs,\n} from '../utils/transport.js';\nimport type { AppliedTrade, Position } from '../types/v2_results.js';\n\n/** Options for a chain-gateway client. */\nexport interface ChainGatewayOptions {\n dexBackendBaseUrl: string;\n httpRequestor?: HttpRequestor | undefined;\n walletAddress?: string | undefined;\n /**\n * Timeout of every gateway request in milliseconds (default 30 000); also the per-read timeout\n * of the services built on this gateway and of `confirm()`. `Infinity` arms no timer, for an\n * app whose HTTP stack owns request lifetimes.\n */\n chainCallTimeoutMs?: number | undefined;\n /**\n * Wire format of every request of this gateway and of the services built on it: the headers\n * (`userAgent`, `headers`) of reads AND of the POSTs that submit writes, and the query encoding\n * of reads. `X-Wallet-Address` and `X-Shadow` always win over a same-named `wire.headers` entry.\n */\n wire?: WireOptions | undefined;\n /**\n * Tells the gateway which rejections of YOUR `httpRequestor` mean \"no HTTP answer arrived\" (the\n * connection failed, was reset or dropped), as opposed to an answer your requestor turned into\n * an error (an interceptor that rejects on a 4xx, a version wall). Used only when submitting a\n * write: a rejection it accepts becomes `SUBMISSION_OUTCOME_UNKNOWN` with `reason: 'transport'`\n * (the request may have been queued; the original error is `cause`), and any other rejection\n * reaches the caller unchanged. The SDK's own `TRANSPORT_ERROR` (the default `fetch` requestor,\n * `httpRequestorFromAxios`) always counts, so this is only for requestors that reject with\n * their own errors. Never throw from it; a throw is treated as \"not a transport failure\".\n *\n * @example\n * ```ts\n * new ChainGateway({\n * dexBackendBaseUrl,\n * httpRequestor: galaFetch, // a fetch wrapper: its TypeError is the network failing\n * isTransportFailure: (error) => error instanceof TypeError,\n * });\n * ```\n */\n isTransportFailure?: ((error: unknown) => boolean) | undefined;\n /**\n * Tells the gateway which rejections of YOUR `httpRequestor` are an HTTP ANSWER, and what the\n * answer was: a requestor built on an HTTP client that rejects every non-2xx (an interceptor\n * that throws on a 4xx, a version wall that throws on a 426) loses the answer the SDK reads\n * errors from. Return `{ status, body }` (the parsed JSON, or the raw text; `headers` for\n * `Retry-After`) for such a rejection and the write is handled exactly as if the requestor had\n * resolved that answer: the gateway's own code becomes its catalogued error\n * (`DTO_INVALID`, `RATE_LIMITED`, `CHAIN_DISPATCH_FAILED`, ...), an uncoded body `HTTP_ERROR`,\n * both carrying the signed `uniqueKey` and classified by `classifyFailure` as a write. Return\n * `undefined` for any other rejection: it reaches the caller unchanged. Used only when\n * submitting a write; `isTransportFailure` is asked first (no answer proves nothing, so\n * \"maybe queued\" wins), and a throw from this hook, or a `status` outside 100-599, means \"not an\n * answer\". Never throw from it.\n *\n * @example\n * ```ts\n * new ChainGateway({\n * dexBackendBaseUrl,\n * httpRequestor: httpRequestorFromAxios(instance, { rejectOnHttpError: true }),\n * answerOfRejection: (error) =>\n * error instanceof GatewayError && error.status !== undefined\n * ? { status: error.status, body: error.data }\n * : undefined,\n * });\n * ```\n */\n answerOfRejection?: ((error: unknown) => RejectedAnswer | undefined) | undefined;\n}\n\n/** The HTTP answer a rejection of the app's requestor stands for (see `ChainGatewayOptions.answerOfRejection`). */\nexport interface RejectedAnswer {\n /** The HTTP status of the answer (100-599). */\n status: number;\n /** The answer's body: parsed JSON when it was JSON, else the raw text. */\n body: unknown;\n /** The answer's headers, for `Retry-After`. */\n headers?: Record<string, string | undefined> | undefined;\n}\n\n/** Optional attribution and operation-specific confirmation hooks for a write. */\nexport interface ChainSubmitOptions {\n walletAddress?: string | undefined;\n positionConfirmation?: ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;\n}\n\n/** Thin client for backend-routed v2 writes: synchronous liquidity writes and queued RequestTrade. */\nexport class ChainGateway {\n private readonly requestor: HttpRequestor;\n private readonly walletAddress: string | undefined;\n private readonly chainCallTimeoutMs: number;\n private readonly isTransportFailure: ((error: unknown) => boolean) | undefined;\n private readonly answerOfRejectionHook:\n ((error: unknown) => RejectedAnswer | undefined) | undefined;\n /** The request timeout in milliseconds (`Infinity` when no timer is armed). */\n public readonly requestTimeoutMs: number;\n /** The swap backend base URL every request is sent to, without a trailing slash. */\n public readonly dexBackendBaseUrl: string;\n /** Wire format shared by the read services built on this gateway. */\n public readonly wire: WireOptions;\n\n /** Create a chain gateway client. */\n constructor(options: ChainGatewayOptions) {\n this.dexBackendBaseUrl = trimTrailingSlash(options.dexBackendBaseUrl);\n this.requestor = options.httpRequestor ?? fetchRequestor;\n this.walletAddress = options.walletAddress;\n this.chainCallTimeoutMs = validateTimeoutMs(\n options.chainCallTimeoutMs ?? 30_000,\n 'chainCallTimeoutMs',\n );\n this.requestTimeoutMs = this.chainCallTimeoutMs;\n this.wire = options.wire ?? {};\n this.isTransportFailure = options.isTransportFailure;\n this.answerOfRejectionHook = options.answerOfRejection;\n }\n\n /**\n * Submit a signed v2 DTO through the chain gateway.\n *\n * @throws GSwapSDKError `SUBMISSION_OUTCOME_UNKNOWN` when no answer was read: `params.reason` is\n * `'timeout'` (the POST exceeded `chainCallTimeoutMs`) or `'transport'` (the connection failed\n * or broke off). Either way the write MAY have been queued: keep `error.uniqueKey` and confirm\n * it. Whether to offer the user a Retry (a NEW request under a fresh key) is the app's policy;\n * the SDK states only that the outcome is unknown. Reads keep `TRANSPORT_ERROR`.\n */\n public async submit(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>>;\n public async submit(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction<Position | null>>;\n public async submit(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<SubmittedTransaction> {\n // The synchronous swap was removed from the contract and from this SDK. This is the only\n // place the retired name may appear in the write path; the class guard in\n // tests/foundation.test.ts pins that nothing signs or submits it.\n if (method === 'Trade') {\n throw new GSwapSDKError('METHOD_NOT_SUPPORTED', { method });\n }\n const url = this.writeUrl(method);\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n const headers = buildRequestHeaders(this.wire, {\n json: true,\n fixed: walletAddress === undefined ? {} : { 'X-Wallet-Address': walletAddress },\n });\n const { response, body } = await this.post(method, url, headers, signedBody);\n // Every failure after an answer names the write it is about, so an app can confirm it and a\n // failure classifier can tell a write's HTTP failure from a read's.\n const uniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\n const context = responseContext(response, body, url, uniqueKey);\n\n if (!response.ok) {\n throw gatewayError(response, body, url, uniqueKey);\n }\n\n const envelope = asRecord(body);\n // `error: true` is the gateway refusing the write, even inside a 2xx. It is never a transaction.\n if (envelope?.['error'] === true) {\n throw new GSwapSDKError(\n 'GATEWAY_REPORTED_ERROR',\n { serverMessage: serverMessageOfBody(envelope) },\n context,\n );\n }\n const data = asRecord(envelope?.['data'] ?? envelope?.['Data']);\n if (data === undefined) {\n throw new GSwapSDKError('GATEWAY_DATA_MISSING', {}, context);\n }\n\n const transactionId = getStringProperty(data, 'transactionId');\n const mode = getStringProperty(data, 'mode');\n const rawTransactionId = data['transactionId'];\n const bodyBlockNumber = data['blockNumber'];\n const invalidMode = (): GSwapSDKError<'GATEWAY_MODE_INVALID'> =>\n new GSwapSDKError('GATEWAY_MODE_INVALID', {}, context);\n if (mode !== 'sync' && mode !== 'queued') {\n throw invalidMode();\n }\n if (\n ('transactionId' in data && typeof rawTransactionId !== 'string') ||\n (bodyBlockNumber !== undefined && bodyBlockNumber !== null && !isBlockNumber(bodyBlockNumber))\n ) {\n throw invalidMode();\n }\n if (method === 'RequestTrade' && mode === 'sync') {\n throw new GSwapSDKError('GATEWAY_SYNC_REQUEST_TRADE', {}, context);\n }\n if (method === 'RequestTrade' && mode === 'queued') {\n assertQueuedUnderSignedKey(response, body, url, data, signedBody);\n } else if (mode === 'queued' || !('result' in data)) {\n throw invalidMode();\n }\n\n // Only synchronous writes carry an executed chain result in the gateway response.\n if (mode === 'sync') {\n const embeddedResult = asRecord(data['result']);\n if (embeddedResult !== undefined) {\n const resultStatus = embeddedResult['Status'];\n if (resultStatus !== undefined && resultStatus !== 1) {\n throw GSwapSDKError.fromChainError(\n getStringProperty(embeddedResult, 'ErrorKey') ?? 'CHAIN_ERROR',\n getStringProperty(embeddedResult, 'Message') ?? '',\n context,\n );\n }\n }\n }\n\n const headerTransactionId = readHeader(response, 'x-transaction-id');\n const resolvedTransactionId =\n transactionId === undefined || transactionId === '' ? headerTransactionId : transactionId;\n const blockNumber: number | undefined =\n bodyBlockNumber === null || bodyBlockNumber === undefined\n ? readBlockNumberHeader(response)\n : isBlockNumber(bodyBlockNumber)\n ? bodyBlockNumber\n : undefined;\n return new SubmittedTransaction({\n method,\n uniqueKey,\n transactionId:\n resolvedTransactionId === undefined || resolvedTransactionId === ''\n ? null\n : resolvedTransactionId,\n blockNumber: blockNumber ?? null,\n mode,\n result: mode === 'queued' ? undefined : data['result'],\n envelope: body,\n dexBackendBaseUrl: this.dexBackendBaseUrl,\n httpRequestor: this.requestor,\n requestTimeoutMs: this.chainCallTimeoutMs,\n wire: this.wire,\n ...(options?.positionConfirmation === undefined\n ? {}\n : { positionConfirmation: options.positionConfirmation }),\n });\n }\n\n /**\n * Submit a signed v2 DTO as a SHADOW (dark) write: the same route and body as {@link submit},\n * plus `X-Wallet-Address` and `X-Shadow: true`, so defi-backend marks the transaction private\n * before it reaches the contract. The wallet address is required (the backend resolves the\n * owner from it).\n *\n * Unlike `submit`, EVERY HTTP status resolves: the result is the raw `{ httpStatus, body }`,\n * because shadow failures are classified from the status together with the body's `code`\n * (`SHADOW_UNAVAILABLE`, `SHADOW_UNSUPPORTED_TYPE`, `SHADOW_RELAY_REJECTED`);\n * see `readShadowSubmitOutcome`. Only a failure to get an answer rejects, and it rejects with\n * `SUBMISSION_OUTCOME_UNKNOWN` (`params.reason` `'timeout'` or `'transport'`): the request may\n * have been accepted. Every error it throws has `error.shadow === true`, and a non-SDK object\n * that escapes (your requestor's own rejection) answers `isShadowError(error)`.\n *\n * @example\n * ```ts\n * const result = await gateway.submitShadow('RequestTrade', signedDto, { walletAddress });\n * const outcome = readShadowSubmitOutcome('RequestTrade', signedDto, result);\n * ```\n */\n public async submitShadow(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<ShadowSubmitResult> {\n return shadowFailures(() => this.sendShadow(method, signedBody, options));\n }\n\n private async sendShadow(\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ): Promise<ShadowSubmitResult> {\n if (method === 'Trade') {\n throw new GSwapSDKError('METHOD_NOT_SUPPORTED', { method });\n }\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n if (walletAddress === undefined) {\n throw new GSwapSDKError('SHADOW_SUBMIT_NEEDS_WALLET_ADDRESS', {});\n }\n // Header order is frontend_v2's: X-Wallet-Address, then X-Shadow.\n const headers = buildRequestHeaders(this.wire, {\n json: true,\n fixed: { 'X-Wallet-Address': walletAddress, 'X-Shadow': 'true' },\n });\n const { response, body } = await this.post(method, this.writeUrl(method), headers, signedBody);\n return { httpStatus: response.status, body };\n }\n\n private writeUrl(method: string): string {\n return `${this.dexBackendBaseUrl}/v1/chain/asset/dex-contract/${method}`;\n }\n\n /**\n * POSTs a signed body and reads the answer. Neither a timeout nor a transport failure proves the\n * write was not submitted, so both are `SUBMISSION_OUTCOME_UNKNOWN` (`params.reason` says which),\n * never a retryable read failure. A rejection that is an answer (see `isTransportFailure`) is\n * rethrown unchanged.\n */\n private async post(\n method: string,\n url: string,\n headers: Record<string, string>,\n signedBody: Record<string, unknown>,\n ): Promise<{ response: HTTPResponse; body: unknown }> {\n // Serialized BEFORE the request is attempted and outside the try below: a body that cannot be\n // serialized (a cycle, a BigInt) was never sent, so it must not be mistaken for a transport\n // failure the app's `isTransportFailure` might claim, which would call it \"maybe queued\".\n let payload: string;\n try {\n payload = JSON.stringify(signedBody);\n } catch (cause: unknown) {\n throw new GSwapSDKError('SIGNING_FAILED', { method, reason: 'failed' }, { cause });\n }\n const outcomeUnknown = (\n reason: SubmissionOutcomeUnknownReason,\n cause: unknown,\n ): GSwapSDKError<'SUBMISSION_OUTCOME_UNKNOWN'> =>\n new GSwapSDKError(\n 'SUBMISSION_OUTCOME_UNKNOWN',\n { reason },\n { uniqueKey: getStringProperty(signedBody, 'uniqueKey') ?? '', url, cause },\n );\n let response: HTTPResponse;\n try {\n response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers,\n body: payload,\n },\n this.chainCallTimeoutMs,\n );\n } catch (error: unknown) {\n if (isGSwapError(error, 'REQUEST_TIMEOUT')) throw outcomeUnknown('timeout', error);\n if (isGSwapError(error, 'TRANSPORT_ERROR') || this.isTransportRejection(error)) {\n throw outcomeUnknown('transport', error);\n }\n // A rejection that IS an HTTP answer (the app's interceptor rejecting on a non-2xx, a\n // version wall) is handled exactly as the answer would have been, so the app does not\n // rebuild the SDK's error from it. Anything else the app's requestor threw reaches the\n // caller unchanged.\n const answered = this.answerOfRejection(error);\n if (answered !== undefined) return answered;\n throw error;\n }\n try {\n return { response, body: await readResponseBody(response) };\n } catch (error: unknown) {\n // The answer's headers arrived but its body broke off: the status alone does not say what\n // the gateway did with the write.\n throw outcomeUnknown('transport', error);\n }\n }\n\n /**\n * The HTTP answer a rejection of the app's requestor stands for, as the response the gateway\n * would have read. `undefined` when the app named none, when its hook throws, or when what it\n * returned is not an HTTP status; then the rejection is not an answer.\n */\n private answerOfRejection(error: unknown): { response: HTTPResponse; body: unknown } | undefined {\n let answer: RejectedAnswer | undefined;\n try {\n answer = this.answerOfRejectionHook?.(error);\n } catch {\n return undefined;\n }\n if (answer === undefined) return undefined;\n const { status, body, headers } = answer;\n if (!Number.isInteger(status) || status < 100 || status > 599) return undefined;\n const text = typeof body === 'string' ? body : '';\n const response: HTTPResponse = {\n ok: status >= 200 && status < 300,\n status,\n json: async () => body,\n text: async () => text,\n headers: headers ?? {},\n };\n return { response, body };\n }\n\n private isTransportRejection(error: unknown): boolean {\n try {\n return this.isTransportFailure?.(error) === true;\n } catch {\n return false;\n }\n }\n\n /** Expose the requestor for sibling read services that share this gateway transport. */\n public get httpRequestor(): HttpRequestor {\n return this.requestor;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/u, '');\n}\n\nfunction responseContext(\n response: HTTPResponse,\n body: unknown,\n url: string,\n uniqueKey?: string,\n): GSwapErrorContext {\n return {\n status: response.status,\n body,\n url,\n ...(uniqueKey === undefined || uniqueKey === '' ? {} : { uniqueKey }),\n };\n}\n\n/**\n * A queued RequestTrade acknowledgement is a swap only if it names the exact key that was signed:\n * the key is the only handle `confirm()` and every recovery path have on the trade, so an\n * acknowledgement without it (or with another) proves nothing about THIS request. Fails closed:\n * an absent echo is as unacceptable as a wrong one. The code is `MISSING_UNIQUE_KEY` or\n * `UNIQUE_KEY_MISMATCH`, `error.uniqueKey` the signed key.\n *\n * Only RequestTrade is checked: a synchronous write is proven by its own executed chain result,\n * and the apps never required an echo for it.\n */\nfunction assertQueuedUnderSignedKey(\n response: HTTPResponse,\n body: unknown,\n url: string,\n data: Record<string, unknown>,\n signedBody: Record<string, unknown>,\n): void {\n const signedUniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\n const echoed = data['uniqueKey'];\n if (typeof echoed === 'string' && echoed !== '' && echoed === signedUniqueKey) return;\n const missing = echoed === undefined || echoed === null || echoed === '';\n const context: GSwapErrorContext = {\n ...responseContext(response, body, url),\n uniqueKey: signedUniqueKey,\n };\n throw missing\n ? new GSwapSDKError('MISSING_UNIQUE_KEY', {}, context)\n : new GSwapSDKError('UNIQUE_KEY_MISMATCH', {}, context);\n}\n\nfunction gatewayError(\n response: HTTPResponse,\n body: unknown,\n url: string,\n uniqueKey: string,\n): GSwapSDKError {\n // The version wall is decided by the status alone, whatever the body names: nothing was queued.\n if (response.status === UPDATE_REQUIRED_STATUS) {\n return new GSwapSDKError(\n 'UPDATE_REQUIRED',\n { status: response.status },\n responseContext(response, body, url, uniqueKey),\n );\n }\n const object = asRecord(body);\n const nested = getObjectProperty(body, 'error');\n const code =\n getStringProperty(object, 'code') ??\n getStringProperty(nested, 'code') ??\n getStringProperty(nested, 'ErrorKey') ??\n 'HTTP_ERROR';\n // Missing server text is an empty param, never SDK-written English standing in for it. A body\n // that is not JSON (an HTML 502 page, a WAF block) is kept as error.bodyText.\n const message = serverMessageOfBody(body);\n const retryAfterMs = response.status === 429 ? readRetryAfter(response) : undefined;\n if (code === 'HTTP_ERROR') {\n return new GSwapSDKError(\n 'HTTP_ERROR',\n { status: response.status, url, serverMessage: message },\n responseContext(response, body, url, uniqueKey),\n );\n }\n return GSwapSDKError.fromGatewayBounce(\n code,\n message,\n response.status,\n body,\n url,\n retryAfterMs,\n uniqueKey === '' ? undefined : uniqueKey,\n );\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\nfunction isBlockNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isInteger(value) && value >= 0;\n}\n","/** SDK deployment environment. */\nexport type GSwapEnv = 'prod' | 'stage';\n\n/** Backend URLs used by one SDK deployment environment. */\nexport interface GSwapEnvironmentConfig {\n dexBackendBaseUrl: string;\n /** The realtime stream endpoint (raw WebSocket, JSON-RPC 2.0). */\n dexBackendWsUrl: string;\n}\n\n/** Built-in GalaSwap deployment environments. */\nexport const GSWAP_ENVIRONMENTS: Readonly<Record<GSwapEnv, GSwapEnvironmentConfig>> = {\n prod: {\n dexBackendBaseUrl: 'https://dex-backend-prod1.defi.gala.com',\n dexBackendWsUrl: 'wss://dex-backend-prod1.defi.gala.com/ws',\n },\n stage: {\n dexBackendBaseUrl: 'https://swap-backend.stage.defi.ovh.gala.com',\n dexBackendWsUrl: 'wss://swap-backend.stage.defi.ovh.gala.com/ws',\n },\n};\n","import debug from 'debug';\n\nexport const debugLog = debug('GSWAP_SDK');\n","/** Options for {@link ReconnectionBackoff}. */\nexport interface ReconnectionBackoffOptions {\n /** Attempts allowed before giving up. */\n maxAttempts: number;\n /** Delay before the first attempt, in milliseconds. */\n baseDelayMs: number;\n /** Ceiling the doubling delay never exceeds, in milliseconds. */\n maxDelayMs?: number;\n}\n\n/** Counts reconnect attempts and doubles the delay between them, up to a ceiling. */\nexport class ReconnectionBackoff {\n private attempts = 0;\n private delayMs: number;\n private readonly maxDelayMs: number;\n\n constructor(private readonly options: ReconnectionBackoffOptions) {\n this.delayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? 30_000;\n }\n\n /** Whether another attempt is allowed. */\n shouldRetry(): boolean {\n return this.attempts < this.options.maxAttempts;\n }\n\n /** The delay to wait before the next attempt. */\n nextDelayMs(): number {\n return this.delayMs;\n }\n\n /** Record that an attempt is being made, and double the next delay. */\n recordAttempt(): void {\n this.attempts += 1;\n this.delayMs = Math.min(this.delayMs * 2, this.maxDelayMs);\n }\n\n /** Forget every attempt: the connection is healthy again. */\n reset(): void {\n this.attempts = 0;\n this.delayMs = this.options.baseDelayMs;\n }\n\n get attemptCount(): number {\n return this.attempts;\n }\n\n get maxAttempts(): number {\n return this.options.maxAttempts;\n }\n}\n","import { GSWAP_ENVIRONMENTS } from '../types/env.js';\nimport { debugLog } from '../utils/debug.js';\nimport { ReconnectionBackoff } from '../utils/reconnection.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\nconst GDEX_SUBPROTOCOL = 'gdex.jsonrpc.v1';\nconst RATE_LIMITED = -32003;\nconst MAX_RESUBSCRIBE_RATE_RETRIES = 5;\nconst WEBSOCKET_OPEN = 1;\n\n/** Options for {@link GdexStreamService}. */\nexport interface GdexStreamConfig {\n /** Stream endpoint. Defaults to production (`wss://dex-backend-prod1.defi.gala.com/ws`). */\n url?: string | undefined;\n /** Reconnect attempts after an unexpected close. Default 5. */\n reconnectAttempts?: number | undefined;\n /** Delay before the first reconnect attempt; doubles each attempt. Default 2000 ms. */\n reconnectDelayMs?: number | undefined;\n /** How long a request waits for its response. Default 15000 ms. */\n requestTimeoutMs?: number | undefined;\n /**\n * A standards-compatible WebSocket constructor. Required on Node.js older than 22, which has no\n * global `WebSocket` (pass the one from the `ws` package).\n */\n webSocketImpl?: unknown;\n /**\n * Presents `x-api-key` on the WebSocket upgrade request, which defi-backend uses to serve the\n * PRIVILEGED view (shadow swaps with the wallet unredacted). Without it, or with a wrong key, the\n * connection is simply public: the server never says whether a privileged mode exists.\n *\n * It must travel as an HTTP header, because the server reads no other credential, and a browser\n * `WebSocket` cannot set headers. So this option needs a constructor that accepts them as its\n * third argument (`{ headers }`): the `ws` package on Node.js, or React Native's built-in\n * `WebSocket`. It therefore REQUIRES `webSocketImpl` (the platform default is never assumed to\n * honor headers, and a key that is silently dropped would look like a working privileged\n * connection); the constructor throws otherwise. Use it from server-side code only: a key\n * shipped inside a browser or app bundle is not a secret. Browser clients stay public.\n */\n apiKey?: string | undefined;\n}\n\n/** The channels of the realtime stream. */\nexport type GdexChannel = 'pool' | 'balance' | 'poolCreated' | 'swap' | 'liquidity' | 'blocks';\n\n/** A pool named by its two token class keys (pipe form) and fee tier. */\nexport interface GdexPoolKey {\n token0ClassKey: string;\n token1ClassKey: string;\n fee: number;\n}\n\n/** A pool named either by its key or by its hash (`v2:<poolRef>` for a v2 pool). */\nexport type GdexPoolSelector = { pool: GdexPoolKey } | { poolHash: string };\n\n/** Options common to every subscription. */\nexport interface GdexSubscribeOptions {\n /** Send the current state right after the subscribe response. */\n snapshot?: boolean | undefined;\n /** Trim each event to these fields; identity and envelope fields always stay. */\n fields?: string[] | undefined;\n}\n\n/** Filters for {@link GdexStreamService.subscribeLiquidity}; all optional. */\nexport interface GdexLiquidityFilter {\n /** Only this pool, named by its key. */\n pool?: GdexPoolKey | undefined;\n /** Only this pool, named by its hash (`v2:<poolRef>` for a v2 pool). */\n poolHash?: string | undefined;\n /** Only events for this LP wallet (the position's owner). */\n owner?: string | undefined;\n /** Only this transaction. */\n transactionId?: string | undefined;\n /** Contract version filter. */\n version?: 'v1' | 'v2' | 'all' | undefined;\n}\n\n/** One committed add, remove or collect, as the `liquidity` channel reports it. */\nexport interface GdexLiquidityEvent {\n version: 'v1' | 'v2';\n pool: GdexPoolKey;\n poolHash: string;\n transactionId: string;\n /** `add`, `remove` or `collect`. */\n action: 'add' | 'remove' | 'collect';\n /** The position's owner (the LP wallet). */\n owner: string;\n /** v1: the position id. v2: the chain position key `<pool>|<tickLow>|<tickHigh>|<owner>`. */\n positionId?: string;\n tickLower?: number;\n tickUpper?: number;\n /** v2 only: the position's liquidity after the operation; `\"0\"` means it is closed. */\n liquidityAfter?: string;\n /** Principal moved: deposited by an add, withdrawn by a remove, `\"0\"` for a collect. */\n amount0: string;\n amount1: string;\n /** Fees paid out. v2: always present (`\"0\"` for an add). v1: present on a collect only. */\n fees0?: string;\n fees1?: string;\n /** v2 only. */\n token0Symbol?: string;\n token1Symbol?: string;\n blockNumber: number;\n timestamp: string;\n}\n\nconst LIQUIDITY_ACTIONS: readonly unknown[] = ['add', 'remove', 'collect'];\n\n/** Whether a stream payload carries every field of a {@link GdexLiquidityEvent}. */\nexport function isGdexLiquidityEvent(\n value: Record<string, unknown>,\n): value is Record<string, unknown> & GdexLiquidityEvent {\n const { pool } = value;\n return (\n (value['version'] === 'v1' || value['version'] === 'v2') &&\n typeof pool === 'object' &&\n pool !== null &&\n typeof value['poolHash'] === 'string' &&\n typeof value['transactionId'] === 'string' &&\n LIQUIDITY_ACTIONS.includes(value['action']) &&\n typeof value['owner'] === 'string' &&\n typeof value['amount0'] === 'string' &&\n typeof value['amount1'] === 'string' &&\n typeof value['blockNumber'] === 'number' &&\n typeof value['timestamp'] === 'string'\n );\n}\n\n/** A live subscription. */\nexport interface GdexSubscription {\n subscriptionId: string;\n unsubscribe(): Promise<void>;\n}\n\n/** A JSON-RPC error answered by the stream. */\nexport class GdexStreamError extends Error {\n /** The JSON-RPC error code. */\n readonly code: number;\n /** The error's optional `data` member, as the server sent it. */\n readonly data?: unknown;\n\n constructor(code: number, message: string, data?: unknown) {\n super(message);\n this.name = 'GdexStreamError';\n this.code = code;\n if (data !== undefined) this.data = data;\n }\n}\n\ninterface WebSocketLike {\n readonly readyState: number;\n send(data: string): void;\n close(code?: number, reason?: string): void;\n onopen: ((event: unknown) => void) | null;\n onmessage: ((event: { data: unknown }) => void) | null;\n onclose: ((event: { code?: number; reason?: string }) => void) | null;\n onerror: ((event: unknown) => void) | null;\n}\n\ninterface WebSocketConstructor {\n new (\n url: string,\n protocols?: string | string[],\n options?: { headers: Record<string, string> },\n ): WebSocketLike;\n}\n\ninterface PendingRequest {\n resolve(value: unknown): void;\n reject(error: Error): void;\n timeout: ReturnType<typeof setTimeout>;\n /**\n * Runs SYNCHRONOUSLY when the response frame is handled, before any frame that follows it in\n * the same read. Subscriptions register here: the server writes a snapshot right after the\n * subscribe response, and a runtime that delivers both frames without yielding to microtasks\n * (Node's `ws` does, for frames in one chunk) would otherwise drop the snapshot because the\n * awaiting caller has not registered the subscription yet.\n */\n onResult?: ((value: unknown) => void) | undefined;\n}\n\ntype EventCallback = (event: Record<string, unknown>) => void;\n\ninterface ActiveSubscription {\n serverId: string;\n readonly params: Record<string, unknown>;\n readonly callback: EventCallback;\n readonly handle: MutableGdexSubscription;\n active: boolean;\n}\n\ninterface MutableGdexSubscription extends GdexSubscription {\n subscriptionId: string;\n}\n\nfunction readSubscriptionId(value: unknown): string {\n const id =\n typeof value === 'object' && value !== null\n ? (value as { subscriptionId?: unknown }).subscriptionId\n : undefined;\n if (typeof id !== 'string') {\n throw new GdexStreamError(-32603, 'GDEX subscribe response is missing its subscriptionId');\n }\n return id;\n}\n\ninterface JsonRpcResponse {\n id?: unknown;\n method?: unknown;\n result?: unknown;\n error?: { code?: unknown; message?: unknown; data?: unknown };\n params?: unknown;\n}\n\n/**\n * Client for the gSwap realtime stream (gdex WebSocket Protocol v1): JSON-RPC 2.0 over one raw\n * WebSocket, with automatic reconnect and resubscribe.\n *\n * @example\n * ```typescript\n * const stream = new GdexStreamService();\n * await stream.connect();\n * await stream.subscribeLiquidity(event => console.log(event.action, event.owner), {\n * owner: 'client|618ae395c1c653111d3315be',\n * });\n * ```\n */\nexport class GdexStreamService {\n private readonly url: string;\n private readonly requestTimeoutMs: number;\n private readonly apiKey: string | undefined;\n private readonly webSocketConstructor: WebSocketConstructor;\n private readonly backoff: ReconnectionBackoff;\n private socket: WebSocketLike | undefined;\n private connectPromise: Promise<void> | undefined;\n private nextRequestId = 0;\n private readonly pending = new Map<number, PendingRequest>();\n private readonly subscriptionsByServerId = new Map<string, ActiveSubscription>();\n private readonly activeSubscriptions = new Set<ActiveSubscription>();\n private intentionalClose = false;\n private reconnecting = false;\n private reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n private reconnectDelayResolve: (() => void) | undefined;\n\n constructor(config: GdexStreamConfig = {}) {\n this.url = config.url ?? GSWAP_ENVIRONMENTS.prod.dexBackendWsUrl;\n this.requestTimeoutMs = config.requestTimeoutMs ?? 15_000;\n this.backoff = new ReconnectionBackoff({\n maxAttempts: config.reconnectAttempts ?? 5,\n baseDelayMs: config.reconnectDelayMs ?? 2_000,\n });\n\n const implementation =\n config.webSocketImpl ?? (globalThis as { WebSocket?: unknown }).WebSocket;\n if (typeof implementation !== 'function') {\n throw new GSwapSDKError('STREAM_WEBSOCKET_UNAVAILABLE', {});\n }\n this.webSocketConstructor = implementation as WebSocketConstructor;\n if (config.apiKey !== undefined) {\n if (config.apiKey === '' || config.webSocketImpl === undefined) {\n throw new GSwapSDKError('STREAM_API_KEY_UNUSABLE', {});\n }\n this.apiKey = config.apiKey;\n }\n }\n\n /** Open the connection. Resolves at once when already connected. */\n connect(): Promise<void> {\n if (this.isConnected()) return Promise.resolve();\n if (this.connectPromise) return this.connectPromise;\n this.intentionalClose = false;\n this.clearReconnectTimer();\n this.connectPromise = this.openSocket();\n return this.connectPromise;\n }\n\n /** Close the connection and stop reconnecting. */\n disconnect(): void {\n this.intentionalClose = true;\n this.reconnecting = false;\n this.clearReconnectTimer();\n this.rejectPending(new GSwapSDKError('STREAM_DISCONNECTED', {}));\n const socket = this.socket;\n this.socket = undefined;\n this.connectPromise = undefined;\n socket?.close(1000, 'client disconnect');\n }\n\n /** `true` while the socket is open (false while connecting, reconnecting or after `disconnect()`). */\n isConnected(): boolean {\n return this.socket?.readyState === WEBSOCKET_OPEN;\n }\n\n /** Raw JSON-RPC escape hatch. */\n request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T> {\n return this.send<T>(method, params);\n }\n\n private send<T>(\n method: string,\n params: Record<string, unknown> | undefined,\n onResult?: (value: unknown) => void,\n ): Promise<T> {\n if (!this.isConnected() || !this.socket) {\n return Promise.reject(new GSwapSDKError('STREAM_NOT_CONNECTED', {}));\n }\n\n const id = ++this.nextRequestId;\n const frame: Record<string, unknown> = { jsonrpc: '2.0', id, method };\n if (params !== undefined) frame['params'] = params;\n\n return new Promise<T>((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(id);\n reject(\n new GSwapSDKError('STREAM_REQUEST_TIMEOUT', { method, timeoutMs: this.requestTimeoutMs }),\n );\n }, this.requestTimeoutMs);\n this.pending.set(id, { resolve: (value) => resolve(value as T), reject, timeout, onResult });\n\n try {\n this.socket?.send(JSON.stringify(frame));\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(id);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n /** `gdex_serverInfo`: the server's own description of itself, as it sends it. */\n serverInfo(): Promise<Record<string, unknown>> {\n return this.request('gdex_serverInfo');\n }\n\n /** `gdex_ping`: a round trip that answers `{ pong, serverTime }`. */\n ping(): Promise<{ pong: boolean; serverTime: string }> {\n return this.request('gdex_ping');\n }\n\n /** `gdex_getPool`: the current state of one pool, selected by its key or hash. */\n getPool(selector: GdexPoolSelector): Promise<Record<string, unknown>> {\n return this.request('gdex_getPool', selector);\n }\n\n /** `gdex_getBalance`: an owner's balances, or only the one of `tokenClassKey` when given. */\n getBalance(owner: string, tokenClassKey?: string): Promise<Record<string, unknown>> {\n return this.request(\n 'gdex_getBalance',\n tokenClassKey === undefined ? { owner } : { owner, tokenClassKey },\n );\n }\n\n /**\n * `gdex_getPositions`: an owner's positions, optionally in one pool, a page at a time. Pass the\n * returned `bookmark` back in as `bookmark` for the next page.\n */\n getPositions(opts: {\n owner: string;\n pool?: GdexPoolKey;\n poolHash?: string;\n limit?: number;\n bookmark?: string;\n }): Promise<{ positions: Record<string, unknown>[]; bookmark: string }> {\n return this.request('gdex_getPositions', opts);\n }\n\n /** `gdex_getBlockHeight`: the block number the server reports, with its timestamp. */\n getBlockHeight(): Promise<{ blockNumber: number; timestamp: string }> {\n return this.request('gdex_getBlockHeight');\n }\n\n /** `gdex_quote`: a quote over the stream; give exactly one of `amountIn` or `amountOut`. */\n quote(params: {\n tokenIn: string;\n tokenOut: string;\n fee?: number;\n amountIn?: string;\n amountOut?: string;\n }): Promise<Record<string, unknown>> {\n return this.request('gdex_quote', params);\n }\n\n /** `gdex_getToken`: the server's record of one token class, as it sends it. */\n getToken(tokenClassKey: string): Promise<Record<string, unknown>> {\n return this.request('gdex_getToken', { tokenClassKey });\n }\n\n /** One event per committed swap. Omit the pool to receive every pool's swaps. */\n subscribeSwaps(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & {\n pool?: GdexPoolKey;\n poolHash?: string;\n transactionId?: string;\n } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('swap', cb, opts);\n }\n\n /**\n * State changes of one pool (price, tick, reserves, liquidity). These events carry no acting wallet:\n * on v2 `creator` is whoever created the pool, not whoever just traded or added liquidity. For\n * \"who did it\", use {@link subscribeLiquidity} (`owner`) or {@link subscribeSwaps} (`sender`).\n */\n subscribePool(\n selector: GdexPoolSelector,\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('pool', cb, { ...selector, ...opts });\n }\n\n /** Balance changes of one wallet. */\n subscribeBalances(\n owner: string,\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & { tokenClassKey?: string } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('balance', cb, { owner, ...opts });\n }\n\n /** Each newly created pool. */\n subscribePoolCreated(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions & { tokenClassKey?: string } = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('poolCreated', cb, opts);\n }\n\n /**\n * One event per committed AddLiquidity, RemoveLiquidity and CollectPositionFees, on both contract\n * versions. Every filter is optional; with none, every liquidity event arrives. These events never\n * appear on {@link subscribeSwaps}. There is no snapshot: read positions with {@link getPositions}.\n * Deduplicate by `transactionId` plus `positionId`: a v1 BatchSubmit can hold several operations\n * under one transaction id.\n */\n subscribeLiquidity(\n cb: (event: GdexLiquidityEvent) => void,\n opts: GdexSubscribeOptions & GdexLiquidityFilter = {},\n ): Promise<GdexSubscription> {\n return this.subscribe(\n 'liquidity',\n (event) => {\n if (isGdexLiquidityEvent(event)) cb(event);\n else debugLog('Ignoring a malformed liquidity event from the GDEX stream');\n },\n opts,\n );\n }\n\n /** Each block-height advance. */\n subscribeBlocks(\n cb: (event: Record<string, unknown>) => void,\n opts: GdexSubscribeOptions = {},\n ): Promise<GdexSubscription> {\n return this.subscribe('blocks', cb, opts);\n }\n\n private openSocket(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n let opened = false;\n const socket =\n this.apiKey === undefined\n ? new this.webSocketConstructor(this.url, GDEX_SUBPROTOCOL)\n : new this.webSocketConstructor(this.url, GDEX_SUBPROTOCOL, {\n headers: { 'x-api-key': this.apiKey },\n });\n this.socket = socket;\n\n socket.onopen = () => {\n if (this.socket !== socket) return;\n opened = true;\n this.connectPromise = undefined;\n if (!this.reconnecting) this.backoff.reset();\n debugLog('Connected to GDEX stream');\n resolve();\n };\n socket.onmessage = (event) => this.handleMessage(event.data);\n socket.onerror = () => {\n if (!opened) reject(new GSwapSDKError('STREAM_CONNECT_FAILED', { url: this.url }));\n };\n socket.onclose = (event) => {\n if (this.socket !== socket) return;\n this.socket = undefined;\n this.connectPromise = undefined;\n if (!opened) {\n reject(new GSwapSDKError('STREAM_CLOSED_BEFORE_CONNECT', { closeCode: event.code ?? 0 }));\n }\n this.rejectPending(\n new GSwapSDKError('STREAM_CONNECTION_CLOSED', { closeCode: event.code ?? 0 }),\n );\n if (!this.intentionalClose && !this.reconnecting) this.startReconnectLoop();\n };\n });\n }\n\n private handleMessage(data: unknown): void {\n if (typeof data !== 'string') {\n debugLog('Ignoring non-text GDEX WebSocket frame');\n return;\n }\n\n let message: JsonRpcResponse;\n try {\n message = JSON.parse(data) as JsonRpcResponse;\n } catch {\n debugLog('Ignoring invalid JSON from GDEX stream');\n return;\n }\n\n if (typeof message.id === 'number') {\n const pending = this.pending.get(message.id);\n if (!pending) return;\n clearTimeout(pending.timeout);\n this.pending.delete(message.id);\n if (message.error) {\n const code = typeof message.error.code === 'number' ? message.error.code : -32603;\n const errorMessage =\n typeof message.error.message === 'string' ? message.error.message : 'GDEX request failed';\n pending.reject(new GdexStreamError(code, errorMessage, message.error.data));\n } else {\n try {\n pending.onResult?.(message.result);\n } catch (error) {\n pending.reject(error instanceof Error ? error : new Error(String(error)));\n return;\n }\n pending.resolve(message.result);\n }\n return;\n }\n\n if (message.method !== 'gdex_subscription' || !this.isRecord(message.params)) return;\n const subscriptionId = message.params['subscription'];\n const result = message.params['result'];\n if (typeof subscriptionId !== 'string' || !this.isRecord(result)) return;\n const subscription = this.subscriptionsByServerId.get(subscriptionId);\n if (!subscription?.active) return;\n try {\n subscription.callback(result);\n } catch (error) {\n debugLog('GDEX subscription callback failed', error);\n }\n }\n\n private async subscribe(\n channel: GdexChannel,\n callback: EventCallback,\n options: object,\n ): Promise<GdexSubscription> {\n const params: Record<string, unknown> = { channel, ...options };\n const handle: MutableGdexSubscription = {\n subscriptionId: '',\n unsubscribe: async () => this.unsubscribe(subscription),\n };\n const subscription: ActiveSubscription = {\n serverId: '',\n params,\n callback,\n handle,\n active: true,\n };\n // Registered inside the response handler, not after the await: see PendingRequest.onResult.\n await this.send('gdex_subscribe', params, (value) => {\n const serverId = readSubscriptionId(value);\n subscription.serverId = serverId;\n handle.subscriptionId = serverId;\n this.activeSubscriptions.add(subscription);\n this.subscriptionsByServerId.set(serverId, subscription);\n });\n return handle;\n }\n\n private async unsubscribe(subscription: ActiveSubscription): Promise<void> {\n if (!subscription.active) return;\n subscription.active = false;\n this.activeSubscriptions.delete(subscription);\n this.subscriptionsByServerId.delete(subscription.serverId);\n if (this.isConnected()) {\n await this.request('gdex_unsubscribe', { subscriptionId: subscription.serverId });\n }\n }\n\n private startReconnectLoop(): void {\n if (this.reconnecting || this.intentionalClose) return;\n this.reconnecting = true;\n void this.reconnectLoop();\n }\n\n private async reconnectLoop(): Promise<void> {\n while (!this.intentionalClose && this.backoff.shouldRetry()) {\n const delay = this.backoff.nextDelayMs();\n this.backoff.recordAttempt();\n debugLog(\n `GDEX reconnect attempt ${this.backoff.attemptCount}/${this.backoff.maxAttempts} in ${delay}ms`,\n );\n await this.waitForReconnectDelay(delay);\n // `disconnect()` can run while the asynchronous delay is pending.\n if (this.intentionalClose) break;\n\n try {\n await this.openSocket();\n await this.resubscribeAll();\n this.backoff.reset();\n this.reconnecting = false;\n return;\n } catch (error) {\n debugLog(\n `GDEX reconnect failed: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n this.reconnecting = false;\n if (!this.intentionalClose) debugLog('GDEX reconnection attempts exhausted');\n }\n\n private async resubscribeAll(): Promise<void> {\n this.subscriptionsByServerId.clear();\n for (const subscription of this.activeSubscriptions) {\n if (!subscription.active) continue;\n const params = { ...subscription.params, snapshot: true };\n const result = await this.resubscribeWithRateLimitRetry(params, (value) => {\n const serverId = readSubscriptionId(value);\n // The consumer can unsubscribe while the asynchronous subscribe request is pending.\n if (!subscription.active) return;\n subscription.serverId = serverId;\n subscription.handle.subscriptionId = serverId;\n this.subscriptionsByServerId.set(serverId, subscription);\n });\n if (!subscription.active) {\n await this.request('gdex_unsubscribe', { subscriptionId: result.subscriptionId });\n }\n }\n }\n\n private async resubscribeWithRateLimitRetry(\n params: Record<string, unknown>,\n onResult: (value: unknown) => void,\n ): Promise<{ subscriptionId: string }> {\n for (let attempt = 0; ; attempt++) {\n try {\n return await this.send('gdex_subscribe', params, onResult);\n } catch (error) {\n if (\n !(error instanceof GdexStreamError) ||\n error.code !== RATE_LIMITED ||\n attempt >= MAX_RESUBSCRIBE_RATE_RETRIES\n ) {\n throw error;\n }\n const retryAfterMs = this.readRetryAfterMs(error.data);\n debugLog(`GDEX resubscribe rate limited; retrying in ${retryAfterMs}ms`);\n await new Promise<void>((resolve) => setTimeout(resolve, retryAfterMs));\n }\n }\n }\n\n private waitForReconnectDelay(delay: number): Promise<void> {\n return new Promise((resolve) => {\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = undefined;\n this.reconnectDelayResolve = undefined;\n resolve();\n }, delay);\n this.reconnectDelayResolve = resolve;\n });\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer !== undefined) clearTimeout(this.reconnectTimer);\n this.reconnectTimer = undefined;\n const resolve = this.reconnectDelayResolve;\n this.reconnectDelayResolve = undefined;\n resolve?.();\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n pending.reject(error);\n }\n this.pending.clear();\n }\n\n private readRetryAfterMs(data: unknown): number {\n if (\n !this.isRecord(data) ||\n typeof data['retryAfterMs'] !== 'number' ||\n data['retryAfterMs'] < 0\n )\n return 1_000;\n return data['retryAfterMs'];\n }\n\n private isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n }\n}\n","import type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { debugLog } from '../utils/debug.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport {\n buildQueryString,\n buildRequestHeaders,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n} from '../utils/transport.js';\n\nexport class HttpClient {\n /**\n * Create an HTTP client around fetch or an injected requestor. `wire` selects the query\n * encoding and the `User-Agent` (see {@link WireOptions}).\n */\n constructor(\n private readonly httpRequestor: HttpRequestor = fetchRequestor,\n private readonly timeoutMs = 30_000,\n private readonly wire: WireOptions = {},\n ) {}\n\n private async sendRequest<TReturnType>(\n method: 'POST' | 'GET',\n baseUrl: string,\n basePath: string,\n endpoint: string,\n body?: unknown,\n options?: Pick<RequestInit, 'signal'>,\n ): Promise<TReturnType> {\n const url = `${baseUrl}${basePath}${endpoint}`;\n debugLog(`Sending request to ${url} with body:`, body);\n\n const hasBody = Boolean(body);\n const response = await requestWithTimeout(\n this.httpRequestor,\n url,\n {\n method,\n // Content-Type describes a body, so a GET carries none: it also keeps a browser's\n // cross-origin GET a simple request instead of forcing a CORS preflight.\n headers: buildRequestHeaders(this.wire, { json: hasBody }),\n ...(hasBody ? { body: JSON.stringify(body) } : {}),\n ...(options?.signal === undefined ? {} : { signal: options.signal }),\n },\n this.timeoutMs,\n );\n\n if (!response.ok) {\n throw await GSwapSDKError.fromErrorResponse(url, response);\n }\n\n const json = await readResponseBody(response);\n debugLog(`Response from ${baseUrl}${basePath}${endpoint}:`, json);\n\n return json as TReturnType;\n }\n\n /** Send a JSON POST request and decode its response. */\n async sendPostRequest<TReturnType>(\n baseUrl: string,\n basePath: string,\n endpoint: string,\n body: unknown,\n ): Promise<TReturnType> {\n return this.sendRequest('POST', baseUrl, basePath, endpoint, body);\n }\n\n /** Send a GET request with URL-encoded query parameters and decode its response. */\n async sendGetRequest<TReturnType>(\n baseUrl: string,\n basePath: string,\n endpoint: string,\n params?: Record<string, string>,\n options?: Pick<RequestInit, 'signal'>,\n ): Promise<TReturnType> {\n const endpointWithParams = params\n ? `${endpoint}?${buildQueryString(params, this.wire.queryEncoding)}`\n : endpoint;\n\n return this.sendRequest('GET', baseUrl, basePath, endpointWithParams, undefined, options);\n }\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** One row of a list answer that the SDK skipped because it was not usable. */\nexport interface InvalidEntry {\n /** Which read the row came from. */\n source: 'pools' | 'symbols' | 'positions';\n /** Position of the row in the answer's array. */\n index: number;\n /** The row exactly as the backend sent it. */\n entry: unknown;\n /** Why it was skipped, in words. */\n reason: string;\n}\n\n/**\n * Called once per skipped row, in order, before the read resolves. It is a diagnostics hook: what it\n * does, or throws, never changes the result of the read.\n */\nexport type InvalidEntryHandler = (invalid: InvalidEntry) => void;\n\n/** The outcome of reading one row. */\nexport type EntryParse<T> = { ok: true; value: T } | { ok: false; reason: string };\n\n/** A usable row. */\nexport function entryOk<T>(value: T): EntryParse<T> {\n return { ok: true, value };\n}\n\n/** An unusable row, with the reason it is reported under. */\nexport function entryRejected<T>(reason: string): EntryParse<T> {\n return { ok: false, reason };\n}\n\n/**\n * Reads a list answer row by row: a row that cannot be used is skipped and reported, instead of\n * rejecting the whole list because of one bad row. An answer that is not a list at all is still\n * `INVALID_CHAIN_RESPONSE`: nothing in it can be trusted.\n */\nexport function readEntries<T>(\n source: InvalidEntry['source'],\n data: unknown,\n parse: (entry: unknown) => EntryParse<T>,\n onInvalidEntry?: InvalidEntryHandler,\n): T[] {\n if (!Array.isArray(data)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: `${source} list` },\n { body: data },\n );\n }\n const rows: T[] = [];\n (data as unknown[]).forEach((entry, index) => {\n const parsed = parse(entry);\n if (parsed.ok) {\n rows.push(parsed.value);\n return;\n }\n try {\n onInvalidEntry?.({ source, index, entry, reason: parsed.reason });\n } catch {\n // A diagnostics hook must not turn a lenient read into a failed one.\n }\n });\n return rows;\n}\n\n/** A plain JSON object (not null, not an array). */\nexport function asEntryRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** A finite number, or a non-empty numeric string, as a number; otherwise `undefined`. */\nexport function finiteNumberOf(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined;\n if (typeof value === 'string' && value.trim() !== '') {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\n\n/**\n * Token class keys that never throw: the `$`-joined composite key and the non-throwing parsers.\n * This module imports nothing at run time (the key type is erased), so an app shell that reads a\n * stored key pays for a few hundred bytes, never for the error class or the catalog. The parser\n * that THROWS an SDK error on a bad key (`parseTokenClassKey`) lives in `ordering.ts`.\n */\n\n/** Return the `$`-joined composite key used by GalaChain object identities. */\nexport function compositeKeyOf(token: GalaChainTokenClassKey): string {\n return [token.collection, token.category, token.type, token.additionalKey].join('$');\n}\n\n/**\n * Splits `collection<d>category<d>type<d>additionalKey` from the right, or `undefined` when there\n * are fewer than four segments or any of the four is empty. The one place the split is written;\n * the strict `parseTokenClassKey` calls it too.\n *\n * The LAST three segments are always `category`, `type` and `additionalKey`; everything before\n * them is the `collection`. Parsing from the right is required because real collections contain\n * the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`\n * shifts every field.\n */\nexport function splitClassKey(\n key: string,\n delimiter: '|' | '$',\n): GalaChainTokenClassKey | undefined {\n const segments = key.split(delimiter);\n const tail = segments.slice(-3);\n const collection = segments.slice(0, -3).join(delimiter);\n if (segments.length < 4 || collection.length === 0 || tail.some((part) => part.length === 0)) {\n return undefined;\n }\n const [category, type, additionalKey] = tail;\n return {\n collection,\n category: category as string,\n type: type as string,\n additionalKey: additionalKey as string,\n };\n}\n\n/**\n * The non-throwing `parseTokenClassKey`: the class key, or `undefined` when `value` is not\n * one. A string is split exactly as `parseTokenClassKey` splits it (`|` form when it contains a\n * `|`, else `$`, from the right, all four parts non-empty). Unlike `parseTokenClassKey`, an\n * object is VALIDATED, not just copied: all four fields must be non-empty strings. Anything else\n * (`undefined`, `null`, a number, an array) is `undefined`, so it is safe on untrusted input (a\n * stored token, a URL parameter, a wallet row) without a `try`/`catch`.\n *\n * Use {@link tryParseCompositeKey} instead when only the `$` form is valid input.\n *\n * @example\n * ```ts\n * const key = tryParseTokenClassKey(row.compositeKey);\n * if (key === undefined) return failClosed(); // no class is known: never invent one from a symbol\n * ```\n */\nexport function tryParseTokenClassKey(value: unknown): GalaChainTokenClassKey | undefined {\n if (typeof value === 'string') return splitClassKey(value, value.includes('|') ? '|' : '$');\n if (typeof value !== 'object' || value === null) return undefined;\n try {\n const { collection, category, type, additionalKey } = value as Record<string, unknown>;\n if (\n typeof collection !== 'string' ||\n typeof category !== 'string' ||\n typeof type !== 'string' ||\n typeof additionalKey !== 'string' ||\n collection === '' ||\n category === '' ||\n type === '' ||\n additionalKey === ''\n ) {\n return undefined;\n }\n return { collection, category, type, additionalKey };\n } catch {\n // A getter or proxy that throws is not a token class key.\n return undefined;\n }\n}\n\n/**\n * Parses a `$`-joined composite key (`Collection$Category$Type$AdditionalKey`, what\n * {@link compositeKeyOf} writes) and nothing else, or `undefined`. It is {@link tryParseTokenClassKey}\n * for a string that may ONLY be in the `$` form: a key that contains `|` is NOT read as the pipe\n * form here (it stays part of a segment), and only a string is accepted. The split is from the\n * right, so a collection that itself contains `$` (production's `$GMUSIC`, stage's\n * `$GMUSIC_TEST1`) stays whole; `'GALA'`, `'GALA$Unit$none'`, `'ETIME$$$'`, `'GALA$Unit$none$'` and\n * `'$$$$'` are `undefined`.\n *\n * It replaces an app's own `parseCompositeKey(key): Components | null` (`?? null`), which had\n * exactly these semantics.\n *\n * @example\n * ```ts\n * tryParseCompositeKey('$GMUSIC_TEST1$Unit$none$none')?.collection; // '$GMUSIC_TEST1'\n * tryParseCompositeKey('GALA$Unit$none'); // undefined\n * ```\n */\nexport function tryParseCompositeKey(value: unknown): GalaChainTokenClassKey | undefined {\n return typeof value === 'string' ? splitClassKey(value, '$') : undefined;\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { GalaChainTokenClassKey } from '../types/token.js';\nimport { splitClassKey } from './class_key.js';\n\n/** A symbol or a GalaChain token class key accepted by v2 operations. */\nexport type TokenRef = string | GalaChainTokenClassKey;\n\n/** Return two trading symbols in the contract's plain-string order. */\nexport function orderSymbols(a: string, b: string): [string, string] {\n return a < b ? [a, b] : [b, a];\n}\n\n/** Read an ordered symbol pair from a tuple or object returned by a boundary helper.\n *\n * @example\n * ```ts\n * const pair = readOrderedSymbols(['GALA', 'GUSDC']);\n * console.log(pair.token0);\n * ```\n */\nexport function readOrderedSymbols(value: unknown): { token0: string; token1: string } {\n if (Array.isArray(value) && value.length >= 2) {\n const token0 = (value as unknown[])[0];\n const token1 = (value as unknown[])[1];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n if (typeof value === 'object' && value !== null) {\n const record = value as Record<string, unknown>;\n const token0 = record['token0'];\n const token1 = record['token1'];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n throw new GSwapSDKError('UNORDERABLE_SYMBOLS', {\n received: Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value,\n });\n}\n\n/**\n * Parse a pipe- or dollar-separated token class key.\n *\n * The LAST three segments are always `category`, `type` and `additionalKey`; everything before\n * them is the `collection`. Parsing from the right is required because real collections contain\n * the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`\n * shifts every field. Nothing here says anything about the token's symbol: a class key carries\n * no symbol, which must come from the token class or trading-symbol registry.\n *\n * @example\n * ```ts\n * parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'\n * ```\n */\nexport function parseTokenClassKey(tokenClassKey: TokenRef): GalaChainTokenClassKey {\n if (typeof tokenClassKey === 'object') {\n return {\n collection: tokenClassKey.collection,\n category: tokenClassKey.category,\n type: tokenClassKey.type,\n additionalKey: tokenClassKey.additionalKey,\n };\n }\n\n const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes('|') ? '|' : '$');\n if (parsed === undefined) throw new GSwapSDKError('INVALID_TOKEN_CLASS_KEY', { tokenClassKey });\n return parsed;\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { TradingSymbol } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport type { TokenRef } from '../utils/ordering.js';\nimport { compositeKeyOf } from '../utils/class_key.js';\nimport { orderSymbols, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend } from '../utils/pre_send.js';\nimport { isProposableTradingSymbol } from '../utils/validation.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { ChainGateway } from './gateway.js';\nimport { HttpClient } from './http_client.js';\n\nconst SYMBOL_CACHE_TTL_MS = 60_000;\n\n/** Symbol registry client for the current GalaChainDex contract. */\nexport class Symbols {\n private cachedSymbols: TradingSymbol[] | undefined;\n private cachedAt = 0;\n private refreshInFlight: Promise<TradingSymbol[]> | undefined;\n\n private readonly http: HttpClient;\n\n /**\n * Create a symbol service backed by the swap backend. `onInvalidEntry` is told about every\n * registry row that was skipped as unusable (see {@link InvalidEntryHandler}).\n */\n constructor(\n private readonly gateway: Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n },\n private readonly options: { onInvalidEntry?: InvalidEntryHandler | undefined } = {},\n ) {\n this.http = new HttpClient(gateway.httpRequestor, gateway.requestTimeoutMs, gateway.wire);\n }\n\n /**\n * List all registered GalaChainDex trading symbols, cached for 60 seconds. A registry row that\n * is not a usable symbol is skipped (and reported to `onInvalidEntry`) instead of failing the\n * whole list.\n */\n public async list(): Promise<TradingSymbol[]> {\n if (this.cachedSymbols !== undefined && Date.now() - this.cachedAt < SYMBOL_CACHE_TTL_MS) {\n return this.cachedSymbols;\n }\n if (this.refreshInFlight !== undefined) return this.refreshInFlight;\n this.refreshInFlight = this.http\n .sendGetRequest<{ data: unknown }>(this.gateway.dexBackendBaseUrl, '/v2/trade', '/symbols')\n .then((response) =>\n readEntries('symbols', response.data, parseTradingSymbol, this.options.onInvalidEntry),\n )\n .then((symbols) => {\n this.cachedSymbols = symbols;\n this.cachedAt = Date.now();\n return symbols;\n })\n .finally(() => {\n this.refreshInFlight = undefined;\n });\n return this.refreshInFlight;\n }\n\n /** Invalidate the cached symbol registry after a write changes registration state.\n *\n * @example\n * ```ts\n * gSwap.symbols.invalidate();\n * ```\n */\n public invalidate(): void {\n this.cachedSymbols = undefined;\n this.cachedAt = 0;\n }\n\n /** Force one registry refresh, bypassing the cache.\n *\n * @example\n * ```ts\n * const symbols = await gSwap.symbols.refresh();\n * ```\n */\n public async refresh(): Promise<TradingSymbol[]> {\n this.invalidate();\n // list() would otherwise return an ALREADY in-flight refresh that started before this\n // call (built from pre-invalidation state) — bypassing it too is what makes this\n // actually force a fresh fetch, not just satisfy the cache-freshness check.\n this.refreshInFlight = undefined;\n return this.list();\n }\n\n /** Resolve a symbol or token class key to its registered symbol metadata. */\n public async resolve(ref: TokenRef): Promise<TradingSymbol> {\n let symbols = await this.list();\n const composite =\n typeof ref === 'string'\n ? isCompositeKey(ref)\n ? compositeKeyOf(parseTokenClassKey(ref))\n : undefined\n : compositeKeyOf(ref);\n const resolved = symbols.find(\n (entry) =>\n entry.symbol === ref || (composite !== undefined && compositeKeyOf(entry) === composite),\n );\n if (resolved === undefined) {\n symbols = await this.refresh();\n const refreshed = symbols.find(\n (entry) =>\n entry.symbol === ref || (composite !== undefined && compositeKeyOf(entry) === composite),\n );\n if (refreshed === undefined) throw GSwapSDKError.unknownTokenError(ref);\n return refreshed;\n }\n return resolved;\n }\n\n /**\n * The trading symbol to put in a token's first CreatePool.\n *\n * 1. The symbol ALREADY registered for exactly this class key, if any: proposing another one\n * fails the gateway's registry-conflict check.\n * 2. Otherwise `displaySymbol` (the token's curated symbol), when it is proposable\n * ({@link isProposableTradingSymbol}).\n * 3. Otherwise a `NO_VALID_TRADING_SYMBOL` error: a symbol is never derived from the key (BNB's collection is\n * `GBNB`, a launchpad token's is the reserved word `Token`).\n *\n * `registryFailure: 'ignore'` treats an unreachable registry as an empty one and falls through\n * to step 2 (the gateway still rejects a conflicting symbol); the default `'throw'` propagates\n * the failure.\n *\n * @example\n * ```ts\n * const symbol = await gSwap.symbols.proposeSymbol(\n * { collection: 'GALA_TEST1', category: 'Unit', type: 'none', additionalKey: 'none' },\n * 'GALATEST',\n * );\n * ```\n */\n public async proposeSymbol(\n classKey: GalaChainTokenClassKey,\n displaySymbol: string,\n options: { registryFailure?: 'throw' | 'ignore' | undefined } = {},\n ): Promise<string> {\n let registry: TradingSymbol[] = [];\n try {\n registry = await this.list();\n } catch (error: unknown) {\n if (options.registryFailure !== 'ignore') throw error;\n }\n const wanted = compositeKeyOf(classKey);\n const registered = registry.find(\n (entry) =>\n entry.collection === classKey.collection &&\n entry.category === classKey.category &&\n entry.type === classKey.type &&\n entry.additionalKey === classKey.additionalKey,\n );\n if (registered !== undefined) return registered.symbol;\n if (isProposableTradingSymbol(displaySymbol)) return displaySymbol;\n throw new GSwapSDKError('NO_VALID_TRADING_SYMBOL', { classKey: wanted, displaySymbol });\n }\n\n /** Resolve and put two token references in canonical trading-symbol order. */\n public async orderPair(\n a: TokenRef,\n b: TokenRef,\n ): Promise<{\n token0: TradingSymbol;\n token1: TradingSymbol;\n flipped: boolean;\n }> {\n const [resolvedA, resolvedB] = await Promise.all([this.resolve(a), this.resolve(b)]);\n const [token0Symbol, token1Symbol] = orderSymbols(resolvedA.symbol, resolvedB.symbol);\n return {\n token0: token0Symbol === resolvedA.symbol ? resolvedA : resolvedB,\n token1: token1Symbol === resolvedB.symbol ? resolvedB : resolvedA,\n flipped: token0Symbol !== resolvedA.symbol,\n };\n }\n}\n\n/** Reads one registry row: all four class-key parts, a symbol and non-negative integer decimals. */\nfunction parseTradingSymbol(value: unknown): EntryParse<TradingSymbol> {\n const entry = asEntryRecord(value);\n if (entry === undefined) return entryRejected('the row is not an object');\n const { symbol, collection, category, type, additionalKey, decimals } = entry;\n if (typeof symbol !== 'string') return entryRejected('symbol is not a string');\n if (symbol.length === 0) return entryRejected('symbol is empty');\n if (typeof collection !== 'string') return entryRejected('collection is not a string');\n if (typeof category !== 'string') return entryRejected('category is not a string');\n if (typeof type !== 'string') return entryRejected('type is not a string');\n if (typeof additionalKey !== 'string') return entryRejected('additionalKey is not a string');\n if (typeof decimals !== 'number' || !Number.isInteger(decimals) || decimals < 0) {\n return entryRejected('decimals is not a non-negative integer');\n }\n return entryOk({ symbol, collection, category, type, additionalKey, decimals });\n}\n\nfunction isCompositeKey(ref: string): boolean {\n return ref.includes('|') || ref.includes('$');\n}\n\n/** Alias exported for callers that use the contract's shorter type name. */\nexport type TokenClassKey = GalaChainTokenClassKey;\n\n/**\n * What the services need from a token resolver: how a token reference becomes a trading symbol,\n * and whether requests carry the caller's references untouched. {@link Symbols} is the registry\n * resolver (one `GET /v2/trade/symbols`, cached); {@link CanonicalSymbols} is the offline one.\n */\nexport interface TokenResolver {\n resolve(ref: TokenRef): Promise<TradingSymbol>;\n /**\n * True when reads send the caller's token references verbatim (a symbol, or a composite key as\n * the caller wrote it) and let the backend resolve and orient the pair — no registry request\n * and no client-side ordering or tick flip.\n */\n readonly passthrough?: boolean | undefined;\n}\n\n/** A token reference as the caller wrote it: a string verbatim, a class key as its `$` composite. */\nexport function rawTokenOf(ref: TokenRef): string {\n return typeof ref === 'string' ? ref : compositeKeyOf(ref);\n}\n\n/** The trading symbol of a reference, or `SYMBOL_NOT_FOUND` when the resolver has none. */\nexport async function tradingSymbolOf(resolver: TokenResolver, ref: TokenRef): Promise<string> {\n const resolved = await resolvePreSend(rawTokenOf(ref), () => resolver.resolve(ref));\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('SYMBOL_NOT_FOUND', { token: rawTokenOf(ref) });\n}\n\n/** What a read request names a token by: the reference itself in pass-through mode, else its symbol. */\nexport async function queryTokenOf(resolver: TokenResolver, ref: TokenRef): Promise<string> {\n return resolver.passthrough === true ? rawTokenOf(ref) : tradingSymbolOf(resolver, ref);\n}\n\n/**\n * The offline resolver for apps that already hold the backend's canonical trading symbols (from\n * `/quote`, `/add-liq-estimate`, a position row) and must not make a registry request of their own.\n *\n * - `resolve` accepts a bare trading symbol and returns it as is; a class key (object, `$` or `|`\n * form) is not a symbol and is refused as `UNKNOWN_TOKEN`. `createPool` relies on that refusal to\n * fall back to the symbols its caller supplies.\n * - `orderPair` orders two symbols by plain string comparison, as the contract does.\n * - Reads are pass-through (see {@link TokenResolver.passthrough}): the caller's references go on\n * the wire verbatim, composite keys included, and the backend orients the pair.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, new CanonicalSymbols(), signer, walletAddress);\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '10' });\n * ```\n */\nexport class CanonicalSymbols implements TokenResolver {\n public readonly passthrough = true;\n\n /** Resolve a bare trading symbol to itself. */\n public resolve(ref: TokenRef): Promise<TradingSymbol> {\n if (typeof ref === 'string' && !isCompositeKey(ref)) {\n return Promise.resolve({\n symbol: ref,\n collection: '',\n category: '',\n type: '',\n additionalKey: '',\n decimals: 0,\n });\n }\n return Promise.reject(GSwapSDKError.unknownTokenError(ref));\n }\n\n /** Put two symbols in canonical (string) order. */\n public async orderPair(\n a: TokenRef,\n b: TokenRef,\n ): Promise<{ token0: TradingSymbol; token1: TradingSymbol; flipped: boolean }> {\n const [resolvedA, resolvedB] = await Promise.all([this.resolve(a), this.resolve(b)]);\n const [first] = orderSymbols(resolvedA.symbol, resolvedB.symbol);\n const flipped = first !== resolvedA.symbol;\n return {\n token0: flipped ? resolvedB : resolvedA,\n token1: flipped ? resolvedA : resolvedB,\n flipped,\n };\n }\n\n /** There is no registry state to drop. */\n public invalidate(): void {\n // Nothing is cached: every answer is derived from the reference itself.\n }\n}\n","import type { FEE_TIER } from '../types/fees.js';\nimport type { CompositePool, PoolInfo, PoolListInfo, Slot0 } from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n finiteNumberOf,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport type { ChainGateway } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, rawTokenOf, tradingSymbolOf, type TokenResolver } from './symbols.js';\nimport { validateFee } from '../utils/validation.js';\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\ntype PoolGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** The sort keys of `GET /v2/trade/pools`. */\nexport type PoolSortBy = 'tvl' | 'volume1d' | 'volume30d';\n\n/** Options of {@link Pools.getPools}. Omit all of `search`, `sortBy`, `sortOrder`, `page`, `limit` for the full, unsorted list. */\nexport interface PoolListOptions {\n signal?: AbortSignal | undefined;\n /** Case-insensitive match on the pair's symbols; `A/B` or `A B` matches either order. At most 64 characters. */\n search?: string | undefined;\n sortBy?: PoolSortBy | undefined;\n sortOrder?: 'asc' | 'desc' | undefined;\n /** 1-based page number; only meaningful together with `limit`. */\n page?: number | undefined;\n /** Rows per page, 1-1000; omitted returns every row. */\n limit?: number | undefined;\n /** Overrides the service-level handler for this call. */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n}\n\n/** Read-only pool and current-price access for the current GalaChainDex contract. */\nexport class Pools {\n /**\n * Creates a pool service. `options.onInvalidEntry` is told about every pool row that was\n * skipped as unusable (see {@link InvalidEntryHandler}).\n *\n * @example\n * ```ts\n * const pools = new Pools(gateway, symbols);\n * ```\n */\n constructor(\n private readonly gateway: PoolGateway,\n private readonly symbols: TokenResolver,\n private readonly options: { onInvalidEntry?: InvalidEntryHandler | undefined } = {},\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Fetches current-contract pools from the swap backend, optionally searched, sorted and paged\n * by the backend. A row that is not a usable pool is skipped and reported to `onInvalidEntry`\n * instead of failing the whole list; an answer that is not a list at all is\n * `INVALID_CHAIN_RESPONSE`.\n *\n * @example\n * ```ts\n * const top = await service.getPools({ sortBy: 'tvl', sortOrder: 'desc', page: 1, limit: 8 });\n * console.log(top.length);\n * ```\n */\n public async getPools(options?: PoolListOptions): Promise<PoolListInfo[]> {\n const response = await this.http.sendGetRequest<BackendEnvelope<unknown>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/pools',\n poolListParams(options),\n options?.signal === undefined ? undefined : { signal: options.signal },\n );\n return readEntries(\n 'pools',\n response.data,\n parsePoolListInfo,\n options?.onInvalidEntry ?? this.options.onInvalidEntry,\n );\n }\n\n /**\n * Fetches one pool from the backend, preserving whether the request order was flipped.\n *\n * @example\n * ```ts\n * const pool = await service.getPool('GUSDC', 'GALA', 3000);\n * console.log(pool.flippedFromRequest);\n * ```\n */\n public async getPool(token0: TokenRef, token1: TokenRef, fee: FEE_TIER): Promise<PoolInfo> {\n validateFee(fee);\n return this.getBackend<PoolInfo>('/pool', await this.backendParams(token0, token1, fee));\n }\n\n /**\n * Fetches the current sqrt price, price, and tick for one pool.\n *\n * @example\n * ```ts\n * const slot0 = await service.getSlot0('GALA', 'GUSDC', 3000);\n * console.log(slot0.tick);\n * ```\n */\n public async getSlot0(token0: TokenRef, token1: TokenRef, fee: FEE_TIER): Promise<Slot0> {\n validateFee(fee);\n return this.getBackend<Slot0>('/slot0', await this.backendParams(token0, token1, fee));\n }\n\n /**\n * Fetches the complete chain composite pool snapshot, in canonical symbol order.\n *\n * @example\n * ```ts\n * const composite = await service.getCompositePool('GALA', 'GUSDC', 3000);\n * console.log(composite.positions?.length ?? 0);\n * ```\n */\n public async getCompositePool(\n token0: TokenRef,\n token1: TokenRef,\n fee: FEE_TIER,\n ): Promise<CompositePool> {\n validateFee(fee);\n if (this.symbols.passthrough === true) {\n return this.getBackend<CompositePool>('/composite-pool', {\n token0: rawTokenOf(token0),\n token1: rawTokenOf(token1),\n fee: String(fee),\n });\n }\n const first = await tradingSymbolOf(this.symbols, token0);\n const second = await tradingSymbolOf(this.symbols, token1);\n const ordered = readOrderedSymbols(orderSymbols(first, second));\n return this.getBackend<CompositePool>('/composite-pool', {\n token0: ordered.token0,\n token1: ordered.token1,\n fee: String(fee),\n });\n }\n\n private async backendParams(\n token0: TokenRef,\n token1: TokenRef,\n fee: FEE_TIER,\n ): Promise<Record<string, string>> {\n return {\n token0: await queryTokenOf(this.symbols, token0),\n token1: await queryTokenOf(this.symbols, token1),\n fee: String(fee),\n };\n }\n\n private async getBackend<T>(endpoint: string, params: Record<string, string>): Promise<T> {\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<T>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n );\n return response.data;\n } catch (error: unknown) {\n if (error instanceof GSwapSDKError) throw error;\n throw new GSwapSDKError('REQUEST_FAILED', { operation: 'pool' }, { cause: error });\n }\n }\n}\n\nconst SORT_KEYS: readonly string[] = ['tvl', 'volume1d', 'volume30d'];\nconst MAX_SEARCH_LENGTH = 64;\nconst MAX_PAGE_SIZE = 1000;\n\n/** The pool-list query, in the order the apps write it: search, sortBy, sortOrder, page, limit. */\nfunction poolListParams(options: PoolListOptions | undefined): Record<string, string> | undefined {\n if (options === undefined) return undefined;\n const params: Record<string, string> = {};\n if (options.search !== undefined) {\n if (options.search.length > MAX_SEARCH_LENGTH) {\n throw new GSwapSDKError('SEARCH_TOO_LONG', {\n length: options.search.length,\n maxLength: MAX_SEARCH_LENGTH,\n });\n }\n params['search'] = options.search;\n }\n if (options.sortBy !== undefined) {\n if (!SORT_KEYS.includes(options.sortBy)) {\n throw new GSwapSDKError('INVALID_SORT_BY', {\n value: String(options.sortBy),\n allowed: SORT_KEYS.join(','),\n });\n }\n params['sortBy'] = options.sortBy;\n }\n if (options.sortOrder !== undefined) {\n if (options.sortOrder !== 'asc' && options.sortOrder !== 'desc') {\n throw new GSwapSDKError('INVALID_SORT_ORDER', { value: String(options.sortOrder) });\n }\n params['sortOrder'] = options.sortOrder;\n }\n if (options.page !== undefined) {\n if (!Number.isInteger(options.page) || options.page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: options.page });\n }\n params['page'] = String(options.page);\n }\n if (options.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > MAX_PAGE_SIZE) {\n throw new GSwapSDKError('INVALID_LIMIT', {\n value: options.limit,\n min: 1,\n max: MAX_PAGE_SIZE,\n });\n }\n params['limit'] = String(options.limit);\n }\n return Object.keys(params).length === 0 ? undefined : params;\n}\n\nconst OPTIONAL_POOL_STRINGS = [\n 'poolName',\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'creator',\n 'price',\n 'sqrtPrice',\n 'token0Tvl',\n 'token1Tvl',\n] as const;\n\nconst OPTIONAL_POOL_NUMBERS = [\n 'tickSpacing',\n 'protocolFees',\n 'tradingFees',\n 'tick',\n 'volume1d',\n 'volume7d',\n 'volume30d',\n 'trades1d',\n 'fee24h',\n 'token0Price',\n 'token1Price',\n] as const;\n\n/** Fields the apps accept as a number or a numeric string (the wallet does `Number(row.x)`). */\nconst NUMERIC_POOL_FIELDS = ['fee', 'tvlUsd', 'apr1d'] as const;\n\n/**\n * Reads one pool-list row the way the apps do: the identity (`token0`, `token1`, `poolRef`) and\n * `fee` must be usable, every other field is optional but, when present, must have its type.\n * `fee`, `tvlUsd` and `apr1d` may arrive as numeric strings and are returned as numbers. Fields\n * the SDK does not know are kept.\n */\nfunction parsePoolListInfo(entry: unknown): EntryParse<PoolListInfo> {\n const row = asEntryRecord(entry);\n if (row === undefined) return entryRejected('the row is not an object');\n for (const key of ['token0', 'token1', 'poolRef'] as const) {\n if (typeof row[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n if (row['contractVersion'] !== undefined && row['contractVersion'] !== 'v2') {\n return entryRejected('contractVersion is not v2');\n }\n const normalized: Record<string, unknown> = { ...row };\n for (const key of NUMERIC_POOL_FIELDS) {\n const raw = row[key];\n if (raw === undefined && key !== 'fee') continue;\n const value = finiteNumberOf(raw);\n if (value === undefined) return entryRejected(`${key} is not a number`);\n normalized[key] = value;\n }\n for (const key of OPTIONAL_POOL_STRINGS) {\n if (row[key] !== undefined && typeof row[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n for (const key of OPTIONAL_POOL_NUMBERS) {\n const value = row[key];\n if (value !== undefined && (typeof value !== 'number' || !Number.isFinite(value))) {\n return entryRejected(`${key} is not a number`);\n }\n }\n return entryOk(normalized as unknown as PoolListInfo);\n}\n","/**\n * Aligning a tick to a pool's tick spacing without throwing. This module imports nothing, so an\n * app shell (a price input that snaps to a tick) pays for a few dozen bytes, not for the error\n * class and catalog that `alignTickDown` and `alignTickUp` (in `ticks.ts`) carry because they\n * throw `INVALID_TICK_SPACING` for a spacing that is not a positive integer.\n */\n\n/** True for a tick spacing the contract can use: a positive integer. The one definition. */\nexport function hasValidSpacing(spacing: number): boolean {\n return Number.isInteger(spacing) && spacing > 0;\n}\n\n/**\n * {@link alignTickDown} that answers `NaN` instead of throwing: the greatest multiple of `spacing`\n * that is no greater than `tick`, or `NaN` when `spacing` is not a positive integer (a pool whose\n * spacing has not loaded yet) or `tick` is not a number. For an app shell and for a drag handler,\n * which must not throw while the spacing is missing. `alignTickDown` (the SDK's own call sites use\n * it) gives the same value and throws for the bad spacing.\n *\n * @example\n * ```ts\n * alignTickDownOrNaN(-61, 60); // -120: it floors, it does not truncate toward zero\n * alignTickDownOrNaN(100, 0); // NaN\n * ```\n */\nexport function alignTickDownOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.floor(tick / spacing) * spacing : Number.NaN;\n}\n\n/**\n * {@link alignTickUp} that answers `NaN` instead of throwing: the least multiple of `spacing` that\n * is no less than `tick`, or `NaN` for a spacing that is not a positive integer. See\n * {@link alignTickDownOrNaN}.\n */\nexport function alignTickUpOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.ceil(tick / spacing) * spacing : Number.NaN;\n}\n","import { ALLOWED_FEE_TIERS_TEXT } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\nimport { alignTickDownOrNaN, alignTickUpOrNaN, hasValidSpacing } from './tick_align.js';\nimport { DexDecimal, GC_MAX_TICK, GC_MIN_TICK, sqrtPriceToTick } from './tick_math.js';\n\n/**\n * The tick functions that THROW an SDK error on a bad input (`alignTickDown`, `alignTickUp`,\n * `assertTickRange`, `frameSlot0`). The arithmetic that never throws (`tickToPrice`,\n * `tickFromPrice`, `tickToSqrtPrice`, `sqrtPriceToTick`, the bounds) is in `tick_math.ts`, which\n * does not import the error class or the catalog; import it from the package entry as usual.\n */\n\n/** Align a tick down to the nearest multiple of a positive spacing. */\nexport function alignTickDown(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickDownOrNaN(tick, spacing);\n}\n\n/** Align a tick up to the nearest multiple of a positive spacing. */\nexport function alignTickUp(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickUpOrNaN(tick, spacing);\n}\n\n/** Validate a position range against the global tick bounds and fee-tier spacing. */\nexport function assertTickRange(lower: number, upper: number, fee: FEE_TIER): void {\n const spacing = TICK_SPACING_BY_FEE[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower: lower, tickUpper: upper });\n }\n if (lower >= upper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower: lower, tickUpper: upper });\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower: lower,\n tickUpper: upper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new GSwapSDKError('TICKS_NOT_ALIGNED', {\n tickLower: lower,\n tickUpper: upper,\n spacing,\n });\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!hasValidSpacing(spacing)) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: spacing });\n }\n}\n\n/** A pool's current price in the frame of the request that asked for it. */\nexport interface FramedSlot0 {\n /** The square-root price, token1 per token0 in the REQUESTED order. */\n sqrtPrice: string;\n /** The greatest tick whose square-root price is no greater than `sqrtPrice`. */\n tick: number;\n}\n\n/**\n * Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's\n * canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse\n * order the price is inverted here (at 60 significant digits, so a very large or very small\n * reciprocal keeps its precision) and the tick is re-derived from the inverted price with the\n * contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks\n * (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).\n *\n * @example\n * ```ts\n * const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);\n * const { sqrtPrice, tick } = frameSlot0(slot0);\n * ```\n */\nexport function frameSlot0(slot0: {\n sqrtPrice: string;\n tick: number;\n flippedFromRequest?: boolean | undefined;\n}): FramedSlot0 {\n if (slot0.flippedFromRequest !== true) return { sqrtPrice: slot0.sqrtPrice, tick: slot0.tick };\n const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));\n if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_SQRT_PRICE', { sqrtPrice: slot0.sqrtPrice });\n }\n const sqrtPrice = inverted.toString();\n return { sqrtPrice, tick: sqrtPriceToTick(sqrtPrice) };\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { isValidUniqueKey } from './unique_key_syntax.js';\n\n/**\n * The `uniqueKey` prefix frontend_v2 and wallet_extension have always sent\n * (`galaswap-operation-<uuid>`). defi-backend does not depend on it: the chain-write verifier\n * only requires a non-empty key of at most 256 characters, and apply-results accepts\n * `[A-Za-z0-9._:-]{1,128}`; the only code that mints a prefixed key itself is the server-side v1\n * trade builder, which nothing reads back by prefix.\n */\nexport const DEFAULT_UNIQUE_KEY_PREFIX = 'galaswap-operation-';\n\n/** Options shared by the services that mint `uniqueKey`s for writes. */\nexport interface UniqueKeyOptions {\n /**\n * Prefix of every minted `uniqueKey` (`<prefix><uuid>`). Defaults to\n * `DEFAULT_UNIQUE_KEY_PREFIX` (`galaswap-operation-`).\n */\n uniqueKeyPrefix?: string | undefined;\n}\n\n/** A canonical UUID is 36 characters; the apply-results key limit is 128. */\nconst MAX_UNIQUE_KEY_PREFIX_LENGTH = 128 - 36;\nconst UNIQUE_KEY_PREFIX_PATTERN = /^[A-Za-z0-9._:-]*$/u;\n\n/**\n * Validates a caller-supplied `uniqueKey` prefix. The whole key (`<prefix><uuid>`) must stay a\n * valid apply-results key, otherwise `confirm()` could never read the outcome of the write.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY_PREFIX` when the prefix has characters outside\n * `A-Za-z0-9._:-` or is longer than 92 characters.\n */\nexport function resolveUniqueKeyPrefix(prefix: string | undefined): string {\n if (prefix === undefined) return DEFAULT_UNIQUE_KEY_PREFIX;\n if (!UNIQUE_KEY_PREFIX_PATTERN.test(prefix) || prefix.length > MAX_UNIQUE_KEY_PREFIX_LENGTH) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY_PREFIX', {\n uniqueKeyPrefix: prefix,\n maxLength: MAX_UNIQUE_KEY_PREFIX_LENGTH,\n });\n }\n return prefix;\n}\n\n/**\n * Validates a caller-supplied write `uniqueKey`: 1 to 128 characters of `A-Za-z0-9._:-`, the\n * shape the apply-results route accepts, so the write's outcome can always be read back with\n * `confirm()`. A key is one attempt's identity: reuse it only to retry that same attempt.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY` otherwise.\n */\nexport function assertUniqueKey(uniqueKey: string): void {\n if (!isValidUniqueKey(uniqueKey)) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY', { uniqueKey: String(uniqueKey) });\n }\n}\n\n/** A fresh per-attempt key: `<prefix><random UUID>`. */\nexport function createUniqueKey(prefix: string): string {\n return `${prefix}${globalThis.crypto.randomUUID()}`;\n}\n","import BigNumber from 'bignumber.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount, SwapAmount } from '../types/amounts.js';\nimport type {\n AddLiquidityDTO,\n CollectPositionFeesDTO,\n CreatePoolDTO,\n RemoveLiquidityDTO,\n RequestTradeDTO,\n} from '../types/v2_dtos.js';\nimport type { GalaChainTokenClassKey } from '../types/token.js';\nimport { assertTickRange } from './ticks.js';\nimport { assertUniqueKey } from './unique_key.js';\nimport {\n assertCanonicalPair,\n isProposableTradingSymbol,\n validateFee,\n validateNumericAmount,\n} from './validation.js';\n\n// The pure builders of every v2 write DTO. They validate, canonicalize decimals\n// (`BigNumber#toFixed`) and fix the key order, and nothing else: no network, no signer, no\n// clock, no randomness — the `uniqueKey` is an input. The `Swaps` and `Positions` services call\n// exactly these functions, so a DTO an app builds here (to show in an approval popup, to sign on\n// another device, to submit later) is the DTO the services would have built.\n//\n// Inputs are already CANONICAL: `token0 < token1` by plain string comparison, ticks and prices in\n// that orientation. Orienting a caller's pair (and inverting its ticks and price) is the\n// services' job; a reversed pair is refused (`NON_CANONICAL_PAIR`) rather than silently signed.\n\nconst decimalString = (amount: NumericAmount): string => new BigNumber(amount).toFixed();\n\n/** The pool a RequestTrade trades in, its fee tier, the `uniqueKey` and what is traded. */\nexport type RequestTradeInput = {\n /** Canonical pool symbols: `token0 < token1`. Take them from a quote verbatim. */\n token0: string;\n token1: string;\n fee: number;\n /** Which side of the pool is sold: `true` when the input token is `token0`. */\n tokenInIsToken0: boolean;\n uniqueKey: string;\n} & SwapAmount;\n\n/**\n * Builds the RequestTrade DTO: `exactIn` sells that much of the input token (`sell0Qty` or\n * `sell1Qty`), `exactOut` buys that much of the output token (`buy1Qty` or `buy0Qty`), plus the\n * side's slippage bound and an optional `priceLimit`. Key order is\n * `token0, token1, fee, uniqueKey`, then the one quantity, then the slippage bound, then\n * `priceLimit`.\n *\n * @example\n * ```ts\n * const dto = buildRequestTradeDto({\n * token0: quote.token0Symbol, token1: quote.token1Symbol,\n * tokenInIsToken0: quote.tokenInIsToken0, fee: quote.fee,\n * uniqueKey: createUniqueKey('galaswap-operation-'),\n * exactIn: '100', amountOutMinimum: '14',\n * });\n * ```\n */\nexport function buildRequestTradeDto(input: RequestTradeInput): RequestTradeDTO {\n validateFee(input.fee);\n assertCanonicalPair(input.token0, input.token1);\n assertUniqueKey(input.uniqueKey);\n const dto: Record<string, unknown> = {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n uniqueKey: input.uniqueKey,\n };\n if ('exactIn' in input) {\n const exactIn = input.exactIn;\n if (exactIn === undefined) {\n throw new GSwapSDKError('EXACT_AMOUNT_REQUIRED', { field: 'exactIn' });\n }\n validateNumericAmount(exactIn, 'exactIn');\n dto[input.tokenInIsToken0 ? 'sell0Qty' : 'sell1Qty'] = decimalString(exactIn);\n if (input.amountOutMinimum !== undefined) {\n validateNumericAmount(input.amountOutMinimum, 'amountOutMinimum', true);\n dto['amountOutMinimum'] = decimalString(input.amountOutMinimum);\n }\n } else {\n const exactOut = input.exactOut;\n if (exactOut === undefined) {\n throw new GSwapSDKError('EXACT_AMOUNT_REQUIRED', { field: 'exactOut' });\n }\n validateNumericAmount(exactOut, 'exactOut');\n dto[input.tokenInIsToken0 ? 'buy1Qty' : 'buy0Qty'] = decimalString(exactOut);\n if (input.amountInMaximum !== undefined) {\n validateNumericAmount(input.amountInMaximum, 'amountInMaximum', true);\n dto['amountInMaximum'] = decimalString(input.amountInMaximum);\n }\n }\n if (input.priceLimit !== undefined) {\n validateNumericAmount(input.priceLimit, 'priceLimit');\n dto['priceLimit'] = decimalString(input.priceLimit);\n }\n return dto as unknown as RequestTradeDTO;\n}\n\n/** A canonical pool position: the pair, fee tier, tick range and the attempt's `uniqueKey`. */\nexport interface PoolPositionInput {\n token0: string;\n token1: string;\n fee: number;\n tickLower: number;\n tickUpper: number;\n uniqueKey: string;\n}\n\nfunction assertPoolPosition(input: PoolPositionInput): void {\n validateFee(input.fee);\n assertCanonicalPair(input.token0, input.token1);\n assertTickRange(input.tickLower, input.tickUpper, input.fee);\n assertUniqueKey(input.uniqueKey);\n}\n\n/** Exactly one canonical deposit side. */\nexport type AddLiquidityInput = PoolPositionInput &\n (\n | { depositQuantityToken0: NumericAmount; depositQuantityToken1?: undefined }\n | { depositQuantityToken0?: undefined; depositQuantityToken1: NumericAmount }\n );\n\n/**\n * Builds the AddLiquidity DTO: exactly one of `depositQuantityToken0` / `depositQuantityToken1`\n * (the other side is derived on chain). Key order: `token0, token1, fee, tickLower, tickUpper,\n * uniqueKey, <deposit>`.\n */\nexport function buildAddLiquidityDto(input: AddLiquidityInput): AddLiquidityDTO {\n assertPoolPosition(input);\n const side = onlyOne(\n input.depositQuantityToken0,\n input.depositQuantityToken1,\n 'depositQuantityToken0',\n 'depositQuantityToken1',\n );\n if (side === undefined) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'depositQuantityToken0',\n second: 'depositQuantityToken1',\n });\n }\n validateNumericAmount(side.amount, side.name);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n [side.name]: decimalString(side.amount),\n } as AddLiquidityDTO;\n}\n\n/** At most one canonical withdrawal side; neither closes the position. */\nexport type RemoveLiquidityInput = PoolPositionInput & {\n withdrawalQuantityToken0?: NumericAmount | undefined;\n withdrawalQuantityToken1?: NumericAmount | undefined;\n};\n\n/**\n * Builds the RemoveLiquidity DTO: at most one of `withdrawalQuantityToken0` /\n * `withdrawalQuantityToken1`; omitting both closes the position and sweeps its fees.\n */\nexport function buildRemoveLiquidityDto(input: RemoveLiquidityInput): RemoveLiquidityDTO {\n assertPoolPosition(input);\n const side = onlyOne(\n input.withdrawalQuantityToken0,\n input.withdrawalQuantityToken1,\n 'withdrawalQuantityToken0',\n 'withdrawalQuantityToken1',\n true,\n );\n if (side !== undefined) validateNumericAmount(side.amount, side.name);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n ...(side === undefined ? {} : { [side.name]: decimalString(side.amount) }),\n };\n}\n\n/** Builds the CollectPositionFees DTO (the contract sweeps all of a position's fees). */\nexport function buildCollectPositionFeesDto(input: PoolPositionInput): CollectPositionFeesDTO {\n assertPoolPosition(input);\n return {\n token0: input.token0,\n token1: input.token1,\n fee: input.fee,\n tickLower: input.tickLower,\n tickUpper: input.tickUpper,\n uniqueKey: input.uniqueKey,\n };\n}\n\n/** A CreatePool in canonical orientation, with exactly one starting price. */\nexport type CreatePoolInput = {\n token0Key: GalaChainTokenClassKey;\n token1Key: GalaChainTokenClassKey;\n /** The symbols to register; `token0Symbol < token1Symbol` and both proposable. */\n token0Symbol: string;\n token1Symbol: string;\n fee: number;\n /** Optional display name; omitted when undefined or empty. */\n name?: string | undefined;\n isPrivate?: boolean | undefined;\n privateAccess?: string[] | undefined;\n uniqueKey: string;\n} & (\n | { startingPrice: NumericAmount; startingSqrtPrice?: undefined }\n | { startingPrice?: undefined; startingSqrtPrice: NumericAmount }\n);\n\n/**\n * Builds the CreatePool DTO. Key order: `token0Key, token1Key, fee, startingPrice |\n * startingSqrtPrice, token0Symbol, token1Symbol, uniqueKey, name, isPrivate, privateAccess`.\n * Prices are those of the canonical pair (token1 per token0); a price quoted the other way round\n * is inverted by the caller before it gets here.\n */\nexport function buildCreatePoolDto(input: CreatePoolInput): CreatePoolDTO {\n validateFee(input.fee);\n assertUniqueKey(input.uniqueKey);\n assertCanonicalPair(input.token0Symbol, input.token1Symbol);\n for (const symbol of [input.token0Symbol, input.token1Symbol]) {\n if (!isProposableTradingSymbol(symbol)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol });\n }\n }\n for (const key of [input.token0Key, input.token1Key]) assertClassKey(key);\n const price = onlyOne(\n input.startingPrice,\n input.startingSqrtPrice,\n 'startingPrice',\n 'startingSqrtPrice',\n );\n if (price === undefined) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n if (typeof price.amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: price.name });\n }\n const parsed = new BigNumber(price.amount);\n if (!parsed.isFinite() || parsed.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(price.amount) });\n }\n return {\n token0Key: input.token0Key,\n token1Key: input.token1Key,\n fee: input.fee,\n [price.name]: parsed.toFixed(),\n token0Symbol: input.token0Symbol,\n token1Symbol: input.token1Symbol,\n uniqueKey: input.uniqueKey,\n // An empty name is \"no name\", as in frontend_v2's builder (its form yields '').\n ...(input.name === undefined || input.name === '' ? {} : { name: input.name }),\n ...(input.isPrivate === undefined ? {} : { isPrivate: input.isPrivate }),\n ...(input.privateAccess === undefined ? {} : { privateAccess: input.privateAccess }),\n } as CreatePoolDTO;\n}\n\nfunction assertClassKey(key: GalaChainTokenClassKey): void {\n for (const part of ['collection', 'category', 'type', 'additionalKey'] as const) {\n if (typeof key[part] !== 'string' || key[part].length === 0) {\n throw new GSwapSDKError('INCOMPLETE_TOKEN_CLASS_KEY', {\n compositeKey: [key.collection, key.category, key.type, key.additionalKey].join('$'),\n part,\n });\n }\n }\n}\n\n/**\n * Of two mutually exclusive fields, the one that is set (`undefined` when neither is);\n * both set is an error (`AT_MOST_ONE_OF_ALLOWED` or `EXACTLY_ONE_OF_REQUIRED`), and so is\n * neither unless `allowNeither`.\n */\nfunction onlyOne<T>(\n first: T | undefined,\n second: T | undefined,\n firstName: string,\n secondName: string,\n allowNeither = false,\n): { name: string; amount: T } | undefined {\n if (first !== undefined && second !== undefined) {\n throw allowNeither\n ? new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: firstName, second: secondName })\n : new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', { first: firstName, second: secondName });\n }\n if (first !== undefined) return { name: firstName, amount: first };\n if (second !== undefined) return { name: secondName, amount: second };\n return undefined;\n}\n\n/** The methods whose DTOs the builders produce. */\nexport type V2WriteMethod =\n 'RequestTrade' | 'AddLiquidity' | 'RemoveLiquidity' | 'CollectPositionFees' | 'CreatePool';\n\ntype DtoExpectation =\n 'string' | 'number' | 'boolean' | 'class_key' | 'string_array' | 'exactly_once';\n\nfunction invalidDto(\n method: string,\n field: string,\n expected: DtoExpectation,\n): GSwapSDKError<'INVALID_DTO'> {\n return new GSwapSDKError('INVALID_DTO', { method, field, expected });\n}\n\n/**\n * Rebuilds a DTO from its own fields with the builder of its method: the canonical form of the\n * DTO, with the same validation. Key order and decimal text are the builder's.\n */\nfunction rebuildV2Dto(\n method: V2WriteMethod,\n dto: Record<string, unknown>,\n): Record<string, unknown> {\n const text = (field: string): string => {\n const value = dto[field];\n if (typeof value !== 'string') throw invalidDto(method, field, 'string');\n return value;\n };\n const integer = (field: string): number => {\n const value = dto[field];\n if (typeof value !== 'number') throw invalidDto(method, field, 'number');\n return value;\n };\n const optionalText = (field: string): string | undefined =>\n dto[field] === undefined ? undefined : text(field);\n const classKey = (field: string): GalaChainTokenClassKey => {\n const value = dto[field];\n if (typeof value !== 'object' || value === null) throw invalidDto(method, field, 'class_key');\n const key = value as Record<string, unknown>;\n const part = (name: string): string => {\n if (typeof key[name] !== 'string') throw invalidDto(method, `${field}.${name}`, 'string');\n return key[name];\n };\n return {\n collection: part('collection'),\n category: part('category'),\n type: part('type'),\n additionalKey: part('additionalKey'),\n };\n };\n // The pool pair is not a field of CreatePool, so these are read per method, not up front.\n const base = () => ({ token0: text('token0'), token1: text('token1'), fee: integer('fee') });\n const uniqueKey = text('uniqueKey');\n const position = () => ({\n ...base(),\n uniqueKey,\n tickLower: integer('tickLower'),\n tickUpper: integer('tickUpper'),\n });\n switch (method) {\n case 'RequestTrade': {\n const qty = ['sell0Qty', 'sell1Qty', 'buy0Qty', 'buy1Qty'].filter(\n (f) => dto[f] !== undefined,\n );\n const [field] = qty;\n if (qty.length !== 1 || field === undefined) {\n throw invalidDto(method, 'sell0Qty|sell1Qty|buy0Qty|buy1Qty', 'exactly_once');\n }\n const tokenInIsToken0 = field === 'sell0Qty' || field === 'buy1Qty';\n const shared = { ...base(), uniqueKey, tokenInIsToken0 };\n const priceLimit = optionalText('priceLimit');\n return field.startsWith('sell')\n ? buildRequestTradeDto({\n ...shared,\n exactIn: text(field),\n amountOutMinimum: optionalText('amountOutMinimum'),\n priceLimit,\n })\n : buildRequestTradeDto({\n ...shared,\n exactOut: text(field),\n amountInMaximum: optionalText('amountInMaximum'),\n priceLimit,\n });\n }\n case 'AddLiquidity': {\n const token0Side = optionalText('depositQuantityToken0');\n const token1Side = optionalText('depositQuantityToken1');\n return buildAddLiquidityDto({\n ...position(),\n ...(token0Side === undefined\n ? { depositQuantityToken1: token1Side as string }\n : { depositQuantityToken0: token0Side }),\n });\n }\n case 'RemoveLiquidity':\n return buildRemoveLiquidityDto({\n ...position(),\n withdrawalQuantityToken0: optionalText('withdrawalQuantityToken0'),\n withdrawalQuantityToken1: optionalText('withdrawalQuantityToken1'),\n });\n case 'CollectPositionFees':\n return buildCollectPositionFeesDto(position());\n case 'CreatePool': {\n const price = optionalText('startingPrice');\n const sqrtPrice = optionalText('startingSqrtPrice');\n const privateAccess = dto['privateAccess'];\n if (\n privateAccess !== undefined &&\n (!Array.isArray(privateAccess) || privateAccess.some((entry) => typeof entry !== 'string'))\n ) {\n throw invalidDto(method, 'privateAccess', 'string_array');\n }\n if (dto['isPrivate'] !== undefined && typeof dto['isPrivate'] !== 'boolean') {\n throw invalidDto(method, 'isPrivate', 'boolean');\n }\n return buildCreatePoolDto({\n token0Key: classKey('token0Key'),\n token1Key: classKey('token1Key'),\n token0Symbol: text('token0Symbol'),\n token1Symbol: text('token1Symbol'),\n fee: integer('fee'),\n uniqueKey,\n name: optionalText('name'),\n isPrivate: dto['isPrivate'],\n privateAccess: privateAccess as string[] | undefined,\n ...(price === undefined\n ? { startingSqrtPrice: sqrtPrice as string }\n : { startingPrice: price }),\n });\n }\n }\n}\n\n/**\n * Asserts that `dto` is EXACTLY what the builder of `method` produces for its own fields — the\n * same fields, canonical decimal text, builder key order, nothing extra (no `signature`). The\n * `submit*` methods use it so that what an app showed a user (a DTO it built) is byte for byte\n * what gets signed; a DTO edited by hand, or built elsewhere, is refused rather than signed.\n *\n * @throws GSwapSDKError `INVALID_DTO` or `DTO_NOT_CANONICAL`.\n */\nexport function assertCanonicalV2Dto(method: V2WriteMethod, dto: Record<string, unknown>): void {\n const rebuilt = rebuildV2Dto(method, dto);\n if (JSON.stringify(rebuilt) !== JSON.stringify(dto)) {\n throw new GSwapSDKError('DTO_NOT_CANONICAL', { method });\n }\n}\n","import BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './error_catalog.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport type { ChainGateway, ChainSubmitOptions } from './gateway.js';\nimport type { PositionConfirmationResult, SubmittedTransaction } from './submitted_transaction.js';\nimport { HttpClient } from './http_client.js';\nimport type { GalaChainSigner } from './signers.js';\nimport { rawTokenOf, type Symbols, type TokenResolver } from './symbols.js';\nimport type { NumericAmount, PriceIn } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\nimport type {\n AddLiquidityDTO,\n CollectPositionFeesDTO,\n CreatePoolDTO,\n RemoveLiquidityDTO,\n} from '../types/v2_dtos.js';\nimport type {\n AddLiquidityEstimate,\n Position,\n RemoveLiquidityEstimate,\n} from '../types/v2_results.js';\nimport type { WireOptions } from '../types/wire.js';\nimport {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { compositeKeyOf } from '../utils/class_key.js';\nimport { type TokenRef, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend, signPreSend } from '../utils/pre_send.js';\nimport {\n isProposableTradingSymbol,\n validateFee,\n validateNumericAmount,\n} from '../utils/validation.js';\nimport { tickFromPrice } from '../utils/tick_math.js';\nimport { alignTickDown, alignTickUp, assertTickRange } from '../utils/ticks.js';\nimport {\n assertCanonicalV2Dto,\n buildAddLiquidityDto,\n buildCollectPositionFeesDto,\n buildCreatePoolDto,\n buildRemoveLiquidityDto,\n} from '../utils/dto_builders.js';\nimport {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n type UniqueKeyOptions,\n} from '../utils/unique_key.js';\n\ntype PositionGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n submit: (\n method: string,\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<Position | null>>;\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\ntype PositionSymbols = TokenResolver & Pick<Symbols, 'orderPair'> & { invalidate?: () => void };\n\n/** Options of {@link Positions}: the `uniqueKey` prefix and a handler for skipped list rows. */\nexport interface PositionsOptions extends UniqueKeyOptions {\n /** Told about every position row of a list that was skipped as unusable. */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n}\n\n/** A write's optional attempt identity. */\ninterface UniqueKeyArg {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing, or to retry the SAME\n * attempt after a lost response; never reuse it for another write.\n */\n uniqueKey?: string | undefined;\n}\n\n/** Arguments of {@link Positions.addLiquidityByTicks} and {@link Positions.buildAddLiquidity}. */\nexport interface AddLiquidityArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n /** Whether `amount` is of `token0` as the caller passed it (not of the canonical token0). */\n amountIsToken0: boolean;\n}\n\n/** Arguments of {@link Positions.removeLiquidity} and {@link Positions.buildRemoveLiquidity}. */\nexport interface RemoveLiquidityArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n /** Withdraw this much of the caller's `token0`; give at most one of `amount0` / `amount1`. */\n amount0?: NumericAmount | undefined;\n amount1?: NumericAmount | undefined;\n}\n\n/** Arguments of {@link Positions.collectPositionFees} and {@link Positions.buildCollectPositionFees}. */\nexport interface CollectPositionFeesArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n}\n\n/** Arguments of {@link Positions.createPool} and {@link Positions.buildCreatePool}. */\nexport interface CreatePoolArgs extends UniqueKeyArg {\n token0: TokenRef;\n token1: TokenRef;\n token0Symbol?: string | undefined;\n token1Symbol?: string | undefined;\n fee: FEE_TIER;\n startingPrice?: NumericAmount | undefined;\n startingSqrtPrice?: NumericAmount | undefined;\n /** Optional pool display name, sent as the DTO's `name`; omitted when undefined or empty. */\n name?: string | undefined;\n isPrivate?: boolean | undefined;\n privateAccess?: string[] | undefined;\n}\n\n/** The pool position a liquidity DTO names, as its confirmation needs it. */\nfunction identityOf(\n dto: Pick<CollectPositionFeesDTO, 'token0' | 'token1' | 'fee' | 'tickLower' | 'tickUpper'>,\n): PositionIdentity {\n return {\n token0: dto.token0,\n token1: dto.token1,\n fee: dto.fee,\n tickLower: dto.tickLower,\n tickUpper: dto.tickUpper,\n };\n}\n\n/**\n * The outcome of {@link Positions.readPosition}. Only `not_found` is chain-confirmed absence (the\n * backend answers HTTP 404 only when the chain itself found no such position); `unknown` is \"no\n * evidence either way\" — a transport failure, a gateway timeout, any other error status or an\n * answer that is not a position — and must never be read as a removal.\n */\nexport type PositionRead =\n | { kind: 'found'; data: Position }\n | { kind: 'not_found' }\n | { kind: 'unknown'; error: GSwapSDKError };\n\ninterface BackendEnvelope<TData> {\n data: TData;\n}\n\ninterface AddLiquidityEstimateWire {\n amount0: string;\n amount1: string;\n liquidity: string;\n token0Symbol: string;\n token1Symbol: string;\n tickLower: number;\n tickUpper: number;\n amountIsCanonicalToken0: boolean;\n}\n\ninterface RemoveLiquidityEstimateWire {\n amount0: string;\n amount1: string;\n}\n\ninterface ResolvedCreateToken {\n symbol: string;\n classKey: ReturnType<typeof parseTokenClassKey>;\n}\n\ninterface PositionIdentity {\n token0: string;\n token1: string;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n}\n\n/** Tells `submit()` how to prove a write's own effect for `SubmittedTransaction.confirm()`. */\ntype PositionSubmitConfirmation =\n | { kind: 'add' | 'removePartial' | 'removeFull' | 'collect'; identity: PositionIdentity }\n | { kind: 'createPool'; token0: string; token1: string; fee: FEE_TIER };\n\n/**\n * Manages current-contract concentrated-liquidity positions.\n *\n * @example\n * ```typescript\n * const positions = gSwap.positions;\n * const mine = await positions.getUserPositions('client|012345678901234567890123');\n * console.log(mine.length);\n * ```\n */\nexport class Positions {\n constructor(\n private readonly gateway: PositionGateway,\n private readonly symbols: PositionSymbols,\n private readonly signer?: GalaChainSigner,\n private readonly walletAddress?: string,\n options: PositionsOptions = {},\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\n this.onInvalidEntry = options.onInvalidEntry;\n }\n\n private readonly http: HttpClient;\n private readonly uniqueKeyPrefix: string;\n private readonly onInvalidEntry: InvalidEntryHandler | undefined;\n\n /**\n * Gets all current-contract positions owned by an address.\n *\n * @param owner - GalaChain owner identity.\n * @returns Enriched positions from the v2 trade backend, token images included. A row that is\n * not a usable position is skipped and reported to `onInvalidEntry`.\n * @example\n * ```typescript\n * const positions = await gSwap.positions.getUserPositions('client|012345678901234567890123');\n * ```\n */\n async getUserPositions(owner: string): Promise<Position[]> {\n const response = await this.get<unknown>('/positions', { user: owner });\n return readEntries('positions', response.data, parsePosition, this.onInvalidEntry);\n }\n\n /**\n * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.\n * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.\n *\n * @param args - Pair, owner, fee, and position tick range.\n * @returns The position, or `null` when the backend returns 404.\n * @example\n * ```typescript\n * const position = await gSwap.positions.getPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async getPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<Position | null> {\n const response = await this.getNullable<unknown>(\n '/position',\n await this.positionParams(args),\n signal,\n );\n return response === null ? null : readPositionBody(response.data);\n }\n\n /**\n * Reads one position and classifies the outcome instead of throwing: `found` with the position\n * (fees included), `not_found` (the backend's HTTP 404, which it sends only when the chain\n * itself has no such position) or `unknown` (any other failure, carried as `error`). Use it\n * to confirm a write: `unknown` is \"no evidence either way\", never a confirmed absence.\n *\n * Only the caller's own abort rethrows. With a pass-through resolver ({@link CanonicalSymbols})\n * the pair and ticks go to the backend exactly as given and the backend orients them.\n *\n * @example\n * ```typescript\n * const read = await gSwap.positions.readPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * if (read.kind === 'found') console.log(read.data.fees0);\n * ```\n */\n async readPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<PositionRead> {\n try {\n const position = await this.getPosition(args, signal);\n return position === null ? { kind: 'not_found' } : { kind: 'found', data: position };\n } catch (error: unknown) {\n if (signal?.aborted === true) throw error;\n return {\n kind: 'unknown',\n error: isGSwapError(error)\n ? error\n : new GSwapSDKError('REQUEST_FAILED', { operation: 'position' }, { cause: error }),\n };\n }\n }\n\n /**\n * The `/position` query: canonical symbols and canonical ticks after a client-side flip, or,\n * for a pass-through resolver, the caller's references and ticks untouched.\n */\n private async positionParams(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n }): Promise<Record<string, string>> {\n if (this.symbols.passthrough === true) {\n return {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n owner: args.owner,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n };\n }\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n return {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: `${args.fee}`,\n owner: args.owner,\n tickLower: `${ticks.tickLower}`,\n tickUpper: `${ticks.tickUpper}`,\n };\n }\n\n /**\n * Estimates the other token amount and resulting liquidity for a deposit.\n *\n * @param args - Pair, tick range, deposit amount, and the amount's caller-side token index.\n * @returns Backend liquidity estimate.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async estimateAddLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n amountIsToken0: boolean;\n }): Promise<AddLiquidityEstimate> {\n validateNumericAmount(args.amount, 'amount');\n const response = await this.get<AddLiquidityEstimateWire>('/add-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n amount: new BigNumber(args.amount).toFixed(),\n amountIsToken0: String(args.amountIsToken0),\n });\n return response.data;\n }\n\n /**\n * Estimates token amounts released by burning liquidity.\n *\n * @param args - Pair, tick range, fee tier, and liquidity quantity.\n * @returns Estimated token0 and token1 quantities.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateRemoveLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, liquidity: '1000',\n * });\n * ```\n */\n async estimateRemoveLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n liquidity: NumericAmount;\n }): Promise<RemoveLiquidityEstimate> {\n validateNumericAmount(args.liquidity, 'liquidity');\n const response = await this.get<RemoveLiquidityEstimateWire>('/remove-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n liquidity: new BigNumber(args.liquidity).toFixed(),\n });\n return response.data;\n }\n\n /**\n * Adds liquidity using an explicit tick range. Exactly one canonical deposit field is emitted.\n *\n * @param args - Pair, fee, range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByTicks({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * await tx.confirm();\n * ```\n */\n async addLiquidityByTicks(args: AddLiquidityArgs) {\n return this.submitAddLiquidity(await this.buildAddLiquidity(args));\n }\n\n /**\n * Builds the AddLiquidity DTO that {@link addLiquidityByTicks} would sign, without signing or\n * sending it: to show in an approval popup, or to sign elsewhere. Submit exactly this DTO with\n * {@link submitAddLiquidity}. The pure counterpart, with canonical inputs and no resolution,\n * is `buildAddLiquidityDto`.\n *\n * @example\n * ```typescript\n * const dto = await gSwap.positions.buildAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async buildAddLiquidity(args: AddLiquidityArgs): Promise<AddLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n // Caller-facing checks first, so a refusal names the caller's own argument (`amount`).\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n validateNumericAmount(args.amount, 'amount');\n const base = {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n };\n return pair.flipped !== args.amountIsToken0\n ? buildAddLiquidityDto({ ...base, depositQuantityToken0: args.amount })\n : buildAddLiquidityDto({ ...base, depositQuantityToken1: args.amount });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildAddLiquidity} or `buildAddLiquidityDto`; it must\n * be exactly what the builder produces. The returned transaction confirms by proving the\n * position's liquidity grew.\n */\n async submitAddLiquidity(dto: AddLiquidityDTO) {\n assertCanonicalV2Dto('AddLiquidity', dto);\n return this.submit('AddLiquidity', dto, { kind: 'add', identity: identityOf(dto) });\n }\n\n /**\n * Adds liquidity from prices, flooring the lower tick and ceiling the upper tick to fee spacing.\n * The resulting range is therefore no narrower than the requested price interval.\n *\n * @param args - Pair, fee, price range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByPrice({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * minPrice: '0.14', maxPrice: '0.16', amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async addLiquidityByPrice(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n minPrice: PriceIn;\n maxPrice: PriceIn;\n amount: NumericAmount;\n amountIsToken0: boolean;\n /** The attempt's `uniqueKey`; default a fresh one (see {@link AddLiquidityArgs.uniqueKey}). */\n uniqueKey?: string | undefined;\n }) {\n validateFee(args.fee);\n this.rejectNumber(args.minPrice, 'minPrice');\n this.rejectNumber(args.maxPrice, 'maxPrice');\n const minPrice = new BigNumber(args.minPrice);\n const maxPrice = new BigNumber(args.maxPrice);\n if (\n !minPrice.isFinite() ||\n !maxPrice.isFinite() ||\n minPrice.isLessThanOrEqualTo(0) ||\n maxPrice.isLessThanOrEqualTo(0)\n ) {\n throw new GSwapSDKError('INVALID_PRICE_BOUNDS', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError('PRICE_BOUNDS_ORDER', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n const spacing = this.tickSpacing(args.fee);\n const tickLower = alignTickDown(tickFromPrice(minPrice), spacing);\n const tickUpper = alignTickUp(tickFromPrice(maxPrice), spacing);\n return this.addLiquidityByTicks({\n token0: args.token0,\n token1: args.token1,\n fee: args.fee,\n tickLower,\n tickUpper,\n amount: args.amount,\n amountIsToken0: args.amountIsToken0,\n uniqueKey: args.uniqueKey,\n });\n }\n\n /**\n * Removes liquidity by withdrawing at most one canonical token quantity.\n * Omitting both amounts closes the position and sweeps all accrued fees.\n *\n * @param args - Pair, fee, range, and optional caller-side withdrawal amount.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.removeLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async removeLiquidity(args: RemoveLiquidityArgs) {\n return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(args));\n }\n\n /**\n * Builds the RemoveLiquidity DTO that {@link removeLiquidity} would sign, without signing or\n * sending it. Submit exactly this DTO with {@link submitRemoveLiquidity}. The pure counterpart\n * is `buildRemoveLiquidityDto`.\n */\n async buildRemoveLiquidity(args: RemoveLiquidityArgs): Promise<RemoveLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n if (args.amount0 !== undefined && args.amount1 !== undefined) {\n throw new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: 'amount0', second: 'amount1' });\n }\n if (args.amount0 !== undefined) validateNumericAmount(args.amount0, 'amount0');\n if (args.amount1 !== undefined) validateNumericAmount(args.amount1, 'amount1');\n // The caller's amount0 / amount1 follow the caller's pair; the DTO's follow the canonical one.\n const [canonical0, canonical1] = pair.flipped\n ? [args.amount1, args.amount0]\n : [args.amount0, args.amount1];\n return buildRemoveLiquidityDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n withdrawalQuantityToken0: canonical0,\n withdrawalQuantityToken1: canonical1,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildRemoveLiquidity} or `buildRemoveLiquidityDto`;\n * it must be exactly what the builder produces. A DTO with no withdrawal quantity closes the\n * position, and the returned transaction then confirms by proving the position is gone.\n */\n async submitRemoveLiquidity(dto: RemoveLiquidityDTO) {\n assertCanonicalV2Dto('RemoveLiquidity', dto);\n const isFullClose =\n dto.withdrawalQuantityToken0 === undefined && dto.withdrawalQuantityToken1 === undefined;\n return this.submit('RemoveLiquidity', dto, {\n kind: isFullClose ? 'removeFull' : 'removePartial',\n identity: identityOf(dto),\n });\n }\n\n /**\n * Collects all accrued fees for a position; the contract does not support partial collection.\n *\n * @param args - Pair, fee, and tick range identifying the position.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.collectPositionFees({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async collectPositionFees(args: CollectPositionFeesArgs) {\n return this.submitCollectPositionFees(await this.buildCollectPositionFees(args));\n }\n\n /**\n * Builds the CollectPositionFees DTO that {@link collectPositionFees} would sign, without\n * signing or sending it. Submit exactly this DTO with {@link submitCollectPositionFees}. The\n * pure counterpart is `buildCollectPositionFeesDto`.\n */\n async buildCollectPositionFees(args: CollectPositionFeesArgs): Promise<CollectPositionFeesDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n return buildCollectPositionFeesDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCollectPositionFees} or\n * `buildCollectPositionFeesDto`; it must be exactly what the builder produces.\n */\n async submitCollectPositionFees(dto: CollectPositionFeesDTO) {\n assertCanonicalV2Dto('CollectPositionFees', dto);\n return this.submit('CollectPositionFees', dto, { kind: 'collect', identity: identityOf(dto) });\n }\n\n /**\n * Creates a pool, resolving registered trading symbols.\n * Reversed symbol order inverts the supplied starting price or square-root price.\n *\n * A token class key carries no symbol, so for a token being proposed into the v2\n * trading-symbol registry for the first time (no existing pool has registered it yet) the\n * caller MUST pass `token0Symbol`/`token1Symbol` (the token class's symbol, from the token\n * list or FetchTokenClasses). The SDK never derives a symbol from the key, and throws a\n * TOKEN_SYMBOL_NOT_REGISTERED error when an unregistered token has none. For an already-registered token a\n * supplied symbol must match the registered one.\n *\n * @param args - Token class keys or references, fee, exactly one starting price field, and privacy options.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.createPool({\n * token0: 'GALA|Unit|none|none', token1: 'GUSDC|Unit|none|none', fee: 3000,\n * startingPrice: '0.15',\n * });\n * ```\n */\n async createPool(args: CreatePoolArgs) {\n return this.submitCreatePool(await this.buildCreatePool(args));\n }\n\n /**\n * Builds the CreatePool DTO that {@link createPool} would sign, without signing or sending it:\n * symbols resolved or proposed, the pair put in canonical order and the price inverted when it\n * was reversed. Submit exactly this DTO with {@link submitCreatePool}. The pure counterpart,\n * with canonical inputs, is `buildCreatePoolDto`.\n */\n async buildCreatePool(args: CreatePoolArgs): Promise<CreatePoolDTO> {\n const hasPrice = args.startingPrice !== undefined;\n const hasSqrtPrice = args.startingSqrtPrice !== undefined;\n if (hasPrice === hasSqrtPrice) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n validateFee(args.fee);\n const [tokenA, tokenB] = await Promise.all([\n this.resolveCreateToken(args.token0, args.token0Symbol),\n this.resolveCreateToken(args.token1, args.token1Symbol),\n ]);\n const flipped = tokenA.symbol > tokenB.symbol;\n const [token0, token1] = flipped ? [tokenB, tokenA] : [tokenA, tokenB];\n const sourcePriceInput = hasPrice\n ? (args.startingPrice as NumericAmount)\n : (args.startingSqrtPrice as NumericAmount);\n this.rejectNumber(sourcePriceInput, hasPrice ? 'startingPrice' : 'startingSqrtPrice');\n const sourcePrice = new BigNumber(sourcePriceInput);\n if (!sourcePrice.isFinite() || sourcePrice.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(sourcePriceInput) });\n }\n const canonicalPrice = flipped ? new BigNumber(1).dividedBy(sourcePrice) : sourcePrice;\n const shared = {\n token0Key: token0.classKey,\n token1Key: token1.classKey,\n token0Symbol: token0.symbol,\n token1Symbol: token1.symbol,\n fee: args.fee,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n name: args.name,\n isPrivate: args.isPrivate,\n privateAccess: args.privateAccess,\n };\n return hasPrice\n ? buildCreatePoolDto({ ...shared, startingPrice: canonicalPrice })\n : buildCreatePoolDto({ ...shared, startingSqrtPrice: canonicalPrice });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCreatePool} or `buildCreatePoolDto`; it must be\n * exactly what the builder produces. The returned transaction confirms by the pool existing, and\n * the cached symbol registry is dropped, since the pool may have registered new symbols.\n */\n async submitCreatePool(dto: CreatePoolDTO) {\n assertCanonicalV2Dto('CreatePool', dto);\n const transaction = await this.submit('CreatePool', dto, {\n kind: 'createPool',\n token0: dto.token0Symbol,\n token1: dto.token1Symbol,\n fee: dto.fee,\n });\n this.symbols.invalidate?.();\n return transaction;\n }\n\n private async submit(\n method: string,\n dto: Record<string, unknown>,\n confirmation?: PositionSubmitConfirmation,\n ) {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const signed = await signPreSend(this.signer, method, dto);\n const submitOptions =\n this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n const owner = this.walletAddress;\n const positionConfirmation = this.buildPositionConfirmation(confirmation, owner);\n const options: ChainSubmitOptions = {\n ...submitOptions,\n ...(positionConfirmation === undefined ? {} : { positionConfirmation }),\n };\n return this.gateway.submit(method, signed, options);\n }\n\n /**\n * Builds a confirmation closure that proves the write's own effect, not just that a\n * position row exists (true before most of these writes run too, for any operation on a\n * pre-existing position — existence alone would false-confirm before the write executes,\n * and would never confirm a full close, whose whole point is that the position stops\n * existing).\n *\n * The \"before\" state is captured lazily, on the confirmation closure's own first poll —\n * not eagerly here in `submit()` — so confirming a write never adds an extra round-trip to\n * the write itself; the cost of establishing the baseline is paid by `confirm()`, only if\n * and when the caller actually asks to confirm.\n */\n private buildPositionConfirmation(\n confirmation: PositionSubmitConfirmation | undefined,\n owner: string | undefined,\n ): ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined {\n if (confirmation === undefined) return undefined;\n\n if (confirmation.kind === 'createPool') {\n const { token0, token1, fee } = confirmation;\n return async (signal) => {\n const pool = await this.getNullable<unknown>(\n '/pool',\n { token0, token1, fee: `${fee}` },\n signal,\n );\n return pool === null ? { confirmed: false } : { confirmed: true, position: null };\n };\n }\n\n if (owner === undefined) return undefined;\n const { kind, identity } = confirmation;\n let baseline: { liquidity: BigNumber; fees: BigNumber } | undefined;\n\n return async (signal) => {\n const current = await this.getPosition({ ...identity, owner }, signal);\n\n if (baseline === undefined) {\n // First poll only establishes the baseline to compare future polls against — it can\n // never itself be the confirmed outcome (nothing has been observed to change yet).\n baseline = {\n liquidity: new BigNumber(current?.liquidity ?? 0),\n fees: new BigNumber(current?.fees0 ?? 0).plus(new BigNumber(current?.fees1 ?? 0)),\n };\n // A full close starting from \"already gone\" (e.g. a retried confirm after the position\n // was already swept) is confirmed immediately rather than waiting for a change that\n // already happened.\n return kind === 'removeFull' && current === null\n ? { confirmed: true, position: null }\n : { confirmed: false };\n }\n\n switch (kind) {\n case 'add':\n return current !== null &&\n new BigNumber(current.liquidity).isGreaterThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removePartial':\n return current !== null && new BigNumber(current.liquidity).isLessThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removeFull':\n return current === null ? { confirmed: true, position: null } : { confirmed: false };\n case 'collect': {\n if (current === null) return { confirmed: false };\n const currentFees = new BigNumber(current.fees0 ?? 0).plus(\n new BigNumber(current.fees1 ?? 0),\n );\n if (currentFees.isLessThan(baseline.fees)) return { confirmed: true, position: current };\n // Nothing to sweep in the first place — a legitimate no-op collect never moves\n // fees, so \"still zero\" is the confirmed outcome, not an unconfirmed one.\n if (baseline.fees.isZero() && currentFees.isZero())\n return { confirmed: true, position: current };\n return { confirmed: false };\n }\n }\n };\n }\n\n private async get<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData>> {\n return this.http.sendGetRequest<BackendEnvelope<TData>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n signal === undefined ? undefined : { signal },\n );\n }\n\n private async getNullable<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData> | null> {\n try {\n return await this.get<TData>(endpoint, params, signal);\n } catch (error: unknown) {\n if (this.isNotFound(error)) return null;\n throw error;\n }\n }\n\n private isNotFound(error: unknown): boolean {\n return error instanceof GSwapSDKError && error.status === 404;\n }\n\n private canonicalTicks(tickLower: number, tickUpper: number, flipped: boolean) {\n return flipped ? { tickLower: -tickUpper, tickUpper: -tickLower } : { tickLower, tickUpper };\n }\n\n private tickSpacing(fee: number): number {\n const spacing = (TICK_SPACING_BY_FEE as Record<number, number>)[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n }\n\n /** The caller's `uniqueKey` (validated), else a fresh one. */\n private uniqueKeyFor(supplied: string | undefined): string {\n if (supplied === undefined) return createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(supplied);\n return supplied;\n }\n\n /**\n * The pair in canonical order. A resolver failure that is not an SDK error (an app's own\n * resolver, an app requestor's rejection during the registry read) is `TOKEN_RESOLUTION_FAILED`.\n */\n private orderPair(a: TokenRef, b: TokenRef) {\n return resolvePreSend(`${rawTokenOf(a)}/${rawTokenOf(b)}`, () => this.symbols.orderPair(a, b));\n }\n\n private async resolveCreateToken(\n ref: TokenRef,\n symbolOverride?: string,\n ): Promise<ResolvedCreateToken> {\n try {\n const lookupRef = typeof ref === 'object' ? compositeKeyOf(ref) : ref;\n const resolved = await resolvePreSend(rawTokenOf(ref), () => this.symbols.resolve(lookupRef));\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError('SYMBOL_DISAGREES_WITH_REGISTRY', {\n token: rawTokenOf(ref),\n suppliedSymbol: symbolOverride,\n registeredSymbol: resolved.symbol,\n });\n }\n const suppliedClassKey = this.tryParseClassKey(ref);\n if (suppliedClassKey === undefined && resolved.collection === '') {\n // An offline resolver knows a bare symbol but not its class key; a pool needs the key.\n throw new GSwapSDKError('CREATE_POOL_NEEDS_CLASS_KEY', { token: rawTokenOf(ref) });\n }\n return {\n symbol: resolved.symbol,\n classKey:\n suppliedClassKey ??\n parseTokenClassKey({\n collection: resolved.collection,\n category: resolved.category,\n type: resolved.type,\n additionalKey: resolved.additionalKey,\n }),\n };\n } catch (error: unknown) {\n if (!(error instanceof GSwapSDKError) || error.code !== 'UNKNOWN_TOKEN') {\n throw error;\n }\n let classKey: ReturnType<typeof parseTokenClassKey>;\n try {\n classKey = parseTokenClassKey(ref);\n } catch {\n throw error;\n }\n // First-time registration: a class key carries NO symbol (collection and symbol disagree\n // for many tokens, launchpad tokens all share collection `Token`, and some collections\n // contain `$`), so the symbol to propose must be supplied by the caller from the token\n // class / registry. Never derive it from the key.\n if (symbolOverride === undefined || symbolOverride === '') {\n throw new GSwapSDKError('TOKEN_SYMBOL_NOT_REGISTERED', { token: rawTokenOf(ref) });\n }\n if (!isProposableTradingSymbol(symbolOverride)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol: symbolOverride });\n }\n return { symbol: symbolOverride, classKey };\n }\n }\n\n private tryParseClassKey(ref: TokenRef): ReturnType<typeof parseTokenClassKey> | undefined {\n try {\n return parseTokenClassKey(ref);\n } catch {\n return undefined;\n }\n }\n}\n\nconst REQUIRED_POSITION_STRINGS = [\n 'token0Symbol',\n 'token1Symbol',\n 'owner',\n 'liquidity',\n 'amount0',\n 'amount1',\n] as const;\nconst REQUIRED_POSITION_NUMBERS = ['fee', 'tickLower', 'tickUpper'] as const;\nconst OPTIONAL_POSITION_STRINGS = [\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'sqrtPrice',\n 'fees0',\n 'fees1',\n] as const;\n\n/**\n * Reads one position row of `/positions` or `/position`: the pair, owner, range, liquidity and\n * amounts must be usable; the composite keys, token images, current tick and price, and the\n * escrowed fees are carried when present. `pool` is the pool reference (`poolRef` wins over\n * `pool`; `''` when the row names neither).\n */\nfunction parsePosition(value: unknown): EntryParse<Position> {\n const wire = asEntryRecord(value);\n if (wire === undefined) return entryRejected('the row is not an object');\n for (const key of REQUIRED_POSITION_STRINGS) {\n if (typeof wire[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n for (const key of REQUIRED_POSITION_NUMBERS) {\n const number = wire[key];\n if (typeof number !== 'number' || !Number.isFinite(number)) {\n return entryRejected(`${key} is not a number`);\n }\n }\n if (typeof wire['inRange'] !== 'boolean') return entryRejected('inRange is not a boolean');\n for (const key of OPTIONAL_POSITION_STRINGS) {\n if (wire[key] !== undefined && typeof wire[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n const currentTick = wire['currentTick'];\n if (\n currentTick !== undefined &&\n (typeof currentTick !== 'number' || !Number.isFinite(currentTick))\n ) {\n return entryRejected('currentTick is not a number');\n }\n const pool = wire['poolRef'] ?? wire['pool'] ?? '';\n if (typeof pool !== 'string') return entryRejected('pool is not a string');\n const optional = Object.fromEntries(\n [...OPTIONAL_POSITION_STRINGS, 'currentTick' as const].flatMap((key) =>\n wire[key] === undefined ? [] : [[key, wire[key]]],\n ),\n );\n return entryOk({\n token0Symbol: wire['token0Symbol'] as string,\n token1Symbol: wire['token1Symbol'] as string,\n fee: wire['fee'] as number,\n tickLower: wire['tickLower'] as number,\n tickUpper: wire['tickUpper'] as number,\n liquidity: wire['liquidity'] as string,\n amount0: wire['amount0'] as string,\n amount1: wire['amount1'] as string,\n inRange: wire['inRange'],\n pool,\n owner: wire['owner'] as string,\n ...optional,\n });\n}\n\n/** The position inside a `/position` answer, or `INVALID_CHAIN_RESPONSE` when it is not one. */\nfunction readPositionBody(data: unknown): Position {\n const parsed = parsePosition(data);\n if (parsed.ok) return parsed.value;\n throw new GSwapSDKError('INVALID_POSITION_RESPONSE', { reason: parsed.reason }, { body: data });\n}\n","import BigNumber from 'bignumber.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport type { QuoteResult } from '../types/v2_results.js';\nimport type { TokenRef } from '../utils/ordering.js';\nimport { validateNumericAmount } from '../utils/validation.js';\nimport type { WireOptions } from '../types/wire.js';\nimport type { ChainGateway } from './gateway.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './error_catalog.js';\nimport { readServerMessage } from '../utils/server_message.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, type TokenResolver } from './symbols.js';\n\ninterface QuoteWire {\n contractVersion: 'v2';\n fee: number;\n amountIn: string;\n amountOut: string;\n currentSqrtPrice?: string;\n newSqrtPrice?: string;\n currentPrice?: string;\n newPrice?: string;\n newTick: number;\n tradingFees: string;\n protocolFees: string;\n totalFees: string;\n feeTokenSymbol: string;\n token0Symbol: string;\n token1Symbol: string;\n tokenInIsToken0: boolean;\n}\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\n/** The transport a quote service reads through: the same shape `Pools` and `Symbols` take. */\ntype QuoteGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** Read-only quote service backed by the v2 offline quote engine. */\nexport class Quoting {\n /**\n * Creates a quote service.\n *\n * @example\n * ```ts\n * const quoting = new Quoting(gateway, symbols); // a ChainGateway, or any { dexBackendBaseUrl, httpRequestor }\n * ```\n */\n constructor(\n private readonly gateway: QuoteGateway,\n private readonly symbols: TokenResolver,\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Quotes the output for a positive exact-input amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactInput('GALA', 'GUSDC', '100');\n * console.log(quote.amountOut);\n * ```\n */\n public async quoteExactInput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountIn: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountIn, 'amountIn');\n return this.quote(tokenIn, tokenOut, { amountIn: toDecimalString(amountIn) }, fee);\n }\n\n /**\n * Quotes the input for a positive exact-output amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactOutput('GALA', 'GUSDC', '10', 3000);\n * console.log(quote.amountIn);\n * ```\n */\n public async quoteExactOutput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountOut: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountOut, 'amountOut');\n return this.quote(tokenIn, tokenOut, { amountOut: toDecimalString(amountOut) }, fee);\n }\n\n private async quote(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amount: { amountIn: string } | { amountOut: string },\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateOptionalFee(fee);\n\n const params: Record<string, string> = {\n tokenIn: await queryTokenOf(this.symbols, tokenIn),\n tokenOut: await queryTokenOf(this.symbols, tokenOut),\n ...amount,\n };\n if (fee !== undefined) params['fee'] = String(fee);\n\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<QuoteWire>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/quote',\n params,\n );\n return mapQuote(response.data);\n } catch (error: unknown) {\n throw mapQuoteError(error, tokenIn, tokenOut, fee, {\n tokenIn: params['tokenIn'] ?? '',\n tokenOut: params['tokenOut'] ?? '',\n });\n }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError('INVALID_CHAIN_RESPONSE', { resource: 'quote' }, { body: value });\n }\n const wire = value;\n const currentPrice =\n wire.currentPrice !== undefined\n ? new BigNumber(wire.currentPrice)\n : orientPrice(wire.currentSqrtPrice!, wire.tokenInIsToken0);\n const newPrice =\n wire.newPrice !== undefined\n ? new BigNumber(wire.newPrice)\n : orientPrice(wire.newSqrtPrice!, wire.tokenInIsToken0);\n const priceImpact = newPrice.minus(currentPrice).dividedBy(currentPrice);\n\n return {\n contractVersion: wire.contractVersion,\n fee: wire.fee,\n amountIn: wire.amountIn,\n amountOut: wire.amountOut,\n ...(wire.currentSqrtPrice === undefined ? {} : { currentSqrtPrice: wire.currentSqrtPrice }),\n ...(wire.newSqrtPrice === undefined ? {} : { newSqrtPrice: wire.newSqrtPrice }),\n feeTier: wire.fee,\n newTick: wire.newTick,\n tradingFees: wire.tradingFees,\n protocolFees: wire.protocolFees,\n totalFees: wire.totalFees,\n feeTokenSymbol: wire.feeTokenSymbol,\n token0Symbol: wire.token0Symbol,\n token1Symbol: wire.token1Symbol,\n tokenInIsToken0: wire.tokenInIsToken0,\n currentPrice,\n newPrice,\n priceImpact,\n };\n}\n\n// The default BigNumber.DECIMAL_PLACES (20) underflows 1/poolPrice to exactly 0 for a\n// pool price above ~1e20 (a real, in-range price for a low-unit-value token quoted\n// against a high-value one) — 60dp matches the precision ticks.ts's DexMath already\n// uses for this same class of division.\nconst HighPrecision = BigNumber.clone({ DECIMAL_PLACES: 60 });\n\nfunction orientPrice(sqrtPrice: string, tokenInIsToken0: boolean): BigNumber {\n const poolPrice = new HighPrecision(sqrtPrice).pow(2);\n return tokenInIsToken0 ? poolPrice : new HighPrecision(1).dividedBy(poolPrice);\n}\n\nfunction isQuoteWire(value: unknown): value is QuoteWire {\n if (typeof value !== 'object' || value === null) return false;\n const wire = value as Record<string, unknown>;\n const requiredStrings = [\n 'amountIn',\n 'amountOut',\n 'tradingFees',\n 'protocolFees',\n 'totalFees',\n 'feeTokenSymbol',\n 'token0Symbol',\n 'token1Symbol',\n ];\n return (\n wire['contractVersion'] === 'v2' &&\n typeof wire['fee'] === 'number' &&\n Number.isFinite(wire['fee']) &&\n requiredStrings.every((key) => typeof wire[key] === 'string') &&\n typeof wire['newTick'] === 'number' &&\n Number.isInteger(wire['newTick']) &&\n typeof wire['tokenInIsToken0'] === 'boolean' &&\n optionalPositiveDecimal(wire['currentSqrtPrice']) &&\n optionalPositiveDecimal(wire['newSqrtPrice']) &&\n optionalPositiveDecimal(wire['currentPrice']) &&\n optionalPositiveDecimal(wire['newPrice']) &&\n (wire['currentSqrtPrice'] !== undefined || wire['currentPrice'] !== undefined) &&\n (wire['newSqrtPrice'] !== undefined || wire['newPrice'] !== undefined)\n );\n}\n\nfunction optionalPositiveDecimal(value: unknown): boolean {\n if (value === undefined) return true;\n if (typeof value !== 'string') return false;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this validates an untrusted backend field, so an unparseable value\n // must fail validation cleanly (INVALID_CHAIN_RESPONSE), not throw raw.\n const decimal = new BigNumber(value);\n return decimal.isFinite() && decimal.isGreaterThan(0);\n } catch {\n return false;\n }\n}\n\n/**\n * The ways the backend says a pair has no market at all: no pool at ANY fee tier (\"No pools found\n * with sufficient liquidity\") or a missing pool (\"Pool does not exist on the new DEX contract\").\n * A pool that exists but is too thin says \"Insufficient liquidity: ...\" instead.\n */\nconst NO_MARKET_MESSAGE = /no pool|no pools|pool does not exist/iu;\n\n/**\n * A token the DEX contract never registered: the backend's symbol registry answers\n * `Token <token> has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`\n * with an HTTP 400, naming the token exactly as the quote request sent it. That is a different\n * fact from \"no pool for this pair\" (the token itself is unknown), so it is `UNKNOWN_TOKEN` with\n * the token, not `NO_POOL_AVAILABLE`. Token class keys and symbols contain no whitespace.\n */\nconst NO_SYMBOL_MESSAGE = /Token (\\S+) has no trading symbol on the new DEX contract/u;\n\n/** The token the quote request named in the form the caller gave it, else as the backend echoed it. */\nfunction unknownTokenOf(\n echoed: string,\n queried: { tokenIn: string; tokenOut: string },\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n): TokenRef {\n if (echoed === queried.tokenIn) return tokenIn;\n if (echoed === queried.tokenOut) return tokenOut;\n return echoed;\n}\n\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n queried: { tokenIn: string; tokenOut: string },\n): GSwapSDKError {\n if (isGSwapError(error)) {\n // The backend's own English is read ONLY to classify its answer; it is never surfaced. The\n // SDK's generated `message` is never matched: its templates are not a contract.\n const message = readServerMessage(error) ?? '';\n const unregistered = NO_SYMBOL_MESSAGE.exec(message)?.[1];\n if (unregistered !== undefined) {\n return GSwapSDKError.unknownTokenError(\n unknownTokenOf(unregistered, queried, tokenIn, tokenOut),\n error,\n );\n }\n if (error.status === 404 || NO_MARKET_MESSAGE.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee, error);\n }\n if (error.status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee, error);\n }\n return error;\n }\n return new GSwapSDKError('REQUEST_FAILED', { operation: 'quote' }, { cause: error });\n}\n\nfunction validateOptionalFee(fee: FEE_TIER | undefined): void {\n if (fee !== undefined && !ALL_FEE_TIERS.some((tier) => Number(tier) === Number(fee))) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: Number(fee),\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n","import { getStringProperty, GSwapSDKError } from './gswap_sdk_error.js';\n\n/** The raw answer to a shadow (dark) write: every HTTP status resolves. */\nexport interface ShadowSubmitResult {\n httpStatus: number;\n /** Parsed JSON body, or the raw text when the body was not JSON. */\n body: unknown;\n}\n\n/**\n * Machine-readable codes defi-backend returns in a shadow failure body (`{ code, message }`, with\n * no `statusCode`; the HTTP status carries the number).\n *\n * - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back\n * silently to a public swap.\n * - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.\n * - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;\n * `message` is the gateway's verbatim string.\n */\nexport const SHADOW_SUBMIT_CODES = [\n 'SHADOW_UNAVAILABLE',\n 'SHADOW_UNSUPPORTED_TYPE',\n 'SHADOW_RELAY_REJECTED',\n] as const;\n\n/** One member of {@link SHADOW_SUBMIT_CODES}. */\nexport type ShadowSubmitCode = (typeof SHADOW_SUBMIT_CODES)[number];\n\n/**\n * Every `kind` of a failed {@link ShadowSubmitOutcome}, for an app that maps each to its own text\n * (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled` (the shadow route\n * answered 400: the request is not a dark-swappable one, e.g. `SHADOW_UNSUPPORTED_TYPE`; Shadow\n * Swaps themselves are enabled in every environment), `rejected` (carries the gateway's `message`)\n * and `unknown`.\n */\nexport const SHADOW_FAILURE_KINDS = ['unavailable', 'disabled', 'rejected', 'unknown'] as const;\n\n/** One member of {@link SHADOW_FAILURE_KINDS}. */\nexport type ShadowFailureKind = (typeof SHADOW_FAILURE_KINDS)[number];\n\n/** A RequestTrade the gateway queued: the handle to confirm it with `confirmAppliedTrade`. */\nexport interface ShadowQueuedRequest {\n uniqueKey: string;\n requestTransactionId: string | null;\n}\n\n/** A shadow write the gateway refused or did not answer: `kind` says why (see {@link SHADOW_FAILURE_KINDS}). */\nexport type ShadowSubmitFailure =\n | { ok: false; kind: 'unavailable'; retryable: true }\n | { ok: false; kind: 'disabled'; retryable: false }\n | { ok: false; kind: 'rejected'; retryable: false; message: string }\n | { ok: false; kind: 'unknown'; retryable: false };\n\n/**\n * The normalized outcome of a shadow RequestTrade (a dark swap). A success (`ok: true`) ALWAYS\n * carries `queued`, the exact key the gateway acknowledged: a RequestTrade answer that does not\n * queue the signed key is not an outcome but a thrown `SHADOW_NOT_QUEUED`. So after `if (outcome.ok)`\n * the app reads `outcome.queued` with no `undefined` branch.\n */\nexport type ShadowSubmitOutcome =\n | {\n ok: true;\n /** The request transaction id (`''` when the gateway gave none). */\n bundleId: string;\n /** Confirm with `confirmAppliedTrade`. */\n queued: ShadowQueuedRequest;\n }\n | ShadowSubmitFailure;\n\n/**\n * The success of a shadow write that is NOT a RequestTrade and executed synchronously\n * (`mode: 'sync'`, a liquidity write): there is nothing queued to confirm, so `queued` is absent.\n */\nexport interface ShadowSyncSuccess {\n ok: true;\n /** The transaction id (`''` when the gateway gave none). */\n bundleId: string;\n queued?: undefined;\n}\n\n/** Maps an HTTP status to a failure kind: 503 retryable, 400 disabled, anything else unknown. */\nexport function classifyShadowSubmitStatus(status: number): ShadowFailureKind {\n if (status === 503) return 'unavailable';\n if (status === 400) return 'disabled';\n return 'unknown';\n}\n\n/**\n * Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.\n * `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway\n * rejection; `SHADOW_UNSUPPORTED_TYPE` and any other 400 map to \"disabled\".\n */\nexport function classifyShadowSubmitError(status: number, code?: string): ShadowFailureKind {\n if (code === 'SHADOW_UNAVAILABLE') return 'unavailable';\n if (code === 'SHADOW_RELAY_REJECTED') return 'rejected';\n if (code === 'SHADOW_UNSUPPORTED_TYPE') return 'disabled';\n return classifyShadowSubmitStatus(status);\n}\n\n/**\n * Normalizes a shadow write's raw answer. For `'RequestTrade'` the result is a\n * {@link ShadowSubmitOutcome}, whose success always has `queued`; any other method may also be a\n * {@link ShadowSyncSuccess} (no `queued`).\n *\n * A 2xx envelope with `error === false` is a success when it is a queued RequestTrade that\n * acknowledges the EXACT signed `uniqueKey`, or a synchronous (`mode: 'sync'`) liquidity write.\n * Everything else is classified as a failure from the status and the body's `code`.\n *\n * @throws GSwapSDKError SHADOW_NOT_QUEUED when a RequestTrade success does not queue the\n * signed `uniqueKey` (a synchronous or mismatched answer must never be accepted as a swap).\n */\nexport function readShadowSubmitOutcome(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess {\n const { httpStatus, body } = result;\n const envelope = asRecord(body);\n if (httpStatus >= 200 && httpStatus < 300 && envelope?.['error'] === false) {\n const data = asRecord(envelope['data']);\n const rawTransactionId =\n typeof data?.['transactionId'] === 'string' ? data['transactionId'] : undefined;\n if (method === 'RequestTrade') {\n const requestedKey = signedBody['uniqueKey'];\n if (\n data?.['mode'] !== 'queued' ||\n typeof requestedKey !== 'string' ||\n data['uniqueKey'] !== requestedKey\n ) {\n throw new GSwapSDKError(\n 'SHADOW_NOT_QUEUED',\n {},\n {\n status: httpStatus,\n body,\n shadow: true,\n ...(typeof requestedKey === 'string' ? { uniqueKey: requestedKey } : {}),\n },\n );\n }\n return {\n ok: true,\n bundleId: rawTransactionId ?? '',\n queued: { uniqueKey: requestedKey, requestTransactionId: rawTransactionId ?? null },\n };\n }\n if (data?.['mode'] === 'sync') return { ok: true, bundleId: rawTransactionId ?? '' };\n }\n\n const kind = classifyShadowSubmitError(httpStatus, getStringProperty(body, 'code'));\n if (kind === 'rejected') {\n return {\n ok: false,\n kind: 'rejected',\n retryable: false,\n message: getStringProperty(body, 'message') ?? '',\n };\n }\n return kind === 'unavailable'\n ? { ok: false, kind, retryable: true }\n : { ok: false, kind, retryable: false };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n","import type { SwapAmount } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport { assertCanonicalV2Dto, buildRequestTradeDto } from '../utils/dto_builders.js';\nimport { signPreSend } from '../utils/pre_send.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport { assertCanonicalPair, validateFee } from '../utils/validation.js';\nimport type { ChainSubmitOptions } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { GalaChainSigner } from './signers.js';\nimport {\n readShadowSubmitOutcome,\n type ShadowSubmitOutcome,\n type ShadowSubmitResult,\n} from './shadow_submit.js';\nimport { SubmittedTransaction } from './submitted_transaction.js';\nimport type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { RequestTradeDTO } from '../types/v2_dtos.js';\nimport type { AppliedTrade, QuoteResult } from '../types/v2_results.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { tradingSymbolOf, type TokenResolver } from './symbols.js';\nimport {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n type UniqueKeyOptions,\n} from '../utils/unique_key.js';\n\ninterface SwapGateway {\n submit: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<AppliedTrade>>;\n submitShadow: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<ShadowSubmitResult>;\n readonly dexBackendBaseUrl: string;\n readonly httpRequestor: HttpRequestor;\n readonly requestTimeoutMs: number;\n readonly wire?: WireOptions | undefined;\n}\n\n/** The canonical pool a swap trades in, as a quote names it. */\nexport interface SwapPool {\n token0: string;\n token1: string;\n}\n\n/** Options of a swap. */\nexport interface SwapOptions {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing (to remember it, to\n * show it), or to retry the SAME attempt after a lost response; never reuse it for another trade.\n */\n uniqueKey?: string | undefined;\n /**\n * Pin the pool: take `token0` / `token1` verbatim from the quote the user saw, instead of\n * ordering `tokenIn` / `tokenOut` by string comparison. `tokenIn` and `tokenOut` must be exactly\n * these two symbols, and `token0` must sort before `token1`. See {@link swapRouteFromQuote}.\n */\n pool?: SwapPool | undefined;\n}\n\n/** Everything {@link Swaps.swap} needs to trade in the pool a quote priced. */\nexport interface SwapRoute {\n tokenIn: string;\n tokenOut: string;\n fee: FEE_TIER;\n pool: SwapPool;\n}\n\n/**\n * The route of a quote: its fee tier and pool, with `tokenIn` / `tokenOut` taken from\n * `tokenInIsToken0`, nothing re-derived. Use it to swap in exactly the pool a quote priced:\n *\n * @example\n * ```ts\n * const route = swapRouteFromQuote(quote);\n * await swaps.swap(route.tokenIn, route.tokenOut, route.fee, { exactIn: '100' }, { pool: route.pool });\n * ```\n */\nexport function swapRouteFromQuote(\n quote: Pick<QuoteResult, 'token0Symbol' | 'token1Symbol' | 'tokenInIsToken0' | 'fee'>,\n): SwapRoute {\n validateFee(quote.fee);\n assertCanonicalPair(quote.token0Symbol, quote.token1Symbol);\n const [tokenIn, tokenOut] = quote.tokenInIsToken0\n ? [quote.token0Symbol, quote.token1Symbol]\n : [quote.token1Symbol, quote.token0Symbol];\n return {\n tokenIn,\n tokenOut,\n fee: quote.fee,\n pool: { token0: quote.token0Symbol, token1: quote.token1Symbol },\n };\n}\n\n/** Executes queued current-contract RequestTrade operations through the Chain Gateway. */\nexport class Swaps {\n /**\n * Creates a swap service.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, symbols, signer, 'client|alice');\n * ```\n */\n constructor(\n private readonly gateway: SwapGateway,\n private readonly symbols: TokenResolver,\n private readonly signer?: GalaChainSigner,\n private readonly walletAddress?: string,\n options: UniqueKeyOptions = {},\n ) {\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\n }\n\n private readonly uniqueKeyPrefix: string;\n\n /**\n * Signs and submits an exact-input or exact-output RequestTrade DTO. The returned transaction\n * is QUEUED; call `await tx.confirm()` to obtain the executed trade or chain rejection.\n *\n * @example\n * ```ts\n * const submitted = await swaps.swap('GALA', 'GUSDC', 3000, {\n * exactIn: '100',\n * amountOutMinimum: '14',\n * });\n * ```\n */\n public async swap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>> {\n return this.submitSwap(await this.buildSwap(tokenIn, tokenOut, fee, amount, options));\n }\n\n /**\n * Signs and submits a SHADOW (dark) swap: the same RequestTrade as {@link swap}, relayed with\n * `X-Shadow: true` so defi-backend marks it private before it reaches the contract. Requires a\n * `walletAddress`. Resolves the normalized outcome instead of throwing on a gateway refusal:\n * `ok: false` carries `unavailable` (retryable), `disabled`, `rejected` (with the gateway's\n * message) or `unknown`. A success carries `queued`, to be confirmed with\n * `confirmSwap(queued.uniqueKey)`; never fall back to a public swap on failure. Whatever this\n * THROWS (a validation error, the signer, a lost connection, `SHADOW_NOT_QUEUED`) has\n * `error.shadow === true` (`isShadowError`), so an app can apply its dark-swap policy to it.\n *\n * @example\n * ```ts\n * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * if (outcome.ok) await swaps.confirmSwap(outcome.queued.uniqueKey);\n * ```\n */\n public async swapShadow(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () =>\n this.submitSwapShadow(await this.buildSwap(tokenIn, tokenOut, fee, amount, options)),\n );\n }\n\n /**\n * Builds the RequestTrade DTO that {@link swap} would sign, without signing or sending it: to\n * show in an approval popup, to remember its `uniqueKey`, or to sign elsewhere. Submit exactly\n * this DTO with {@link submitSwap}. The pure counterpart, with canonical inputs and no\n * resolution, is `buildRequestTradeDto`.\n *\n * @example\n * ```ts\n * const dto = await swaps.buildSwap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * showApproval(dto);\n * const submitted = await swaps.submitSwap(dto);\n * ```\n */\n public async buildSwap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<RequestTradeDTO> {\n validateFee(fee);\n const uniqueKey = options?.uniqueKey ?? createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(uniqueKey);\n const tokenInSymbol = await tradingSymbolOf(this.symbols, tokenIn);\n const tokenOutSymbol = await tradingSymbolOf(this.symbols, tokenOut);\n const ordered = this.orientPool(tokenInSymbol, tokenOutSymbol, options?.pool);\n return buildRequestTradeDto({\n token0: ordered.token0,\n token1: ordered.token1,\n fee,\n tokenInIsToken0: tokenInSymbol === ordered.token0,\n uniqueKey,\n ...amount,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildSwap} or `buildRequestTradeDto`. The DTO must be\n * exactly what the builder produces (no signature, canonical decimals, builder key order), so\n * what an app showed is what gets signed.\n *\n * @example\n * ```ts\n * const submitted = await swaps.submitSwap(dto);\n * const applied = await submitted.confirm();\n * ```\n */\n public async submitSwap(dto: RequestTradeDTO): Promise<SubmittedTransaction<AppliedTrade>> {\n const signed = await this.signRequestTrade(dto);\n return this.gateway.submit('RequestTrade', signed, this.submitOptions());\n }\n\n /** Signs and shadow-submits a DTO built by {@link buildSwap}; see {@link swapShadow}. */\n public async submitSwapShadow(dto: RequestTradeDTO): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () => {\n const signed = await this.signRequestTrade(dto);\n const result = await this.gateway.submitShadow('RequestTrade', signed, this.submitOptions());\n return readShadowSubmitOutcome('RequestTrade', signed, result);\n });\n }\n\n private submitOptions(): ChainSubmitOptions {\n return this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n }\n\n private async signRequestTrade(dto: RequestTradeDTO): Promise<Record<string, unknown>> {\n assertCanonicalV2Dto('RequestTrade', dto);\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n return signPreSend(this.signer, 'RequestTrade', dto);\n }\n\n /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */\n private orientPool(\n tokenInSymbol: string,\n tokenOutSymbol: string,\n pool: SwapPool | undefined,\n ): SwapPool {\n if (pool === undefined) {\n return readOrderedSymbols(orderSymbols(tokenInSymbol, tokenOutSymbol));\n }\n const sameSet =\n (tokenInSymbol === pool.token0 && tokenOutSymbol === pool.token1) ||\n (tokenInSymbol === pool.token1 && tokenOutSymbol === pool.token0);\n if (!sameSet) {\n throw new GSwapSDKError('POOL_MISMATCH', {\n tokenIn: tokenInSymbol,\n tokenOut: tokenOutSymbol,\n poolToken0: pool.token0,\n poolToken1: pool.token1,\n });\n }\n return { token0: pool.token0, token1: pool.token1 };\n }\n\n /**\n * Confirm a swap by its durable `uniqueKey` without resubmitting it. This is the recovery\n * path after a `CONFIRMATION_TIMEOUT`, a `SUBMISSION_OUTCOME_UNKNOWN`, a `409` replay\n * conflict, or a process restart: it reads the same apply-results record that\n * `SubmittedTransaction.confirm()` reads (retained for 7 days) and resolves the applied trade\n * or throws the chain's rejection. The first read happens immediately unless\n * `initialDelayMs` is given.\n *\n * @example\n * ```ts\n * const applied = await swaps.confirmSwap('galaswap-operation-2f1c…');\n * ```\n */\n public async confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade> {\n assertUniqueKey(uniqueKey);\n const transaction = new SubmittedTransaction<AppliedTrade>({\n method: 'RequestTrade',\n uniqueKey,\n transactionId: null,\n mode: 'queued',\n result: undefined,\n dexBackendBaseUrl: this.gateway.dexBackendBaseUrl,\n httpRequestor: this.gateway.httpRequestor,\n requestTimeoutMs: this.gateway.requestTimeoutMs,\n wire: this.gateway.wire,\n });\n return transaction.confirm({ initialDelayMs: 0, ...options });\n }\n}\n","import { Assets } from './assets.js';\nimport { DexFees } from './dex_fees.js';\nimport { ChainGateway } from './gateway.js';\nimport { GdexStreamService } from './gdex_stream.js';\nimport { HttpClient } from './http_client.js';\nimport { Pools } from './pools.js';\nimport { Positions } from './positions.js';\nimport { Quoting } from './quoting.js';\nimport type { GalaChainSigner } from './signers.js';\nimport { CanonicalSymbols, Symbols } from './symbols.js';\nimport type { InvalidEntryHandler } from '../utils/lenient.js';\nimport { Swaps } from './swaps.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { GSwapEnv } from '../types/env.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { GSWAP_ENVIRONMENTS } from '../types/env.js';\n\n/** Options for constructing a backend-routed SDK client. */\nexport interface GSwapOptions {\n /** Signs every write. Without one, reads work and any write throws `NO_SIGNER`. */\n signer?: GalaChainSigner | undefined;\n /**\n * The selected account, sent as `X-Wallet-Address` on writes (attribution only; the chain\n * recovers the signer from the signature). Required for shadow writes.\n */\n walletAddress?: string | undefined;\n /** `'stage'` or `'prod'` swap backend preset; defaults to `'prod'`. */\n env?: GSwapEnv | undefined;\n /** Overrides the preset's swap backend base URL (a test or private deployment). */\n dexBackendBaseUrl?: string | undefined;\n /** HTTP transport for every request; defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Request timeout in milliseconds (default 30 000); `Infinity` arms no timer. */\n chainCallTimeoutMs?: number | undefined;\n /** Query encoding and `User-Agent` of the read requests (see {@link WireOptions}). */\n wire?: WireOptions | undefined;\n /**\n * How tokens are turned into trading symbols. `'registry'` (default) reads the symbol registry\n * once (`GET /v2/trade/symbols`, cached) and accepts symbols or class keys. `'canonical'` makes\n * no registry request: the caller passes the backend's canonical trading symbols (from a quote,\n * an estimate or a position), reads send tokens and ticks exactly as given (composite keys\n * included) and the backend orients the pair; see {@link CanonicalSymbols}.\n */\n symbolResolution?: 'registry' | 'canonical' | undefined;\n /**\n * Told about every row of a pool, symbol or position list that was skipped as unusable (see\n * {@link InvalidEntryHandler}); without it such rows are skipped silently.\n */\n onInvalidEntry?: InvalidEntryHandler | undefined;\n /** Realtime stream endpoint. Defaults to the environment's, or is derived from `dexBackendBaseUrl`. */\n dexBackendWsUrl?: string | undefined;\n /** WebSocket constructor for the realtime stream; required on Node.js older than 22. */\n webSocketImpl?: unknown;\n /**\n * `x-api-key` for the privileged stream view; server-side only, and it requires `webSocketImpl`\n * (see `GdexStreamConfig.apiKey`).\n */\n streamApiKey?: string | undefined;\n /**\n * Prefix of every write's `uniqueKey` (`<prefix><uuid>`). Defaults to `galaswap-operation-`,\n * what frontend_v2 and wallet_extension send; defi-backend does not depend on it.\n */\n uniqueKeyPrefix?: string | undefined;\n}\n\n/**\n * Main entry point for the current GalaChainDex SDK: one client bundling the services that read\n * and write through the swap backend (`quoting`, `swaps`, `pools`, `positions`, `assets`,\n * `symbols`, `fees`, `stream`). See {@link GSwapOptions} for configuration.\n */\nexport class GSwap {\n /** The swap backend base URL every request goes to, without a trailing slash. */\n public readonly dexBackendBaseUrl: string;\n /** The request timeout in milliseconds (default 30 000; `Infinity` arms no timer). */\n public readonly chainCallTimeoutMs: number;\n /** The signer given at construction, if any. */\n public readonly signer: GalaChainSigner | undefined;\n /** The account given at construction, if any. */\n public readonly walletAddress: string | undefined;\n /** The chain-gateway client every other service reads and writes through. */\n public readonly gateway: ChainGateway;\n /** The trading-symbol registry. */\n public readonly symbols: Symbols;\n /** Read-only exact-input and exact-output quotes. */\n public readonly quoting: Quoting;\n /** Pool, slot0 and composite-pool reads. */\n public readonly pools: Pools;\n /** Position reads, liquidity estimates and liquidity / pool-creation writes. */\n public readonly positions: Positions;\n /** Queued swaps (`RequestTrade`), dark swaps and swap confirmation. */\n public readonly swaps: Swaps;\n /** User token balances. */\n public readonly assets: Assets;\n /** Network-fee quotes (DryRun) signed with this client's signer. */\n public readonly fees: DexFees;\n /** The realtime stream endpoint {@link GSwap.stream} connects to. */\n public readonly dexBackendWsUrl: string;\n private readonly webSocketImpl: unknown;\n private readonly streamApiKey: string | undefined;\n private streamClient: GdexStreamService | undefined;\n\n /**\n * Create an SDK client for prod (the default) or stage, or for a `dexBackendBaseUrl` of your own.\n *\n * @example\n * ```typescript\n * const gSwap = new GSwap({ env: 'stage' });\n * const symbols = await gSwap.symbols.list();\n * ```\n */\n constructor(options?: GSwapOptions) {\n const environment = GSWAP_ENVIRONMENTS[options?.env ?? 'prod'];\n this.dexBackendBaseUrl = trimTrailingSlash(\n options?.dexBackendBaseUrl ?? environment.dexBackendBaseUrl,\n );\n this.chainCallTimeoutMs = options?.chainCallTimeoutMs ?? 30_000;\n this.signer = options?.signer;\n this.walletAddress = options?.walletAddress;\n\n const httpClient = new HttpClient(\n options?.httpRequestor,\n this.chainCallTimeoutMs,\n options?.wire,\n );\n this.gateway = new ChainGateway({\n dexBackendBaseUrl: this.dexBackendBaseUrl,\n chainCallTimeoutMs: this.chainCallTimeoutMs,\n ...(options?.wire === undefined ? {} : { wire: options.wire }),\n ...(options?.httpRequestor === undefined ? {} : { httpRequestor: options.httpRequestor }),\n ...(this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress }),\n });\n const lenient = { onInvalidEntry: options?.onInvalidEntry };\n this.symbols = new Symbols(this.gateway, lenient);\n // The services resolve tokens through the registry by default; the offline resolver sends the\n // caller's canonical symbols and keys as they are and never reads the registry.\n const resolver =\n options?.symbolResolution === 'canonical' ? new CanonicalSymbols() : this.symbols;\n this.quoting = new Quoting(this.gateway, resolver);\n this.pools = new Pools(this.gateway, resolver, lenient);\n const keyOptions = { uniqueKeyPrefix: options?.uniqueKeyPrefix, ...lenient };\n this.positions = new Positions(\n this.gateway,\n resolver,\n this.signer,\n this.walletAddress,\n keyOptions,\n );\n this.swaps = new Swaps(this.gateway, resolver, this.signer, this.walletAddress, keyOptions);\n this.assets = new Assets(this.dexBackendBaseUrl, httpClient);\n this.fees = new DexFees(this.gateway, this.signer);\n this.dexBackendWsUrl =\n options?.dexBackendWsUrl ??\n (options?.dexBackendBaseUrl === undefined\n ? environment.dexBackendWsUrl\n : `${this.dexBackendBaseUrl.replace(/^http/u, 'ws')}/ws`);\n this.webSocketImpl = options?.webSocketImpl;\n this.streamApiKey = options?.streamApiKey;\n }\n\n /**\n * The realtime stream client for this environment (created on first use, not connected until you\n * call `connect()`).\n *\n * @example\n * ```typescript\n * const gSwap = new GSwap({ env: 'stage' });\n * await gSwap.stream.connect();\n * await gSwap.stream.subscribeLiquidity((event) => console.log(event.action, event.amount0));\n * ```\n */\n get stream(): GdexStreamService {\n this.streamClient ??= new GdexStreamService({\n url: this.dexBackendWsUrl,\n ...(this.webSocketImpl === undefined ? {} : { webSocketImpl: this.webSocketImpl }),\n ...(this.streamApiKey === undefined ? {} : { apiKey: this.streamApiKey }),\n });\n return this.streamClient;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/u, '');\n}\n","import type { FailureOutcome } from './failure_outcomes.js';\n\n/**\n * The classification values an app shell may need on their own: what an outcome allows. This module\n * is deliberately tiny and imports nothing at run time (the outcome type is erased), so an app\n * shell that builds `classification('not_sent')` or reads `NOT_QUEUED_FINAL` loads a few hundred\n * bytes, not the table of error codes that lives with `classifyFailure`.\n */\n\n/** The result of `classifyFailure`. */\nexport interface FailureClassification {\n readonly outcome: FailureOutcome;\n /**\n * May the app offer the user Retry: repeat the operation as a NEW request (a fresh key for a\n * write) without any risk of applying it twice? Always `false` for `unknown` (confirm the same\n * key instead) and `invalid_input` (the same call fails again). It says a repeat is SAFE, not\n * that it will succeed, and it is the SDK's floor: an app may still withhold Retry (the\n * wallet and frontend_v2 do after a Dark swap: see `isShadowError`).\n */\n readonly retryable: boolean;\n}\n\n/**\n * The SDK's default Retry answer for each outcome. A decision that departs from it (a refusal the\n * gateway will repeat, `SHADOW_NOT_QUEUED`) is written out in the table of `classifyFailure`.\n */\nconst DEFAULT_RETRYABLE = {\n rejected: true,\n unknown: false,\n not_queued: true,\n not_sent: true,\n invalid_input: false,\n transient: true,\n} as const satisfies Record<FailureOutcome, boolean>;\n\n/**\n * Builds the classification the SDK itself gives an outcome, so an app that classifies a step of\n * its OWN (one that is not an SDK call) uses the SDK's type and its values instead of a\n * hard-coded `{ outcome, retryable }` literal. `retryable` is the SDK's default for that outcome\n * (`false` for `unknown` and `invalid_input`, `true` for the rest). Each call returns a new\n * object, safe to mutate or freeze.\n *\n * `options.retryable: false` WITHHOLDS Retry from an outcome that would otherwise allow it: the\n * SDK's own `not_queued` for a refusal the gateway will repeat is\n * `classification('not_queued', { retryable: false })` (also exported, frozen, as\n * {@link NOT_QUEUED_FINAL}). An app may take Retry away from an outcome but never grant it to one\n * that cannot have it, so only `false` is accepted.\n *\n * @example\n * ```ts\n * // The app refreshes a quote before it asks the SDK to sign; the refresh failed.\n * throw new AppSwapError(text, classification('not_sent'));\n * // The app refuses a request for a reason a repeat cannot fix.\n * throw new AppSwapError(text, classification('not_queued', { retryable: false }));\n * ```\n */\nexport function classification(\n outcome: FailureOutcome,\n options: { readonly retryable?: false } = {},\n): FailureClassification {\n return { outcome, retryable: options.retryable === false ? false : DEFAULT_RETRYABLE[outcome] };\n}\n\n/**\n * `classification('not_queued', { retryable: false })`: the gateway refused the write before\n * queueing it AND will refuse a repeat the same way (the version wall, a dark swap that did not\n * queue, an HTTP 4xx). Nothing is pending and Retry is not offered. It is frozen: use it as it is\n * (`classification: NOT_QUEUED_FINAL`) instead of spreading `classification('not_queued')` and\n * overriding `retryable`; `{ ...NOT_QUEUED_FINAL }` is a mutable copy.\n */\nexport const NOT_QUEUED_FINAL: Readonly<FailureClassification> = Object.freeze(\n classification('not_queued', { retryable: false }),\n);\n\n/**\n * `classification('not_sent')`: a step of the app's own failed before anything was signed or\n * sent (a quote refresh, a balance read), so nothing is pending and a repeat is safe.\n */\nexport function notSentClassification(): FailureClassification {\n return classification('not_sent');\n}\n","import type { GSWAP_ERROR_CATALOG, GSwapErrorCode } from '../classes/error_catalog.js';\nimport { isCatalogCode } from '../classes/error_phase_table.js';\nimport { classification, NOT_QUEUED_FINAL, type FailureClassification } from './classification.js';\nimport { isWriteView, numberParamOf, stringParamOf, toFailureView } from './failure_view.js';\nimport type { FailureView } from './failure_view.js';\n\n/**\n * `classifyFailure` and `mayHaveBeenQueued`: the one module that holds the decision for every\n * catalog code (~135 names, a floor no minifier can remove). It needs the code table and nothing\n * else: the classification values live in `classification.ts`, the yes/no guards in\n * `failure_guards.ts`, and the error class and catalog are only named as types.\n */\n\nconst REJECTED: FailureClassification = classification('rejected');\nconst UNKNOWN: FailureClassification = classification('unknown');\nconst NOT_QUEUED: FailureClassification = classification('not_queued');\nconst NOT_SENT: FailureClassification = classification('not_sent');\nconst INVALID_INPUT: FailureClassification = classification('invalid_input');\nconst TRANSIENT: FailureClassification = classification('transient');\n\n/**\n * The classification of every code whose meaning does not depend on the failing answer. A code\n * missing here is a compile error (unless it is `pre_send`, see {@link CodeTable}), so adding a\n * catalog code forces a decision.\n */\nconst BY_CODE = {\n // ----------------------------------------------------------------------------------- transport\n REQUEST_TIMEOUT: TRANSIENT,\n TRANSPORT_ERROR: TRANSIENT,\n REQUEST_FAILED: TRANSIENT,\n\n // ------------------------------------------------------------------------------- write: unknown\n // No answer was read, or a 2xx answer that does not prove the write was queued under the signed\n // key: it may have been applied.\n SUBMISSION_OUTCOME_UNKNOWN: UNKNOWN,\n GATEWAY_REPORTED_ERROR: UNKNOWN,\n GATEWAY_DATA_MISSING: UNKNOWN,\n GATEWAY_MODE_INVALID: UNKNOWN,\n GATEWAY_SYNC_REQUEST_TRADE: UNKNOWN,\n MISSING_UNIQUE_KEY: UNKNOWN,\n UNIQUE_KEY_MISMATCH: UNKNOWN,\n\n // --------------------------------------------------------------------- write: refused, not queued\n SHADOW_NOT_QUEUED: NOT_QUEUED_FINAL,\n METHOD_NOT_ALLOWED: NOT_QUEUED,\n SIGNATURE_INVALID: NOT_QUEUED,\n SIGNER_MISMATCH: NOT_QUEUED,\n DTO_INVALID: NOT_QUEUED,\n BOUNDS_VIOLATION: NOT_QUEUED,\n SYMBOL_CONFLICT: NOT_QUEUED,\n RATE_LIMITED: NOT_QUEUED,\n GATEWAY_REJECTED: NOT_QUEUED,\n\n // ----------------------------------------------------------------------- the chain's own verdict\n CHAIN_REJECTED: REJECTED,\n\n // ----------------------------------------------------------------------- reads of backend data\n INVALID_CHAIN_RESPONSE: TRANSIENT,\n INVALID_POSITION_RESPONSE: TRANSIENT,\n\n // -------------------------------------------------------------------------------- confirmation\n CONFIRMATION_TIMEOUT: UNKNOWN,\n CONFIRMATION_ABORTED: UNKNOWN,\n CONFIRMATION_FAILED: UNKNOWN,\n CONFIRMATION_MALFORMED: UNKNOWN,\n CONFIRMATION_KEY_MISMATCH: UNKNOWN,\n\n // ------------------------------------------------------------------------------ the realtime stream\n STREAM_DISCONNECTED: TRANSIENT,\n STREAM_REQUEST_TIMEOUT: TRANSIENT,\n STREAM_CONNECT_FAILED: TRANSIENT,\n STREAM_CLOSED_BEFORE_CONNECT: TRANSIENT,\n STREAM_CONNECTION_CLOSED: TRANSIENT,\n\n // ----------------------------------------------- pre-send: an app-supplied callback failed\n // The signer, the key provider or the token resolver threw before anything was transmitted. The\n // original error is `cause`. A repeat cannot apply anything twice.\n SIGNING_FAILED: NOT_SENT,\n KEY_PROVIDER_FAILED: NOT_SENT,\n TOKEN_RESOLUTION_FAILED: NOT_SENT,\n\n // ------------------------------------------- the call cannot work as written, found AFTER an answer\n // (a pre_send code needs no row: it is `invalid_input` by default, see `CodeTable`)\n NO_WALLET_ADDRESS: INVALID_INPUT,\n NO_POOL_AVAILABLE: INVALID_INPUT,\n INSUFFICIENT_LIQUIDITY: INVALID_INPUT,\n} as const satisfies CodeTable;\n\n/** A code whose catalog phase is `pre_send`. */\ntype PreSendCode = {\n [C in GSwapErrorCode]: (typeof GSWAP_ERROR_CATALOG)[C]['phase'] extends 'pre_send' ? C : never;\n}[GSwapErrorCode];\n\n/** The codes whose classification depends on the failing answer, not on a table row. */\ntype AnswerDependentCode =\n 'HTTP_ERROR' | 'UPDATE_REQUIRED' | 'CHAIN_DISPATCH_FAILED' | 'INVALID_PRIVATE_KEY';\n\n/**\n * Every code that is NOT `pre_send` needs a row (a new one is a compile error until it has one);\n * a `pre_send` code may have one (`SIGNING_FAILED` is `not_sent`). A `pre_send` code without a row\n * is `invalid_input`: nothing was transmitted, so it cannot be `unknown`, and it is not a\n * condition a repeat clears. That keeps the 90-odd validation codes out of the table, which is\n * what keeps `classifyFailure` small enough for an app shell.\n */\ntype CodeTable = {\n readonly [C in Exclude<GSwapErrorCode, PreSendCode | AnswerDependentCode>]: FailureClassification;\n} & {\n readonly [C in Exclude<PreSendCode, AnswerDependentCode>]?: FailureClassification;\n};\n\n/**\n * A key that is not valid is the input's fault (`invalid_input`), except `no_key_provided`: the\n * provider had nothing to give right now (a locked wallet, an empty slot). That is the same\n * situation as a provider that throws (`KEY_PROVIDER_FAILED`), and it clears once a key exists, so\n * it is `not_sent` and Retry is safe.\n */\nfunction classifyInvalidPrivateKey(view: FailureView): FailureClassification {\n return stringParamOf(view, 'reason') === 'no_key_provided' ? NOT_SENT : INVALID_INPUT;\n}\n\n/** The status of an HTTP failure: the one it carries, else its `status` param. */\nfunction statusOfView(view: FailureView): number | undefined {\n return view.status ?? numberParamOf(view, 'status');\n}\n\n/**\n * An HTTP failure with no gateway or chain code: its meaning depends on the status and on read vs\n * write. A view that states no status at all cannot be judged: `unknown`.\n */\nfunction classifyHttpError(view: FailureView): FailureClassification {\n const status = statusOfView(view);\n if (status === undefined) return UNKNOWN;\n if (isWriteView(view)) {\n // A gateway that answered 5xx or 408 may still have queued the write; 429 and 4xx did not.\n if (status === 429) return NOT_QUEUED;\n if (status === 408 || status >= 500) return UNKNOWN;\n return NOT_QUEUED_FINAL;\n }\n return status === 408 || status === 429 || status >= 500 ? TRANSIENT : INVALID_INPUT;\n}\n\n/**\n * The version wall (HTTP 426). On a write the gateway refused it before queueing anything, and a\n * repeat of the same app version is refused the same way, so it is `not_queued` with no Retry. On a\n * read nothing changed either, and only an update helps: `invalid_input`, no Retry. Both say \"show\n * the update screen\", not \"try again\".\n */\nfunction classifyUpdateRequired(view: FailureView): FailureClassification {\n return isWriteView(view) ? NOT_QUEUED_FINAL : INVALID_INPUT;\n}\n\n/**\n * The chain dispatch failed. The gateway echoes the upstream status: 409 is \"this uniqueKey was\n * already consumed\" (the first attempt may be applied), 422 is the chain evaluating the write and\n * refusing it (definite), another 5xx is an upstream outage after which the write may have landed,\n * and a 4xx is a refusal before anything was queued.\n */\nfunction classifyChainDispatchFailed(view: FailureView): FailureClassification {\n const status = view.status;\n if (status === undefined || status === 409 || status >= 500) return UNKNOWN;\n return status === 422 ? REJECTED : NOT_QUEUED;\n}\n\n/**\n * Classifies any thrown value from its code (and, for two codes, its HTTP status), never from\n * message text, so an app does not have to re-derive \"may I offer Retry?\" and \"is the outcome\n * unknown?\" for every code. The decision for each code is in this module's table; a new catalog\n * code cannot be added without one.\n *\n * A failure BEFORE the request left (`error.phase === 'pre_send'`, `isPreSendError`) can never be\n * `unknown` or `rejected`: it is `invalid_input` (the input has to change) or `not_sent` (nothing\n * was transmitted; a repeat is safe). Every app-supplied callback the SDK calls before it sends\n * (the signer, the key provider, a token resolver) has its failure wrapped into such an error\n * (`SIGNING_FAILED`, `KEY_PROVIDER_FAILED`, `TOKEN_RESOLUTION_FAILED`, the original as `cause`),\n * so an app NEVER needs an error class of its own to say \"nothing was sent\": a locked wallet,\n * a declined signature and a failed lookup all arrive as `not_sent`, retryable.\n *\n * It accepts a `GSwapSDKError` or a plain-object VIEW of one ({@link FailureView}: `{ code,\n * params?, status?, uniqueKey?, ... }`, the shape of the wrapper an app builds from an SDK error;\n * `toFailureView` reads any value), and decides from the same fields, so an app does not need to\n * keep the original error to ask. `{ afterQueued: true }` says the write is already queued (the\n * step being classified is a confirmation): `retryable` is then always `false`.\n *\n * Anything that is not an SDK error or such a view, or a view whose `code` the catalog does not\n * define, is `{ outcome: 'unknown', retryable: false }`: the SDK\n * cannot say what happened, and refusing Retry is the safe answer. That is only what escapes AFTER\n * the request left (an app requestor that rejects with its own error, a callback of yours that\n * throws once bytes were sent). An error your own code raises BEFORE it calls the SDK says so\n * itself: give it a code of its own and `outcome` (`{ code: 'POSITION_STALE', outcome: 'not_sent'\n * }`), and the SDK answers with that outcome's classification and `mayHaveBeenQueued` is `false`.\n * The declared `outcome` is read only for a code the catalog does not define.\n *\n * A failure is a WRITE's unless it states `write: false` (`GSwapSDKError.write`, set for every\n * SDK read): see {@link FailureView}. A view that lost its `uniqueKey` is therefore still judged as\n * a write (a 5xx stays `unknown`), never as a retryable read.\n *\n * To learn that a failure came from the dark (shadow) path, read `error.shadow` (a typed field of\n * every `GSwapSDKError`) or call `isShadowError(error)`, which also covers a non-SDK object that\n * escaped `swapShadow` / `submitSwapShadow` / `ChainGateway.submitShadow`. The classification is\n * the same as on the public path; an app that withholds Retry or a public fallback after a dark\n * swap applies that policy on top of `retryable`.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { outcome, retryable } = classifyFailure(error);\n * if (outcome === 'unknown') keepPendingAndConfirm(error); // never a second swap\n * else if (retryable) offerRetry(); // a new request under a fresh key\n * }\n * ```\n */\nexport function classifyFailure(\n error: unknown,\n options: ClassifyFailureOptions = {},\n): FailureClassification {\n const result = classifyView(toFailureView(error));\n // A `rejected` outcome is the chain's definite no: the queued write was evaluated and NOT\n // applied, so a new request under a fresh key cannot double-apply it and Retry stays as it is.\n return options.afterQueued === true && result.outcome !== 'rejected'\n ? { ...result, retryable: false }\n : result;\n}\n\n/** Options of {@link classifyFailure}. */\nexport interface ClassifyFailureOptions {\n /**\n * The write is ALREADY queued (the gateway acknowledged it with this `uniqueKey`), and what is\n * being classified is a later step: confirming it, reading its apply result. Whatever the\n * outcome, `retryable` is then `false`: a NEW request would be a second trade, so the app\n * confirms the same key (or forgets it) and never offers \"Try again\". `outcome` is unchanged.\n *\n * The one exception is `rejected`: the chain evaluated the queued write and refused it (an\n * apply result of `Status: 0`, `CHAIN_REJECTED`; a 422 dispatch). That PROVES it was not\n * applied, so a new request under a fresh key cannot make a second trade, and `retryable`\n * keeps the answer it has without this option (`true`). Every outcome that does not prove\n * \"not applied\" (`unknown`, `transient`, `not_queued`, ...) is `false`.\n */\n afterQueued?: boolean | undefined;\n}\n\n/**\n * The classification of a failure view: the table decision for its code, the status-dependent\n * decision for the four codes whose meaning needs it, and for a code the catalog does not define\n * (a wallet error, an ethers `ACTION_REJECTED`, a typo, an app's own error): `unknown` unless the\n * view DECLARES its `outcome` (an app's error, `{ code: 'POSITION_STALE', outcome: 'not_sent' }`),\n * then the SDK's own classification of that outcome. A value with no view is `unknown`.\n */\nfunction classifyView(view: FailureView | undefined): FailureClassification {\n if (view === undefined) return { ...UNKNOWN };\n if (!isCatalogCode(view.code)) {\n if (view.outcome === undefined) return { ...UNKNOWN };\n // Withhold-only: `retryable: false` removes Retry from the declared outcome, never adds it.\n return view.retryable === false\n ? classification(view.outcome, { retryable: false })\n : classification(view.outcome);\n }\n const { code } = view;\n if (code === 'HTTP_ERROR') return { ...classifyHttpError(view) };\n if (code === 'UPDATE_REQUIRED') return { ...classifyUpdateRequired(view) };\n if (code === 'CHAIN_DISPATCH_FAILED') return { ...classifyChainDispatchFailed(view) };\n if (code === 'INVALID_PRIVATE_KEY') return { ...classifyInvalidPrivateKey(view) };\n const row: FailureClassification | undefined = (\n BY_CODE as Readonly<Partial<Record<GSwapErrorCode, FailureClassification>>>\n )[code];\n return { ...(row ?? INVALID_INPUT) };\n}\n\n/**\n * True when the failed call was a WRITE that may nevertheless have been queued: its outcome is\n * `unknown` (`classifyFailure(error).outcome === 'unknown'`: a timeout or broken connection after\n * the request left, an acknowledgement that proves nothing, a gateway 409 or 5xx, a failed\n * confirmation). The app must keep `error.uniqueKey` and confirm it, and must NOT submit again\n * under a fresh key. Every other outcome (`rejected`, `not_queued`, `not_sent`, `invalid_input`,\n * `transient`) proves the write is not pending.\n *\n * A value the SDK cannot judge (an app requestor's own rejection after the request left) is\n * `unknown` too, so it is `true`; handle errors your own code raised BEFORE calling the SDK first.\n * Meant for the catch of a write; a read never has a pending key to keep.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * if (mayHaveBeenQueued(error)) keepPendingAndConfirm(error);\n * }\n * ```\n */\nexport function mayHaveBeenQueued(error: unknown): boolean {\n return classifyFailure(error).outcome === 'unknown';\n}\n","import { classifyFailure } from '../utils/failure_classification.js';\nimport type { FailureOutcome } from '../utils/failure_outcomes.js';\n\n/**\n * What to do with a pending swap after confirming it failed (the answer of\n * {@link pendingSwapFateFor}).\n *\n * - `forget`: the chain REFUSED the trade, so it did not happen. Drop it AND tell the user.\n * - `forget_quietly`: the confirmation can never succeed (the key is refused: `invalid_input`).\n * Drop it without claiming anything about the trade.\n * - `keep`: the trade may still have been applied (a timeout, a broken connection, a gateway\n * hiccup, anything not proven). Leave it pending and look again later.\n *\n * This module holds the decision and nothing of the store, so an app shell that only needs the\n * fate pays for `classifyFailure` and this table, not for `PendingSwapStore`.\n */\nexport const PENDING_SWAP_FATES = ['forget', 'forget_quietly', 'keep'] as const;\n\n/** One member of {@link PENDING_SWAP_FATES}. */\nexport type PendingSwapFate = (typeof PENDING_SWAP_FATES)[number];\n\n/**\n * The fate of a pending swap for each failure OUTCOME. Only a chain rejection proves the trade did\n * not happen; an input that can never be confirmed is dropped quietly; every other outcome leaves\n * the trade possibly applied. Typed over `FailureOutcome`, so a new outcome does not compile until\n * it is decided here.\n */\nconst FATE_OF_OUTCOME = {\n rejected: 'forget',\n invalid_input: 'forget_quietly',\n unknown: 'keep',\n not_queued: 'keep',\n not_sent: 'keep',\n transient: 'keep',\n} as const satisfies Record<FailureOutcome, PendingSwapFate>;\n\n/**\n * {@link pendingSwapFateFor} from an outcome the app already holds (for example the\n * `classifyFailure(error).outcome` it stored on its own failure wrapper). An outcome this SDK\n * version does not know (a newer SDK at run time) is `keep`: never forget what may have happened.\n */\nexport function pendingSwapFateOfOutcome(outcome: FailureOutcome): PendingSwapFate {\n return Object.hasOwn(FATE_OF_OUTCOME, outcome) ? FATE_OF_OUTCOME[outcome] : 'keep';\n}\n\n/**\n * The fate of a queued swap whose confirmation (`confirmAppliedTrade`) just failed with `error`,\n * from the SDK's classification alone: `forget` for a chain rejection (`rejected`), `forget_quietly`\n * for a key that can never be confirmed (`invalid_input`), `keep` for every other outcome\n * (`unknown`, `not_queued`, `not_sent`, `transient`) and for any value the SDK cannot judge. It\n * accepts an SDK error or a plain-object view of one (see `FailureView`). It replaces the wallet's\n * `pendingSwapActionFor` and frontend_v2's `confirmationStanceOf`.\n *\n * @example\n * ```ts\n * try {\n * await confirmAppliedTrade(client, swap);\n * } catch (error) {\n * if ((await store.settle(swap.uniqueKey, error)) === 'forget') tellTheUserItFailed();\n * }\n * ```\n */\nexport function pendingSwapFateFor(error: unknown): PendingSwapFate {\n return pendingSwapFateOfOutcome(classifyFailure(error, { afterQueued: true }).outcome);\n}\n","import { isValidUniqueKey } from '../utils/unique_key_syntax.js';\nimport { pendingSwapFateFor, type PendingSwapFate } from './pending_swap_fate.js';\nimport type { StorageAdapter } from './storage_adapters.js';\n\n/** Key the wallet_extension has always used; its storage value is a plain array of entries. */\nexport const PENDING_SWAPS_STORAGE_KEY = 'pendingSwaps.v1';\n\n/** Entries older than this are dropped the next time a wallet's swaps are listed. */\nexport const PENDING_SWAP_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** A RequestTrade that was accepted by the gateway but whose outcome has not been read yet. */\nexport interface PendingSwap {\n uniqueKey: string;\n requestTransactionId: string | null;\n /** The wallet (account) that submitted the swap; `list` filters by it. */\n wallet: string;\n token0Symbol: string;\n token1Symbol: string;\n /** Whether the swap was a shadow (\"dark\") swap. */\n isDarkSwap: boolean;\n /** Epoch milliseconds when the swap was queued. */\n createdAt: number;\n}\n\n/**\n * Why the store dropped a pending swap (the `reason` of {@link PrunedPendingSwap}).\n *\n * - `expired`: older than {@link PENDING_SWAP_EXPIRY_MS}.\n * - `invalid_unique_key`: its `uniqueKey` is not a valid apply-results key (1 to 128 characters\n * of `A-Za-z0-9._:-`). `confirmAppliedTrade` refuses such a key with `INVALID_UNIQUE_KEY`\n * before reading anything and always will, so keeping the entry would retry it forever. The\n * SDK never signs such a key; an entry like this is corrupt or foreign.\n * - `chain_rejected`: {@link PendingSwapStore.settle} dropped it because a confirmation proved the\n * chain REFUSED the trade (`pendingSwapFateFor` is `forget`): it did not happen.\n * - `unconfirmable`: {@link PendingSwapStore.settle} dropped it because a confirmation failed in a\n * way that never changes (`forget_quietly`: the key itself is refused): nothing can be learned.\n */\nexport const PENDING_SWAP_PRUNE_REASONS = [\n 'expired',\n 'invalid_unique_key',\n 'chain_rejected',\n 'unconfirmable',\n] as const;\n\n/** One member of {@link PENDING_SWAP_PRUNE_REASONS}. */\nexport type PendingSwapPruneReason = (typeof PENDING_SWAP_PRUNE_REASONS)[number];\n\n/** A pending swap the store dropped, and why. */\nexport interface PrunedPendingSwap {\n swap: PendingSwap;\n reason: PendingSwapPruneReason;\n}\n\n/** Options for {@link PendingSwapStore}. */\nexport interface PendingSwapStoreOptions {\n /**\n * Called once per dropped entry (after the drop is persisted, for `list`; at once for a\n * `remember` that refuses an invalid key), so the app can tell the user or log why a swap it\n * was tracking is gone. Diagnostics only: what it does, or throws, never changes the store.\n */\n onPrune?: ((pruned: PrunedPendingSwap) => void) | undefined;\n /** Storage key. Default {@link PENDING_SWAPS_STORAGE_KEY}. */\n storageKey?: string | undefined;\n /**\n * The stored name of the dark-swap flag. `isDarkSwap` (default) is wallet_extension's shape;\n * `shadow` is frontend_v2's. Entries are always exposed to callers as `isDarkSwap`.\n */\n darkFlagField?: 'isDarkSwap' | 'shadow' | undefined;\n /**\n * Where `remember` puts a new entry in the stored array: `end` (default, wallet_extension) or\n * `start` (frontend_v2).\n */\n insertAt?: 'end' | 'start' | undefined;\n /**\n * The order of `list`: `stored` (default, wallet_extension: oldest first for `insertAt: 'end'`)\n * or `newest-first` (frontend_v2).\n */\n listOrder?: 'stored' | 'newest-first' | undefined;\n /** Clock, in epoch milliseconds. Defaults to `Date.now`. */\n now?: (() => number) | undefined;\n}\n\n/**\n * Remembers queued swaps so their outcome can be confirmed after the UI, popup or service worker\n * that submitted them is gone (`confirmAppliedTrade` with the stored `uniqueKey`).\n *\n * Guarantees:\n * - Persistence is best effort and NEVER throws: a failing or missing storage must not turn an\n * accepted request into a client-side resubmission. `list` resolves `[]` when storage fails.\n * - Operations of one store instance are serialized, so concurrent `remember` / `forget` calls\n * cannot lose each other's write (read-modify-write over an async adapter). Two store instances\n * over the same storage (for example popup and service worker) are not coordinated.\n * - Entries that do not match the expected shape are ignored and dropped on the next write.\n * - Entries expire after seven days (an entry exactly seven days old is expired; frontend_v2\n * kept it for that one millisecond); `list` removes them from storage, which frontend_v2 never\n * did on read.\n * - An entry whose `uniqueKey` is not a valid apply-results key is terminal, not pending:\n * `confirmAppliedTrade` fails it with `INVALID_UNIQUE_KEY` every time, so a resume loop would\n * retry it forever. `list` prunes it like an expired one, and `remember` refuses to save it;\n * both tell `onPrune` the reason (`PENDING_SWAP_PRUNE_REASONS`).\n * - New entries go to the end (or `insertAt: 'start'`); `list` returns the wallet's entries in\n * stored order (or `listOrder: 'newest-first'`).\n * - The stored shape is wallet_extension's by default; `storageKey`, `darkFlagField`, `insertAt`\n * and `listOrder` reproduce frontend_v2's. JSON key order inside an entry is not preserved.\n *\n * Passing no `storage` yields a store that remembers nothing.\n *\n * @example\n * ```ts\n * const store = new PendingSwapStore({\n * get: async (key) => (await chrome.storage.local.get(key))[key],\n * set: (key, value) => chrome.storage.local.set({ [key]: value }),\n * });\n * await store.remember({ uniqueKey, requestTransactionId, wallet, token0Symbol: 'GALA',\n * token1Symbol: 'GUSDC', isDarkSwap: false, createdAt: Date.now() });\n * for (const swap of await store.list(wallet)) await confirmAppliedTrade(client, swap);\n * ```\n */\nexport class PendingSwapStore {\n private readonly storageKey: string;\n private readonly darkFlagField: 'isDarkSwap' | 'shadow';\n private readonly insertAt: 'end' | 'start';\n private readonly listOrder: 'stored' | 'newest-first';\n private readonly now: () => number;\n private readonly onPrune: ((pruned: PrunedPendingSwap) => void) | undefined;\n private queue: Promise<unknown> = Promise.resolve();\n\n constructor(\n private readonly storage: StorageAdapter | undefined,\n options: PendingSwapStoreOptions = {},\n ) {\n this.storageKey = options.storageKey ?? PENDING_SWAPS_STORAGE_KEY;\n this.darkFlagField = options.darkFlagField ?? 'isDarkSwap';\n this.insertAt = options.insertAt ?? 'end';\n this.listOrder = options.listOrder ?? 'stored';\n this.now = options.now ?? Date.now;\n this.onPrune = options.onPrune;\n }\n\n /**\n * Saves (or replaces, by `uniqueKey`) a pending swap. A swap whose `uniqueKey` is not a valid\n * apply-results key is not saved (it could never be confirmed); it is reported to `onPrune` as\n * `invalid_unique_key`.\n */\n public remember(swap: PendingSwap): Promise<void> {\n if (!isValidUniqueKey(swap.uniqueKey)) {\n this.report([{ swap, reason: 'invalid_unique_key' }]);\n return Promise.resolve();\n }\n return this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const others = current\n .filter((entry) => entry.uniqueKey !== swap.uniqueKey)\n .map(this.toStored);\n const stored = this.toStored(swap);\n await storage.set(\n this.storageKey,\n this.insertAt === 'end' ? [...others, stored] : [stored, ...others],\n );\n });\n }\n\n /** Removes a pending swap once its outcome is known. */\n public forget(uniqueKey: string): Promise<void> {\n return this.enqueue(async (storage) => {\n const current = await this.read(storage);\n await storage.set(\n this.storageKey,\n current.filter((entry) => entry.uniqueKey !== uniqueKey).map(this.toStored),\n );\n });\n }\n\n /**\n * Applies {@link pendingSwapFateFor} to a swap whose confirmation failed with `error`, and\n * returns the fate so the app can word it (tell the user on `forget`, say nothing on\n * `forget_quietly`, keep polling on `keep`):\n *\n * - `forget`: the entry is removed and `onPrune` hears `chain_rejected`.\n * - `forget_quietly`: the entry is removed and `onPrune` hears `unconfirmable`.\n * - `keep`: nothing changes and `onPrune` is not called.\n *\n * Like every store operation it is serialized and best effort: if storage fails the entry stays\n * (a later `settle` or `list` handles it) and the fate is still returned. A key that is not\n * stored (already forgotten) is not an error and `onPrune` is not called for it.\n */\n public async settle(uniqueKey: string, error: unknown): Promise<PendingSwapFate> {\n const fate = pendingSwapFateFor(error);\n if (fate === 'keep') return fate;\n const removed = await this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const swap = current.find((entry) => entry.uniqueKey === uniqueKey);\n if (swap === undefined) return undefined;\n await storage.set(\n this.storageKey,\n current.filter((entry) => entry.uniqueKey !== uniqueKey).map(this.toStored),\n );\n return swap;\n });\n if (removed !== undefined) {\n this.report([\n { swap: removed, reason: fate === 'forget' ? 'chain_rejected' : 'unconfirmable' },\n ]);\n }\n return fate;\n }\n\n /**\n * The wallet's pending swaps that can still be confirmed (see `listOrder`). Entries that never\n * can be are pruned from storage, for every wallet, and reported to `onPrune`: expired ones\n * (`expired`) and ones whose `uniqueKey` is not a valid apply-results key\n * (`invalid_unique_key`: `confirmAppliedTrade` would fail `INVALID_UNIQUE_KEY` on it forever).\n */\n public async list(wallet: string): Promise<PendingSwap[]> {\n const result = await this.enqueue(async (storage) => {\n const current = await this.read(storage);\n const now = this.now();\n const pruned: PrunedPendingSwap[] = [];\n const kept: PendingSwap[] = [];\n for (const entry of current) {\n const reason = this.pruneReasonOf(entry, now);\n if (reason === undefined) kept.push(entry);\n else pruned.push({ swap: entry, reason });\n }\n if (pruned.length > 0) {\n await storage.set(this.storageKey, kept.map(this.toStored));\n this.report(pruned);\n }\n const mine = kept.filter((entry) => entry.wallet === wallet);\n return this.listOrder === 'newest-first'\n ? mine.sort((left, right) => right.createdAt - left.createdAt)\n : mine;\n });\n return result ?? [];\n }\n\n private pruneReasonOf(entry: PendingSwap, now: number): PendingSwapPruneReason | undefined {\n if (!isValidUniqueKey(entry.uniqueKey)) return 'invalid_unique_key';\n return now - entry.createdAt < PENDING_SWAP_EXPIRY_MS ? undefined : 'expired';\n }\n\n /** Tells `onPrune` about each dropped entry; the hook is diagnostics and cannot break the store. */\n private report(pruned: readonly PrunedPendingSwap[]): void {\n for (const entry of pruned) {\n try {\n this.onPrune?.(entry);\n } catch {\n // A diagnostics hook must not turn a store operation into a failure.\n }\n }\n }\n\n private enqueue<T>(operation: (storage: StorageAdapter) => Promise<T>): Promise<T | undefined> {\n const storage = this.storage;\n if (storage === undefined) return Promise.resolve(undefined);\n const run = this.queue.then(async () => {\n try {\n return await operation(storage);\n } catch {\n // Storage can be missing, full, or disappear while a context is closing. Persistence is\n // best effort by contract.\n return undefined;\n }\n });\n this.queue = run;\n return run;\n }\n\n private async read(storage: StorageAdapter): Promise<PendingSwap[]> {\n const value = await storage.get(this.storageKey);\n if (!Array.isArray(value)) return [];\n const entries: PendingSwap[] = [];\n for (const item of value as unknown[]) {\n const entry = this.fromStored(item);\n if (entry !== undefined) entries.push(entry);\n }\n return entries;\n }\n\n private readonly toStored = (swap: PendingSwap): Record<string, unknown> => ({\n uniqueKey: swap.uniqueKey,\n requestTransactionId: swap.requestTransactionId,\n wallet: swap.wallet,\n token0Symbol: swap.token0Symbol,\n token1Symbol: swap.token1Symbol,\n [this.darkFlagField]: swap.isDarkSwap,\n createdAt: swap.createdAt,\n });\n\n private fromStored(value: unknown): PendingSwap | undefined {\n if (value === null || typeof value !== 'object') return undefined;\n const entry = value as Record<string, unknown>;\n const flag = entry[this.darkFlagField];\n const { uniqueKey, requestTransactionId, wallet, token0Symbol, token1Symbol, createdAt } =\n entry;\n if (\n typeof uniqueKey !== 'string' ||\n !(typeof requestTransactionId === 'string' || requestTransactionId === null) ||\n typeof wallet !== 'string' ||\n typeof token0Symbol !== 'string' ||\n typeof token1Symbol !== 'string' ||\n typeof flag !== 'boolean' ||\n typeof createdAt !== 'number' ||\n !Number.isFinite(createdAt)\n ) {\n return undefined;\n }\n return {\n uniqueKey,\n requestTransactionId,\n wallet,\n token0Symbol,\n token1Symbol,\n isDarkSwap: flag,\n createdAt,\n };\n }\n}\n","/**\n * Genuine EIP-712 typed-data signing for the four v2 dex-contract operations proven (2026-09-16,\n * live bisection against stage — see defi-backend's `chain-findings-artifact` memory /\n * https://claude.ai/artifact/3N9MevSjoQdU7gqnVB3dfU) to recover the `client|` identity correctly\n * via `eth_signTypedData_v4`, unlike `personal_sign` (which only ever resolves the bare `eth|`\n * form — see `BrowserWalletSigner`'s own doc comment). Mirrors frontend_v2's\n * `src/Services/eip712Types.ts` + `readWriteUtilsV2.ts`'s `EIP712_FIELD_COMPLETERS` exactly —\n * ported here rather than shared as a package because gswap-sdk has no frontend_v2 dependency\n * and should not gain one for four small functions.\n */\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** EIP-712 `types`: each struct name mapped to its ordered `{ name, type }` fields. */\nexport type EIP712Types = Record<string, Array<{ name: string; type: string }>>;\n\n/**\n * Derives the EIP-712 `types` for a DTO from its runtime shape.\n *\n * The generated `types` travel with the signed payload and are what BOTH sides hash, so they\n * must enumerate EVERY field the chain-side DTO will carry. GalaChain refuses any signature\n * whose `types` leave a DTO field uncovered (`assertNoUnsignedFields`, the fix for the\n * 2026-08-18 unsigned-field-injection drain); when that happens signature recovery fails\n * outright and the chain reports \"Missing signerPublicKey or signerAddress field in dto\".\n */\nexport function generateEIP712Types(\n typeName: string,\n params: Record<string, unknown>,\n): EIP712Types {\n const types: EIP712Types = {};\n types[typeName] = [];\n\n // Every `name` this is ever called with (the top-level `typeName`, or a nested struct's own\n // name) is unconditionally assigned `types[name] = []` on the line immediately before any\n // recursive call that could reach here; TypeScript still types `types[name]` as\n // possibly-undefined (index-signature access), so the guard below stays for real type safety\n // even though no current call path can actually trigger it.\n function fieldsFor(name: string): Array<{ name: string; type: string }> {\n const fields = types[name];\n /* c8 ignore next */\n if (!fields) throw new Error(`Missing EIP-712 type definition for ${name}`);\n return fields;\n }\n\n function addField(\n name: string,\n fieldValue: unknown,\n parentTypeName: string,\n onlyGetType = false,\n ): string | undefined {\n if (Array.isArray(fieldValue)) {\n const type =\n fieldValue.length > 0 ? addField(name, fieldValue[0], parentTypeName, true) : 'string';\n if (!onlyGetType) fieldsFor(parentTypeName).push({ name, type: (type ?? name) + '[]' });\n } else if (typeof fieldValue === 'object' && fieldValue !== null) {\n if (types[name]) {\n throw new GSwapSDKError('EIP712_NAME_COLLISION', { name });\n }\n types[name] = [];\n Object.entries(fieldValue).forEach(([key, value]) => {\n addField(key, value, name);\n });\n if (!onlyGetType) fieldsFor(parentTypeName).push({ name, type: name });\n } else {\n let eipType: string;\n switch (typeof fieldValue) {\n case 'string':\n eipType = 'string';\n break;\n case 'number':\n eipType = 'int256';\n break;\n case 'boolean':\n eipType = 'bool';\n break;\n case 'bigint':\n case 'symbol':\n case 'undefined':\n case 'function':\n case 'object':\n throw new GSwapSDKError('EIP712_UNSUPPORTED_VALUE', { valueType: typeof fieldValue });\n }\n if (onlyGetType) {\n return eipType;\n }\n fieldsFor(parentTypeName).push({ name, type: eipType });\n }\n return undefined;\n }\n\n Object.entries(params).forEach(([key, value]) => {\n addField(key, value, typeName);\n });\n\n return types;\n}\n\n/** The EIP-712 domain carried by a signed payload: GalaChain only uses `name` and `chainId`. */\nexport interface EIP712DomainValue {\n name: string;\n chainId: number;\n}\n\n/**\n * Builds the EIP-712 domain from the wallet's LIVE `eth_chainId` result, exactly like frontend_v2\n * (DEFI-1895): a wallet hashes whatever domain it is handed, and MetaMask refuses a `chainId` that\n * differs from its active network, so a hardcoded `1` breaks every wallet that is not on Mainnet.\n * defi-backend recovers the signer from the `domain` the payload carries (live-proven for chain\n * ids 1, 56 and 11155111), so following the wallet is correct on every network.\n *\n * @param chainId - The raw `eth_chainId` result: a `0x` hex string (the JSON-RPC form) or an integer.\n * @throws GSwapSDKError (`INVALID_CHAIN_ID`) when the wallet answers with anything else.\n */\nexport function eip712DomainFor(chainId: unknown): EIP712DomainValue {\n const parsed =\n typeof chainId === 'string' && /^0x[0-9a-fA-F]+$/u.test(chainId)\n ? Number(chainId)\n : typeof chainId === 'number'\n ? chainId\n : Number.NaN;\n if (!Number.isSafeInteger(parsed) || parsed <= 0) {\n throw new GSwapSDKError('INVALID_CHAIN_ID', {\n chainId:\n typeof chainId === 'string' || typeof chainId === 'number'\n ? String(chainId)\n : typeof chainId,\n });\n }\n return { name: 'ethereum', chainId: parsed };\n}\n\n/**\n * The four v2 operations proven to recover the signer correctly via genuine EIP-712: `RequestTrade`\n * never had the problem (one numeric field). `AddLiquidity`/`RemoveLiquidity`/\n * `CollectPositionFees` each need their `types` completed with a handful of fields their real\n * server-side DTO always carries — see the `complete*Fields` functions below. `CreatePool` is a\n * genuinely different, unsolved problem (nested `TokenClassKey` structs, not a flat\n * missing-field gap) and is NOT in this set — callers must keep using `personal-sign` for it.\n */\nexport const EIP712_CAPABLE_METHODS: ReadonlySet<string> = new Set([\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n]);\n\n/**\n * Every `complete*Fields` function below shares the same two live-proven rules:\n * 1. Numeric completeness fields MUST be JS `number`, never numeric strings —\n * `generateEIP712Types` infers a field's Solidity type from `typeof`, and declaring one as\n * EIP-712 `string` instead of `int256` breaks recovery identically to omitting the field\n * entirely (verified live on AddLiquidity: `amount0Min: '0'` fails with the exact same\n * \"Missing signerPublicKey\" error as `amount0Min` being absent; `amount0Min: 0` succeeds).\n * 2. `positionId` has no such constraint — an empty string works, and does not target an\n * existing position (`positionId: ''` created a fresh position on AddLiquidity, not an add\n * to position id `''`; on RemoveLiquidity/CollectPositionFees the real position is still\n * resolved from `token0`/`token1`/`fee`/`tickLower`/`tickUpper`, not from this field).\n */\nfunction numericOr0(dto: Record<string, unknown>, field: string): number {\n return typeof dto[field] === 'number' ? dto[field] : 0;\n}\n\n/**\n * `AddLiquidity`'s real server-side DTO always carries `amount0Desired`/`amount0Min`/\n * `amount1Desired`/`amount1Min`/`positionId` once reconstructed, regardless of which deposit\n * convention the caller used (`Positions.addLiquidityByTicks` only ever sends\n * `depositQuantityToken0`/`depositQuantityToken1`). Proven empirically by bisection: none of the\n * five alone fixes recovery, all five together does (live 201, tx `407d9b24...`, block\n * `2429022`).\n */\nfunction completeAddLiquidityFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount0Desired: numericOr0(dto, 'amount0Desired'),\n amount0Min: numericOr0(dto, 'amount0Min'),\n amount1Desired: numericOr0(dto, 'amount1Desired'),\n amount1Min: numericOr0(dto, 'amount1Min'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\n/**\n * `RemoveLiquidity`'s real server-side DTO always carries `amount`/`amount0Min`/`amount1Min`/\n * `positionId` — `Positions.removeLiquidity` only ever sends a `withdrawalQuantityTokenX` (or\n * neither, for a full close). Proven empirically: every subset of these four fails, all four\n * together succeeds (live, random-signer probe — recovery confirmed by the response moving from\n * \"Missing signerPublicKey\" to a genuine position-not-found 404).\n */\nfunction completeRemoveLiquidityFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount: numericOr0(dto, 'amount'),\n amount0Min: numericOr0(dto, 'amount0Min'),\n amount1Min: numericOr0(dto, 'amount1Min'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\n/**\n * `CollectPositionFees`'s real server-side DTO always carries `amount0Requested`/\n * `amount1Requested`/`positionId` — `Positions.collectPositionFees` sends only the five identity\n * fields. Proven empirically the same way as `completeRemoveLiquidityFields`.\n */\nfunction completeCollectPositionFeesFields(dto: Record<string, unknown>): Record<string, unknown> {\n return {\n ...dto,\n amount0Requested: numericOr0(dto, 'amount0Requested'),\n amount1Requested: numericOr0(dto, 'amount1Requested'),\n positionId: dto['positionId'] ?? '',\n };\n}\n\nexport const EIP712_FIELD_COMPLETERS: Readonly<\n Record<string, (dto: Record<string, unknown>) => Record<string, unknown>>\n> = {\n AddLiquidity: completeAddLiquidityFields,\n RemoveLiquidity: completeRemoveLiquidityFields,\n CollectPositionFees: completeCollectPositionFeesFields,\n};\n\n/**\n * Completes a DTO's fields for EIP-712 signing (a no-op for methods with no known gap, e.g.\n * `RequestTrade`) and derives its `types`. Exported separately from the signing call itself so tests\n * can assert on the exact payload without needing a live provider.\n */\nexport function buildEIP712Payload(\n methodName: string,\n dto: Record<string, unknown>,\n): { completedDto: Record<string, unknown>; types: EIP712Types } {\n const completer = EIP712_FIELD_COMPLETERS[methodName];\n const completedDto = completer ? completer(dto) : dto;\n const types = generateEIP712Types(methodName, completedDto);\n return { completedDto, types };\n}\n","/**\n * SDK-owned signing primitives.\n *\n * Everything the SDK needs to produce a GalaChain signature lives here, with no dependency on\n * `@gala-chain/api` (which drags `secp256k1` native bindings, `reflect-metadata`, `class-validator`\n * and its own `bignumber.js` major into every consumer). The only runtime dependencies are the\n * audited, pure-JS `@noble/curves` (secp256k1) and `@noble/hashes` (keccak256), which run\n * unchanged in browsers, MV3 service workers, Node and React Native/Hermes.\n *\n * Every function here is pinned byte-for-byte to the signatures produced by `@gala-chain/api`\n * (`serialize`, `signatures.getSignature`), `@gala-chain/connect`, the Gala Wallet extension and\n * frontend_v2 by the golden-vector suite in `tests/signing-golden.test.ts`.\n */\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { bytesToHex } from '@noble/hashes/utils';\nimport type { InvalidPrivateKeyReason } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nconst textEncoder = new TextEncoder();\n\nfunction toDeterministicNode(node: unknown): unknown {\n if (node === null || node === undefined) return node;\n if (node instanceof RegExp) return node.toString();\n const candidate = node as { toJSON?: unknown };\n return typeof candidate.toJSON === 'function'\n ? (Reflect.apply(candidate.toJSON, node, []) as unknown)\n : node;\n}\n\nfunction deterministicNode(rawNode: unknown): string | undefined {\n const node = toDeterministicNode(rawNode);\n if (node === undefined) return undefined;\n if (typeof node !== 'object' || node === null) return JSON.stringify(node);\n\n if (Array.isArray(node)) {\n const items = (node as unknown[]).map((item) => deterministicNode(item) ?? 'null');\n return `[${items.join(',')}]`;\n }\n\n const record = node as Record<string, unknown>;\n const members: string[] = [];\n for (const key of Object.keys(record).sort()) {\n const value = deterministicNode(record[key]);\n if (value === undefined) continue;\n members.push(`${JSON.stringify(key)}:${value}`);\n }\n return `{${members.join(',')}}`;\n}\n\n/**\n * GalaChain's deterministic JSON: object keys sorted (UTF-16 code-unit order) at every depth, no\n * whitespace, `undefined`/function members dropped, `toJSON()` honored. Byte-identical to\n * `serialize` from `@gala-chain/api` / `json-stringify-deterministic` for every JSON-shaped\n * value, which is all a DTO ever is.\n *\n * @throws TypeError for circular structures and BigInt values (as `JSON.stringify` does) and\n * when the value itself has no JSON representation (`undefined`, a function, a symbol).\n */\nexport function serialize(value: unknown): string {\n // Same cycle/BigInt guard json-stringify-deterministic runs before walking the value.\n JSON.stringify(value);\n const result = deterministicNode(value);\n if (result === undefined) {\n throw new TypeError('Cannot serialize a value with no JSON representation.');\n }\n return result;\n}\n\n/**\n * The exact string GalaChain hashes for a DTO: the (optional, string) `prefix` field PREPENDED to\n * the deterministic serialization of the DTO WITHOUT `signature`, `multisig`, `trace` and `prefix`.\n * Equivalent to `@gala-chain/api` 3.x `getPayloadToSign` for every non-EIP-712 DTO.\n */\nexport function getPayloadToSign(dto: Record<string, unknown>): string {\n const { prefix, ...rest } = dto;\n delete rest['signature'];\n delete rest['multisig'];\n delete rest['trace'];\n const head = typeof prefix === 'string' ? prefix : '';\n return head + serialize(rest);\n}\n\n// Built via String.fromCharCode rather than a literal escape ON PURPOSE: a literal control byte in\n// source is invisible and fragile under editors/diffs/copy-paste; this keeps the source ordinary.\nconst ETHEREUM_SIGNED_MESSAGE = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\n\n/**\n * The EIP-191 header for `message`: `\"\\x19Ethereum Signed Message:\\n\"` + the message's UTF-8 BYTE\n * length. This is what a wallet's `personal_sign` prepends, and what the chain recomputes when it\n * recovers a personal-signed DTO.\n */\nexport function calculatePersonalSignPrefix(message: string): string {\n return ETHEREUM_SIGNED_MESSAGE + String(textEncoder.encode(message).length);\n}\n\n/**\n * The EIP-191 header for `serialize(dto)` (any `prefix` already on the DTO is ignored). This is\n * deliberately the same string the signers hand a wallet to sign, so the header's length can never\n * disagree with the signed message. Wallet-neutral: it is the value both a browser wallet's\n * `personal_sign` and Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepend.\n */\nexport function personalSignPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n return calculatePersonalSignPrefix(serialize(withoutPrefix));\n}\n\n/**\n * The `@gala-chain/connect`-style prefix frontend_v2 puts in the body of an EIP-712 write: the\n * EIP-191 header whose number counts the prefix string ITSELF plus the body (the UTF-8 length of\n * `getPayloadToSign({ ...dto, prefix })`), found by fixpoint because adding the prefix changes the\n * length (a body of 99 bytes settles on 101).\n *\n * It is NOT a personal-sign prefix (a personal-sign write with this value recovers a phantom\n * signer; use `personalSignPrefixFor`). Under EIP-712 the field is an untyped extra that the\n * typed-data hash ignores and defi-backend recomputes, so it only exists to keep the submitted\n * body byte-identical to what frontend_v2 has always sent.\n */\nexport function fixpointPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n let payloadLength = textEncoder.encode(getPayloadToSign(withoutPrefix)).length;\n let prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n let previousLength = -1;\n while (payloadLength !== previousLength) {\n previousLength = payloadLength;\n prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n payloadLength = textEncoder.encode(getPayloadToSign({ ...withoutPrefix, prefix })).length;\n }\n return prefix;\n}\n\nfunction invalidPrivateKey(reason: InvalidPrivateKeyReason): GSwapSDKError<'INVALID_PRIVATE_KEY'> {\n return new GSwapSDKError('INVALID_PRIVATE_KEY', { reason });\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction decodeBase64(input: string): Uint8Array | undefined {\n if (!/^[A-Za-z0-9+/]+={0,2}$/u.test(input) || input.length % 4 !== 0) return undefined;\n const unpadded = input.replace(/=+$/u, '');\n const bytes: number[] = [];\n let buffer = 0;\n let bits = 0;\n for (const char of unpadded) {\n buffer = (buffer << 6) | BASE64_ALPHABET.indexOf(char);\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n bytes.push((buffer >> bits) & 0xff);\n }\n }\n return Uint8Array.from(bytes);\n}\n\nfunction decodeHex(input: string): Uint8Array {\n const bytes = new Uint8Array(input.length / 2);\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = parseInt(input.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Normalizes a secp256k1 private key to a fresh 32-byte array (the caller may zero it). Also\n * accepts 32 raw bytes, which are validated and copied. For strings it accepts what `@gala-chain/api`'s\n * `normalizePrivateKey` accepted for a usable key: 64 hex characters (optionally `0x`-prefixed;\n * a 63-character hex key is left-padded with a zero) or a 44-character base64 string.\n *\n * @throws GSwapSDKError (`INVALID_PRIVATE_KEY`; `params.reason` is one of\n * `INVALID_PRIVATE_KEY_REASONS`: `wrong_length` for raw bytes that are not 32 long,\n * `bad_encoding` for any other string shape, `not_on_curve` for an out-of-range scalar).\n */\nexport function normalizePrivateKey(input: string | Uint8Array): Uint8Array {\n if (typeof input !== 'string') {\n // Raw bytes: validated, then COPIED, so zeroing the result never touches the caller's array.\n if (!(input instanceof Uint8Array) || input.length !== 32) {\n throw invalidPrivateKey('wrong_length');\n }\n if (!secp256k1.utils.isValidSecretKey(input)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return Uint8Array.from(input);\n }\n const withoutPrefix = input.startsWith('0x') ? input.slice(2) : input;\n let key: Uint8Array | undefined;\n if (/^[0-9a-fA-F]{63,64}$/u.test(withoutPrefix)) {\n key = decodeHex(withoutPrefix.length === 63 ? `0${withoutPrefix}` : withoutPrefix);\n } else if (withoutPrefix.length === 44) {\n key = decodeBase64(withoutPrefix);\n }\n if (key?.length !== 32) {\n throw invalidPrivateKey('bad_encoding');\n }\n if (!secp256k1.utils.isValidSecretKey(key)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return key;\n}\n\n/**\n * Signs a 32-byte keccak256 hash and returns GalaChain's recoverable signature: 64 hex `r` +\n * 64 hex `s` + `1b`/`1c` (`v`), lowercase, no `0x`. Deterministic (RFC 6979) and low-S, exactly\n * what `@gala-chain/api` and the Gala Wallet produce. A DER signature carries no recovery byte\n * and cannot be used: the chain RECOVERS the signer from the signature.\n */\nexport function signHash(privateKey: Uint8Array, hash: Uint8Array): string {\n if (hash.length !== 32) {\n throw new GSwapSDKError('INVALID_SIGNING_HASH_LENGTH', { length: hash.length });\n }\n const signature = secp256k1.sign(hash, privateKey, { prehash: false, lowS: true });\n // compact raw bytes are r (32) || s (32); the recovery id becomes v.\n return bytesToHex(signature.toBytes('compact')) + (signature.recovery === 1 ? '1c' : '1b');\n}\n\n/**\n * The lowercase `0x` Ethereum address (last 20 bytes of keccak256 of the uncompressed public key)\n * of a normalized private key. The Gala `eth|` identity of a key is this address.\n */\nexport function ethAddressOfPrivateKey(privateKey: Uint8Array): string {\n const publicKey = secp256k1.getPublicKey(privateKey, false);\n return `0x${bytesToHex(keccak_256(publicKey.slice(1)).slice(-20))}`;\n}\n\n/** keccak256 of a string's UTF-8 bytes. */\nexport function keccak256Utf8(data: string): Uint8Array {\n return keccak_256(textEncoder.encode(data));\n}\n\n/**\n * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes, with no\n * prefix and no signature envelope. The caller owns serialization, so the bytes shown to a user\n * and the bytes signed can never diverge.\n */\nexport function signSerializedNative(privateKey: Uint8Array, serializedDto: string): string {\n return signHash(privateKey, keccak256Utf8(serializedDto));\n}\n\n/**\n * GalaChain NATIVE signature for a DTO: keccak256 of `getPayloadToSign(dto)`, signed with\n * secp256k1. Byte-identical to `signatures.getSignature` from `@gala-chain/api`.\n */\nexport function signNative(privateKey: Uint8Array, dto: Record<string, unknown>): string {\n return signSerializedNative(privateKey, getPayloadToSign(dto));\n}\n\n/**\n * Personal-sign hash and signature: keccak256(`prefix` + `message`), both hashed VERBATIM with no\n * further EIP-191 wrapping. Passing `prefix = calculatePersonalSignPrefix(message)` reproduces a\n * wallet's `personal_sign` of `message`. Gala Wallet's `gala_signChainDto` (personal-sign\n * scheme) hashes `prefix` + the exact string it is handed, which can differ from the bare message\n * (see the `signatureOverPrefixlessBody` vectors); that quirk is why the two inputs stay separate.\n */\nexport function signPersonalMessage(\n privateKey: Uint8Array,\n prefix: string,\n message: string,\n): string {\n return signHash(privateKey, keccak256Utf8(prefix + message));\n}\n","import { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport {\n buildEIP712Payload,\n EIP712_CAPABLE_METHODS,\n eip712DomainFor,\n type EIP712DomainValue,\n type EIP712Types,\n} from '../utils/eip712.js';\nimport {\n ethAddressOfPrivateKey,\n fixpointPrefixFor,\n normalizePrivateKey,\n personalSignPrefixFor,\n serialize,\n signNative,\n} from '../utils/signing.js';\n\n// Personal-sign prefix, computed the way THE CHAIN verifies it.\n//\n// GalaChain (SDK 3.x) recovers a personal-signed DTO from\n// keccak256(<prefix field> + <canonical JSON of the DTO WITHOUT the prefix field>)\n// and a browser wallet's `personal_sign` (EIP-191) hashes\n// \"\\u0019Ethereum Signed Message:\\n\" + <byte length of message> + <message>.\n// They agree exactly when the wallet signs the bare canonical DTO and `prefix` is the EIP-191\n// header for that message's UTF-8 BYTE length. Any other message still yields a valid-looking\n// signature — it just recovers to an address nobody holds. This SDK used to embed `prefix` in\n// the signed message (the SDK 1.10 client recipe): observed on stage 2026-09-23, such a\n// MetaMask-signed CreatePool executed on chain under a phantom creator, and defi-backend's\n// bouncer now rejects that shape outright.\n//\n// `@gala-chain/connect`'s prefix helper must NOT be used for wallet `personal_sign`: its\n// fixpoint counts the prefix itself and targets the SDK's raw-payload signer. The same header\n// is also what Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepends before hashing,\n// so one value serves both paths.\n//\n// The header itself is computed by `personalSignPrefixFor` in ../utils/signing.ts.\n\n/** The signing schemes supported by the Gala Wallet signer. */\nexport type GalaWalletScheme = 'native' | 'personal-sign';\n\n/** The request surface used by an EIP-1193 browser wallet. */\nexport interface BrowserWalletProvider {\n request(args: { method: string; params?: unknown[] }): Promise<unknown>;\n}\n\ninterface GalaWalletProvider {\n request(args: { method: string; params?: unknown[] }): Promise<unknown>;\n /** Gala Wallet's \"act as this account\" switch; absent on other providers. */\n setAddress?: (address: string) => Promise<void>;\n}\n\ninterface WindowWithGala {\n gala?: GalaWalletProvider;\n}\n\ninterface GlobalWithWindow {\n window?: WindowWithGala;\n}\n\n/** A DTO together with the signature that belongs in the gateway request body. */\nexport type SignedDto<T extends Record<string, unknown>> = T & { signature: string };\n\n/**\n * A signer for complete GalaChain write bodies.\n *\n * Implementations return the DTO fields together with the signature that belongs in the\n * gateway request body. Signer identity is recovered from that signature; implementations do\n * not add signer hints, typed-data metadata, or a domain.\n */\nexport interface GalaChainSigner {\n /**\n * Signs a DTO for a named GalaChain contract method.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n */\n signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;\n}\n\nfunction getWalletProvider(): GalaWalletProvider {\n const globalObject = globalThis as GlobalWithWindow;\n const wallet = globalObject.window?.gala;\n if (!wallet) {\n throw new GSwapSDKError('GALA_WALLET_NOT_AVAILABLE', {});\n }\n return wallet;\n}\n\nfunction getNativeSignature(value: unknown): string {\n if (typeof value !== 'string') {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'native' });\n }\n // 130 hex digits (r || s || v), bare as Gala Wallet returns it or `0x`-prefixed; passed on\n // verbatim, because the backend recovers the signer from either spelling.\n if (!/^(?:0x)?[0-9a-fA-F]{130}$/u.test(value)) {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'native' });\n }\n return value;\n}\n\nfunction getPersonalSignature(value: unknown): string {\n if (typeof value !== 'string' || !/^(?:0x)?[0-9a-fA-F]{130}$/u.test(value)) {\n throw new GSwapSDKError('INVALID_SIGNATURE', { scheme: 'personal-sign' });\n }\n return value;\n}\n\n/**\n * The `0x`-prefixed Ethereum address a Gala account is signed by, or `undefined` when the account\n * names no key (a `client|` alias or a bare GalaChain id is not derivable from a key). Accepts\n * `0x` plus 40 hex digits and `eth|` plus 40 hex digits, with or without `0x`; the caller's casing\n * is kept. For {@link LazyPrivateKeySignerOptions.expectedAddress}, which should only be set for\n * an account whose key can be checked.\n *\n * @example\n * ```ts\n * createLazyPrivateKeySigner(getKey, { expectedAddress: ethereumAddressOfAccount(account) });\n * ```\n */\nexport function ethereumAddressOfAccount(account: string): string | undefined {\n const match = /^(?:eth\\|(?:0x)?|0x)([0-9a-fA-F]{40})$/u.exec(account);\n return match?.[1] === undefined ? undefined : `0x${match[1]}`;\n}\n\nfunction normalizeEthereumAccount(address: string, allowGalaPrefix: boolean): string {\n const normalized = allowGalaPrefix ? (ethereumAddressOfAccount(address) ?? address) : address;\n if (!/^0x[0-9a-fA-F]{40}$/u.test(normalized)) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'walletAddress', value: address });\n }\n // The caller's casing is kept on purpose: frontend_v2 and the wallet hand the wallet the\n // checksummed account, and EIP-1193 / Gala Wallet accept any case, so passing the value through\n // unchanged is the only choice that cannot differ from what they send.\n return normalized;\n}\n\n/**\n * The account handed to Gala Wallet as the signer address. An Ethereum account is held to the\n * same strict check as ever (`0x` plus 40 hex digits; `eth|` plus 40 hex digits, with or without\n * `0x`, is normalized to it). A GalaChain id the wallet can also be asked to sign for is passed\n * through verbatim: `client|` plus 24 hex digits, or the bare 24 hex digits that frontend_v2 keeps\n * in `state.user.wallet` after a direct `client|` login. Nothing else is accepted.\n */\nfunction normalizeGalaWalletAccount(address: string): string {\n const eth = /^eth\\|(?:0x)?([0-9a-fA-F]{40})$/u.exec(address);\n if (eth?.[1] !== undefined) return `0x${eth[1]}`;\n if (/^0x[0-9a-fA-F]{40}$/u.test(address) || /^(?:client\\|)?[0-9a-fA-F]{24}$/u.test(address)) {\n return address;\n }\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'walletAddress', value: address });\n}\n\n/** An identity Gala Wallet can act as: an account form above, any `eth|`/`client|` alias, verbatim. */\nfunction assertWalletIdentity(identity: string): void {\n if (\n !/^(?:eth\\|(?:0x)?[0-9a-fA-F]{40}|0x[0-9a-fA-F]{40}|(?:client\\|)?[0-9a-fA-F]{24})$/u.test(\n identity,\n )\n ) {\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field: 'selectAddress', value: identity });\n }\n}\n\n/** Provider-wide queue: `setAddress` + the signature request must not interleave across signers. */\nconst walletIdentityQueue = new WeakMap<object, Promise<unknown>>();\n\n/**\n * Runs `signWith` with `identity` selected on a Gala Wallet that supports `setAddress`. Gala\n * Wallet holds ONE current account, so two signatures for different identities in flight at once\n * would sign as whichever selection came last; the pair (select, sign) is therefore serialized\n * per provider. A failed selection fails the signature (nothing is requested).\n */\nfunction withSelectedIdentity<T>(\n wallet: GalaWalletProvider,\n identity: string | undefined,\n signWith: () => Promise<T>,\n): Promise<T> {\n const { setAddress } = wallet;\n if (identity === undefined || typeof setAddress !== 'function') return signWith();\n const previous = walletIdentityQueue.get(wallet) ?? Promise.resolve();\n const run = previous\n .catch(() => undefined)\n .then(async () => {\n await setAddress.call(wallet, identity);\n return signWith();\n });\n walletIdentityQueue.set(wallet, run);\n return run;\n}\n\nfunction personalSign<T extends Record<string, unknown>>(\n provider: GalaWalletProvider | BrowserWalletProvider,\n dto: T,\n walletAddress: string,\n methodName?: string,\n): Promise<T & { prefix: string; signature: string }> {\n const prefix = personalSignPrefixFor(dto);\n const payload = { ...dto, prefix };\n // A browser wallet's `personal_sign` applies the EIP-191 header ITSELF, so it must sign the\n // bare DTO; Gala Wallet's `gala_signChainDto` (personal-sign scheme) instead extracts the\n // `prefix` field from what it is handed and prepends it before hashing, so it is handed the\n // prefixed payload. Both submit `{ ...dto, prefix, signature }`.\n const params =\n methodName !== undefined\n ? [serialize(payload), walletAddress, methodName]\n : [serialize(dto), walletAddress];\n\n return provider\n .request({ method: methodName !== undefined ? 'gala_signChainDto' : 'personal_sign', params })\n .then((value) => ({ ...payload, signature: getPersonalSignature(value) }));\n}\n\n/**\n * Signs a DTO via genuine EIP-712 (`eth_signTypedData_v4`) — correctly resolves the `client|`\n * identity, unlike `personal_sign`, for the operations in `EIP712_CAPABLE_METHODS`.\n *\n * Constructs the raw JSON-RPC payload by hand (`{domain, types: {...types, EIP712Domain},\n * primaryType, message}`) rather than depending on ethers.js, matching exactly what\n * `ethers.TypedDataEncoder.getPayload`/`Wallet.signTypedData` produce internally — verified\n * byte-for-byte equivalent (same recovered address from the same signature against both\n * constructions) before this shipped, since gswap-sdk deliberately has no ethers dependency.\n */\nasync function signEIP712<T extends Record<string, unknown>>(\n provider: BrowserWalletProvider,\n methodName: string,\n dto: T,\n walletAddress: string,\n): Promise<T & { types: EIP712Types; domain: EIP712DomainValue; signature: string }> {\n const { completedDto, types } = buildEIP712Payload(methodName, dto);\n // The wallet's LIVE chain id, read on every signature: a user can switch networks after\n // connecting, and a cached or hardcoded id would sign a domain MetaMask itself rejects.\n const domain = eip712DomainFor(await provider.request({ method: 'eth_chainId', params: [] }));\n // The body `prefix` is not part of the EIP-712 `types`, so it is never hashed; it carries the\n // connect-style fixpoint value only to keep the submitted body byte-identical to frontend_v2's.\n const prefix = fixpointPrefixFor(completedDto);\n const message = { ...completedDto, prefix };\n const eip712Domain = [\n { name: 'name', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n ];\n const payload = {\n domain,\n types: { ...types, EIP712Domain: eip712Domain },\n primaryType: methodName,\n message,\n };\n\n const value = await provider.request({\n method: 'eth_signTypedData_v4',\n params: [walletAddress, JSON.stringify(payload)],\n });\n // Key order matches frontend_v2's submitted body: ..., prefix, signature, types, domain.\n return {\n ...(message as T & { prefix: string }),\n signature: getPersonalSignature(value),\n types,\n domain,\n };\n}\n\n/**\n * A GalaChain native signer backed by a secp256k1 private key.\n *\n * Native signing produces the bare GalaChain signature format, without a personal-sign prefix\n * or EIP-712 metadata. The private-key identity is recovered by the chain.\n */\nexport class PrivateKeySigner implements GalaChainSigner {\n private readonly privateKey: Uint8Array;\n\n /**\n * Creates a native signer from a hex or base64 secp256k1 private key.\n *\n * @example\n * ```typescript\n * const signer = new PrivateKeySigner('1'.padStart(64, '0'));\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n */\n constructor(privateKey: string) {\n this.privateKey = normalizePrivateKey(privateKey);\n }\n\n /**\n * Signs the DTO with GalaChain native signing.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * fee: 3000,\n * });\n * ```\n */\n public signObject<T extends Record<string, unknown>>(\n _methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const signature = signNative(this.privateKey, dto);\n return Promise.resolve({ ...dto, signature });\n }\n}\n\n/** Supplies a private key at sign time: a hex/base64 string, possibly fetched asynchronously. */\nexport type PrivateKeyProvider = () => Promise<string> | string;\n\n/** Options for {@link createLazyPrivateKeySigner}. */\nexport interface LazyPrivateKeySignerOptions {\n /**\n * When set, every signature first checks that the fetched key belongs to this account (`0x...`\n * or the Gala `eth|0x...` / `eth|<40 hex>` form, case-insensitive) and refuses to sign otherwise\n * (`SIGNER_ADDRESS_MISMATCH`). Use it when the key lives in a slot another surface can switch\n * between the moment a request was approved and the moment it is signed.\n */\n expectedAddress?: string | undefined;\n}\n\n/**\n * Calls the app's key provider. Whatever it throws or rejects with is the app's own failure to\n * produce a key before anything was signed or sent, so it becomes `KEY_PROVIDER_FAILED` (the\n * original is `cause`); an SDK error is already catalogued and passes through.\n */\nasync function keyFrom(getPrivateKey: PrivateKeyProvider): Promise<unknown> {\n try {\n return await getPrivateKey();\n } catch (cause: unknown) {\n throw isGSwapError(cause) ? cause : new GSwapSDKError('KEY_PROVIDER_FAILED', {}, { cause });\n }\n}\n\n/**\n * Creates the native-signing equivalent of {@link PrivateKeySigner} for apps that must not hold a\n * key in a long-lived object (an extension that reads its session key at sign time).\n *\n * `getPrivateKey` is called once per `signObject` call, never cached, never shared between calls\n * (concurrent signatures each fetch their own key), and the normalized key bytes are zeroed\n * before `signObject` settles, also on failure. A rejection or exception from `getPrivateKey` (the\n * app's \"wallet is locked\", a storage read that failed) is a `KEY_PROVIDER_FAILED` error with the\n * original error as `cause`: nothing has been sent, so `classifyFailure` says `not_sent` and Retry\n * is safe, and the app needs no error class of its own to tell this apart. A provider that returns\n * no usable string (`''`, `undefined`) is `INVALID_PRIVATE_KEY` with `reason: 'no_key_provided'`,\n * classified the same way; any other key that is not a valid secp256k1 key string is an\n * `INVALID_PRIVATE_KEY` error. An SDK error the provider throws itself is passed through.\n * Signatures are byte-identical to `new PrivateKeySigner(key).signObject(...)`.\n *\n * A JavaScript string cannot be wiped; the provider owns the lifetime of the string it returns.\n *\n * @example\n * ```typescript\n * const signer = createLazyPrivateKeySigner(\n * () => SecurityHelper.getSessionSecret(SecurityHelper.SESSION_PRIVATE_KEY_KEY),\n * { expectedAddress: account.address },\n * );\n * const gswap = new GSwap({ signer });\n * ```\n */\nexport function createLazyPrivateKeySigner(\n getPrivateKey: PrivateKeyProvider,\n options: LazyPrivateKeySignerOptions = {},\n): GalaChainSigner {\n const expected = options.expectedAddress;\n const expectedLower =\n expected === undefined ? undefined : normalizeEthereumAccount(expected, true).toLowerCase();\n\n return {\n async signObject<T extends Record<string, unknown>>(\n _methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const provided: unknown = await keyFrom(getPrivateKey);\n if (typeof provided !== 'string' || provided === '') {\n throw new GSwapSDKError('INVALID_PRIVATE_KEY', { reason: 'no_key_provided' });\n }\n const key = normalizePrivateKey(provided);\n try {\n if (expectedLower !== undefined && ethAddressOfPrivateKey(key) !== expectedLower) {\n throw new GSwapSDKError('SIGNER_ADDRESS_MISMATCH', {});\n }\n return { ...dto, signature: signNative(key, dto) };\n } finally {\n key.fill(0);\n }\n },\n };\n}\n\n/**\n * A Gala Wallet signer using native GalaChain signing, with an opt-in personal-sign mode.\n *\n * The selected Ethereum account is passed to Gala Wallet. There is NO automatic fallback: a\n * wallet that rejects `native` surfaces its error to the caller, because the only alternative,\n * `personal-sign`, silently recovers a phantom signer on every released Gala Wallet.\n *\n * `scheme: 'personal-sign'` calls\n * `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])` and REQUIRES\n * a wallet build that contains wallet_extension commit 34ca4e4 (strips the embedded `prefix`\n * field and hashes `prefix` + the prefix-less canonical body, the chain's scheme). Wallets\n * released before that fix hash the string with the `prefix` field still inside it and the\n * signature recovers to an address nobody holds, so only opt in once the fixed wallet is\n * released. See SIGNING-PARITY.md.\n */\nexport class GalaWalletSigner implements GalaChainSigner {\n /** The wallet address supplied to Gala Wallet for each signing request. */\n public readonly walletAddress: string;\n\n /** The signing scheme used for every request; it never changes after construction. */\n public readonly scheme: GalaWalletScheme;\n\n /**\n * Creates a Gala Wallet signer.\n *\n * @example\n * ```typescript\n * const signer = new GalaWalletSigner('0x0123456789012345678901234567890123456789');\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n *\n * @param walletAddress - The account passed to Gala Wallet as the signer address. An Ethereum\n * account is `0x` plus 40 hex digits (Gala Wallet's `eth|...` form is normalized to it and held\n * to the same check); a GalaChain id is `client|` plus 24 hex digits, or the bare 24 hex digits\n * frontend_v2 keeps for a direct `client|` login, and is passed through unchanged.\n * @param options - Select native signing (default) or personal-sign explicitly.\n * `'personal-sign'` requires a Gala Wallet build with wallet_extension commit 34ca4e4.\n * `selectAddress` is the identity (`client|...` / `eth|...`) Gala Wallet is switched to with\n * `window.gala.setAddress` before every signature, when the wallet offers it.\n */\n constructor(\n walletAddress: string,\n options: { scheme?: GalaWalletScheme | undefined; selectAddress?: string | undefined } = {},\n ) {\n this.walletAddress = normalizeGalaWalletAccount(walletAddress);\n this.scheme = options.scheme ?? 'native';\n if (options.selectAddress !== undefined) assertWalletIdentity(options.selectAddress);\n this.selectAddress = options.selectAddress;\n }\n\n /** The identity Gala Wallet is switched to before each signature, if one was given. */\n public readonly selectAddress: string | undefined;\n\n /**\n * Signs a DTO through `gala_signChainDto`.\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('AddLiquidity', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * tickLower: -60,\n * tickUpper: 60,\n * });\n * ```\n */\n public async signObject<T extends Record<string, unknown>>(\n methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n const wallet = getWalletProvider();\n\n return withSelectedIdentity(wallet, this.selectAddress, async () => {\n if (this.scheme === 'personal-sign') {\n return personalSign(wallet, dto, this.walletAddress, methodName);\n }\n const signature = await wallet.request({\n method: 'gala_signChainDto',\n params: [serialize(dto), this.walletAddress, methodName, 'native'],\n });\n return { ...dto, signature: getNativeSignature(signature) };\n });\n }\n}\n\n/**\n * A personal-sign signer for MetaMask and other EIP-1193 browser wallets.\n *\n * The chain recovers this signature using the EIP-191 wrap applied by the wallet to\n * `personal_sign`. This is the browser-wallet path used by the v2 frontend and resolves the\n * bare `eth|` identity.\n */\nexport class BrowserWalletSigner implements GalaChainSigner {\n /**\n * Creates a browser-wallet signer.\n *\n * Defaults to `personal_sign` — unchanged from every existing integration, since it only ever\n * resolves the bare `eth|` identity and changing that silently would be a real behavior\n * break for anyone already depending on it. Pass `{ scheme: 'eip712' }` to correctly resolve\n * a registered `client|` alias instead, for `RequestTrade`/`AddLiquidity`/`RemoveLiquidity`/\n * `CollectPositionFees` (`EIP712_CAPABLE_METHODS`) — `CreatePool` and any other method still\n * falls back to `personal_sign` even in `'eip712'` mode, since its EIP-712 signing is a\n * separate, unsolved chain-side problem.\n *\n * @example\n * ```typescript\n * const signer = new BrowserWalletSigner(window.ethereum, '0x0123456789012345678901234567890123456789');\n * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });\n * ```\n * @example\n * ```typescript\n * // Correctly resolves a registered client| alias instead of the bare eth| address.\n * const signer = new BrowserWalletSigner(window.ethereum, walletAddress, { scheme: 'eip712' });\n * ```\n */\n constructor(\n private readonly provider: BrowserWalletProvider,\n walletAddress: string,\n options: { scheme?: 'personal-sign' | 'eip712' } = {},\n ) {\n this.walletAddress = normalizeEthereumAccount(walletAddress, false);\n this.scheme = options.scheme ?? 'personal-sign';\n }\n\n /** The selected `0x` Ethereum account every signature is requested for. */\n public readonly walletAddress: string;\n private readonly scheme: 'personal-sign' | 'eip712';\n\n /**\n * Signs the DTO with `eth_signTypedData_v4` (when constructed with `{ scheme: 'eip712' }` and\n * `methodName` is in `EIP712_CAPABLE_METHODS`) or the EIP-1193 `personal_sign` method\n * (otherwise — the default).\n *\n * @example\n * ```typescript\n * const signed = await signer.signObject('RequestTrade', {\n * token0: 'GALA',\n * token1: 'GUSDC',\n * fee: 3000,\n * });\n * ```\n */\n public signObject<T extends Record<string, unknown>>(\n methodName: string,\n dto: T,\n ): Promise<SignedDto<T>> {\n if (this.scheme === 'eip712' && EIP712_CAPABLE_METHODS.has(methodName)) {\n return signEIP712(this.provider, methodName, dto, this.walletAddress);\n }\n return personalSign(this.provider, dto, this.walletAddress);\n }\n}\n","/**\n * Async key/value storage the pending-swap store persists through. It stores STRUCTURED VALUES\n * (the store never serializes), so each platform decides how a value lands on disk:\n *\n * - `chrome.storage.local`: `get: async (k) => (await chrome.storage.local.get(k))[k]`,\n * `set: (k, v) => chrome.storage.local.set({ [k]: v })`. This is the wallet's stored shape.\n * {@link storageAdapterFromChromeStorage} builds it.\n * - `localStorage` (frontend_v2): JSON text under the key. {@link webStorageAdapter} builds it,\n * and returns CORRUPT JSON as a value (the raw string), not as a rejection: a value that is not\n * an array reads as \"no entries\" and the next write repairs it, whereas a `get` that rejects\n * forever makes every `remember` a no-op.\n * - React Native: AsyncStorage with the same JSON wrapping and the same corrupt-JSON rule.\n *\n * `get` resolves `undefined` for a missing key. Either method may reject; the store treats that\n * as \"storage unavailable\" and never lets it surface (see `PendingSwapStore`).\n *\n * This module imports nothing, so an app shell that only builds an adapter pays for the adapter.\n */\nexport interface StorageAdapter {\n get(key: string): Promise<unknown>;\n set(key: string, value: unknown): Promise<void>;\n}\n\n/**\n * The part of a `chrome.storage` area ({@link storageAdapterFromChromeStorage}) the adapter uses,\n * written structurally so the SDK needs no `chrome` types: `chrome.storage.local`,\n * `chrome.storage.session`, `browser.storage.local` (webextension-polyfill) and any object with\n * these two promise-returning methods satisfy it. It is the Manifest V3 promise form: the methods\n * are called WITHOUT a callback.\n */\nexport interface ChromeStorageAreaLike {\n get(key: string): Promise<Record<string, unknown>>;\n set(items: Record<string, unknown>): Promise<void>;\n}\n\n/**\n * A {@link StorageAdapter} over a `chrome.storage` area, the shape the wallet stores pending swaps\n * in: the value lands under the key as the structured value it is (the browser clones it; nothing\n * is serialized here). A missing key resolves `undefined`; a rejection of the area reaches the\n * store, which treats it as \"storage unavailable\".\n *\n * Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is\n * built: a module that is imported where `chrome` does not exist yet (a test, a closing extension\n * context) then fails only when the store touches storage, and that failure (a throw inside the\n * function) is the same \"storage unavailable\" rejection.\n *\n * @example\n * ```ts\n * const store = new PendingSwapStore(storageAdapterFromChromeStorage(chrome.storage.local));\n * const lazy = new PendingSwapStore(storageAdapterFromChromeStorage(() => chrome.storage.local));\n * ```\n */\nexport function storageAdapterFromChromeStorage(\n area: ChromeStorageAreaLike | (() => ChromeStorageAreaLike),\n): StorageAdapter {\n const areaNow = (): ChromeStorageAreaLike => (typeof area === 'function' ? area() : area);\n return {\n async get(key) {\n const items = await areaNow().get(key);\n return Object.hasOwn(items, key) ? items[key] : undefined;\n },\n async set(key, value) {\n await areaNow().set({ [key]: value });\n },\n };\n}\n\n/**\n * The part of a Web Storage area ({@link webStorageAdapter}) the adapter uses, written\n * structurally so the SDK needs no DOM types: `localStorage`, `sessionStorage` and any object with\n * these two synchronous methods (a React Native MMKV wrapper, a test double) satisfy it.\n */\nexport interface WebStorageLike {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\n/**\n * A {@link StorageAdapter} over a Web Storage area (`localStorage`, `sessionStorage`), the shape\n * frontend_v2 stores pending swaps in: the value lands under the key as JSON text. A missing key\n * resolves `undefined`. CORRUPT JSON resolves as the raw string, never a rejection (the store\n * reads a value that is not an array as \"no entries\" and the next write repairs it, whereas a\n * `get` that rejects forever would make every `remember` a no-op). A throwing area (storage blocked\n * by the browser, quota exceeded on `setItem`) rejects, which the store treats as \"storage\n * unavailable\".\n *\n * Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is\n * built: where `localStorage` does not exist (server rendering, a test, a blocked context)\n * the access throws inside the function, which is the same \"storage unavailable\" rejection, and\n * the module that builds the adapter still loads.\n *\n * @example\n * ```ts\n * const store = new PendingSwapStore(webStorageAdapter(() => localStorage));\n * ```\n */\nexport function webStorageAdapter(area: WebStorageLike | (() => WebStorageLike)): StorageAdapter {\n const areaNow = (): WebStorageLike => (typeof area === 'function' ? area() : area);\n return {\n async get(key) {\n const raw = areaNow().getItem(key);\n if (raw === null) return undefined;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return raw;\n }\n },\n async set(key, value) {\n areaNow().setItem(key, JSON.stringify(value));\n },\n };\n}\n","/**\n * String-key signing entry points for apps that hold a private key only briefly (the Gala Wallet\n * extension reads its session key at sign time and must not keep it in a long-lived object).\n *\n * These are thin, byte-exact ports of the functions the wallet shipped in\n * `wallet_extension/src/helpers/wallet/signing.ts` (including the fail-closed personal-sign\n * payload resolver from its commit 34ca4e4), re-expressed over the SDK's own primitives. Every\n * function takes the key as a string (`0x`-optional hex, or base64) or as bytes, normalizes it per\n * call, and zeroes the normalized copy before returning, so nothing in this module retains a key.\n * A JavaScript string cannot be wiped; the caller owns the lifetime of the string it passes in.\n */\nimport BigNumber from 'bignumber.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport {\n normalizePrivateKey,\n serialize,\n signPersonalMessage,\n signSerializedNative,\n} from './signing.js';\n\n/** A secp256k1 private key as a hex/base64 string or as raw 32 bytes. */\nexport type PrivateKeyInput = string | Uint8Array;\n\n/**\n * Runs `action` with a private normalized copy of the key, zeroed afterwards (also when `action`\n * throws). Bytes given by the caller are copied, never modified: the caller owns them.\n */\nexport function withPrivateKey<T>(privateKey: PrivateKeyInput, action: (key: Uint8Array) => T): T {\n const key = normalizePrivateKey(privateKey);\n try {\n return action(key);\n } finally {\n key.fill(0);\n }\n}\n\n/**\n * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes with no\n * prefix and no envelope (wallet `signChainDtoNative`). The caller owns serialization, so the\n * bytes a user reviewed and the bytes signed cannot diverge.\n *\n * @returns 130 lowercase hex characters, `r || s || v` with `v` = `1b`/`1c`, no `0x`.\n */\nexport function signChainDtoNative(privateKey: PrivateKeyInput, serializedDto: string): string {\n return withPrivateKey(privateKey, (key) => signSerializedNative(key, serializedDto));\n}\n\n/**\n * The personal-sign hash primitive (wallet `signChainDtoHash`): keccak256(`prefix` + `message`),\n * both verbatim, with no further EIP-191 wrap. `message` must be the DTO's serialization WITHOUT\n * its `prefix` field; callers holding a dApp-supplied string go through `signChainDtoPersonalSign`,\n * which derives both inputs from it.\n */\nexport function signChainDtoHash(\n privateKey: PrivateKeyInput,\n prefix: string,\n message: string,\n): string {\n return withPrivateKey(privateKey, (key) => signPersonalMessage(key, prefix, message));\n}\n\nconst PERSONAL_SIGN_HEADER = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\nconst PERSONAL_SIGN_LENGTH_PATTERN = /^(?:0|[1-9][0-9]*)$/u;\n\n// A header with a body starting `{` can never collide with another EIP-191 message's hash, and\n// anything that is not a header (arbitrary bytes the user cannot see on an approval card) is\n// refused. The number is NOT required to equal the byte length: the chain hashes whatever prefix\n// the submitted DTO carries, and defi-backend's bouncer rejects a mismatched header loudly.\nfunction isPersonalSignHeader(prefix: string): boolean {\n return (\n prefix.startsWith(PERSONAL_SIGN_HEADER) &&\n PERSONAL_SIGN_LENGTH_PATTERN.test(prefix.slice(PERSONAL_SIGN_HEADER.length))\n );\n}\n\n/**\n * Top-level fields that would make the chain (`getPayloadToSign`) or defi-backend's personal-sign\n * verifier hash something other than `prefix + serialize(dto minus prefix)`. An unsigned DTO from\n * a dApp never legitimately carries any of them, so they fail closed. Order is part of the error\n * message the wallet shows its user.\n */\nconst PERSONAL_SIGN_FORBIDDEN_FIELDS = [\n 'signature',\n 'multisig',\n 'trace',\n 'types',\n 'domain',\n 'stringsInstructions',\n] as const;\n\n/** What a `gala_signChainDto` personal-sign request hashes. */\nexport interface PersonalSignChainDtoPayload {\n /** The `prefix` the chain prepends: the DTO's own `prefix` field, or `''` when it has none. */\n prefix: string;\n /** The exact message hashed after `prefix`. */\n message: string;\n}\n\n/**\n * Derives what to hash for a `gala_signChainDto` personal-sign request from the exact string the\n * dApp sent (and the approval card displayed): wallet `resolvePersonalSignChainDtoPayload`.\n *\n * The dApp submits `{ ...dto, prefix, signature }`, which the chain recovers from\n * `keccak256(prefix + serialize(dto WITHOUT prefix))`. So when the string embeds a `prefix`\n * field, that field is removed and the remainder re-serialized; the prefix used is the dApp's own\n * value byte for byte. A string with no `prefix` field is hashed verbatim with an empty prefix\n * (chain-equivalent to a native signature of that exact string).\n *\n * Fails closed (throws `GSwapSDKError` `PERSONAL_SIGN_NOT_JSON`, `PERSONAL_SIGN_NOT_OBJECT`,\n * `PERSONAL_SIGN_BAD_PREFIX`, `PERSONAL_SIGN_ENVELOPE_FIELDS` or `PERSONAL_SIGN_NOT_CANONICAL`) on:\n * malformed JSON; JSON that is not a plain object; a `prefix` that is not an EIP-191\n * \"Ethereum Signed Message\" header; any signing-envelope field (`signature`, `multisig`, `trace`,\n * `types`, `domain`, `stringsInstructions`); and a string that is not already the canonical\n * serialization of what it parses to (duplicate keys, lossy numbers, key-order tricks the card\n * would render differently). Stripping `prefix` is therefore the ONLY byte change between the\n * reviewed string and the signed message.\n */\nexport function resolvePersonalSignChainDtoPayload(data: string): PersonalSignChainDtoPayload {\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_JSON', {});\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_OBJECT', {});\n }\n const dto = parsed as Record<string, unknown>;\n if (!Object.prototype.hasOwnProperty.call(dto, 'prefix')) {\n return { prefix: '', message: data };\n }\n\n const { prefix, ...withoutPrefix } = dto;\n if (typeof prefix !== 'string' || !isPersonalSignHeader(prefix)) {\n throw new GSwapSDKError('PERSONAL_SIGN_BAD_PREFIX', {});\n }\n const forbidden = PERSONAL_SIGN_FORBIDDEN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(withoutPrefix, field),\n );\n if (forbidden.length > 0) {\n throw new GSwapSDKError('PERSONAL_SIGN_ENVELOPE_FIELDS', { fields: forbidden.join(', ') });\n }\n if (serialize(dto) !== data) {\n throw new GSwapSDKError('PERSONAL_SIGN_NOT_CANONICAL', {});\n }\n return { prefix, message: serialize(withoutPrefix) };\n}\n\n/**\n * Signs a GalaChain personal-sign scheme DTO from the exact string a dApp sent through\n * `gala_signChainDto` (wallet `signChainDtoPersonalSign`). See\n * `resolvePersonalSignChainDtoPayload` for what is signed and what is refused; the signature\n * recovers, under the chain's `getPayloadToSign`, to this key for the DTO the dApp submits with\n * its `prefix`, and equals a `personal_sign` of the bare body when that prefix is the EIP-191\n * header of the bare body's byte length.\n *\n * @throws GSwapSDKError (`PERSONAL_SIGN_*`, see `resolvePersonalSignChainDtoPayload`) before any\n * signing when the input is refused.\n */\nexport function signChainDtoPersonalSign(privateKey: PrivateKeyInput, data: string): string {\n const { prefix, message } = resolvePersonalSignChainDtoPayload(data);\n return signChainDtoHash(privateKey, prefix, message);\n}\n\n/**\n * Raw object signing (wallet `signObject`), used for transfers, bridge and fee-dry-run DTOs the\n * wallet signs itself. Removes ONLY `signature`, signs `keccak256(serialize(rest))` natively\n * (no `prefix` handling, and `trace` / `multisig` stay in the signed bytes, unlike\n * `signNative`), and returns `{ signature, ...rest }` with the signature as the FIRST key, exactly\n * like the wallet. Callers that must not sign extra fields strip them first.\n */\nexport function signRawObject(\n privateKey: PrivateKeyInput,\n obj: Record<string, unknown>,\n): { signature: string } & Record<string, unknown> {\n const rest = { ...obj };\n delete rest['signature'];\n return {\n signature: signChainDtoNative(privateKey, serialize(rest)),\n ...rest,\n };\n}\n\n/**\n * Drops the `EIP712Domain` entry from a dApp-supplied types map (a typed-data encoder derives the\n * domain type itself and rejects an explicit one). The order of the remaining types is preserved.\n */\nexport function stripEip712DomainType<T>(types: Record<string, T>): Record<string, T> {\n const stripped: Record<string, T> = {};\n for (const typeName of Object.keys(types)) {\n if (typeName !== 'EIP712Domain') stripped[typeName] = types[typeName] as T;\n }\n return stripped;\n}\n\n/**\n * `collection$category$type$additionalKey` for a token-class object (wallet `decodeTokenData`).\n * Lenient on purpose: any missing or non-string part becomes `''`, so a display layer never\n * throws on odd input.\n */\nexport function tokenClassDollarKey(token: Record<string, unknown> | null | undefined): string {\n const part = (field: string): string => {\n const value = token?.[field];\n return typeof value === 'string' ? value : '';\n };\n return `${part('collection')}$${part('category')}$${part('type')}$${part('additionalKey')}`;\n}\n\n/**\n * A quantity in the form GalaChain's `IsBigNumber` validator accepts: FIXED notation, no leading\n * zeros, no trailing decimal zeros (`BigNumber#toFixed()`; never `toString()`, which turns\n * `0.00000001` into `1e-8`, and never a JS number in between).\n *\n * @throws GSwapSDKError (`INVALID_DECIMAL`) for a value that is not a finite number. The wallet's\n * `cleanNumber` returned the string `'NaN'` there; signing that text can only fail on chain.\n */\nexport function canonicalDecimalString(value: string | number): string {\n let parsed = new BigNumber(Number.NaN);\n try {\n parsed = new BigNumber(value);\n } catch {\n // BigNumber throws instead of returning NaN when its DEBUG flag is on; both mean \"invalid\".\n }\n if (!parsed.isFinite()) {\n throw new GSwapSDKError('INVALID_DECIMAL', { value: String(value) });\n }\n return parsed.toFixed();\n}\n","/**\n * EIP-712 (`eth_signTypedData_v4`) hashing and signing for ARBITRARY dApp typed data, built on the\n * SDK's own primitives (`@noble/curves`, `@noble/hashes`) so a wallet can sign a dApp's typed-data\n * approval without ethers. It replaces the wallet's `new ethers.Wallet(key).signTypedData(...)`\n * and is pinned to it: the golden suite reproduces every fixture signature exactly and a seeded\n * differential fuzz compares the digest and signature with ethers for every supported type.\n *\n * Compared with ethers this encoder is deliberately STRICTER (it fails closed rather than coerce):\n * `bool` accepts only a boolean, numbers accept only safe integers / decimal or `0x` strings,\n * strings must be well-formed UTF-16, struct values must be objects whose fields are their own\n * properties, and every struct, field and type name must be a plain identifier. Anything ethers\n * accepts that is NOT in that set is refused here instead of being signed in a different shape\n * from what a user reviewed.\n */\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { signHash } from './signing.js';\nimport { withPrivateKey, type PrivateKeyInput } from './chain_dto_signing.js';\n\n/** A typed-data payload as `eth_signTypedData_v4` carries it, minus `primaryType` (it is inferred). */\nexport interface TypedDataPayload {\n domain: Record<string, unknown>;\n /** Struct definitions WITHOUT `EIP712Domain` (see `stripEip712DomainType`). */\n types: Record<string, readonly unknown[]>;\n message: Record<string, unknown>;\n}\n\ninterface TypedField {\n name: string;\n type: string;\n}\n\nconst textEncoder = new TextEncoder();\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;\nconst TYPE_SYNTAX = /^([A-Za-z_$][A-Za-z0-9_$]*)((?:\\[(?:0|[1-9][0-9]*)?\\])*)$/u;\nconst BIGINT_DECIMAL = /^-?[0-9]+$/u;\nconst BIGINT_HEX = /^-?0x[0-9a-fA-F]+$/u;\n\n/** The EIP-712 domain members and their types, in the order ethers (and the spec) hash them. */\nconst DOMAIN_FIELDS: readonly TypedField[] = [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n { name: 'salt', type: 'bytes32' },\n];\n\nfunction concat(parts: readonly Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((total, part) => total + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\nfunction bigintToWord(value: bigint): Uint8Array {\n const word = new Uint8Array(32);\n // Every caller has bounds-checked `value` against its Solidity type, so it fits in 256 bits.\n let rest = value < 0n ? value + (1n << 256n) : value;\n for (let index = 31; index >= 0; index -= 1) {\n word[index] = Number(rest & 0xffn);\n rest >>= 8n;\n }\n return word;\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const body = hex.slice(2);\n const out = new Uint8Array(body.length / 2);\n for (let index = 0; index < out.length; index += 1) {\n out[index] = parseInt(body.slice(index * 2, index * 2 + 2), 16);\n }\n return out;\n}\n\nfunction toBytes(value: unknown, what: string): Uint8Array {\n if (value instanceof Uint8Array) return value;\n if (typeof value === 'string' && /^0x(?:[0-9a-fA-F]{2})*$/u.test(value)) return hexToBytes(value);\n throw new GSwapSDKError('TYPED_DATA_NOT_HEX_BYTES', { what });\n}\n\nfunction toBigInt(value: unknown, what: string): bigint {\n if (typeof value === 'bigint') return value;\n if (typeof value === 'number') {\n if (!Number.isSafeInteger(value))\n throw new GSwapSDKError('TYPED_DATA_NOT_SAFE_INTEGER', { what });\n return BigInt(value);\n }\n if (typeof value === 'string') {\n if (BIGINT_DECIMAL.test(value)) return BigInt(value);\n if (BIGINT_HEX.test(value)) {\n return value.startsWith('-') ? -BigInt(value.slice(1)) : BigInt(value);\n }\n }\n throw new GSwapSDKError('TYPED_DATA_NOT_INTEGER', { what });\n}\n\nfunction utf8(value: unknown, what: string): Uint8Array {\n if (typeof value !== 'string') throw new GSwapSDKError('TYPED_DATA_NOT_STRING', { what });\n for (let index = 0; index < value.length; index += 1) {\n const unit = value.charCodeAt(index);\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (!(next >= 0xdc00 && next <= 0xdfff)) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n index += 1;\n } else if (unit >= 0xdc00 && unit <= 0xdfff) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n }\n return textEncoder.encode(value);\n}\n\n/** EIP-55: a mixed-case address must carry the right checksum; all-lower / all-upper is accepted. */\nfunction addressBytes(value: unknown): Uint8Array {\n if (typeof value !== 'string' || !/^0x[0-9a-fA-F]{40}$/u.test(value)) {\n throw new GSwapSDKError('TYPED_DATA_BAD_ADDRESS', {});\n }\n const digits = value.slice(2);\n if (/[A-F]/u.test(digits) && /[a-f]/u.test(digits)) {\n const hash = keccak_256(textEncoder.encode(digits.toLowerCase()));\n for (let index = 0; index < 40; index += 1) {\n const nibble = ((hash[index >> 1] as number) >> (index % 2 === 0 ? 4 : 0)) & 0xf;\n const char = digits.charAt(index);\n const expected = nibble >= 8 ? char.toUpperCase() : char.toLowerCase();\n if (char !== expected) throw new GSwapSDKError('TYPED_DATA_BAD_CHECKSUM', {});\n }\n }\n return hexToBytes(value);\n}\n\ntype LeafEncoder = (value: unknown) => Uint8Array;\n\n/** The encoder for a non-struct, non-array type, or undefined when `base` is not one. */\nfunction leafEncoder(base: string): LeafEncoder | undefined {\n if (base === 'string') return (value) => keccak_256(utf8(value, 'string'));\n if (base === 'bytes') return (value) => keccak_256(toBytes(value, 'bytes'));\n if (base === 'bool') {\n return (value) => {\n if (typeof value !== 'boolean') throw new GSwapSDKError('TYPED_DATA_NOT_BOOLEAN', {});\n return bigintToWord(value ? 1n : 0n);\n };\n }\n if (base === 'address') {\n return (value) => concat([new Uint8Array(12), addressBytes(value)]);\n }\n const fixed = /^bytes([1-9][0-9]?)$/u.exec(base);\n if (fixed !== null) {\n const width = Number(fixed[1]);\n if (width > 32 || String(width) !== fixed[1]) return undefined;\n return (value) => {\n const bytes = toBytes(value, base);\n if (bytes.length !== width) {\n throw new GSwapSDKError('TYPED_DATA_BYTES_LENGTH', { type: base, width });\n }\n return concat([bytes, new Uint8Array(32 - width)]);\n };\n }\n const integer = /^(u?)int([1-9][0-9]*)$/u.exec(base);\n if (integer !== null) {\n const width = Number(integer[2]);\n if (width % 8 !== 0 || width > 256 || String(width) !== integer[2]) return undefined;\n const signed = integer[1] === '';\n const lower = signed ? -(1n << BigInt(width - 1)) : 0n;\n const upper = signed ? (1n << BigInt(width - 1)) - 1n : (1n << BigInt(width)) - 1n;\n return (value) => {\n const number = toBigInt(value, base);\n if (number < lower || number > upper) {\n throw new GSwapSDKError('TYPED_DATA_OUT_OF_BOUNDS', { type: base });\n }\n return bigintToWord(number);\n };\n }\n return undefined;\n}\n\ninterface ParsedType {\n base: string;\n /** Array suffixes outermost-last, e.g. `uint256[2][]` is `[2, -1]` (-1 = dynamic). */\n dimensions: number[];\n}\n\nfunction parseType(type: string): ParsedType {\n const match = TYPE_SYNTAX.exec(type);\n if (match === null) throw new GSwapSDKError('TYPED_DATA_UNSUPPORTED_TYPE', { type });\n const dimensions = [...(match[2] ?? '').matchAll(/\\[([0-9]*)\\]/gu)].map((dimension) =>\n dimension[1] === '' ? -1 : Number(dimension[1]),\n );\n return { base: match[1] as string, dimensions };\n}\n\nfunction parseFields(typeName: string, rawFields: readonly unknown[]): TypedField[] {\n if (!Array.isArray(rawFields))\n throw new GSwapSDKError('TYPED_DATA_FIELDS_NOT_LIST', { typeName });\n const seen = new Set<string>();\n return rawFields.map((raw: unknown) => {\n const field = raw as { name?: unknown; type?: unknown } | null;\n if (typeof field?.name !== 'string' || typeof field.type !== 'string') {\n throw new GSwapSDKError('TYPED_DATA_FIELD_MALFORMED', { typeName });\n }\n if (!IDENTIFIER.test(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_FIELD_NAME', { name: field.name });\n }\n if (seen.has(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_DUPLICATE_FIELD', { name: field.name, typeName });\n }\n seen.add(field.name);\n // A bare `int` / `uint` is the 256-bit type and is hashed as `int256` / `uint256`, like ethers.\n const parsed = parseType(field.type);\n const base =\n parsed.base === 'uint' || parsed.base === 'int' ? `${parsed.base}256` : parsed.base;\n return { name: field.name, type: base + field.type.slice(parsed.base.length) };\n });\n}\n\ninterface StructEncoder {\n primaryType: string;\n hashStruct: (typeName: string, value: unknown) => Uint8Array;\n}\n\n/**\n * Builds the struct encoder for a set of type definitions: validates the type graph (unknown or\n * circular references, duplicate fields) and infers the primary type as the single type no other\n * type references, exactly like ethers' `TypedDataEncoder`.\n */\nfunction createStructEncoder(rawTypes: Record<string, readonly unknown[]>): StructEncoder {\n const names = Object.keys(rawTypes);\n const fields = new Map<string, TypedField[]>();\n for (const name of names) {\n if (!IDENTIFIER.test(name)) throw new GSwapSDKError('TYPED_DATA_INVALID_TYPE_NAME', { name });\n fields.set(name, parseFields(name, rawTypes[name] as readonly unknown[]));\n }\n\n const children = new Map<string, Set<string>>();\n const parents = new Map<string, Set<string>>();\n for (const name of names) {\n children.set(name, new Set());\n parents.set(name, new Set());\n }\n for (const [name, list] of fields) {\n for (const field of list) {\n const { base } = parseType(field.type);\n if (base === name) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (leafEncoder(base) !== undefined) continue;\n if (!fields.has(base)) {\n throw new GSwapSDKError('TYPED_DATA_UNKNOWN_FIELD_TYPE', { type: base, typeName: name });\n }\n children.get(name)?.add(base);\n parents.get(base)?.add(name);\n }\n }\n\n const roots = names.filter((name) => parents.get(name)?.size === 0);\n if (roots.length === 0) throw new GSwapSDKError('TYPED_DATA_NO_PRIMARY_TYPE', {});\n if (roots.length > 1) {\n throw new GSwapSDKError('TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE', { roots: roots.join(', ') });\n }\n const primaryType = roots[0] as string;\n\n const visiting = new Set<string>();\n const checked = new Set<string>();\n const checkCircular = (name: string): void => {\n if (visiting.has(name)) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (checked.has(name)) return;\n visiting.add(name);\n for (const child of children.get(name) ?? []) checkCircular(child);\n visiting.delete(name);\n checked.add(name);\n };\n checkCircular(primaryType);\n\n const dependencies = (name: string, found: Set<string>): Set<string> => {\n for (const child of children.get(name) ?? []) {\n if (!found.has(child)) {\n found.add(child);\n dependencies(child, found);\n }\n }\n return found;\n };\n const encodeOne = (name: string): string =>\n `${name}(${(fields.get(name) ?? []).map((field) => `${field.type} ${field.name}`).join(',')})`;\n const typeHashes = new Map<string, Uint8Array>();\n for (const name of names) {\n const sorted = [...dependencies(name, new Set())].filter((dep) => dep !== name).sort();\n typeHashes.set(name, keccak_256(textEncoder.encode([name, ...sorted].map(encodeOne).join(''))));\n }\n\n const encodeValue = (parsed: ParsedType, value: unknown, depth: number): Uint8Array => {\n // The LAST bracket written is the outermost array: `uint8[][2]` is two `uint8[]`.\n const dimension = parsed.dimensions[parsed.dimensions.length - 1 - depth];\n if (dimension !== undefined) {\n if (!Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_EXPECTED', { type: parsed.base });\n }\n if (dimension !== -1 && dimension !== value.length) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_LENGTH_MISMATCH', {});\n }\n return keccak_256(concat(value.map((item) => encodeValue(parsed, item, depth + 1))));\n }\n const leaf = leafEncoder(parsed.base);\n if (leaf !== undefined) return leaf(value);\n return hashStruct(parsed.base, value);\n };\n\n function hashStruct(typeName: string, value: unknown): Uint8Array {\n const list = fields.get(typeName);\n const typeHash = typeHashes.get(typeName);\n if (list === undefined || typeHash === undefined) {\n // createStructEncoder has already validated every struct name this is called with.\n throw new Error(`Internal error: no encoder for struct ${typeName}`);\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_STRUCT_NOT_OBJECT', { typeName });\n }\n const record = value as Record<string, unknown>;\n const words = list.map((field) => {\n if (!Object.prototype.hasOwnProperty.call(record, field.name)) {\n throw new GSwapSDKError('TYPED_DATA_MISSING_FIELD', { typeName, field: field.name });\n }\n // Struct-valued fields are encoded to their 32-byte struct hash by encodeValue.\n return encodeValue(parseType(field.type), record[field.name], 0);\n });\n return keccak_256(concat([typeHash, ...words]));\n }\n\n return { primaryType, hashStruct };\n}\n\nfunction hashDomain(domain: Record<string, unknown>): Uint8Array {\n if (domain === null || typeof domain !== 'object' || Array.isArray(domain)) {\n throw new GSwapSDKError('TYPED_DATA_DOMAIN_NOT_OBJECT', {});\n }\n for (const key of Object.keys(domain)) {\n if (!DOMAIN_FIELDS.some((field) => field.name === key)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_DOMAIN_KEY', { key: JSON.stringify(key) });\n }\n }\n const present = DOMAIN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(domain, field.name),\n );\n const encoder = createStructEncoder({ EIP712Domain: present });\n return encoder.hashStruct('EIP712Domain', domain);\n}\n\n/**\n * The EIP-712 digest `keccak256(0x1901 || domainSeparator || hashStruct(primaryType, message))`\n * that a wallet signs for `eth_signTypedData_v4`. The primary type is inferred, as ethers does.\n *\n * @throws GSwapSDKError (`TYPED_DATA_*`) for any type graph or value it cannot encode\n * exactly (see the module note on strictness).\n */\nexport function hashTypedData(payload: TypedDataPayload): Uint8Array {\n const domainHash = hashDomain(payload.domain);\n const encoder = createStructEncoder(payload.types);\n const structHash = encoder.hashStruct(encoder.primaryType, payload.message);\n return keccak_256(concat([Uint8Array.of(0x19, 0x01), domainHash, structHash]));\n}\n\n/**\n * Signs a dApp's EIP-712 typed-data approval (the wallet's `signTypedMessage` path), replacing\n * `new ethers.Wallet(key).signTypedData(domain, types, message)`. `types` must already have\n * `EIP712Domain` removed (`stripEip712DomainType`).\n *\n * @returns `0x` + r + s + v with `v` = `0x1b`/`0x1c` (27/28): ethers' serialized signature form,\n * recoverable with `verifyTypedData` / `eth_signTypedData_v4` verifiers. Rejects (never throws\n * synchronously) on invalid input.\n */\nexport async function signTypedDataPayload(\n privateKey: PrivateKeyInput,\n payload: TypedDataPayload,\n): Promise<string> {\n const digest = hashTypedData(payload);\n return withPrivateKey(privateKey, (key) => `0x${signHash(key, digest)}`);\n}\n","import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\n\n/** What the adapter reads of an axios response. */\nexport interface AxiosLikeResponse {\n status: number;\n data?: unknown;\n /** axios' `AxiosHeaders` (has `get`) or a plain header record. */\n headers?: unknown;\n}\n\n/** The request config the adapter hands to axios. */\nexport interface AxiosLikeConfig {\n headers: Record<string, string>;\n signal?: AbortSignal;\n validateStatus?: () => boolean;\n}\n\n/**\n * The part of an axios instance the adapter calls. Declared structurally, so the SDK takes no\n * dependency on axios and any axios instance (with its interceptors) satisfies it.\n */\nexport interface AxiosLikeInstance {\n get(url: string, config?: AxiosLikeConfig): Promise<unknown>;\n post(url: string, data?: unknown, config?: AxiosLikeConfig): Promise<unknown>;\n}\n\n/** Options of {@link httpRequestorFromAxios}. */\nexport interface AxiosRequestorOptions {\n /**\n * `true`: leave axios' default status validation alone, so a 4xx/5xx REJECTS through the\n * instance's own interceptors and the SDK rethrows what the app's error handling produced.\n * `false`: every HTTP status resolves, so the SDK classifies it itself (shadow submits,\n * apply-results reads); transport failures still reject.\n */\n rejectOnHttpError: boolean;\n /**\n * Request headers NOT to hand to axios, matched case-insensitively. Default `['content-type']`:\n * axios derives `Content-Type: application/json` from the object body it is given, and an\n * interceptor may set its own, so the SDK's copy would only be a second opinion.\n */\n omitHeaders?: readonly string[] | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * An axios interceptor may resolve something that is not a response at all (for example a string\n * for ECONNREFUSED). That is a transport failure, not an HTTP answer.\n */\nfunction isAxiosLikeResponse(value: unknown): value is AxiosLikeResponse {\n return isRecord(value) && typeof value['status'] === 'number';\n}\n\nfunction readAxiosHeader(headers: unknown, name: string): string | null {\n if (!isRecord(headers)) return null;\n const getter = headers['get'];\n if (typeof getter === 'function') {\n const value: unknown = getter.call(headers, name);\n return typeof value === 'string' ? value : null;\n }\n const match = Object.entries(headers).find(([key]) => key.toLowerCase() === name.toLowerCase());\n return typeof match?.[1] === 'string' ? match[1] : null;\n}\n\nfunction toHttpResponse(answer: unknown, url: string): HTTPResponse {\n if (!isAxiosLikeResponse(answer)) {\n throw new GSwapSDKError('TRANSPORT_ERROR', { url }, { url });\n }\n const { status, data, headers } = answer;\n return {\n ok: status >= 200 && status < 300,\n status,\n json: () => Promise.resolve(data),\n text: () => Promise.resolve(typeof data === 'string' ? data : JSON.stringify(data)),\n headers: { get: (name: string) => readAxiosHeader(headers, name) },\n };\n}\n\nfunction headersFor(\n init: RequestInit | undefined,\n omit: readonly string[],\n): Record<string, string> {\n const omitted = new Set(omit.map((name) => name.toLowerCase()));\n const raw = init?.headers;\n const entries: Array<[string, string]> =\n raw === undefined\n ? []\n : raw instanceof Headers\n ? [...raw.entries()]\n : Array.isArray(raw)\n ? raw.map(([name, value]): [string, string] => [String(name), String(value)])\n : Object.entries(raw).map(([name, value]): [string, string] => [name, String(value)]);\n return Object.fromEntries(entries.filter(([name]) => !omitted.has(name.toLowerCase())));\n}\n\n/**\n * An SDK {@link HttpRequestor} over an axios instance, so the SDK's requests travel through the\n * app's own base URL, interceptors and error handling.\n *\n * A POST's string body is parsed back to the object the SDK serialized it from (axios serializes\n * again, and an interceptor may read the object); a GET goes through `instance.get`. The answer\n * is an HTTP response whose `json()`/`text()` read `response.data`. An answer that is not an\n * axios response is a `TRANSPORT_ERROR` rejection, and so is a rejection that means no HTTP\n * answer arrived (the original error is `cause`): any rejection with `rejectOnHttpError: false`\n * (every status resolves there), an axios error without a `response` with `true`. Any other\n * rejection (an interceptor's error for a 4xx, say) is rethrown unchanged, and so is an abort.\n *\n * Pair it with `ChainGateway`'s `dexBackendBaseUrl: ''` when the instance owns the base URL.\n *\n * @example\n * ```ts\n * const submitGateway = new ChainGateway({\n * dexBackendBaseUrl: '',\n * httpRequestor: httpRequestorFromAxios(chainGatewayInstance, { rejectOnHttpError: true }),\n * });\n * ```\n */\nexport function httpRequestorFromAxios(\n instance: AxiosLikeInstance,\n options: AxiosRequestorOptions,\n): HttpRequestor {\n const omit = options.omitHeaders ?? ['content-type'];\n return async (uri, init) => {\n const signal = init?.signal ?? undefined;\n const config: AxiosLikeConfig = {\n headers: headersFor(init, omit),\n ...(signal ? { signal } : {}),\n ...(options.rejectOnHttpError ? {} : { validateStatus: () => true }),\n };\n const isPost = (init?.method ?? 'GET').toUpperCase() === 'POST';\n const body: unknown =\n isPost && typeof init?.body === 'string' ? JSON.parse(init.body) : undefined;\n let answer: unknown;\n try {\n answer = await (isPost ? instance.post(uri, body, config) : instance.get(uri, config));\n } catch (error: unknown) {\n // An abort is the caller's or the SDK's timeout, and the request layer knows which.\n if (signal?.aborted === true || !isTransportRejection(error, options.rejectOnHttpError)) {\n throw error;\n }\n throw new GSwapSDKError('TRANSPORT_ERROR', { url: uri }, { url: uri, cause: error });\n }\n return toHttpResponse(answer, uri);\n };\n}\n\n/**\n * Whether an axios rejection means no HTTP answer arrived. With `rejectOnHttpError: false` every\n * status resolves, so any rejection is one. With `true`, a 4xx/5xx rejects too, so only an axios\n * error that carries no `response` is (an interceptor's own error is an app answer and passes\n * through; an app whose interceptors turn network errors into their own class names it in\n * `ChainGatewayOptions.isTransportFailure`).\n */\nfunction isTransportRejection(error: unknown, rejectOnHttpError: boolean): boolean {\n if (!rejectOnHttpError) return true;\n return isRecord(error) && error['isAxiosError'] === true && error['response'] === undefined;\n}\n","import type { BrowserWalletProvider } from '../classes/signers.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { stripEip712DomainType } from './chain_dto_signing.js';\n\n/**\n * The part of an ethers v6 signer (`JsonRpcSigner`, `Wallet`) the adapter calls. Declared\n * structurally, so the SDK takes no dependency on ethers and an ethers object satisfies it as is.\n */\nexport interface EthersLikeSigner {\n signTypedData(\n domain: Record<string, unknown>,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>,\n ): Promise<string>;\n signMessage(message: string): Promise<string>;\n}\n\n/** The part of an ethers v6 provider (`BrowserProvider`) the adapter calls. */\nexport interface EthersLikeProvider {\n getSigner(): Promise<EthersLikeSigner>;\n /** The raw JSON-RPC passthrough (`BrowserProvider.send`). */\n send(method: string, params: unknown[]): Promise<unknown>;\n}\n\n/** Options of {@link eip1193ProviderFromEthers}. */\nexport interface EthersEip1193Options {\n /**\n * Signs a `personal_sign` message when the provider cannot or should not: a wallet SDK that\n * signs through its own object (TrustWallet's `web3Wallet.signMessage`). When set it answers\n * every `personal_sign`, and the provider is not touched for it.\n */\n personalSign?: ((message: string) => Promise<string>) | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTypedDataTypes(\n value: unknown,\n): value is Record<string, Array<{ name: string; type: string }>> {\n return (\n isRecord(value) &&\n Object.values(value).every(\n (fields) =>\n Array.isArray(fields) &&\n fields.every(\n (field) =>\n isRecord(field) &&\n typeof field['name'] === 'string' &&\n typeof field['type'] === 'string',\n ),\n )\n );\n}\n\nfunction malformed(method: string): GSwapSDKError {\n return new GSwapSDKError('MALFORMED_WALLET_REQUEST', { method });\n}\n\n/** Splits `eth_signTypedData_v4` params (`[account, JSON payload]`) into what ethers' signer takes. */\nfunction readTypedDataRequest(params: unknown[] | undefined): {\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n message: Record<string, unknown>;\n} {\n const raw = params?.[1];\n let payload: unknown;\n try {\n payload = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n throw malformed('eth_signTypedData_v4');\n }\n if (!isRecord(payload)) throw malformed('eth_signTypedData_v4');\n const { domain, types, message } = payload;\n if (!isRecord(domain) || !isTypedDataTypes(types) || !isRecord(message)) {\n throw malformed('eth_signTypedData_v4');\n }\n // ethers refuses an explicit EIP712Domain type; the JSON-RPC form includes it.\n return { domain, types: stripEip712DomainType(types), message };\n}\n\n/**\n * An EIP-1193 provider over an ethers v6 provider, for {@link BrowserWalletSigner}: apps whose\n * wallet connection is an ethers `BrowserProvider` sign through the very ethers calls they always\n * made, with no hand-written shim.\n *\n * - `eth_chainId` is `provider.send('eth_chainId', [])`: the wallet's LIVE chain. Never\n * `provider.getNetwork()`, which ethers caches and does not invalidate on `chainChanged`, so a\n * user who switches networks after connecting would sign against a stale chainId.\n * - `eth_signTypedData_v4` parses the `[account, JSON]` params and calls\n * `signer.signTypedData(domain, types, message)` with `EIP712Domain` removed from `types`.\n * - `personal_sign` is `options.personalSign(message)` when given, else `signer.signMessage`.\n * - Anything else is `UNSUPPORTED_WALLET_METHOD`; a malformed request is\n * `MALFORMED_WALLET_REQUEST`; a missing provider is `WALLET_UNAVAILABLE`.\n *\n * `provider` may be `null`/`undefined` (nothing connected): a request that needs it then fails\n * with `WALLET_UNAVAILABLE` rather than at construction, so a signer can be built before the\n * connection state is known.\n *\n * @example\n * ```ts\n * const signer = new BrowserWalletSigner(eip1193ProviderFromEthers(browserProvider), account, {\n * scheme: 'eip712',\n * });\n * ```\n */\nexport function eip1193ProviderFromEthers(\n provider: EthersLikeProvider | null | undefined,\n options: EthersEip1193Options = {},\n): BrowserWalletProvider {\n const connected = (): EthersLikeProvider => {\n if (provider === null || provider === undefined) {\n throw new GSwapSDKError('WALLET_UNAVAILABLE', {});\n }\n return provider;\n };\n return {\n request: async ({ method, params }) => {\n switch (method) {\n case 'eth_chainId':\n return connected().send('eth_chainId', []);\n case 'eth_signTypedData_v4': {\n const wallet = connected();\n const { domain, types, message } = readTypedDataRequest(params);\n return (await wallet.getSigner()).signTypedData(domain, types, message);\n }\n case 'personal_sign': {\n const message = params?.[0];\n if (typeof message !== 'string') throw malformed('personal_sign');\n if (options.personalSign !== undefined) return options.personalSign(message);\n return (await connected().getSigner()).signMessage(message);\n }\n default:\n throw new GSwapSDKError('UNSUPPORTED_WALLET_METHOD', { method });\n }\n },\n };\n}\n","import type { GSwapErrorCode } from '../classes/error_catalog.js';\nimport { toFailureView } from './failure_view.js';\n\n/**\n * Where a failed CONFIRMATION of a queued write stopped, as a closed set a screen can switch on:\n *\n * - `aborted`: the caller's own `AbortSignal` ended the wait (`CONFIRMATION_ABORTED`). The person\n * or the screen gave up waiting; the write may still land, and its `uniqueKey` is still the handle.\n * - `timeout`: the wait ran out before an apply result arrived (`CONFIRMATION_TIMEOUT`). The write\n * is still pending as far as anyone knows.\n * - `failed`: the apply-results read itself failed or answered something unusable\n * (`CONFIRMATION_FAILED`, `CONFIRMATION_MALFORMED`, `CONFIRMATION_KEY_MISMATCH`).\n *\n * All three are `unknown` to `classifyFailure`: never submit again, confirm the same key.\n */\nexport type ConfirmationState = 'aborted' | 'timeout' | 'failed';\n\n/** The state of every confirmation code (a typo is caught by the all-codes test). */\nconst STATE_OF_CODE = {\n CONFIRMATION_ABORTED: 'aborted',\n CONFIRMATION_TIMEOUT: 'timeout',\n CONFIRMATION_FAILED: 'failed',\n CONFIRMATION_MALFORMED: 'failed',\n CONFIRMATION_KEY_MISMATCH: 'failed',\n} as const satisfies Partial<Record<GSwapErrorCode, ConfirmationState>>;\n\n/**\n * The {@link ConfirmationState} of a failure, or `undefined` when it is not a failed confirmation.\n * Accepts an SDK error or a plain-object view of one (an app's wrapper with a `code`), and decides\n * from the code alone, so a screen never matches `'CONFIRMATION_ABORTED'` itself.\n *\n * @example\n * ```ts\n * switch (confirmationStateOf(error)) {\n * case 'aborted': return; // the person closed the dialog\n * case 'timeout': return showStillPending(error.uniqueKey);\n * case 'failed': return showCouldNotCheck(error.uniqueKey);\n * case undefined: return showFailure(error);\n * }\n * ```\n */\nexport function confirmationStateOf(error: unknown): ConfirmationState | undefined {\n const code = toFailureView(error)?.code;\n if (code === undefined) return undefined;\n return Object.entries(STATE_OF_CODE).find(([known]) => known === code)?.[1];\n}\n\n/** True when the wait for the apply result was ended by the caller's `AbortSignal`. */\nexport function isConfirmationAborted(error: unknown): boolean {\n return confirmationStateOf(error) === 'aborted';\n}\n\n/** True when the wait for the apply result ran out of time (`CONFIRMATION_TIMEOUT`). */\nexport function isConfirmationTimeout(error: unknown): boolean {\n return confirmationStateOf(error) === 'timeout';\n}\n","/**\n * True when a rejection of a `fetch`-based requestor means NO HTTP ANSWER ARRIVED: the network\n * failed, the connection was reset, the host did not resolve, CORS blocked it. For a write that\n * is not a refusal (the request may have been queued), so this is the default\n * `ChainGatewayOptions.isTransportFailure` for a requestor that wraps `fetch` and rejects with\n * its own errors.\n *\n * - Yes: a `TypeError` (what `fetch` rejects with in every engine: `Failed to fetch`, `Load failed`,\n * `NetworkError when attempting to fetch resource`, undici's `fetch failed`), recognised by name\n * too so one from another realm (an extension page, an iframe) still counts, and a\n * `DOMException` named `NetworkError`.\n * - No: an abort (`AbortError`) or a timeout (`TimeoutError`). The SDK's own request layer knows\n * whether its timer or the caller's signal aborted, and reports those itself\n * (`REQUEST_TIMEOUT`, or the caller's own abort unchanged); claiming them here would turn the\n * caller's cancel into \"maybe queued\".\n * - No: anything else, including an SDK error and a value that is not an object.\n *\n * It never throws.\n *\n * @example\n * ```ts\n * new ChainGateway({ dexBackendBaseUrl, httpRequestor: galaFetch, isTransportFailure: isFetchTransportFailure });\n * ```\n */\nexport function isFetchTransportFailure(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false;\n try {\n const name: unknown = 'name' in error ? error.name : undefined;\n if (name === 'AbortError' || name === 'TimeoutError') return false;\n return error instanceof TypeError || name === 'TypeError' || name === 'NetworkError';\n } catch {\n // A hostile or revoked object (a Proxy that throws on property access) proves nothing.\n return false;\n }\n}\n","import type { GSwapErrorCode } from '../classes/error_catalog.js';\nimport type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { isWriteView, stringParamOf, toFailureView } from './failure_view.js';\n\n/**\n * The yes/no questions an app asks about a failure from its CODE alone. They read only the failure\n * view and a short list of codes: no table of every code (that is `classifyFailure`'s, in\n * `failure_classification.ts`), no error class and no catalog (the imports above are types, erased\n * at build time). An app shell that imports one of them pays for this module and nothing else.\n */\n\n/**\n * True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a\n * `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied\n * (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting\n * again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&\n * error.status === 409` and the regex on \"already saved\". Accepts an SDK error or a plain-object\n * view ({@link FailureView}: `code` and `status`); every other value is `false`.\n *\n * @example\n * ```ts\n * if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);\n * ```\n */\nexport function isUniqueKeyConsumed(error: unknown): boolean {\n const view = toFailureView(error);\n return view?.code === 'CHAIN_DISPATCH_FAILED' && view.status === 409;\n}\n\nconst UNPROVEN_ACKNOWLEDGEMENT_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_DATA_MISSING',\n 'GATEWAY_MODE_INVALID',\n 'GATEWAY_SYNC_REQUEST_TRADE',\n 'MISSING_UNIQUE_KEY',\n 'UNIQUE_KEY_MISMATCH',\n];\n\n/**\n * True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no\n * `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.\n * The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an\n * app shows is one line for all five (\"the backend did not confirm it queued the request\"), so\n * the app asks this instead of keeping its own list of the codes. A gateway that says\n * `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.\n *\n * @example\n * ```ts\n * if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);\n * ```\n */\nexport function isUnprovenAcknowledgement(error: unknown): boolean {\n return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);\n}\n\n/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */\nfunction isCodeIn(code: string, codes: readonly GSwapErrorCode[]): boolean {\n return codes.some((known) => known === code);\n}\n\n/**\n * True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose\n * `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet\n * error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.\n */\nfunction hasCodeIn(error: unknown, codes: readonly GSwapErrorCode[]): boolean {\n const view = toFailureView(error);\n // `codes` holds catalog codes only, so membership already means \"a catalog code\": no table needed.\n return view !== undefined && isCodeIn(view.code, codes);\n}\n\n/**\n * The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app\n * may show as it is (and falls back to its own line when it is empty): a refusal the gateway made\n * (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the\n * SDK knows, and `GATEWAY_REJECTED` for one it does not).\n */\nconst RELAYABLE_REFUSAL_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_REPORTED_ERROR',\n 'METHOD_NOT_ALLOWED',\n 'SIGNATURE_INVALID',\n 'SIGNER_MISMATCH',\n 'DTO_INVALID',\n 'BOUNDS_VIOLATION',\n 'SYMBOL_CONFLICT',\n 'RATE_LIMITED',\n 'CHAIN_DISPATCH_FAILED',\n 'GATEWAY_REJECTED',\n];\n\n/**\n * True when the error is a gateway refusal whose `params.serverMessage` an app may relay to the\n * person as the gateway sent it: `GATEWAY_REPORTED_ERROR`, the gateway bounces (`METHOD_NOT_ALLOWED`,\n * `SIGNATURE_INVALID`, `SIGNER_MISMATCH`, `DTO_INVALID`, `BOUNDS_VIOLATION`, `SYMBOL_CONFLICT`,\n * `RATE_LIMITED`, `GATEWAY_REJECTED`) and `CHAIN_DISPATCH_FAILED`. The app shows `serverMessage` when\n * it is not empty and its own line when it is; the SDK's English `message` is never what to show.\n *\n * It accepts a plain-object view of an SDK error too ({@link FailureView}: an app's wrapper with a\n * `code`), and decides from the code in the same way. It narrows to `GSwapSDKError<...>` ONLY when\n * called with an SDK error; with an `unknown` or a view it answers `boolean` (narrow with\n * `isGSwapError` first, or read the view's own `params`).\n *\n * It is a test on the code alone, so it also holds for `CHAIN_DISPATCH_FAILED` with HTTP 409\n * (the `uniqueKey` was already consumed; `classifyFailure` says `unknown`): an app that words that\n * case itself (\"already submitted\", then confirm the key) checks `error.status === 409` BEFORE\n * relaying. It is false for `CHAIN_REJECTED` (the chain's verdict, worded by where it is shown: the\n * submit and confirm screens differ), for `HTTP_ERROR` (a proxy's page, not an answer to this\n * write) and for the five unproven acknowledgements (`isUnprovenAcknowledgement`: they carry no\n * server text).\n *\n * @example\n * ```ts\n * if (isRelayableRefusal(error)) show(error.params.serverMessage || t('swap.requestFailed'));\n * ```\n */\nexport function isRelayableRefusal(error: GSwapSDKError): error is GSwapSDKError<RelayableCode>;\nexport function isRelayableRefusal(error: unknown): boolean;\nexport function isRelayableRefusal(error: unknown): boolean {\n return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);\n}\n\n/** The codes {@link isRelayableRefusal} is true for. */\nexport type RelayableCode =\n | 'GATEWAY_REPORTED_ERROR'\n | 'METHOD_NOT_ALLOWED'\n | 'SIGNATURE_INVALID'\n | 'SIGNER_MISMATCH'\n | 'DTO_INVALID'\n | 'BOUNDS_VIOLATION'\n | 'SYMBOL_CONFLICT'\n | 'RATE_LIMITED'\n | 'CHAIN_DISPATCH_FAILED'\n | 'GATEWAY_REJECTED';\n\n/**\n * True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in\n * `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements\n * (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).\n * The outcome is `unknown` for all six. It replaces the app's own\n * `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.\n */\nexport function isUninterpretedAnswer(error: unknown): boolean {\n return isUnprovenAcknowledgement(error) || hasCodeIn(error, ['GATEWAY_REPORTED_ERROR']);\n}\n\n/**\n * The chain's own machine-readable `ErrorKey` of a failure (`'TOKEN_NOT_FOUND'`,\n * `'NOT_ENOUGH_LIQUIDITY'`, ...), for an app that maps a chain refusal to its own copy: the\n * `params.errorKey` of a `CHAIN_REJECTED` (an apply result, or a body that carries the chain's\n * error) and of a `CHAIN_DISPATCH_FAILED` (the gateway adds the chain's key to the body it\n * answered). `undefined` when the failure is neither, or when it carries no key (the gateway sent\n * none: the SDK writes `''`, which is not a key). Map the KEY, never the message text.\n *\n * Accepts an SDK error or a plain-object view ({@link FailureView}: `code` and `params`); every\n * other value is `undefined`. Other codes are `undefined` even when they have an `errorKey`-named\n * param, so a stray field cannot pass for a chain verdict.\n *\n * @example\n * ```ts\n * const key = chainErrorKeyOf(error);\n * if (key === 'NOT_ENOUGH_LIQUIDITY') showTooThin(); else showGeneric(error);\n * ```\n */\nexport function chainErrorKeyOf(error: unknown): string | undefined {\n const view = toFailureView(error);\n if (view === undefined) return undefined;\n if (view.code !== 'CHAIN_REJECTED' && view.code !== 'CHAIN_DISPATCH_FAILED') return undefined;\n const errorKey = stringParamOf(view, 'errorKey');\n return errorKey === undefined || errorKey === '' ? undefined : errorKey;\n}\n\n/** Codes that mean \"there is no market for this\" however the app reached them. */\nconst NO_MARKET_CODES: readonly GSwapErrorCode[] = [\n 'NO_POOL_AVAILABLE',\n 'INSUFFICIENT_LIQUIDITY',\n 'UNKNOWN_TOKEN',\n];\n\n/**\n * True when a failure means \"there is no market to trade this pair\": `NO_POOL_AVAILABLE` (no pool\n * at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX\n * has no trading symbol for the token), or a READ that was answered 404 (a quote the backend\n * cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||\n * notFound` list, so the empty-state (\"No market for this pair\") has one definition.\n *\n * A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing\n * market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every\n * other value is `false`.\n *\n * @example\n * ```ts\n * if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);\n * ```\n */\nexport function isNoMarket(error: unknown): boolean {\n const view = toFailureView(error);\n if (view === undefined) return false;\n if (isCodeIn(view.code, NO_MARKET_CODES)) return true;\n return !isWriteView(view) && (view.notFound === true || view.status === 404);\n}\n","/**\n * What a write's gateway answer says about the write, as one vocabulary for every app.\n *\n * The gateway answers `{ status, message, error, data }`. `data.mode` is `'sync'` for a liquidity\n * write (its executed chain result is in `data.result`) and `'queued'` for a RequestTrade\n * acknowledgement (accepted, NOT executed: the outcome is read from apply-results with\n * `confirm()`). `error: true` is the gateway refusing the write.\n *\n * A {@link SubmittedTransaction} only exists for an answer the SDK accepted, so its\n * {@link SubmitStatus} is `'executed'` or `'queued'`; a refused answer is a thrown\n * {@link GSwapSDKError}. The predicates below classify a RAW envelope instead, for an app that\n * holds one (`SubmittedTransaction.envelope`, `GSwapSDKError.body`, a stored answer) and for the\n * answers that never became a transaction. They reproduce frontend_v2's `isV2SubmitSuccess` /\n * `isV2SubmitQueued` / `isV2SubmitRejected` exactly, so the app can delete its own copies.\n */\n\n/** The state of an accepted write: executed on chain (`mode: 'sync'`) or queued (`mode: 'queued'`). */\nexport type SubmitStatus = 'executed' | 'queued';\n\n/**\n * How a raw gateway envelope classifies:\n *\n * - `'executed'`: `error === false` and `data.mode === 'sync'` (the executed result came back).\n * - `'queued'`: `error === false`, `data.mode === 'queued'` and `data.uniqueKey` is a string.\n * - `'rejected'`: no envelope at all, or `error === true`: a DEFINITE failure.\n * - `'unconfirmed'`: anything else (`error: false` with another or no `mode`, a queued answer\n * with no `uniqueKey`, an envelope with no boolean `error`): accepted, outcome not known. It is\n * NOT a rejection and must not be shown as one.\n *\n * The four are mutually exclusive and exhaustive.\n */\nexport type SubmitClassification = SubmitStatus | 'rejected' | 'unconfirmed';\n\n/** The `mode` of `envelope.data`, or `undefined` when there is no such field. */\nfunction modeOf(envelope: Record<string, unknown>): unknown {\n const data = envelope['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)['mode']\n : undefined;\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** True when the envelope is a definite failure: absent, or `error === true`. */\nexport function isSubmitRejected(envelope: unknown): boolean {\n if (!envelope) return true;\n return recordOf(envelope)?.['error'] === true;\n}\n\n/**\n * True when the envelope carries an executed result: `error === false` and `data.mode === 'sync'`.\n * A queued RequestTrade acknowledgement is deliberately NOT executed: its outcome is not known\n * until apply-results resolves.\n */\nexport function isSubmitExecuted(envelope: unknown): boolean {\n const record = recordOf(envelope);\n return record?.['error'] === false && modeOf(record) === 'sync';\n}\n\n/** True when the envelope acknowledges a `uniqueKey` as queued (`data.mode === 'queued'`). */\nexport function isSubmitQueued(envelope: unknown): boolean {\n const record = recordOf(envelope);\n if (record?.['error'] !== false || modeOf(record) !== 'queued') return false;\n return typeof recordOf(record['data'])?.['uniqueKey'] === 'string';\n}\n\n/** Classifies a raw gateway envelope; see {@link SubmitClassification}. */\nexport function classifySubmitEnvelope(envelope: unknown): SubmitClassification {\n if (isSubmitRejected(envelope)) return 'rejected';\n if (isSubmitExecuted(envelope)) return 'executed';\n if (isSubmitQueued(envelope)) return 'queued';\n return 'unconfirmed';\n}\n"],"mappings":"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"}