@gala-chain/gswap-sdk 1.1.1 → 1.2.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -5
- package/dist/browser/index.js +4 -3
- package/dist/browser/index.js.map +1 -1
- package/dist/index.cjs +3282 -610
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2021 -471
- package/dist/index.d.ts +2021 -471
- package/dist/index.mjs +3213 -608
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["asRecord","trimTrailingSlash","resolveSymbol","toDecimalString","resolveSymbol","globalObject"],"sources":["../../src/classes/gswap_sdk_error.ts","../../src/types/fees.ts","../../src/utils/ticks.ts","../../src/utils/validation.ts","../../src/classes/assets.ts","../../src/utils/transport.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/version.ts","../../src/classes/http_client.ts","../../src/utils/ordering.ts","../../src/classes/pools.ts","../../src/classes/positions.ts","../../src/classes/quoting.ts","../../src/classes/symbols.ts","../../src/classes/swaps.ts","../../src/classes/gswap.ts","../../src/utils/eip712.ts","../../src/classes/signers.ts"],"sourcesContent":["import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { HTTPResponse } from '../types/http_requestor.js';\n\n/** Error raised by the SDK for validation, gateway, chain, or transaction failures. */\nexport class GSwapSDKError extends Error {\n public readonly chainMessage: string | undefined;\n public readonly retryAfterMs: number | undefined;\n\n constructor(\n message: string,\n public readonly code: string,\n public readonly details?: Record<string, unknown>,\n chainMessage?: string,\n retryAfterMs?: number,\n ) {\n super(message);\n this.name = 'GSwapSDKError';\n this.chainMessage = chainMessage;\n this.retryAfterMs = retryAfterMs;\n }\n\n /** Create the standard missing-signer error. */\n public static noSignerError(): GSwapSDKError {\n return new GSwapSDKError(\n 'This method requires a signer. Please provide a signer to the GSwap constructor.',\n 'NO_SIGNER',\n );\n }\n\n /** Create the error used when confirming a position write without a configured wallet address. */\n public static noWalletAddressError(): GSwapSDKError {\n return new GSwapSDKError(\n 'Cannot confirm this write: no walletAddress was provided to the GSwap constructor, so ' +\n 'the resulting position cannot be looked up to confirm it landed on chain.',\n 'NO_WALLET_ADDRESS',\n );\n }\n\n /** Create the error used when no pool can quote the requested pair. */\n public static noPoolAvailableError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n ): GSwapSDKError {\n return new GSwapSDKError('No pool is available for the requested pair.', 'NO_POOL_AVAILABLE', {\n tokenIn,\n tokenOut,\n ...(fee === undefined ? {} : { fee }),\n });\n }\n\n /** Create the error used when a pool lacks liquidity for a quote. */\n public static insufficientLiquidityError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n ): GSwapSDKError {\n return new GSwapSDKError(\n 'The selected pool has insufficient liquidity for the requested quote.',\n 'INSUFFICIENT_LIQUIDITY',\n { tokenIn, tokenOut, ...(fee === undefined ? {} : { fee }) },\n );\n }\n\n /** Convert a chain-gateway bounce into a typed SDK error. */\n public static fromGatewayBounce(\n code: string,\n message: string,\n status: number,\n retryAfterMs?: number,\n ): GSwapSDKError {\n const details: Record<string, unknown> = { status, chainMessage: message };\n if (retryAfterMs !== undefined) details['retryAfterMs'] = retryAfterMs;\n const sdkMessage =\n code === 'CHAIN_DISPATCH_FAILED' ? message : `Gateway rejected ${code}: ${message}`;\n return new GSwapSDKError(sdkMessage, code, details, message, retryAfterMs);\n }\n\n /** Convert a GalaChain `Status: 0` response into a typed SDK error. */\n public static fromChainError(\n errorKey: string,\n message: string,\n details?: Record<string, unknown>,\n ): GSwapSDKError {\n return new GSwapSDKError(\n `GalaChain error ${errorKey}: ${message}`,\n errorKey,\n { ...details, errorKey, message },\n message,\n );\n }\n\n /** Create the error used when a token is not registered by the current DEX contract. */\n public static unknownTokenError(token: GalaChainTokenClassKey | string): GSwapSDKError {\n const tokenText = typeof token === 'string' ? token : JSON.stringify(token);\n return new GSwapSDKError(\n `Token ${tokenText} has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`,\n 'UNKNOWN_TOKEN',\n { token },\n );\n }\n\n /** Create the error used when apply-results confirmation does not arrive in time. */\n public static confirmationTimeoutError(uniqueKey: string, cause?: unknown): GSwapSDKError {\n return new GSwapSDKError(\n 'Transaction confirmation timed out; the trade may still apply. Confirm the same uniqueKey again later instead of resubmitting.',\n 'CONFIRMATION_TIMEOUT',\n { uniqueKey, ...(cause === undefined ? {} : { cause }) },\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\n if (errorKey !== undefined && message !== undefined) {\n return new GSwapSDKError(\n `GalaChain Error ${errorKey} from ${url}: ${message}`,\n errorKey,\n { message, errorKey, status: response.status, body: bodyJson, url },\n message,\n );\n }\n\n return new GSwapSDKError(`Unexpected HTTP Error ${response.status} from ${url}`, 'HTTP_ERROR', {\n status: response.status,\n body: bodyJson ?? bodyText,\n url,\n });\n }\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","/**\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 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/** Return the greatest integer tick whose token1/token0 price is no greater than `price`. */\nexport function tickFromPrice(price: BigNumber.Value): 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 tick = value.ln().dividedBy(new DexDecimal(1.0001).ln()).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) throw new RangeError(`Unsupported fee tier: ${fee}`);\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new RangeError('Ticks must be integers');\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK || lower >= upper) {\n throw new RangeError(\n `Tick range must satisfy ${GC_MIN_TICK} <= lower < upper <= ${GC_MAX_TICK}`,\n );\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new RangeError(`Ticks must be aligned to spacing ${spacing}`);\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!Number.isInteger(spacing) || spacing <= 0)\n throw new RangeError('Tick spacing must be positive');\n}\n","import BigNumber from 'bignumber.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(\n `Invalid ${parameterName}: use a decimal string or BigNumber, not a JavaScript number`,\n 'VALIDATION_ERROR',\n { type: 'INVALID_NUMERIC_AMOUNT', parameterName, value: amount, reason: 'number_input' },\n );\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(\n `Invalid ${parameterName}: must be a finite number`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'not_finite',\n },\n );\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError(`Invalid ${parameterName}: must be positive`, 'VALIDATION_ERROR', {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'zero_not_allowed',\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: must be ${allowZero ? 'non-negative' : 'positive'}`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'negative',\n },\n );\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(\n 'Invalid price values: use decimal strings or BigNumber values, not JavaScript numbers',\n 'VALIDATION_ERROR',\n { type: 'INVALID_NUMERIC_AMOUNT', reason: 'number_input' },\n );\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(\n 'Invalid price values: all prices must be finite and positive',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_PRICE_VALUES',\n spotPrice,\n lowerPrice,\n upperPrice,\n },\n );\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError(\n 'Invalid price range: lower price must be less than or equal to upper price',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_PRICE_RANGE',\n lowerPrice,\n upperPrice,\n },\n );\n }\n}\n\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: must be a non-negative integer`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TOKEN_DECIMALS',\n parameterName,\n value: decimals,\n },\n );\n }\n}\n\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('Invalid tick values: ticks must be integers', 'VALIDATION_ERROR', {\n type: 'INVALID_TICK_VALUES',\n tickLower,\n tickUpper,\n });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError(\n 'Invalid tick range: tickLower must be less than tickUpper',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_RANGE',\n tickLower,\n tickUpper,\n },\n );\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError(\n `Invalid tick range: ticks must be between ${GC_MIN_TICK} and ${GC_MAX_TICK}`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_BOUNDS',\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n },\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(\n 'Invalid fee tier: must be one of 0, 500, 3000, or 10000',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_FEE',\n value: fee,\n },\n );\n }\n}\n\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError(\n 'Invalid tick spacing: must be a positive integer',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_SPACING',\n value: tickSpacing,\n },\n );\n }\n}\n\nexport function validateWalletAddress(address?: string): asserts address is string {\n if (address === undefined) {\n throw new GSwapSDKError(\n 'Invalid wallet address: No wallet address provided',\n 'VALIDATION_ERROR',\n {\n type: 'MISSING_WALLET_ADDRESS',\n hint: 'Either provide a wallet address to the function you are calling, or set one when instantiating GSwapSDK',\n },\n );\n }\n\n if (!address || typeof address !== 'string' || address.trim().length === 0) {\n throw new GSwapSDKError(\n 'Invalid wallet address: must be a non-empty string',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_WALLET_ADDRESS',\n value: address,\n },\n );\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: must be a positive integer', 'VALIDATION_ERROR', {\n page,\n });\n }\n\n if (!Number.isInteger(limit) || limit < 1 || limit > 100) {\n throw new GSwapSDKError(\n 'Invalid limit: must be an integer between 1 and 100',\n 'VALIDATION_ERROR',\n { limit },\n );\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 'Backend returned an invalid user assets response.',\n 'INVALID_CHAIN_RESPONSE',\n {\n data: value,\n },\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","import type { HTTPResponse, HttpRequestor } from '../types/http_requestor.js';\nimport { GSwapSDKError, parseJson } from '../classes/gswap_sdk_error.js';\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 timer = setTimeout(() => controller.abort(), 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 if (controller.signal.aborted) {\n throw new GSwapSDKError(`Request timed out after ${timeoutMs} ms.`, 'REQUEST_TIMEOUT', {\n url,\n timeoutMs,\n cause: error,\n });\n }\n throw error;\n } finally {\n clearTimeout(timer);\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 non-negative Retry-After header as 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 return Number.isFinite(seconds) && seconds >= 0 ? seconds * 1000 : undefined;\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 { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport type { AppliedTrade, Position, TradeExecution } from '../types/v2_results.js';\nimport { GSwapSDKError, getObjectProperty, getStringProperty } from './gswap_sdk_error.js';\nimport {\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n} from '../utils/transport.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 public readonly mode: 'sync' | 'queued';\n /** The synchronous gateway result, or `undefined` when `mode === 'queued'`. */\n public readonly result: unknown;\n private readonly backendBaseUrl: string;\n private readonly requestor: HttpRequestor;\n private readonly requestTimeoutMs: number;\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 requestTimeoutMs?: number | 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.result = options.result;\n this.backendBaseUrl = options.dexBackendBaseUrl.replace(/\\/$/u, '');\n this.requestor = options.httpRequestor;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;\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 async confirmApplied(options?: ConfirmOptions): Promise<AppliedTrade> {\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 const schedule = createConfirmationSchedule(options, 3_000);\n await schedule.waitForRead();\n const url = `${this.backendBaseUrl}/v1/chain/apply-results/${encodeURIComponent(this.uniqueKey)}?channel=asset&contract=dex-contract`;\n let lastError: unknown;\n\n while (true) {\n let response: HTTPResponse;\n let body: unknown;\n try {\n response = await requestWithTimeout(\n this.requestor,\n url,\n { method: 'GET' },\n this.requestTimeoutMs,\n );\n body = await readResponseBody(response);\n } catch (error: unknown) {\n lastError = error;\n if (!(await schedule.waitForRead())) break;\n continue;\n }\n if (response.status === 200) {\n return this.readAppliedResult(response, body, url);\n }\n if (response.status === 404 || response.status === 429 || isTransient(response.status)) {\n if (response.status === 429) {\n const retryAfter = readRetryAfter(response);\n if (retryAfter !== undefined) {\n if (!(await schedule.waitForRead(retryAfter))) break;\n continue;\n }\n }\n } else {\n throw new GSwapSDKError(bodyMessage(body), 'CONFIRMATION_FAILED', {\n status: response.status,\n body,\n url,\n });\n }\n if (!(await schedule.waitForRead())) break;\n }\n throw GSwapSDKError.confirmationTimeoutError(this.uniqueKey, lastError);\n }\n\n private readAppliedResult(response: HTTPResponse, body: unknown, url: string): AppliedTrade {\n const record = asRecord(body);\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 throw GSwapSDKError.fromChainError(\n getStringProperty(record, 'ErrorKey') ?? 'CHAIN_ERROR',\n getStringProperty(record, 'Message') ?? 'The chain rejected this trade.',\n {\n uniqueKey: this.uniqueKey,\n applyTransactionId,\n blockNumber,\n status: response.status,\n body,\n url,\n },\n );\n }\n if (status !== 1) throw malformedConfirmation(response, body, url);\n const result = parseTradeExecution(record?.['Data']);\n if (result === undefined) throw malformedConfirmation(response, body, url);\n return {\n uniqueKey: this.uniqueKey,\n transactionId: applyTransactionId,\n blockNumber,\n requestTransactionId: this.transactionId,\n result,\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 schedule = createConfirmationSchedule(options, 0);\n await schedule.waitForRead();\n while (true) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);\n try {\n const result = await this.positionConfirmation(controller.signal);\n if (result.confirmed) return result.position;\n } finally {\n clearTimeout(timer);\n }\n if (!(await schedule.waitForRead())) break;\n }\n throw GSwapSDKError.confirmationTimeoutError(this.uniqueKey);\n }\n}\n\n/**\n * Controls timeout and polling behavior for confirmation.\n *\n * - `timeoutMs` (default 60 000): overall deadline, counted from the `confirm()` call and\n * including `initialDelayMs`. At least one read is always made.\n * - `pollIntervalMs` (default 2 000, minimum 500): base interval, doubled with jitter up to 8 s.\n * - `initialDelayMs`: wait before the first read. Defaults to 3 000 for a queued RequestTrade\n * (the AutoApplier needs a few seconds) and 0 for liquidity writes (already executed).\n */\nexport interface ConfirmOptions {\n timeoutMs?: number | undefined;\n pollIntervalMs?: number | undefined;\n initialDelayMs?: number | undefined;\n}\n\ninterface ConfirmationSchedule {\n waitForRead(retryAfterMs?: number): Promise<boolean>;\n}\n\nfunction createConfirmationSchedule(\n options: ConfirmOptions | undefined,\n defaultInitialDelayMs: number,\n): ConfirmationSchedule {\n const timeoutMs = Math.max(0, options?.timeoutMs ?? 60_000);\n const pollIntervalMs = Math.max(500, options?.pollIntervalMs ?? 2_000);\n const initialDelayMs = Math.max(0, options?.initialDelayMs ?? defaultInitialDelayMs);\n const deadline = Date.now() + timeoutMs;\n let firstRead = true;\n let attempt = 0;\n return {\n async waitForRead(retryAfterMs?: number): Promise<boolean> {\n if (firstRead) {\n firstRead = false;\n const remaining = Math.max(0, deadline - Date.now());\n await delay(Math.min(initialDelayMs, remaining));\n return true;\n }\n const backoff = Math.min(8_000, pollIntervalMs * 2 ** Math.min(attempt, 5));\n attempt += 1;\n const waitMs = retryAfterMs === undefined ? jitter(backoff) : retryAfterMs;\n if (Date.now() + waitMs > deadline) return false;\n await delay(waitMs);\n return true;\n },\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 malformedConfirmation(response: HTTPResponse, body: unknown, url: string): GSwapSDKError {\n return new GSwapSDKError(\n 'Transaction confirmation returned a malformed body',\n 'CONFIRMATION_FAILED',\n { status: response.status, body, url },\n );\n}\n\nfunction isTransient(status: number): boolean {\n return status === 500 || status === 502 || status === 503 || status === 504;\n}\n\nfunction bodyMessage(body: unknown): string {\n return (\n getStringProperty(body, 'message') ??\n getStringProperty(body, 'Message') ??\n getStringProperty(getObjectProperty(body, 'error'), 'message') ??\n getStringProperty(getObjectProperty(body, 'error'), 'Message') ??\n (typeof body === 'string' ? body : 'Transaction confirmation failed')\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 delay(milliseconds: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, milliseconds));\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 { HttpRequestor, HTTPResponse } from '../types/http_requestor.js';\nimport { getObjectProperty, getStringProperty, GSwapSDKError } from './gswap_sdk_error.js';\nimport { SubmittedTransaction, type PositionConfirmationResult } from './submitted_transaction.js';\nimport {\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\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 chainCallTimeoutMs?: number | 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 public readonly requestTimeoutMs: number;\n public readonly dexBackendBaseUrl: string;\n\n /** Create a chain gateway client. */\n constructor(options: ChainGatewayOptions) {\n this.dexBackendBaseUrl = trimTrailingSlash(options.dexBackendBaseUrl);\n this.requestor = options.httpRequestor ?? fetch.bind(globalThis);\n this.walletAddress = options.walletAddress;\n this.chainCallTimeoutMs = options.chainCallTimeoutMs ?? 30_000;\n this.requestTimeoutMs = this.chainCallTimeoutMs;\n }\n\n /** Submit a signed v2 DTO through the chain gateway. */\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(\n 'The synchronous Trade method was removed; swaps are queued through RequestTrade.',\n 'METHOD_NOT_SUPPORTED',\n { method },\n );\n }\n const url = `${this.dexBackendBaseUrl}/v1/chain/asset/dex-contract/${method}`;\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n if (walletAddress !== undefined) headers['X-Wallet-Address'] = walletAddress;\n let response: HTTPResponse;\n try {\n response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(signedBody),\n },\n this.chainCallTimeoutMs,\n );\n } catch (error: unknown) {\n if (error instanceof GSwapSDKError && error.code === 'REQUEST_TIMEOUT') {\n throw new GSwapSDKError(\n 'The submission outcome is unknown because the gateway request timed out. Confirm before retrying.',\n 'SUBMISSION_OUTCOME_UNKNOWN',\n { uniqueKey: getStringProperty(signedBody, 'uniqueKey') ?? '', cause: error },\n );\n }\n throw error;\n }\n const body = await readResponseBody(response);\n\n if (!response.ok) {\n throw gatewayError(response, body, url);\n }\n\n const envelope = asRecord(body);\n const data = asRecord(envelope?.['data'] ?? envelope?.['Data']);\n if (data === undefined) {\n throw invalidGatewayResponse(response, body, url, 'Expected a data object.');\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 invalidModeMessage =\n 'Gateway response must contain data.mode=\"sync\" with data.result, or data.mode=\"queued\".';\n if (mode !== 'sync' && mode !== 'queued') {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\n }\n if (\n ('transactionId' in data && typeof rawTransactionId !== 'string') ||\n (bodyBlockNumber !== undefined && bodyBlockNumber !== null && !isBlockNumber(bodyBlockNumber))\n ) {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\n }\n if (method === 'RequestTrade' && mode === 'sync') {\n throw invalidGatewayResponse(\n response,\n body,\n url,\n 'The gateway executed RequestTrade synchronously, which this SDK refuses; RequestTrade must be queued.',\n );\n }\n if (method === 'RequestTrade' && mode === 'queued') {\n const signedUniqueKey = getStringProperty(signedBody, 'uniqueKey');\n if (\n 'uniqueKey' in data &&\n (typeof data['uniqueKey'] !== 'string' || data['uniqueKey'] !== signedUniqueKey)\n ) {\n throw invalidGatewayResponse(\n response,\n body,\n url,\n 'Gateway response data.uniqueKey must match the signed RequestTrade uniqueKey.',\n );\n }\n } else if (mode === 'queued' || !('result' in data)) {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\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') ?? 'The chain rejected this write.',\n { status: response.status, body, url },\n );\n }\n }\n }\n\n const uniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\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 dexBackendBaseUrl: this.dexBackendBaseUrl,\n httpRequestor: this.requestor,\n requestTimeoutMs: this.chainCallTimeoutMs,\n ...(options?.positionConfirmation === undefined\n ? {}\n : { positionConfirmation: options.positionConfirmation }),\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 invalidGatewayResponse(\n response: HTTPResponse,\n body: unknown,\n url: string,\n message: string,\n): GSwapSDKError {\n return new GSwapSDKError(message, 'INVALID_GATEWAY_RESPONSE', {\n status: response.status,\n body,\n url,\n });\n}\n\nfunction gatewayError(response: HTTPResponse, body: unknown, url: string): GSwapSDKError {\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 const message =\n getStringProperty(object, 'message') ??\n getStringProperty(nested, 'message') ??\n getStringProperty(nested, 'Message') ??\n (typeof body === 'string' ? body : `Gateway request failed with HTTP ${response.status}`);\n const retryAfterMs = response.status === 429 ? readRetryAfter(response) : undefined;\n if (code === 'HTTP_ERROR') {\n return new GSwapSDKError(message, code, { status: response.status, body, url });\n }\n return GSwapSDKError.fromGatewayBounce(code, message, response.status, retryAfterMs);\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';\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\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 (url: string, protocols?: string | string[]): WebSocketLike;\n}\n\ninterface PendingRequest {\n resolve(value: unknown): void;\n reject(error: Error): void;\n timeout: ReturnType<typeof setTimeout>;\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\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 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 Error(\n 'GdexStreamService requires a standards-compatible WebSocket constructor. ' +\n 'Node.js versions before 22 must provide one with config.webSocketImpl (for example, from the \"ws\" package).',\n );\n }\n this.webSocketConstructor = implementation as WebSocketConstructor;\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 Error('GDEX 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 if (!this.isConnected() || !this.socket) {\n return Promise.reject(new Error('GDEX stream is not connected. Call connect() first.'));\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(new Error(`GDEX request \"${method}\" timed out after ${this.requestTimeoutMs}ms`));\n }, this.requestTimeoutMs);\n this.pending.set(id, { resolve: (value) => resolve(value as T), reject, timeout });\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 = new this.webSocketConstructor(this.url, GDEX_SUBPROTOCOL);\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 Error(`Failed to connect to GDEX stream at ${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 Error(`GDEX stream closed before connecting (code ${event.code ?? 0})`));\n this.rejectPending(new Error(`GDEX stream connection closed (code ${event.code ?? 0})`));\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 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 result = await this.request<{ subscriptionId: string }>('gdex_subscribe', params);\n // Assigned after the handle because unsubscribe closes over the completed subscription record.\n // eslint-disable-next-line prefer-const\n let active: ActiveSubscription;\n const handle: MutableGdexSubscription = {\n subscriptionId: result.subscriptionId,\n unsubscribe: async () => this.unsubscribe(active),\n };\n active = { serverId: result.subscriptionId, params, callback, handle, active: true };\n this.activeSubscriptions.add(active);\n this.subscriptionsByServerId.set(active.serverId, active);\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);\n // The consumer can unsubscribe while the asynchronous subscribe request is pending.\n if (!subscription.active) {\n await this.request('gdex_unsubscribe', { subscriptionId: result.subscriptionId });\n continue;\n }\n subscription.serverId = result.subscriptionId;\n subscription.handle.subscriptionId = result.subscriptionId;\n this.subscriptionsByServerId.set(result.subscriptionId, subscription);\n }\n }\n\n private async resubscribeWithRateLimitRetry(\n params: Record<string, unknown>,\n ): Promise<{ subscriptionId: string }> {\n for (let attempt = 0; ; attempt++) {\n try {\n return await this.request('gdex_subscribe', params);\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","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.1.1';\n","import type { HttpRequestor } from '../types/http_requestor.js';\nimport { debugLog } from '../utils/debug.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport { readResponseBody, requestWithTimeout } from '../utils/transport.js';\nimport { SDK_VERSION } from '../version.js';\n\nexport class HttpClient {\n /** Create an HTTP client around fetch or an injected requestor. */\n constructor(\n private readonly httpRequestor: HttpRequestor = fetch,\n private readonly timeoutMs = 30_000,\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 response = await requestWithTimeout(\n this.httpRequestor,\n url,\n {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'User-Agent': `GalaChain-SDK/${SDK_VERSION}`,\n },\n ...(body ? { 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 searchParams = params ? new URLSearchParams(params) : undefined;\n const endpointWithParams = searchParams ? `${endpoint}?${searchParams.toString()}` : endpoint;\n\n return this.sendRequest('GET', baseUrl, basePath, endpointWithParams, undefined, options);\n }\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('Unable to order trading symbols.', 'VALIDATION_ERROR', { value });\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 delimiter = tokenClassKey.includes('|') ? '|' : '$';\n const segments = tokenClassKey.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 throw new GSwapSDKError(\n 'Invalid token class key: expected a collection followed by category, type and additionalKey',\n 'VALIDATION_ERROR',\n {\n tokenClassKey,\n },\n );\n }\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","import type { FEE_TIER } from '../types/fees.js';\nimport type { CompositePool, PoolInfo, PoolListInfo, Slot0 } from '../types/v2_results.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 type { Symbols } 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};\ntype PoolSymbols = Pick<Symbols, 'resolve'>;\n\n/** Read-only pool and current-price access for the current GalaChainDex contract. */\nexport class Pools {\n /**\n * Creates a pool service.\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: PoolSymbols,\n ) {\n this.http = new HttpClient(gateway.httpRequestor, gateway.requestTimeoutMs ?? 30_000);\n }\n\n private readonly http: HttpClient;\n\n /**\n * Fetches every current-contract pool from the swap backend.\n *\n * @example\n * ```ts\n * const pools = await service.getPools();\n * console.log(pools.length);\n * ```\n */\n public async getPools(options?: { signal?: AbortSignal | undefined }): Promise<PoolListInfo[]> {\n const response = await this.http.sendGetRequest<BackendEnvelope<unknown>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/pools',\n undefined,\n options?.signal === undefined ? undefined : { signal: options.signal },\n );\n if (!Array.isArray(response.data) || !response.data.every(isPoolListInfo)) {\n throw new GSwapSDKError('Backend returned an invalid pool list.', 'INVALID_CHAIN_RESPONSE', {\n data: response.data,\n });\n }\n return response.data;\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 const first = await resolveSymbol(this.symbols, token0);\n const second = await resolveSymbol(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 resolveSymbol(this.symbols, token0),\n token1: await resolveSymbol(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('Pool request failed.', 'HTTP_ERROR', { cause: error });\n }\n }\n}\n\nasync function resolveSymbol(symbols: PoolSymbols, token: TokenRef): Promise<string> {\n const resolved = await symbols.resolve(token);\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('Token could not be resolved to a trading symbol.', 'SYMBOL_NOT_FOUND', {\n token,\n });\n}\n\nfunction isPoolListInfo(value: unknown): value is PoolListInfo {\n if (typeof value !== 'object' || value === null) return false;\n const row = value as Record<string, unknown>;\n const requiredNumbers = ['fee', 'tickSpacing', 'protocolFees', 'tradingFees'];\n const optionalStrings = [\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'creator',\n 'price',\n 'sqrtPrice',\n 'token0Tvl',\n 'token1Tvl',\n ];\n const optionalNumbers = [\n 'tick',\n 'tvlUsd',\n 'volume1d',\n 'volume7d',\n 'volume30d',\n 'trades1d',\n 'fee24h',\n 'apr1d',\n 'token0Price',\n 'token1Price',\n ];\n return (\n row['contractVersion'] === 'v2' &&\n typeof row['token0'] === 'string' &&\n typeof row['token1'] === 'string' &&\n typeof row['poolName'] === 'string' &&\n typeof row['poolRef'] === 'string' &&\n requiredNumbers.every((key) => isFiniteNumber(row[key])) &&\n optionalStrings.every((key) => isOptionalString(row[key])) &&\n optionalNumbers.every((key) => isOptionalNumber(row[key]))\n );\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nfunction isOptionalString(value: unknown): value is string | undefined {\n return value === undefined || typeof value === 'string';\n}\n\nfunction isOptionalNumber(value: unknown): value is number | undefined {\n return value === undefined || isFiniteNumber(value);\n}\n","import BigNumber from 'bignumber.js';\nimport { GSwapSDKError } 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 type { Symbols } 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 TokenRef, compositeKeyOf, parseTokenClassKey } from '../utils/ordering.js';\nimport { validateFee, validateNumericAmount } from '../utils/validation.js';\nimport { alignTickDown, alignTickUp, assertTickRange, tickFromPrice } from '../utils/ticks.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};\ntype PositionSymbols = Pick<Symbols, 'resolve' | 'orderPair'> & { invalidate?: () => void };\n\ninterface BackendEnvelope<TData> {\n data: TData;\n}\n\ninterface PositionWire {\n token0CompositeKey?: string;\n token1CompositeKey?: string;\n token0Symbol: string;\n token1Symbol: string;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n liquidity: string;\n amount0: string;\n amount1: string;\n inRange: boolean;\n owner: string;\n currentTick?: number;\n sqrtPrice?: string;\n pool?: string;\n poolRef?: string;\n fees0?: string;\n fees1?: string;\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 ) {\n this.http = new HttpClient(gateway.httpRequestor, gateway.requestTimeoutMs ?? 30_000);\n }\n\n private readonly http: HttpClient;\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.\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<PositionWire[]>('/positions', { user: owner });\n return response.data.map((position) => this.mapPosition(position));\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 pair = await this.symbols.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n const response = await this.getNullable<PositionWire>(\n '/position',\n {\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 signal,\n );\n return response === null ? null : this.mapPosition(response.data);\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: this.requestToken(args.token0),\n token1: this.requestToken(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: this.requestToken(args.token0),\n token1: this.requestToken(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: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n amountIsToken0: boolean;\n }) {\n validateFee(args.fee);\n const pair = await this.symbols.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 validateNumericAmount(args.amount, 'amount');\n const amount = new BigNumber(args.amount).toFixed();\n const dto: AddLiquidityDTO = {\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.uniqueKey(),\n ...(pair.flipped !== args.amountIsToken0\n ? { depositQuantityToken0: amount }\n : { depositQuantityToken1: amount }),\n };\n return this.submit('AddLiquidity', dto as unknown as Record<string, unknown>, {\n kind: 'add',\n identity: {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n },\n });\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 }) {\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('Price bounds must be finite and positive.', 'VALIDATION_ERROR');\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError(\n 'minPrice must be less than or equal to maxPrice.',\n 'VALIDATION_ERROR',\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 });\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: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount0?: NumericAmount | undefined;\n amount1?: NumericAmount | undefined;\n }) {\n validateFee(args.fee);\n const pair = await this.symbols.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('Provide at most one of amount0 or amount1.', 'VALIDATION_ERROR');\n }\n if (args.amount0 !== undefined) validateNumericAmount(args.amount0, 'amount0');\n if (args.amount1 !== undefined) validateNumericAmount(args.amount1, 'amount1');\n const withdrawal =\n args.amount0 !== undefined\n ? pair.flipped\n ? { withdrawalQuantityToken1: new BigNumber(args.amount0).toFixed() }\n : { withdrawalQuantityToken0: new BigNumber(args.amount0).toFixed() }\n : args.amount1 !== undefined\n ? pair.flipped\n ? { withdrawalQuantityToken0: new BigNumber(args.amount1).toFixed() }\n : { withdrawalQuantityToken1: new BigNumber(args.amount1).toFixed() }\n : {};\n const dto: RemoveLiquidityDTO = {\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.uniqueKey(),\n ...withdrawal,\n };\n const isFullClose = args.amount0 === undefined && args.amount1 === undefined;\n return this.submit('RemoveLiquidity', dto as unknown as Record<string, unknown>, {\n kind: isFullClose ? 'removeFull' : 'removePartial',\n identity: {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n },\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: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n }) {\n validateFee(args.fee);\n const pair = await this.symbols.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 const dto: CollectPositionFeesDTO = {\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.uniqueKey(),\n };\n return this.submit('CollectPositionFees', dto as unknown as Record<string, unknown>, {\n kind: 'collect',\n identity: {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n },\n });\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 * VALIDATION_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: {\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 isPrivate?: boolean | undefined;\n privateAccess?: string[] | undefined;\n }) {\n const hasPrice = args.startingPrice !== undefined;\n const hasSqrtPrice = args.startingSqrtPrice !== undefined;\n if (hasPrice === hasSqrtPrice) {\n throw new GSwapSDKError(\n 'Provide exactly one of startingPrice or startingSqrtPrice.',\n 'VALIDATION_ERROR',\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('Starting price must be finite and positive.', 'VALIDATION_ERROR');\n }\n const canonicalPrice = flipped ? new BigNumber(1).dividedBy(sourcePrice) : sourcePrice;\n const dto: CreatePoolDTO = {\n token0Key: token0.classKey,\n token1Key: token1.classKey,\n token0Symbol: token0.symbol,\n token1Symbol: token1.symbol,\n fee: args.fee,\n uniqueKey: this.uniqueKey(),\n ...(hasPrice\n ? { startingPrice: canonicalPrice.toFixed() }\n : { startingSqrtPrice: canonicalPrice.toFixed() }),\n ...(args.isPrivate === undefined ? {} : { isPrivate: args.isPrivate }),\n ...(args.privateAccess === undefined ? {} : { privateAccess: args.privateAccess }),\n };\n const transaction = await this.submit('CreatePool', dto, {\n kind: 'createPool',\n token0: token0.symbol,\n token1: token1.symbol,\n fee: args.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 this.signer.signObject(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 if (!(error instanceof GSwapSDKError) || error.details === undefined) return false;\n return error.details['status'] === 404;\n }\n\n private mapPosition(position: PositionWire): Position {\n return {\n token0Symbol: position.token0Symbol,\n token1Symbol: position.token1Symbol,\n ...(position.token0CompositeKey === undefined\n ? {}\n : { token0CompositeKey: position.token0CompositeKey }),\n ...(position.token1CompositeKey === undefined\n ? {}\n : { token1CompositeKey: position.token1CompositeKey }),\n fee: position.fee,\n tickLower: position.tickLower,\n tickUpper: position.tickUpper,\n liquidity: position.liquidity,\n amount0: position.amount0,\n amount1: position.amount1,\n inRange: position.inRange,\n ...(position.currentTick === undefined ? {} : { currentTick: position.currentTick }),\n ...(position.sqrtPrice === undefined ? {} : { sqrtPrice: position.sqrtPrice }),\n pool: position.poolRef ?? position.pool ?? '',\n owner: position.owner,\n ...(position.fees0 === undefined ? {} : { fees0: position.fees0 }),\n ...(position.fees1 === undefined ? {} : { fees1: position.fees1 }),\n };\n }\n\n private requestToken(ref: TokenRef): string {\n return typeof ref === 'string' ? ref : compositeKeyOf(ref);\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(`Unsupported fee tier: ${fee}.`, 'VALIDATION_ERROR');\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: use a decimal string or BigNumber, not a JavaScript number`,\n 'VALIDATION_ERROR',\n );\n }\n }\n\n private uniqueKey(): string {\n return `gswap-sdk-${globalThis.crypto.randomUUID()}`;\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 this.symbols.resolve(lookupRef);\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError(\n `Supplied symbol ${symbolOverride} disagrees with the registered trading symbol ${resolved.symbol}.`,\n 'VALIDATION_ERROR',\n { token: ref, suppliedSymbol: symbolOverride, registeredSymbol: resolved.symbol },\n );\n }\n const suppliedClassKey = this.tryParseClassKey(ref);\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(\n '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 'VALIDATION_ERROR',\n { token: ref },\n );\n }\n if (!/^[A-Za-z0-9]+$/u.test(symbolOverride)) {\n throw new GSwapSDKError(\n 'Invalid trading symbol: must be ASCII letters and digits only.',\n 'VALIDATION_ERROR',\n { symbol: symbolOverride },\n );\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","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 { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { HttpClient } from './http_client.js';\nimport type { Symbols } 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\ntype QuoteSymbols = Pick<Symbols, 'resolve'>;\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('https://swap-backend.stage.defi.ovh.gala.com', http, symbols);\n * ```\n */\n constructor(\n private readonly dexBackendBaseUrl: string,\n private readonly http: HttpClient,\n private readonly symbols: QuoteSymbols,\n ) {}\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 tokenInSymbol = await resolveSymbol(this.symbols, tokenIn);\n const tokenOutSymbol = await resolveSymbol(this.symbols, tokenOut);\n const params: Record<string, string> = {\n tokenIn: tokenInSymbol,\n tokenOut: tokenOutSymbol,\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.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 }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError('Backend returned an invalid quote.', 'INVALID_CHAIN_RESPONSE', {\n data: value,\n });\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\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n): GSwapSDKError {\n if (error instanceof GSwapSDKError) {\n const status = readStatus(error.details);\n const message = readMessage(error.details) ?? error.message;\n if (status === 404 || /no pool|no pools|pool does not exist/iu.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee);\n }\n if (status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee);\n }\n return error;\n }\n return new GSwapSDKError('Quote request failed.', 'HTTP_ERROR', {\n cause: error,\n tokenIn,\n tokenOut,\n fee,\n });\n}\n\nfunction readStatus(details: Record<string, unknown> | undefined): number | undefined {\n const status = details?.['status'];\n return typeof status === 'number' ? status : undefined;\n}\n\nfunction readMessage(details: Record<string, unknown> | undefined): string | undefined {\n const direct = details?.['message'];\n if (typeof direct === 'string') return direct;\n const body = details?.['body'];\n if (typeof body !== 'object' || body === null || Array.isArray(body)) return undefined;\n const message = (body as Record<string, unknown>)['message'];\n return typeof message === 'string' ? message : undefined;\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 tier: ${fee}`, 'VALIDATION_ERROR', { fee });\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n\nasync function resolveSymbol(symbols: QuoteSymbols, token: TokenRef): Promise<string> {\n const resolved = await symbols.resolve(token);\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('Token could not be resolved to a trading symbol.', 'SYMBOL_NOT_FOUND', {\n token,\n });\n}\n","import type { GalaChainTokenClassKey } from '../types/token.js';\nimport type { TradingSymbol } from '../types/v2_results.js';\nimport type { TokenRef } from '../utils/ordering.js';\nimport { compositeKeyOf, orderSymbols, parseTokenClassKey } from '../utils/ordering.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 /** Create a symbol service backed by the swap backend. */\n constructor(\n private readonly gateway: Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n },\n ) {\n this.http = new HttpClient(gateway.httpRequestor, gateway.requestTimeoutMs);\n }\n\n /** List all registered GalaChainDex trading symbols, cached for 60 seconds. */\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) => parseSymbols(response.data))\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 /** 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\nfunction parseSymbols(value: unknown): TradingSymbol[] {\n if (!Array.isArray(value) || !value.every(isTradingSymbol)) {\n throw new GSwapSDKError('Backend returned an invalid symbol list.', 'INVALID_CHAIN_RESPONSE', {\n data: value,\n });\n }\n return value;\n}\n\nfunction isTradingSymbol(value: unknown): value is TradingSymbol {\n if (typeof value !== 'object' || value === null) return false;\n const entry = value as Record<string, unknown>;\n return (\n typeof entry['symbol'] === 'string' &&\n typeof entry['collection'] === 'string' &&\n typeof entry['category'] === 'string' &&\n typeof entry['type'] === 'string' &&\n typeof entry['additionalKey'] === 'string' &&\n typeof entry['decimals'] === 'number' &&\n Number.isInteger(entry['decimals']) &&\n entry['decimals'] >= 0\n );\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","import BigNumber from 'bignumber.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport { validateFee, validateNumericAmount } from '../utils/validation.js';\nimport type { ChainSubmitOptions } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport type { GalaChainSigner } from './signers.js';\nimport { SubmittedTransaction, type ConfirmOptions } from './submitted_transaction.js';\nimport type { AppliedTrade } from '../types/v2_results.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { Symbols } from './symbols.js';\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\nexport type SwapAmount =\n | {\n exactIn: NumericAmount;\n exactOut?: undefined;\n amountOutMinimum?: NumericAmount | undefined;\n amountInMaximum?: undefined;\n }\n | {\n exactIn?: undefined;\n exactOut: NumericAmount;\n amountOutMinimum?: undefined;\n amountInMaximum?: NumericAmount | undefined;\n };\ninterface SwapGateway {\n submit: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<AppliedTrade>>;\n readonly dexBackendBaseUrl: string;\n readonly httpRequestor: HttpRequestor;\n readonly requestTimeoutMs: number;\n}\ntype SwapSymbols = Pick<Symbols, 'resolve'>;\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: SwapSymbols,\n private readonly signer?: GalaChainSigner,\n private readonly walletAddress?: string,\n ) {}\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 ): Promise<SubmittedTransaction<AppliedTrade>> {\n validateFee(fee);\n\n const dto = await this.buildRequestTradeDto(tokenIn, tokenOut, fee, amount);\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const signedDto = await this.signer.signObject('RequestTrade', dto);\n const submitOptions =\n this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n return this.gateway.submit('RequestTrade', signedDto, submitOptions);\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('gswap-sdk-2f1c…');\n * ```\n */\n public async confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade> {\n if (!UNIQUE_KEY_PATTERN.test(uniqueKey)) {\n throw new GSwapSDKError(\n 'uniqueKey must be 1-128 characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n 'VALIDATION_ERROR',\n { uniqueKey },\n );\n }\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 });\n return transaction.confirm({ initialDelayMs: 0, ...options });\n }\n\n private async buildRequestTradeDto(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n ): Promise<Record<string, unknown>> {\n const tokenInSymbol = await resolveSymbol(this.symbols, tokenIn);\n const tokenOutSymbol = await resolveSymbol(this.symbols, tokenOut);\n const ordered = readOrderedSymbols(orderSymbols(tokenInSymbol, tokenOutSymbol));\n const tokenInIsToken0 = tokenInSymbol === ordered.token0;\n\n const dto: Record<string, unknown> = {\n token0: ordered.token0,\n token1: ordered.token1,\n fee,\n uniqueKey: `gswap-sdk-${globalThis.crypto.randomUUID()}`,\n };\n\n if ('exactIn' in amount) {\n const exactIn = amount.exactIn;\n if (exactIn === undefined) {\n throw new GSwapSDKError('exactIn is required for an exact-input swap.', 'VALIDATION_ERROR');\n }\n validateNumericAmount(exactIn, 'exactIn');\n dto[tokenInIsToken0 ? 'sell0Qty' : 'sell1Qty'] = toDecimalString(exactIn);\n if (amount.amountOutMinimum !== undefined) {\n validateNumericAmount(amount.amountOutMinimum, 'amountOutMinimum', true);\n dto['amountOutMinimum'] = toDecimalString(amount.amountOutMinimum);\n }\n } else {\n const exactOut = amount.exactOut;\n if (exactOut === undefined) {\n throw new GSwapSDKError(\n 'exactOut is required for an exact-output swap.',\n 'VALIDATION_ERROR',\n );\n }\n validateNumericAmount(exactOut, 'exactOut');\n dto[tokenInIsToken0 ? 'buy1Qty' : 'buy0Qty'] = toDecimalString(exactOut);\n if (amount.amountInMaximum !== undefined) {\n validateNumericAmount(amount.amountInMaximum, 'amountInMaximum', true);\n dto['amountInMaximum'] = toDecimalString(amount.amountInMaximum);\n }\n }\n return dto;\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n\nasync function resolveSymbol(symbols: SwapSymbols, token: TokenRef): Promise<string> {\n const resolved = await symbols.resolve(token);\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('Token could not be resolved to a trading symbol.', 'SYMBOL_NOT_FOUND', {\n token,\n });\n}\n","import { Assets } from './assets.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 { Symbols } from './symbols.js';\nimport { Swaps } from './swaps.js';\nimport type { HttpRequestor } from '../types/http_requestor.js';\nimport type { GSwapEnv } from '../types/env.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 chainCallTimeoutMs?: number | 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\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 public readonly dexBackendWsUrl: string;\n private readonly webSocketImpl: unknown;\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(options?.httpRequestor, this.chainCallTimeoutMs);\n this.gateway = new ChainGateway({\n dexBackendBaseUrl: this.dexBackendBaseUrl,\n chainCallTimeoutMs: this.chainCallTimeoutMs,\n ...(options?.httpRequestor === undefined ? {} : { httpRequestor: options.httpRequestor }),\n ...(this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress }),\n });\n this.symbols = new Symbols(this.gateway);\n this.quoting = new Quoting(this.dexBackendBaseUrl, httpClient, this.symbols);\n this.pools = new Pools(this.gateway, this.symbols);\n this.positions = new Positions(this.gateway, this.symbols, this.signer, this.walletAddress);\n this.swaps = new Swaps(this.gateway, this.symbols, this.signer, this.walletAddress);\n this.assets = new Assets(this.dexBackendBaseUrl, httpClient);\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 }\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 });\n return this.streamClient;\n }\n}\n\nfunction trimTrailingSlash(value: string): string {\n return value.replace(/\\/$/u, '');\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 */\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 Error('Name collisions not yet supported');\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 Error(\n `Unsupported type, ${typeof fieldValue}, value: ${Object.prototype.toString.call(fieldValue)}`,\n );\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/** Matches every genuine-EIP-712 probe that has actually recovered `client|` on stage. */\nexport const EIP712_DOMAIN: { name: string; chainId: number } = { name: 'ethereum', chainId: 1 };\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","import { serialize, signatures } from '@gala-chain/api';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport {\n buildEIP712Payload,\n EIP712_CAPABLE_METHODS,\n EIP712_DOMAIN,\n type EIP712Types,\n} from '../utils/eip712.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// Built via String.fromCharCode rather than a literal escape ON PURPOSE: the EIP-191 control\n// byte is invisible either way once it's a real character in the string, but a literal escape\n// in source is itself a raw control byte sitting in the file the moment any tool decodes it\n// (an editor save, a diff, a copy-paste) — this keeps the source text itself ordinary and\n// constructs the byte at runtime instead.\nconst ETHEREUM_SIGNED_MESSAGE = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\n\n/** The EIP-191 header for `dto`'s canonical JSON (UTF-8 byte length; any `prefix` on it is ignored). */\nfunction personalSignPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n const message = serialize(withoutPrefix);\n return ETHEREUM_SIGNED_MESSAGE + String(new TextEncoder().encode(message).length);\n}\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}\n\ninterface WindowWithGala {\n gala?: GalaWalletProvider;\n}\n\ninterface GlobalWithWindow {\n window?: WindowWithGala;\n}\n\ntype 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(\n 'Gala wallet is not available. Please ensure the Gala wallet is connected.',\n 'GALA_WALLET_NOT_AVAILABLE',\n );\n }\n return wallet;\n}\n\nfunction getNativeSignature(value: unknown): string {\n if (typeof value !== 'string') {\n throw new GSwapSDKError('Wallet returned an invalid signature.', 'INVALID_SIGNATURE');\n }\n if (!/^[0-9a-fA-F]{130}$/u.test(value)) {\n throw new GSwapSDKError('Wallet returned an invalid native signature.', 'INVALID_SIGNATURE');\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(\n 'Wallet returned an invalid personal-sign signature.',\n 'INVALID_SIGNATURE',\n );\n }\n return value;\n}\n\nfunction normalizeEthereumAccount(address: string, allowGalaPrefix: boolean): string {\n const normalized = allowGalaPrefix && address.startsWith('eth|') ? address.slice(4) : address;\n if (!/^0x[0-9a-fA-F]{40}$/u.test(normalized)) {\n throw new GSwapSDKError(\n 'Wallet address must be the selected Ethereum account in 0x-prefixed form.',\n 'VALIDATION_ERROR',\n { type: 'INVALID_WALLET_ADDRESS', value: address },\n );\n }\n return `0x${normalized.slice(2).toLowerCase()}`;\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'string') {\n return error;\n }\n if (typeof error === 'object' && error !== null && 'message' in error) {\n const message = error.message;\n return typeof message === 'string' ? message : '';\n }\n return '';\n}\n\n// Deliberately does NOT match a generic \"invalid params\" (JSON-RPC -32602) — that code fires\n// for many validation failures unrelated to scheme support (e.g. a malformed DTO), and a false\n// match here would permanently latch effectiveScheme to 'personal-sign' for every future call\n// on this signer, even though native signing was never actually unsupported.\nfunction isUnsupportedNativeSchemeError(error: unknown): boolean {\n return /unsupported|unknown scheme/i.test(getErrorMessage(error));\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 */\nfunction signEIP712<T extends Record<string, unknown>>(\n provider: BrowserWalletProvider,\n methodName: string,\n dto: T,\n walletAddress: string,\n): Promise<T & { types: EIP712Types; domain: typeof EIP712_DOMAIN; signature: string }> {\n const { completedDto, types } = buildEIP712Payload(methodName, dto);\n const prefix = personalSignPrefixFor(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: EIP712_DOMAIN,\n types: { ...types, EIP712Domain: eip712Domain },\n primaryType: methodName,\n message,\n };\n\n return provider\n .request({\n method: 'eth_signTypedData_v4',\n params: [walletAddress, JSON.stringify(payload)],\n })\n .then((value) => ({\n ...(message as T & { prefix: string }),\n types,\n domain: EIP712_DOMAIN,\n signature: getPersonalSignature(value),\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 keyBuffer: Buffer;\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.keyBuffer = signatures.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 = signatures.getSignature(dto, this.keyBuffer);\n return Promise.resolve({ ...dto, signature });\n }\n}\n\n/**\n * A Gala Wallet signer using native GalaChain signing, with an opt-in personal-sign mode and\n * automatic fallback for older wallets.\n *\n * The selected Ethereum account is passed to Gala Wallet. Personal-sign resolves the bare\n * `eth|` identity; the legacy EIP-712 `eth_signTypedData` path is not used. The fallback calls\n * `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])`.\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 scheme currently used, including any automatic native-to-personal fallback. */\n public effectiveScheme: 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 selected Ethereum account (`0x` plus 40 hex digits); Gala Wallet's\n * `eth|0x...` form is also accepted and normalized.\n * @param options - Select native signing or personal-sign explicitly.\n */\n constructor(walletAddress: string, options: { scheme?: GalaWalletScheme | undefined } = {}) {\n this.walletAddress = normalizeEthereumAccount(walletAddress, true);\n this.effectiveScheme = options.scheme ?? 'native';\n }\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 if (this.effectiveScheme === 'personal-sign') {\n return personalSign(wallet, dto, this.walletAddress, methodName);\n }\n\n try {\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 } catch (error: unknown) {\n if (!isUnsupportedNativeSchemeError(error)) {\n throw error;\n }\n this.effectiveScheme = 'personal-sign';\n return personalSign(wallet, dto, this.walletAddress, methodName);\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["UNIQUE_KEY_PATTERN","asRecord","malformed","trimTrailingSlash","asRecord","textEncoder","globalObject","isRecord"],"sources":["../../src/utils/confirmation_schedule.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/classes/dex_fees.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/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/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 { GalaChainTokenClassKey } from '../types/token.js';\nimport type { HTTPResponse } from '../types/http_requestor.js';\n\n/** Error raised by the SDK for validation, gateway, chain, or transaction failures. */\nexport class GSwapSDKError extends Error {\n public readonly chainMessage: string | undefined;\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} or\n * {@link userMessage}, so it cannot reach a user interface by accident.\n */\n public readonly bodyText: string | undefined;\n\n constructor(\n message: string,\n public readonly code: string,\n public readonly details?: Record<string, unknown>,\n chainMessage?: string,\n retryAfterMs?: number,\n ) {\n super(message);\n this.name = 'GSwapSDKError';\n this.chainMessage = chainMessage;\n this.retryAfterMs = retryAfterMs;\n const status = details?.['status'];\n this.status = typeof status === 'number' ? status : undefined;\n const body = details?.['body'];\n this.body = typeof body === 'string' ? undefined : body;\n this.bodyText = typeof body === 'string' ? body : undefined;\n }\n\n /**\n * A message that is safe to show a user as is: the server's own message when it sent one\n * (a gateway or chain rejection), a neutral line naming the status for an HTTP failure with no\n * readable answer, and otherwise {@link message}. Apps that word these differently (a\n * \"network busy\" line for a 502, say) branch on {@link code} and {@link status} instead.\n */\n public get userMessage(): string {\n if (this.chainMessage !== undefined && this.chainMessage !== '') return this.chainMessage;\n if (this.code === 'HTTP_ERROR' && this.status !== undefined) {\n return `The server answered with an unexpected response (HTTP ${this.status}).`;\n }\n return this.message;\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 {\n return new GSwapSDKError(\n 'This method requires a signer. Please provide a signer to the GSwap constructor.',\n 'NO_SIGNER',\n );\n }\n\n /** Create the error used when confirming a position write without a configured wallet address. */\n public static noWalletAddressError(): GSwapSDKError {\n return new GSwapSDKError(\n 'Cannot confirm this write: no walletAddress was provided to the GSwap constructor, so ' +\n 'the resulting position cannot be looked up to confirm it landed on chain.',\n 'NO_WALLET_ADDRESS',\n );\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, body and message are kept (the message as `chainMessage`,\n * so {@link userMessage} is the server's own wording).\n */\n public static noPoolAvailableError(\n tokenIn: GalaChainTokenClassKey | string,\n tokenOut: GalaChainTokenClassKey | string,\n fee?: number,\n source?: GSwapSDKError,\n ): GSwapSDKError {\n return new GSwapSDKError(\n 'No pool is available for the requested pair.',\n 'NO_POOL_AVAILABLE',\n { tokenIn, tokenOut, ...(fee === undefined ? {} : { fee }), ...sourceDetails(source) },\n source?.serverMessage,\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 {\n return new GSwapSDKError(\n 'The selected pool has insufficient liquidity for the requested quote.',\n 'INSUFFICIENT_LIQUIDITY',\n { tokenIn, tokenOut, ...(fee === undefined ? {} : { fee }), ...sourceDetails(source) },\n source?.serverMessage,\n );\n }\n\n /**\n * The message the server put in a JSON answer (`message`, or `error.Message`), when this error\n * came from an HTTP response that had one.\n */\n public get serverMessage(): string | undefined {\n const direct = this.details?.['message'];\n if (typeof direct === 'string') return direct;\n const body = this.body;\n const fromBody = getStringProperty(body, 'message') ?? getStringProperty(body, 'Message');\n return fromBody ?? getStringProperty(getObjectProperty(body, 'error'), 'Message');\n }\n\n /** Convert a chain-gateway bounce into a typed SDK error. */\n public static fromGatewayBounce(\n code: string,\n message: string,\n status: number,\n retryAfterMs?: number,\n ): GSwapSDKError {\n const details: Record<string, unknown> = { status, chainMessage: message };\n if (retryAfterMs !== undefined) details['retryAfterMs'] = retryAfterMs;\n const sdkMessage =\n code === 'CHAIN_DISPATCH_FAILED' ? message : `Gateway rejected ${code}: ${message}`;\n return new GSwapSDKError(sdkMessage, code, details, message, retryAfterMs);\n }\n\n /** Convert a GalaChain `Status: 0` response into a typed SDK error. */\n public static fromChainError(\n errorKey: string,\n message: string,\n details?: Record<string, unknown>,\n ): GSwapSDKError {\n return new GSwapSDKError(\n `GalaChain error ${errorKey}: ${message}`,\n errorKey,\n { ...details, errorKey, message },\n message,\n );\n }\n\n /** Create the error used when a token is not registered by the current DEX contract. */\n public static unknownTokenError(token: GalaChainTokenClassKey | string): GSwapSDKError {\n const tokenText = typeof token === 'string' ? token : JSON.stringify(token);\n return new GSwapSDKError(\n `Token ${tokenText} has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`,\n 'UNKNOWN_TOKEN',\n { token },\n );\n }\n\n /** Create the error used when apply-results confirmation does not arrive in time. */\n public static confirmationTimeoutError(uniqueKey: string, cause?: unknown): GSwapSDKError {\n return new GSwapSDKError(\n 'Transaction confirmation timed out; the trade may still apply. Confirm the same uniqueKey again later instead of resubmitting.',\n 'CONFIRMATION_TIMEOUT',\n { uniqueKey, ...(cause === undefined ? {} : { cause }) },\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\n if (errorKey !== undefined && message !== undefined) {\n return new GSwapSDKError(\n `GalaChain Error ${errorKey} from ${url}: ${message}`,\n errorKey,\n { message, errorKey, status: response.status, body: bodyJson, url },\n message,\n );\n }\n\n return new GSwapSDKError(`Unexpected HTTP Error ${response.status} from ${url}`, 'HTTP_ERROR', {\n status: response.status,\n body: bodyJson ?? bodyText,\n url,\n });\n }\n}\n\n/** The HTTP facts of the error a classified error was derived from. */\nfunction sourceDetails(source: GSwapSDKError | undefined): Record<string, unknown> {\n if (source === undefined) return {};\n return {\n ...(source.status === undefined ? {} : { status: source.status }),\n ...(source.body === undefined ? {} : { body: source.body }),\n ...(source.bodyText === undefined ? {} : { body: source.bodyText }),\n };\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.2';\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 VALIDATION_ERROR 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(\n `${name} must be a positive number of milliseconds, or Infinity for no timeout.`,\n 'VALIDATION_ERROR',\n { [name]: timeoutMs },\n );\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\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 if (controller.signal.aborted) {\n throw new GSwapSDKError(`Request timed out after ${timeoutMs} ms.`, 'REQUEST_TIMEOUT', {\n url,\n timeoutMs,\n cause: error,\n });\n }\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 type { WireOptions } from '../types/wire.js';\nimport {\n buildRequestHeaders,\n readBlockNumberHeader,\n readHeader,\n readResponseBody,\n readRetryAfter,\n requestWithTimeout,\n} from '../utils/transport.js';\nimport { getObjectProperty, getStringProperty, GSwapSDKError } from './gswap_sdk_error.js';\n\n/** The apply-results key constraint of the swap backend (`apply-results.dto.ts`). */\nconst UNIQUE_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/u;\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 itself failed (malformed key or body, a\n * non-retryable HTTP status). The outcome is unknown.\n * - anything else: the chain REJECTED the trade; `code` is the chain `ErrorKey` (or\n * `CHAIN_ERROR`) and `chainMessage` is its message, which is also `message`.\n *\n * `details` always carries `uniqueKey` and, where known, `requestTransactionId`,\n * `applyTransactionId`, `blockNumber`, `status`, `body`, `url` and the last transport `cause`.\n */\nexport class AppliedTradeError extends GSwapSDKError {\n constructor(\n message: string,\n code: string,\n details: Record<string, unknown> = {},\n chainMessage?: string,\n ) {\n super(message, code, details, chainMessage);\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 (!UNIQUE_KEY_PATTERN.test(uniqueKey)) {\n throw new AppliedTradeError(\n 'uniqueKey must be 1-128 characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n 'CONFIRMATION_FAILED',\n { uniqueKey },\n );\n }\n const requestor = client.httpRequestor ?? fetch.bind(globalThis);\n const requestTimeoutMs = client.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const signal = options?.signal;\n const abortError = (cause?: unknown): Error =>\n new AppliedTradeError('Transaction confirmation was aborted.', 'CONFIRMATION_ABORTED', {\n uniqueKey,\n ...(cause === undefined ? {} : { cause }),\n });\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(bodyMessage(body), 'CONFIRMATION_FAILED', {\n uniqueKey,\n status: response.status,\n body,\n url,\n });\n }\n\n throw new AppliedTradeError(\n 'Transaction confirmation timed out; the trade may still apply. Confirm the same uniqueKey again later instead of resubmitting.',\n 'CONFIRMATION_TIMEOUT',\n {\n uniqueKey,\n requestTransactionId: input.requestTransactionId,\n url,\n ...(lastError === undefined ? {} : { cause: lastError }),\n },\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 malformed(\n input,\n response,\n body,\n url,\n 'Apply result key did not match the requested key.',\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') ?? 'The chain rejected this trade.';\n throw new AppliedTradeError(\n chainMessage,\n errorKey,\n {\n uniqueKey,\n requestTransactionId: input.requestTransactionId,\n applyTransactionId,\n blockNumber,\n status: response.status,\n body,\n url,\n errorKey,\n message: chainMessage,\n },\n chainMessage,\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 message = 'Transaction confirmation returned a malformed body',\n): AppliedTradeError {\n return new AppliedTradeError(message, 'CONFIRMATION_FAILED', {\n uniqueKey: input.uniqueKey,\n status: response.status,\n body,\n 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 bodyMessage(body: unknown): string {\n return (\n getStringProperty(body, 'message') ??\n getStringProperty(body, 'Message') ??\n getStringProperty(getObjectProperty(body, 'error'), 'message') ??\n getStringProperty(getObjectProperty(body, 'error'), 'Message') ??\n // A body that is not JSON (a proxy's HTML page, an empty body) is in details.body and\n // error.bodyText, never in the message.\n 'Transaction confirmation failed'\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","/**\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 { 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/** Return the greatest integer tick whose token1/token0 price is no greater than `price`. */\nexport function tickFromPrice(price: BigNumber.Value): 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 tick = value.ln().dividedBy(new DexDecimal(1.0001).ln()).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) throw new RangeError(`Unsupported fee tier: ${fee}`);\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new RangeError('Ticks must be integers');\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK || lower >= upper) {\n throw new RangeError(\n `Tick range must satisfy ${GC_MIN_TICK} <= lower < upper <= ${GC_MAX_TICK}`,\n );\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new RangeError(`Ticks must be aligned to spacing ${spacing}`);\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!Number.isInteger(spacing) || spacing <= 0)\n throw new RangeError('Tick spacing must be positive');\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('Cannot invert a non-positive sqrt price.', 'VALIDATION_ERROR', {\n sqrtPrice: slot0.sqrtPrice,\n });\n }\n const sqrtPrice = inverted.toString();\n return { sqrtPrice, tick: sqrtPriceToTick(sqrtPrice) };\n}\n","import BigNumber from 'bignumber.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(\n `Invalid ${parameterName}: use a decimal string or BigNumber, not a JavaScript number`,\n 'VALIDATION_ERROR',\n { type: 'INVALID_NUMERIC_AMOUNT', parameterName, value: amount, reason: 'number_input' },\n );\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(\n `Invalid ${parameterName}: must be a finite number`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'not_finite',\n },\n );\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError(`Invalid ${parameterName}: must be positive`, 'VALIDATION_ERROR', {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'zero_not_allowed',\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: must be ${allowZero ? 'non-negative' : 'positive'}`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_NUMERIC_AMOUNT',\n parameterName,\n value: amount,\n reason: 'negative',\n },\n );\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(\n 'Invalid price values: use decimal strings or BigNumber values, not JavaScript numbers',\n 'VALIDATION_ERROR',\n { type: 'INVALID_NUMERIC_AMOUNT', reason: 'number_input' },\n );\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(\n 'Invalid price values: all prices must be finite and positive',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_PRICE_VALUES',\n spotPrice,\n lowerPrice,\n upperPrice,\n },\n );\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError(\n 'Invalid price range: lower price must be less than or equal to upper price',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_PRICE_RANGE',\n lowerPrice,\n upperPrice,\n },\n );\n }\n}\n\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: must be a non-negative integer`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TOKEN_DECIMALS',\n parameterName,\n value: decimals,\n },\n );\n }\n}\n\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('Invalid tick values: ticks must be integers', 'VALIDATION_ERROR', {\n type: 'INVALID_TICK_VALUES',\n tickLower,\n tickUpper,\n });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError(\n 'Invalid tick range: tickLower must be less than tickUpper',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_RANGE',\n tickLower,\n tickUpper,\n },\n );\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError(\n `Invalid tick range: ticks must be between ${GC_MIN_TICK} and ${GC_MAX_TICK}`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_BOUNDS',\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n },\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(\n 'Invalid fee tier: must be one of 0, 500, 3000, or 10000',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_FEE',\n value: fee,\n },\n );\n }\n}\n\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError(\n 'Invalid tick spacing: must be a positive integer',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_TICK_SPACING',\n value: tickSpacing,\n },\n );\n }\n}\n\nexport function validateWalletAddress(address?: string): asserts address is string {\n if (address === undefined) {\n throw new GSwapSDKError(\n 'Invalid wallet address: No wallet address provided',\n 'VALIDATION_ERROR',\n {\n type: 'MISSING_WALLET_ADDRESS',\n hint: 'Either provide a wallet address to the function you are calling, or set one when instantiating GSwapSDK',\n },\n );\n }\n\n if (!address || typeof address !== 'string' || address.trim().length === 0) {\n throw new GSwapSDKError(\n 'Invalid wallet address: must be a non-empty string',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_WALLET_ADDRESS',\n value: address,\n },\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 VALIDATION_ERROR (`details.type` = `NON_CANONICAL_PAIR`) otherwise.\n */\nexport function assertCanonicalPair(token0: string, token1: string): void {\n if (!(token0 < token1)) {\n throw new GSwapSDKError(\n `The pair ${token0}/${token1} is not in canonical order: token0 must sort before token1.`,\n 'VALIDATION_ERROR',\n { type: 'NON_CANONICAL_PAIR', token0, token1 },\n );\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: must be a positive integer', 'VALIDATION_ERROR', {\n page,\n });\n }\n\n if (!Number.isInteger(limit) || limit < 1 || limit > 100) {\n throw new GSwapSDKError(\n 'Invalid limit: must be an integer between 1 and 100',\n 'VALIDATION_ERROR',\n { limit },\n );\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 'Backend returned an invalid user assets response.',\n 'INVALID_CHAIN_RESPONSE',\n {\n data: value,\n },\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","import type { HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { buildRequestHeaders, readResponseBody, requestWithTimeout } from '../utils/transport.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 signer.signObject(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 ?? fetch.bind(globalThis);\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; any error the signer\n * throws (for example a locked wallet) propagates unchanged.\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 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('Transaction confirmation was aborted.', 'CONFIRMATION_ABORTED', {\n uniqueKey: this.uniqueKey,\n ...(cause === undefined ? {} : { cause }),\n });\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 { getObjectProperty, getStringProperty, GSwapSDKError } from './gswap_sdk_error.js';\nimport type { ShadowSubmitResult } from './shadow_submit.js';\nimport { SubmittedTransaction, type PositionConfirmationResult } from './submitted_transaction.js';\nimport {\n buildRequestHeaders,\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\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 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 ?? fetch.bind(globalThis);\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 }\n\n /** Submit a signed v2 DTO through the chain gateway. */\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(\n 'The synchronous Trade method was removed; swaps are queued through RequestTrade.',\n 'METHOD_NOT_SUPPORTED',\n { method },\n );\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 = await this.post(url, headers, signedBody);\n const body = await readResponseBody(response);\n\n if (!response.ok) {\n throw gatewayError(response, body, url);\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 getStringProperty(envelope, 'message') || 'The gateway reported an error for this write.',\n 'INVALID_GATEWAY_RESPONSE',\n { status: response.status, body, url, type: 'GATEWAY_REPORTED_ERROR' },\n );\n }\n const data = asRecord(envelope?.['data'] ?? envelope?.['Data']);\n if (data === undefined) {\n throw invalidGatewayResponse(response, body, url, 'Expected a data object.');\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 invalidModeMessage =\n 'Gateway response must contain data.mode=\"sync\" with data.result, or data.mode=\"queued\".';\n if (mode !== 'sync' && mode !== 'queued') {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\n }\n if (\n ('transactionId' in data && typeof rawTransactionId !== 'string') ||\n (bodyBlockNumber !== undefined && bodyBlockNumber !== null && !isBlockNumber(bodyBlockNumber))\n ) {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\n }\n if (method === 'RequestTrade' && mode === 'sync') {\n throw invalidGatewayResponse(\n response,\n body,\n url,\n 'The gateway executed RequestTrade synchronously, which this SDK refuses; RequestTrade must be queued.',\n );\n }\n if (method === 'RequestTrade' && mode === 'queued') {\n assertQueuedUnderSignedKey(response, body, url, data, signedBody);\n } else if (mode === 'queued' || !('result' in data)) {\n throw invalidGatewayResponse(response, body, url, invalidModeMessage);\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') ?? 'The chain rejected this write.',\n { status: response.status, body, url },\n );\n }\n }\n }\n\n const uniqueKey = getStringProperty(signedBody, 'uniqueKey') ?? '';\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 transport failure rejects, and a timeout rejects\n * with `SUBMISSION_OUTCOME_UNKNOWN`.\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 if (method === 'Trade') {\n throw new GSwapSDKError(\n 'The synchronous Trade method was removed; swaps are queued through RequestTrade.',\n 'METHOD_NOT_SUPPORTED',\n { method },\n );\n }\n const walletAddress = options?.walletAddress ?? this.walletAddress;\n if (walletAddress === undefined) {\n throw new GSwapSDKError(\n 'A shadow submission needs a walletAddress (the X-Wallet-Address header): pass one to the GSwap constructor or to this call.',\n 'NO_WALLET_ADDRESS',\n );\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 = await this.post(this.writeUrl(method), headers, signedBody);\n return { httpStatus: response.status, body: await readResponseBody(response) };\n }\n\n private writeUrl(method: string): string {\n return `${this.dexBackendBaseUrl}/v1/chain/asset/dex-contract/${method}`;\n }\n\n /** POSTs a signed body; a timeout means the outcome is unknown, never \"not submitted\". */\n private async post(\n url: string,\n headers: Record<string, string>,\n signedBody: Record<string, unknown>,\n ): Promise<HTTPResponse> {\n try {\n return await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers,\n body: JSON.stringify(signedBody),\n },\n this.chainCallTimeoutMs,\n );\n } catch (error: unknown) {\n if (error instanceof GSwapSDKError && error.code === 'REQUEST_TIMEOUT') {\n throw new GSwapSDKError(\n 'The submission outcome is unknown because the gateway request timed out. Confirm before retrying.',\n 'SUBMISSION_OUTCOME_UNKNOWN',\n { uniqueKey: getStringProperty(signedBody, 'uniqueKey') ?? '', cause: error },\n );\n }\n throw error;\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 invalidGatewayResponse(\n response: HTTPResponse,\n body: unknown,\n url: string,\n message: string,\n): GSwapSDKError {\n return new GSwapSDKError(message, 'INVALID_GATEWAY_RESPONSE', {\n status: response.status,\n body,\n url,\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. `INVALID_GATEWAY_RESPONSE`, `details.type` is\n * `MISSING_UNIQUE_KEY` or `UNIQUE_KEY_MISMATCH`, `details.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 throw new GSwapSDKError(\n missing\n ? 'The gateway acknowledged RequestTrade without echoing its uniqueKey, so it cannot be tied to the signed request.'\n : 'Gateway response data.uniqueKey must match the signed RequestTrade uniqueKey.',\n 'INVALID_GATEWAY_RESPONSE',\n {\n status: response.status,\n body,\n url,\n type: missing ? 'MISSING_UNIQUE_KEY' : 'UNIQUE_KEY_MISMATCH',\n uniqueKey: signedUniqueKey,\n },\n );\n}\n\nfunction gatewayError(response: HTTPResponse, body: unknown, url: string): GSwapSDKError {\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 const message =\n getStringProperty(object, 'message') ??\n getStringProperty(nested, 'message') ??\n getStringProperty(nested, 'Message') ??\n // A body that is not JSON (an HTML 502 page, a WAF block) is kept as details.body /\n // error.bodyText and never becomes the message.\n `Gateway request failed with HTTP ${response.status}`;\n const retryAfterMs = response.status === 429 ? readRetryAfter(response) : undefined;\n if (code === 'HTTP_ERROR') {\n return new GSwapSDKError(message, code, { status: response.status, body, url });\n }\n return GSwapSDKError.fromGatewayBounce(code, message, response.status, retryAfterMs);\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 Error(\n 'GdexStreamService requires a standards-compatible WebSocket constructor. ' +\n 'Node.js versions before 22 must provide one with config.webSocketImpl (for example, from the \"ws\" package).',\n );\n }\n this.webSocketConstructor = implementation as WebSocketConstructor;\n if (config.apiKey !== undefined) {\n if (config.apiKey === '' || config.webSocketImpl === undefined) {\n throw new GSwapSDKError(\n 'GdexStreamConfig.apiKey needs a non-empty key and an explicit webSocketImpl that accepts ' +\n 'upgrade headers as its third argument (the \"ws\" package, or React Native). A browser ' +\n 'WebSocket cannot send x-api-key, so the key would be silently dropped.',\n 'VALIDATION_ERROR',\n );\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 Error('GDEX 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 Error('GDEX stream is not connected. Call connect() first.'));\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(new Error(`GDEX request \"${method}\" timed out after ${this.requestTimeoutMs}ms`));\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 Error(`Failed to connect to GDEX stream at ${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 Error(`GDEX stream closed before connecting (code ${event.code ?? 0})`));\n this.rejectPending(new Error(`GDEX stream connection closed (code ${event.code ?? 0})`));\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 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 = fetch,\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 `Backend returned an invalid ${source} list.`,\n 'INVALID_CHAIN_RESPONSE',\n {\n data,\n },\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('Unable to order trading symbols.', 'VALIDATION_ERROR', { value });\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 delimiter = tokenClassKey.includes('|') ? '|' : '$';\n const segments = tokenClassKey.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 throw new GSwapSDKError(\n 'Invalid token class key: expected a collection followed by category, type and additionalKey',\n 'VALIDATION_ERROR',\n {\n tokenClassKey,\n },\n );\n }\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","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 { 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 `VALIDATION_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(\n `No valid trading symbol for token class ${wanted}: \"${displaySymbol}\" is not an acceptable symbol and none is registered`,\n 'VALIDATION_ERROR',\n { classKey, displaySymbol },\n );\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 resolver.resolve(ref);\n if (resolved.symbol.length > 0) return resolved.symbol;\n throw new GSwapSDKError('Token could not be resolved to a trading symbol.', 'SYMBOL_NOT_FOUND', {\n token: ref,\n });\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('Pool request failed.', 'HTTP_ERROR', { 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(\n `search must be at most ${MAX_SEARCH_LENGTH} characters.`,\n 'VALIDATION_ERROR',\n { search: options.search },\n );\n }\n params['search'] = options.search;\n }\n if (options.sortBy !== undefined) {\n if (!SORT_KEYS.includes(options.sortBy)) {\n throw new GSwapSDKError(\n `sortBy must be one of ${SORT_KEYS.join(', ')}.`,\n 'VALIDATION_ERROR',\n { sortBy: options.sortBy },\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('sortOrder must be asc or desc.', 'VALIDATION_ERROR', {\n sortOrder: options.sortOrder,\n });\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('page must be an integer of at least 1.', 'VALIDATION_ERROR', {\n page: options.page,\n });\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(\n `limit must be an integer from 1 to ${MAX_PAGE_SIZE}.`,\n 'VALIDATION_ERROR',\n { limit: options.limit },\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';\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 VALIDATION_ERROR when the prefix has characters outside `A-Za-z0-9._:-` or\n * 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(\n `uniqueKeyPrefix must be at most ${MAX_UNIQUE_KEY_PREFIX_LENGTH} characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".`,\n 'VALIDATION_ERROR',\n { uniqueKeyPrefix: prefix },\n );\n }\n return prefix;\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 * 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 VALIDATION_ERROR otherwise.\n */\nexport function assertUniqueKey(uniqueKey: string): void {\n if (typeof uniqueKey !== 'string' || !UNIQUE_KEY_PATTERN.test(uniqueKey)) {\n throw new GSwapSDKError(\n 'uniqueKey must be 1-128 characters of A-Z, a-z, 0-9, \".\", \"_\", \":\" or \"-\".',\n 'VALIDATION_ERROR',\n { uniqueKey },\n );\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('exactIn is required for an exact-input swap.', 'VALIDATION_ERROR');\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('exactOut is required for an exact-output swap.', 'VALIDATION_ERROR');\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(\n 'Provide exactly one of depositQuantityToken0 or depositQuantityToken1.',\n 'VALIDATION_ERROR',\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(\n 'Invalid trading symbol: must be 1-32 ASCII letters and digits and not a reserved word (Token, Unit, none).',\n 'VALIDATION_ERROR',\n { symbol },\n );\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(\n 'Provide exactly one of startingPrice or startingSqrtPrice.',\n 'VALIDATION_ERROR',\n );\n }\n if (typeof price.amount === 'number') {\n throw new GSwapSDKError(\n `Invalid ${price.name}: use a decimal string or BigNumber, not a JavaScript number`,\n 'VALIDATION_ERROR',\n );\n }\n const parsed = new BigNumber(price.amount);\n if (!parsed.isFinite() || parsed.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('Starting price must be finite and positive.', 'VALIDATION_ERROR');\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(`Token class key is missing ${part}.`, 'VALIDATION_ERROR', {\n key,\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 a `VALIDATION_ERROR`, and so is 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 new GSwapSDKError(\n allowNeither\n ? `Provide at most one of ${firstName} or ${secondName}.`\n : `Provide exactly one of ${firstName} or ${secondName}.`,\n 'VALIDATION_ERROR',\n );\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\nfunction invalidDto(method: string, field: string, expected: string): GSwapSDKError {\n return new GSwapSDKError(\n `${method} DTO field ${field} must be ${expected}.`,\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_DTO',\n method,\n field,\n },\n );\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, 'a 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, 'a 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, 'a 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}`, 'a 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', 'present 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', 'an array of strings');\n }\n if (dto['isPrivate'] !== undefined && typeof dto['isPrivate'] !== 'boolean') {\n throw invalidDto(method, 'isPrivate', 'a 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 VALIDATION_ERROR (`details.type` = `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(\n `The ${method} DTO is not in the form the SDK builders produce; build it with the matching build function and submit that.`,\n 'VALIDATION_ERROR',\n { type: 'DTO_NOT_CANONICAL', method },\n );\n }\n}\n","import BigNumber from 'bignumber.js';\nimport { GSwapSDKError } 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 {\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:\n error instanceof GSwapSDKError\n ? error\n : new GSwapSDKError('Position request failed.', 'HTTP_ERROR', { 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.symbols.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.symbols.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('Price bounds must be finite and positive.', 'VALIDATION_ERROR');\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError(\n 'minPrice must be less than or equal to maxPrice.',\n 'VALIDATION_ERROR',\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.symbols.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('Provide at most one of amount0 or amount1.', 'VALIDATION_ERROR');\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.symbols.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 * VALIDATION_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(\n 'Provide exactly one of startingPrice or startingSqrtPrice.',\n 'VALIDATION_ERROR',\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('Starting price must be finite and positive.', 'VALIDATION_ERROR');\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 this.signer.signObject(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 if (!(error instanceof GSwapSDKError) || error.details === undefined) return false;\n return error.details['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(`Unsupported fee tier: ${fee}.`, 'VALIDATION_ERROR');\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError(\n `Invalid ${parameterName}: use a decimal string or BigNumber, not a JavaScript number`,\n 'VALIDATION_ERROR',\n );\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 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 this.symbols.resolve(lookupRef);\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError(\n `Supplied symbol ${symbolOverride} disagrees with the registered trading symbol ${resolved.symbol}.`,\n 'VALIDATION_ERROR',\n { token: ref, suppliedSymbol: symbolOverride, 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(\n 'createPool needs each token as a class key; a bare trading symbol does not carry one.',\n 'VALIDATION_ERROR',\n { token: ref },\n );\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(\n '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 'VALIDATION_ERROR',\n { token: ref },\n );\n }\n if (!isProposableTradingSymbol(symbolOverride)) {\n throw new GSwapSDKError(\n 'Invalid trading symbol: must be 1-32 ASCII letters and digits and not a reserved word (Token, Unit, none).',\n 'VALIDATION_ERROR',\n { symbol: symbolOverride },\n );\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('Backend returned an invalid position.', 'INVALID_CHAIN_RESPONSE', {\n data,\n reason: parsed.reason,\n });\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 { GSwapSDKError } 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 }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError('Backend returned an invalid quote.', 'INVALID_CHAIN_RESPONSE', {\n data: value,\n });\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: a token the DEX contract never\n * registered (\"has no trading symbol on the new DEX contract\"), no pool at ANY fee tier (\"No\n * pools found with sufficient liquidity\"), or a missing pool (\"Pool does not exist on the new\n * DEX contract\"). A pool that exists but is too thin says \"Insufficient liquidity: ...\" instead.\n */\nconst NO_MARKET_MESSAGE =\n /no pool|no pools|pool does not exist|has no trading symbol on the new DEX contract/iu;\n\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n): GSwapSDKError {\n if (error instanceof GSwapSDKError) {\n const status = readStatus(error.details);\n const message = readMessage(error.details) ?? error.message;\n if (status === 404 || NO_MARKET_MESSAGE.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee, error);\n }\n if (status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee, error);\n }\n return error;\n }\n return new GSwapSDKError('Quote request failed.', 'HTTP_ERROR', {\n cause: error,\n tokenIn,\n tokenOut,\n fee,\n });\n}\n\nfunction readStatus(details: Record<string, unknown> | undefined): number | undefined {\n const status = details?.['status'];\n return typeof status === 'number' ? status : undefined;\n}\n\nfunction readMessage(details: Record<string, unknown> | undefined): string | undefined {\n const direct = details?.['message'];\n if (typeof direct === 'string') return direct;\n const body = details?.['body'];\n if (typeof body !== 'object' || body === null || Array.isArray(body)) return undefined;\n const message = (body as Record<string, unknown>)['message'];\n return typeof message === 'string' ? message : undefined;\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 tier: ${fee}`, 'VALIDATION_ERROR', { fee });\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 type ShadowSubmitCode =\n 'SHADOW_UNAVAILABLE' | 'SHADOW_DISABLED' | 'SHADOW_UNSUPPORTED_TYPE' | 'SHADOW_RELAY_REJECTED';\n\n/** The normalized outcome of a shadow write. */\nexport type ShadowSubmitOutcome =\n | {\n ok: true;\n /** The request transaction id (`''` when the gateway gave none). */\n bundleId: string;\n /** Present for a queued RequestTrade: confirm with `confirmAppliedTrade`. */\n queued?: { uniqueKey: string; requestTransactionId: string | null };\n }\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\ntype ShadowFailureKind = Exclude<ShadowSubmitOutcome, { ok: true }>['kind'];\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.\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 INVALID_GATEWAY_RESPONSE 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: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome {\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 `The swap backend did not queue the request ${typeof requestedKey === 'string' ? requestedKey : ''}.`,\n 'INVALID_GATEWAY_RESPONSE',\n { httpStatus, body },\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 { 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.\n *\n * @example\n * ```ts\n * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * if (outcome.ok && outcome.queued) 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 this.submitSwapShadow(await this.buildSwap(tokenIn, tokenOut, fee, amount, options));\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 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 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 this.signer.signObject('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(\n 'tokenIn and tokenOut must be the two tokens of the pinned pool.',\n 'VALIDATION_ERROR',\n { type: 'POOL_MISMATCH', tokenIn: tokenInSymbol, tokenOut: tokenOutSymbol, pool },\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","/** 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/** 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/** Options for {@link PendingSwapStore}. */\nexport interface PendingSwapStoreOptions {\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 * - 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 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 }\n\n /** Saves (or replaces, by `uniqueKey`) a pending swap. */\n public remember(swap: PendingSwap): Promise<void> {\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 /** The wallet's unexpired pending swaps (see `listOrder`). Expired entries are pruned. */\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 fresh = current.filter((entry) => now - entry.createdAt < PENDING_SWAP_EXPIRY_MS);\n if (fresh.length !== current.length) {\n await storage.set(this.storageKey, fresh.map(this.toStored));\n }\n const mine = fresh.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 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 Error('Name collisions not yet supported');\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 Error(\n `Unsupported type, ${typeof fieldValue}, value: ${Object.prototype.toString.call(fieldValue)}`,\n );\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('Wallet returned an invalid chain id.', 'INVALID_CHAIN_ID', {\n 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 { 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: string): GSwapSDKError {\n return new GSwapSDKError(`Invalid private key: ${reason}`, 'VALIDATION_ERROR', {\n type: 'INVALID_PRIVATE_KEY',\n });\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 (`VALIDATION_ERROR`) for any other shape or 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('expected exactly 32 bytes.');\n }\n if (!secp256k1.utils.isValidSecretKey(input)) {\n throw invalidPrivateKey('not a valid secp256k1 scalar.');\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('expected 64 hex characters or a 44-character base64 string.');\n }\n if (!secp256k1.utils.isValidSecretKey(key)) {\n throw invalidPrivateKey('not a valid secp256k1 scalar.');\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(\n `secp256k1 can only sign a 32-byte hash (got ${hash.length}).`,\n 'VALIDATION_ERROR',\n );\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 } 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\ntype 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(\n 'Gala wallet is not available. Please ensure the Gala wallet is connected.',\n 'GALA_WALLET_NOT_AVAILABLE',\n );\n }\n return wallet;\n}\n\nfunction getNativeSignature(value: unknown): string {\n if (typeof value !== 'string') {\n throw new GSwapSDKError('Wallet returned an invalid signature.', 'INVALID_SIGNATURE');\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('Wallet returned an invalid native signature.', 'INVALID_SIGNATURE');\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(\n 'Wallet returned an invalid personal-sign signature.',\n 'INVALID_SIGNATURE',\n );\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(\n 'Wallet address must be the selected Ethereum account in 0x-prefixed form.',\n 'VALIDATION_ERROR',\n { type: 'INVALID_WALLET_ADDRESS', value: address },\n );\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(\n 'Wallet address must be the selected Ethereum account (0x plus 40 hex digits, or eth|...) or a GalaChain id (client|... or 24 hex digits).',\n 'VALIDATION_ERROR',\n { type: 'INVALID_WALLET_ADDRESS', value: address },\n );\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(\n 'selectAddress must be an eth| or client| identity, or an account in one of the accepted forms.',\n 'VALIDATION_ERROR',\n { type: 'INVALID_WALLET_ADDRESS', value: identity },\n );\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 * 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` is\n * passed through unchanged, so the app's own \"wallet is locked\" error reaches its caller; a key\n * that is not a valid secp256k1 key string is a `VALIDATION_ERROR` (`INVALID_PRIVATE_KEY`).\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 getPrivateKey();\n if (typeof provided !== 'string') {\n throw new GSwapSDKError(\n 'Invalid private key: the provider returned no key.',\n 'VALIDATION_ERROR',\n {\n type: 'INVALID_PRIVATE_KEY',\n },\n );\n }\n const key = normalizePrivateKey(provided);\n try {\n if (expectedLower !== undefined && ethAddressOfPrivateKey(key) !== expectedLower) {\n throw new GSwapSDKError(\n 'The signing key does not belong to the expected account.',\n 'SIGNER_ADDRESS_MISMATCH',\n );\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\nfunction refusePersonalSign(message: string, type: string): never {\n throw new GSwapSDKError(message, 'INVALID_PERSONAL_SIGN_DTO', { type });\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` `INVALID_PERSONAL_SIGN_DTO`, message text identical to the\n * wallet's) on: 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 return refusePersonalSign('Personal-sign DTO is not valid JSON', 'NOT_JSON');\n }\n if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return refusePersonalSign('Personal-sign DTO must be a JSON object', '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 return refusePersonalSign(\n 'Personal-sign DTO prefix is not an EIP-191 \"Ethereum Signed Message\" header',\n 'BAD_PREFIX',\n );\n }\n const forbidden = PERSONAL_SIGN_FORBIDDEN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(withoutPrefix, field),\n );\n if (forbidden.length > 0) {\n return refusePersonalSign(\n `Personal-sign DTO carries signing-envelope field(s): ${forbidden.join(', ')}`,\n 'ENVELOPE_FIELDS',\n );\n }\n if (serialize(dto) !== data) {\n return refusePersonalSign(\n 'Personal-sign DTO is not in canonical serialized form',\n 'NOT_CANONICAL',\n );\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 (`INVALID_PERSONAL_SIGN_DTO`) before any 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 (`VALIDATION_ERROR`) 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 quantity: ${String(value)}`, 'VALIDATION_ERROR', {\n type: 'INVALID_DECIMAL',\n });\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;\nconst MAX_UINT256 = (1n << 256n) - 1n;\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 refuse(message: string, details?: Record<string, unknown>): never {\n throw new GSwapSDKError(`Invalid typed data: ${message}`, 'INVALID_TYPED_DATA', details);\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 let rest = value < 0n ? value + (1n << 256n) : value;\n if (rest < 0n || rest > MAX_UINT256) return refuse('integer does not fit in 256 bits');\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 return refuse(`${what} must be an even-length 0x hex string`);\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)) return refuse(`${what} must be a safe integer`);\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 return refuse(`${what} must be an integer`);\n}\n\nfunction utf8(value: unknown, what: string): Uint8Array {\n if (typeof value !== 'string') return refuse(`${what} must be a string`);\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)) return refuse(`${what} has an unpaired surrogate`);\n index += 1;\n } else if (unit >= 0xdc00 && unit <= 0xdfff) {\n return refuse(`${what} has an unpaired surrogate`);\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 return refuse('address must be 0x followed by 40 hex digits');\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) return refuse('address has a 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') return refuse('bool must be a 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) return refuse(`${base} must be exactly ${width} bytes`);\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) return refuse(`value out of bounds for ${base}`);\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) return refuse(`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)) return refuse(`type ${typeName} must be a list of fields`);\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 return refuse(`type ${typeName} has a field without a string name and type`);\n }\n if (!IDENTIFIER.test(field.name)) return refuse(`invalid field name \"${field.name}\"`);\n if (seen.has(field.name)) return refuse(`duplicate field \"${field.name}\" in ${typeName}`);\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)) return refuse(`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) return refuse(`circular type reference in ${name}`);\n if (leafEncoder(base) !== undefined) continue;\n if (!fields.has(base)) return refuse(`unknown type \"${base}\" in ${name}`);\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) return refuse('missing primary type');\n if (roots.length > 1) return refuse('ambiguous primary types or unused types', { roots });\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)) return refuse(`circular type reference at ${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)) return refuse(`${parsed.base} array value must be an array`);\n if (dimension !== -1 && dimension !== value.length) return refuse('array length mismatch');\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) return refuse(`unknown type \"${typeName}\"`);\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return refuse(`${typeName} value must be an object`);\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 return refuse(`${typeName} value is missing 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 return refuse('domain must be an object');\n }\n for (const key of Object.keys(domain)) {\n if (!DOMAIN_FIELDS.some((field) => field.name === key)) {\n return refuse(`invalid typed-data domain 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 (`INVALID_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('The request failed before the server answered.', 'TRANSPORT_ERROR', {\n url,\n });\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.\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 if ((init?.method ?? 'GET').toUpperCase() === 'POST') {\n const body: unknown = typeof init?.body === 'string' ? JSON.parse(init.body) : undefined;\n return toHttpResponse(await instance.post(uri, body, config), uri);\n }\n return toHttpResponse(await instance.get(uri, config), uri);\n };\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 * The message of the `WALLET_UNAVAILABLE` error raised when a request needs the provider and\n * there is none (no wallet connected). Default: \"No wallet is connected.\"\n */\n unavailableMessage?: 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(`Wallet ${method} request is malformed.`, 'MALFORMED_WALLET_REQUEST', {\n method,\n });\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(\n options.unavailableMessage ?? 'No wallet is connected.',\n 'WALLET_UNAVAILABLE',\n );\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(\n `Unsupported wallet method ${method}.`,\n 'UNSUPPORTED_WALLET_METHOD',\n { method },\n );\n }\n },\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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"}
|