@gala-chain/gswap-sdk 2.0.0 → 2.1.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -2
- package/dist/browser/classes/apply_results.js.map +1 -1
- package/dist/browser/classes/assets.js.map +1 -1
- package/dist/browser/classes/dex_fees.js +1 -1
- package/dist/browser/classes/dex_fees.js.map +1 -1
- package/dist/browser/classes/gateway.js +1 -1
- package/dist/browser/classes/gateway.js.map +1 -1
- package/dist/browser/classes/gdex_stream.js +1 -1
- package/dist/browser/classes/gdex_stream.js.map +1 -1
- package/dist/browser/classes/gswap.js +1 -1
- package/dist/browser/classes/gswap.js.map +1 -1
- package/dist/browser/classes/gswap_error_catalog.js +1 -1
- package/dist/browser/classes/gswap_error_catalog.js.map +1 -1
- package/dist/browser/classes/gswap_error_phase_table.js +1 -1
- package/dist/browser/classes/gswap_error_phase_table.js.map +1 -1
- package/dist/browser/classes/gswap_sdk_error.js +1 -1
- package/dist/browser/classes/gswap_sdk_error.js.map +1 -1
- package/dist/browser/classes/http_client.js.map +1 -1
- package/dist/browser/classes/leaderboard.js.map +1 -1
- package/dist/browser/classes/market.js.map +1 -1
- package/dist/browser/classes/onramper.js.map +1 -1
- package/dist/browser/classes/pending_swap_fate.js.map +1 -1
- package/dist/browser/classes/pending_swaps.js +1 -1
- package/dist/browser/classes/pending_swaps.js.map +1 -1
- package/dist/browser/classes/pools.js +1 -1
- package/dist/browser/classes/pools.js.map +1 -1
- package/dist/browser/classes/positions.js +1 -1
- package/dist/browser/classes/positions.js.map +1 -1
- package/dist/browser/classes/quoting.js +1 -1
- package/dist/browser/classes/quoting.js.map +1 -1
- package/dist/browser/classes/shadow_submit.js.map +1 -1
- package/dist/browser/classes/storage_adapters.js.map +1 -1
- package/dist/browser/classes/submitted_transaction.js +1 -1
- package/dist/browser/classes/submitted_transaction.js.map +1 -1
- package/dist/browser/classes/swaps.js +1 -1
- package/dist/browser/classes/swaps.js.map +1 -1
- package/dist/browser/classes/symbols.js +1 -1
- package/dist/browser/classes/symbols.js.map +1 -1
- package/dist/browser/types/env.js.map +1 -1
- package/dist/browser/types/fees.js.map +1 -1
- package/dist/browser/types/market.js.map +1 -1
- package/dist/browser/utils/chain_contract.js +2 -0
- package/dist/browser/utils/chain_contract.js.map +1 -0
- package/dist/browser/utils/classification.js.map +1 -1
- package/dist/browser/utils/confirmation_schedule.js.map +1 -1
- package/dist/browser/utils/confirmation_state.js.map +1 -1
- package/dist/browser/utils/debug.js.map +1 -1
- package/dist/browser/utils/dto_builders.js.map +1 -1
- package/dist/browser/utils/failure_classification.js +1 -1
- package/dist/browser/utils/failure_classification.js.map +1 -1
- package/dist/browser/utils/failure_guards.js +1 -1
- package/dist/browser/utils/failure_guards.js.map +1 -1
- package/dist/browser/utils/lenient.js.map +1 -1
- package/dist/browser/utils/ordering.js.map +1 -1
- package/dist/browser/utils/reconnection.js +1 -1
- package/dist/browser/utils/reconnection.js.map +1 -1
- package/dist/browser/utils/resolve_pre_send.js.map +1 -1
- package/dist/browser/utils/server_message.js.map +1 -1
- package/dist/browser/utils/shadow_errors.js.map +1 -1
- package/dist/browser/utils/submit_state.js.map +1 -1
- package/dist/browser/utils/tick_align.js.map +1 -1
- package/dist/browser/utils/tick_math.js.map +1 -1
- package/dist/browser/utils/tick_range.js.map +1 -1
- package/dist/browser/utils/ticks.js.map +1 -1
- package/dist/browser/utils/validation.js.map +1 -1
- package/dist/index.cjs +23 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.mjs +23 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/defineProperty.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/toPrimitive.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/toPropertyKey.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/typeof.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pools.js","names":["_defineProperty","Pools","gateway","symbols","options","HttpClient","response","poolListParams","readEntries","parsePoolListInfo","intervalMs","GSwapSDKError","known","stopped","polling","report","error","wanted","pool","poll","pools","onPool","timer","validateFee","fee","token0","token1","rawTokenOf","first","tradingSymbolOf","second","ordered","readOrderedSymbols","orderSymbols","queryTokenOf","endpoint","params","isGSwapError","SORT_KEYS","MAX_PAGE_SIZE","\"search\"","\"sortBy\"","\"sortOrder\"","\"page\"","\"limit\"","OPTIONAL_POOL_STRINGS","OPTIONAL_POOL_NUMBERS","NUMERIC_POOL_FIELDS","row","asEntryRecord","entry","entryRejected","key","\"contractVersion\"","normalized","raw","value","finiteNumberOf","entryOk"],"sources":["../../../src/classes/pools.ts"],"sourcesContent":["import type { FEE_TIER } from '../types/fees.js';\nimport type { CompositePool, PoolInfo, PoolListInfo, Slot0 } from '../types/v2_results.js';\nimport type { WireOptions } from '@gala-chain/gala-core-sdk';\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, isGSwapError } 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/** Options of {@link Pools.watchNewPools}. */\nexport interface WatchNewPoolsOptions {\n /** Milliseconds between polls (default 30 000; a finite number of at least 1). */\n intervalMs?: number | undefined;\n /** Report only a pool whose `tvlUsd` is at least this (a pool without `tvlUsd` counts as 0). */\n minTvl?: number | undefined;\n /** Report only a pool with one of these symbols as `token0` or `token1`. */\n tokens?: readonly string[] | undefined;\n /** Told about a poll that failed and about an `onPool` that threw; polling goes on either way. */\n onError?: ((error: unknown) => void) | 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 * Watches for pools created from now on, by polling {@link Pools.getPools} every `intervalMs`\n * (the polling alternative to the realtime stream's `GSwap.stream.subscribePoolCreated`, for a\n * client that cannot hold a WebSocket open). The first answer is the baseline: a pool that\n * existed then is never reported. Each later pool is judged once, when it first appears, against\n * `minTvl` and `tokens`. A poll never overlaps the previous one (a tick that finds one still in\n * flight is skipped), and nothing is reported after the returned function stops the watcher.\n *\n * @example\n * ```ts\n * const stop = gSwap.pools.watchNewPools((pool) => console.log('new pool', pool.poolRef), {\n * intervalMs: 60_000,\n * tokens: ['GALA'],\n * });\n * // later\n * stop();\n * ```\n */\n public watchNewPools(\n onPool: (pool: PoolListInfo) => void,\n options: WatchNewPoolsOptions = {},\n ): () => void {\n const intervalMs = options.intervalMs ?? 30_000;\n if (typeof intervalMs !== 'number' || !Number.isFinite(intervalMs) || intervalMs < 1) {\n throw new GSwapSDKError('INVALID_POLL_INTERVAL', { value: String(intervalMs) });\n }\n let known: Set<string> | undefined;\n let stopped = false;\n let polling = false;\n const report = (error: unknown): void => {\n try {\n options.onError?.(error);\n } catch {\n // A diagnostics hook must not stop the watcher.\n }\n };\n const wanted = (pool: PoolListInfo): boolean =>\n (options.minTvl === undefined || (pool.tvlUsd ?? 0) >= options.minTvl) &&\n (options.tokens === undefined ||\n options.tokens.includes(pool.token0) ||\n options.tokens.includes(pool.token1));\n const poll = async (): Promise<void> => {\n if (stopped || polling) return;\n polling = true;\n try {\n const pools = await this.getPools();\n if (known === undefined) {\n known = new Set(pools.map((pool) => pool.poolRef));\n return;\n }\n for (const pool of pools) {\n if (stopped) return;\n if (known.has(pool.poolRef)) continue;\n known.add(pool.poolRef);\n if (!wanted(pool)) continue;\n try {\n onPool(pool);\n } catch (error: unknown) {\n report(error);\n }\n }\n } catch (error: unknown) {\n if (!stopped) report(error);\n } finally {\n polling = false;\n }\n };\n void poll();\n const timer = setInterval(() => void poll(), intervalMs);\n return () => {\n stopped = true;\n clearInterval(timer);\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 // Any SDK error passes through, core's transport errors (`REQUEST_TIMEOUT`,\n // `TRANSPORT_ERROR`, a plain `GalaSDKError`) included: only a foreign failure is wrapped.\n if (isGSwapError(error)) throw error;\n throw new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'pool' },\n { cause: error, write: false },\n );\n }\n }\n}\n\nconst SORT_KEYS: readonly string[] = ['tvl', 'volume1d', 'volume30d'];\nconst MAX_SEARCH_LENGTH = 64;\nconst MAX_PAGE_SIZE = 1000;\n\n/** The pool-list query, in the order the apps write it: search, sortBy, sortOrder, page, limit. */\nfunction poolListParams(options: PoolListOptions | undefined): Record<string, string> | undefined {\n if (options === undefined) return undefined;\n const params: Record<string, string> = {};\n if (options.search !== undefined) {\n if (options.search.length > MAX_SEARCH_LENGTH) {\n throw new GSwapSDKError('SEARCH_TOO_LONG', {\n length: options.search.length,\n maxLength: MAX_SEARCH_LENGTH,\n });\n }\n params['search'] = options.search;\n }\n if (options.sortBy !== undefined) {\n if (!SORT_KEYS.includes(options.sortBy)) {\n throw new GSwapSDKError('INVALID_SORT_BY', {\n value: String(options.sortBy),\n allowed: SORT_KEYS.join(','),\n });\n }\n params['sortBy'] = options.sortBy;\n }\n if (options.sortOrder !== undefined) {\n if (options.sortOrder !== 'asc' && options.sortOrder !== 'desc') {\n throw new GSwapSDKError('INVALID_SORT_ORDER', { value: String(options.sortOrder) });\n }\n params['sortOrder'] = options.sortOrder;\n }\n if (options.page !== undefined) {\n if (!Number.isInteger(options.page) || options.page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: options.page });\n }\n params['page'] = String(options.page);\n }\n if (options.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > MAX_PAGE_SIZE) {\n throw new GSwapSDKError('INVALID_LIMIT', {\n value: options.limit,\n min: 1,\n max: MAX_PAGE_SIZE,\n });\n }\n params['limit'] = String(options.limit);\n }\n return Object.keys(params).length === 0 ? undefined : params;\n}\n\nconst OPTIONAL_POOL_STRINGS = [\n 'poolName',\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'creator',\n 'price',\n 'sqrtPrice',\n 'token0Tvl',\n 'token1Tvl',\n] as const;\n\nconst OPTIONAL_POOL_NUMBERS = [\n 'tickSpacing',\n 'protocolFees',\n 'tradingFees',\n 'tick',\n 'volume1d',\n 'volume7d',\n 'volume30d',\n 'trades1d',\n 'fee24h',\n 'token0Price',\n 'token1Price',\n] as const;\n\n/** Fields the apps accept as a number or a numeric string (the wallet does `Number(row.x)`). */\nconst NUMERIC_POOL_FIELDS = ['fee', 'tvlUsd', 'apr1d'] as const;\n\n/**\n * Reads one pool-list row the way the apps do: the identity (`token0`, `token1`, `poolRef`) and\n * `fee` must be usable, every other field is optional but, when present, must have its type.\n * `fee`, `tvlUsd` and `apr1d` may arrive as numeric strings and are returned as numbers. Fields\n * the SDK does not know are kept.\n */\nfunction parsePoolListInfo(entry: unknown): EntryParse<PoolListInfo> {\n const row = asEntryRecord(entry);\n if (row === undefined) return entryRejected('the row is not an object');\n for (const key of ['token0', 'token1', 'poolRef'] as const) {\n if (typeof row[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n if (row['contractVersion'] !== undefined && row['contractVersion'] !== 'v2') {\n return entryRejected('contractVersion is not v2');\n }\n const normalized: Record<string, unknown> = { ...row };\n for (const key of NUMERIC_POOL_FIELDS) {\n const raw = row[key];\n if (raw === undefined && key !== 'fee') continue;\n const value = finiteNumberOf(raw);\n if (value === undefined) return entryRejected(`${key} is not a number`);\n normalized[key] = value;\n }\n for (const key of OPTIONAL_POOL_STRINGS) {\n if (row[key] !== undefined && typeof row[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n for (const key of OPTIONAL_POOL_NUMBERS) {\n const value = row[key];\n if (value !== undefined && (typeof value !== 'number' || !Number.isFinite(value))) {\n return entryRejected(`${key} is not a number`);\n }\n }\n return entryOk(normalized as unknown as PoolListInfo);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pools.js","names":["_defineProperty","Pools","gateway","symbols","options","HttpClient","response","poolListParams","readEntries","parsePoolListInfo","intervalMs","GSwapSDKError","known","stopped","polling","report","error","wanted","pool","poll","pools","onPool","timer","validateFee","fee","token0","token1","rawTokenOf","first","tradingSymbolOf","second","ordered","readOrderedSymbols","orderSymbols","queryTokenOf","endpoint","params","isGSwapError","SORT_KEYS","MAX_PAGE_SIZE","\"search\"","\"sortBy\"","\"sortOrder\"","\"page\"","\"limit\"","OPTIONAL_POOL_STRINGS","OPTIONAL_POOL_NUMBERS","NUMERIC_POOL_FIELDS","row","asEntryRecord","entry","entryRejected","key","\"contractVersion\"","normalized","raw","value","finiteNumberOf","entryOk"],"sources":["../../../src/classes/pools.ts"],"sourcesContent":["import type { FEE_TIER } from '../types/fees.js';\nimport type { CompositePool, PoolInfo, PoolListInfo, Slot0 } from '../types/v2_results.js';\nimport type { WireOptions } from '@gala-chain/gala-core-sdk';\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, isGSwapError } 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/** Options of {@link Pools.watchNewPools}. */\nexport interface WatchNewPoolsOptions {\n /** Milliseconds between polls (default 30 000; a finite number of at least 1). */\n intervalMs?: number | undefined;\n /** Report only a pool whose `tvlUsd` is at least this (a pool without `tvlUsd` counts as 0). */\n minTvl?: number | undefined;\n /** Report only a pool with one of these symbols as `token0` or `token1`. */\n tokens?: readonly string[] | undefined;\n /** Told about a poll that failed and about an `onPool` that threw; polling goes on either way. */\n onError?: ((error: unknown) => void) | 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 * Watches for pools created from now on, by polling {@link Pools.getPools} every `intervalMs`\n * (the polling alternative to the realtime stream's `GSwap.stream.subscribePoolCreated`, for a\n * client that cannot hold a WebSocket open). The first answer is the baseline: a pool that\n * existed then is never reported. Each later pool is judged once, when it first appears, against\n * `minTvl` and `tokens`. A poll never overlaps the previous one (a tick that finds one still in\n * flight is skipped), and nothing is reported after the returned function stops the watcher.\n *\n * @example\n * ```ts\n * const stop = gSwap.pools.watchNewPools((pool) => console.log('new pool', pool.poolRef), {\n * intervalMs: 60_000,\n * tokens: ['GALA'],\n * });\n * // later\n * stop();\n * ```\n */\n public watchNewPools(\n onPool: (pool: PoolListInfo) => void,\n options: WatchNewPoolsOptions = {},\n ): () => void {\n const intervalMs = options.intervalMs ?? 30_000;\n if (typeof intervalMs !== 'number' || !Number.isFinite(intervalMs) || intervalMs < 1) {\n throw new GSwapSDKError('INVALID_POLL_INTERVAL', { value: String(intervalMs) });\n }\n let known: Set<string> | undefined;\n let stopped = false;\n let polling = false;\n const report = (error: unknown): void => {\n try {\n options.onError?.(error);\n } catch {\n // A diagnostics hook must not stop the watcher.\n }\n };\n const wanted = (pool: PoolListInfo): boolean =>\n (options.minTvl === undefined || (pool.tvlUsd ?? 0) >= options.minTvl) &&\n (options.tokens === undefined ||\n options.tokens.includes(pool.token0) ||\n options.tokens.includes(pool.token1));\n const poll = async (): Promise<void> => {\n if (stopped || polling) return;\n polling = true;\n try {\n const pools = await this.getPools();\n if (known === undefined) {\n known = new Set(pools.map((pool) => pool.poolRef));\n return;\n }\n for (const pool of pools) {\n if (stopped) return;\n if (known.has(pool.poolRef)) continue;\n known.add(pool.poolRef);\n if (!wanted(pool)) continue;\n try {\n onPool(pool);\n } catch (error: unknown) {\n report(error);\n }\n }\n } catch (error: unknown) {\n if (!stopped) report(error);\n } finally {\n polling = false;\n }\n };\n void poll();\n const timer = setInterval(() => void poll(), intervalMs);\n return () => {\n stopped = true;\n clearInterval(timer);\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 // Any SDK error passes through, core's transport errors (`REQUEST_TIMEOUT`,\n // `TRANSPORT_ERROR`, a plain `GalaSDKError`) included: only a foreign failure is wrapped.\n if (isGSwapError(error)) throw error;\n throw new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'pool' },\n { cause: error, write: false },\n );\n }\n }\n}\n\nconst SORT_KEYS: readonly string[] = ['tvl', 'volume1d', 'volume30d'];\nconst MAX_SEARCH_LENGTH = 64;\nconst MAX_PAGE_SIZE = 1000;\n\n/** The pool-list query, in the order the apps write it: search, sortBy, sortOrder, page, limit. */\nfunction poolListParams(options: PoolListOptions | undefined): Record<string, string> | undefined {\n if (options === undefined) return undefined;\n const params: Record<string, string> = {};\n if (options.search !== undefined) {\n if (options.search.length > MAX_SEARCH_LENGTH) {\n throw new GSwapSDKError('SEARCH_TOO_LONG', {\n length: options.search.length,\n maxLength: MAX_SEARCH_LENGTH,\n });\n }\n params['search'] = options.search;\n }\n if (options.sortBy !== undefined) {\n if (!SORT_KEYS.includes(options.sortBy)) {\n throw new GSwapSDKError('INVALID_SORT_BY', {\n value: String(options.sortBy),\n allowed: SORT_KEYS.join(','),\n });\n }\n params['sortBy'] = options.sortBy;\n }\n if (options.sortOrder !== undefined) {\n if (options.sortOrder !== 'asc' && options.sortOrder !== 'desc') {\n throw new GSwapSDKError('INVALID_SORT_ORDER', { value: String(options.sortOrder) });\n }\n params['sortOrder'] = options.sortOrder;\n }\n if (options.page !== undefined) {\n if (!Number.isInteger(options.page) || options.page < 1) {\n throw new GSwapSDKError('INVALID_PAGE', { value: options.page });\n }\n params['page'] = String(options.page);\n }\n if (options.limit !== undefined) {\n if (!Number.isInteger(options.limit) || options.limit < 1 || options.limit > MAX_PAGE_SIZE) {\n throw new GSwapSDKError('INVALID_LIMIT', {\n value: options.limit,\n min: 1,\n max: MAX_PAGE_SIZE,\n });\n }\n params['limit'] = String(options.limit);\n }\n return Object.keys(params).length === 0 ? undefined : params;\n}\n\nconst OPTIONAL_POOL_STRINGS = [\n 'poolName',\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'creator',\n 'price',\n 'sqrtPrice',\n 'token0Tvl',\n 'token1Tvl',\n] as const;\n\nconst OPTIONAL_POOL_NUMBERS = [\n 'tickSpacing',\n 'protocolFees',\n 'tradingFees',\n 'tick',\n 'volume1d',\n 'volume7d',\n 'volume30d',\n 'trades1d',\n 'fee24h',\n 'token0Price',\n 'token1Price',\n] as const;\n\n/** Fields the apps accept as a number or a numeric string (the wallet does `Number(row.x)`). */\nconst NUMERIC_POOL_FIELDS = ['fee', 'tvlUsd', 'apr1d'] as const;\n\n/**\n * Reads one pool-list row the way the apps do: the identity (`token0`, `token1`, `poolRef`) and\n * `fee` must be usable, every other field is optional but, when present, must have its type.\n * `fee`, `tvlUsd` and `apr1d` may arrive as numeric strings and are returned as numbers. Fields\n * the SDK does not know are kept.\n */\nfunction parsePoolListInfo(entry: unknown): EntryParse<PoolListInfo> {\n const row = asEntryRecord(entry);\n if (row === undefined) return entryRejected('the row is not an object');\n for (const key of ['token0', 'token1', 'poolRef'] as const) {\n if (typeof row[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n if (row['contractVersion'] !== undefined && row['contractVersion'] !== 'v2') {\n return entryRejected('contractVersion is not v2');\n }\n const normalized: Record<string, unknown> = { ...row };\n for (const key of NUMERIC_POOL_FIELDS) {\n const raw = row[key];\n if (raw === undefined && key !== 'fee') continue;\n const value = finiteNumberOf(raw);\n if (value === undefined) return entryRejected(`${key} is not a number`);\n normalized[key] = value;\n }\n for (const key of OPTIONAL_POOL_STRINGS) {\n if (row[key] !== undefined && typeof row[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n for (const key of OPTIONAL_POOL_NUMBERS) {\n const value = row[key];\n if (value !== undefined && (typeof value !== 'number' || !Number.isFinite(value))) {\n return entryRejected(`${key} is not a number`);\n }\n }\n return entryOk(normalized as unknown as PoolListInfo);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ALLOWED_FEE_TIERS_TEXT as e}from"./gswap_error_catalog.js";import t from"../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/defineProperty.js";import{GSwapSDKError as n,isGSwapError as r}from"./gswap_sdk_error.js";import{TICK_SPACING_BY_FEE as i}from"../types/fees.js";import{tickFromPrice as a}from"../utils/tick_math.js";import{isProposableTradingSymbol as o,userRef as s,validateFee as c,validateNumericAmount as l}from"../utils/validation.js";import{HttpClient as u}from"./http_client.js";import{asEntryRecord as d,entryOk as f,entryRejected as p,readEntries as m}from"../utils/lenient.js";import{parseTokenClassKey as h}from"../utils/ordering.js";import{resolvePreSend as g}from"../utils/resolve_pre_send.js";import{rawTokenOf as _}from"./symbols.js";import{alignTickDown as v,alignTickUp as y,assertTickRange as b}from"../utils/ticks.js";import{assertCanonicalV2Dto as x,buildAddLiquidityDto as S,buildCollectPositionFeesDto as C,buildCreatePoolDto as w,buildRemoveLiquidityDto as T}from"../utils/dto_builders.js";import{assertUniqueKey as E,compositeKeyOf as D,createUniqueKey as O,resolveUniqueKeyPrefix as k,signPreSend as A}from"@gala-chain/gala-core-sdk";import j from"bignumber.js";function M(e){return{token0:e.token0,token1:e.token1,fee:e.fee,tickLower:e.tickLower,tickUpper:e.tickUpper}}var N=class{constructor(e,n,r,i,a={}){this.gateway=e,this.symbols=n,this.signer=r,t(this,`walletAddress`,void 0),t(this,`http`,void 0),t(this,`uniqueKeyPrefix`,void 0),t(this,`onInvalidEntry`,void 0),this.walletAddress=i===void 0?void 0:s(i,`walletAddress`),this.http=new u(e.httpRequestor,e.requestTimeoutMs??3e4,e.wire),this.uniqueKeyPrefix=k(a.uniqueKeyPrefix),this.onInvalidEntry=a.onInvalidEntry}async getUserPositions(e){let t=await this.get(`/positions`,{user:s(e,`owner`)});return m(`positions`,t.data,L,this.onInvalidEntry)}async getPosition(e,t){let n=await this.getNullable(`/position`,await this.positionParams(e),t);return n===null?null:R(n.data)}async readPosition(e,t){try{let n=await this.getPosition(e,t);return n===null?{kind:`not_found`}:{kind:`found`,data:n}}catch(e){if(t?.aborted===!0)throw e;return{kind:`unknown`,error:r(e)?e:new n(`REQUEST_FAILED`,{operation:`position`},{cause:e,write:!1})}}}async positionParams(e){let t=s(e.owner,`owner`);if(this.symbols.passthrough===!0)return{token0:_(e.token0),token1:_(e.token1),fee:`${e.fee}`,owner:t,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`};let n=await this.orderPair(e.token0,e.token1),r=this.canonicalTicks(e.tickLower,e.tickUpper,n.flipped);return{token0:n.token0.symbol,token1:n.token1.symbol,fee:`${e.fee}`,owner:t,tickLower:`${r.tickLower}`,tickUpper:`${r.tickUpper}`}}async estimateAddLiquidity(e){return l(e.amount,`amount`),(await this.get(`/add-liq-estimate`,{token0:_(e.token0),token1:_(e.token1),fee:`${e.fee}`,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`,amount:new j(e.amount).toFixed(),amountIsToken0:String(e.amountIsToken0)})).data}async estimateRemoveLiquidity(e){return l(e.liquidity,`liquidity`),(await this.get(`/remove-liq-estimate`,{token0:_(e.token0),token1:_(e.token1),fee:`${e.fee}`,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`,liquidity:new j(e.liquidity).toFixed()})).data}async addLiquidityByTicks(e){return this.submitAddLiquidity(await this.buildAddLiquidity(e))}async buildAddLiquidity(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),n=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);b(n.tickLower,n.tickUpper,e.fee),l(e.amount,`amount`);let r={token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:n.tickLower,tickUpper:n.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey)};return t.flipped===e.amountIsToken0?S({...r,depositQuantityToken1:e.amount}):S({...r,depositQuantityToken0:e.amount})}async submitAddLiquidity(e){return x(`AddLiquidity`,e),this.submit(`AddLiquidity`,e,{kind:`add`,identity:M(e)})}async addLiquidityByPrice(e){c(e.fee),this.rejectNumber(e.minPrice,`minPrice`),this.rejectNumber(e.maxPrice,`maxPrice`);let t=new j(e.minPrice),r=new j(e.maxPrice);if(!t.isFinite()||!r.isFinite()||t.isLessThanOrEqualTo(0)||r.isLessThanOrEqualTo(0))throw new n(`INVALID_PRICE_BOUNDS`,{minPrice:String(e.minPrice),maxPrice:String(e.maxPrice)});if(t.isGreaterThan(r))throw new n(`PRICE_BOUNDS_ORDER`,{minPrice:String(e.minPrice),maxPrice:String(e.maxPrice)});let i=this.tickSpacing(e.fee),o=v(a(t),i),s=y(a(r),i);return this.addLiquidityByTicks({token0:e.token0,token1:e.token1,fee:e.fee,tickLower:o,tickUpper:s,amount:e.amount,amountIsToken0:e.amountIsToken0,uniqueKey:e.uniqueKey})}async removeLiquidity(e){return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(e))}async buildRemoveLiquidity(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),r=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);if(b(r.tickLower,r.tickUpper,e.fee),e.amount0!==void 0&&e.amount1!==void 0)throw new n(`AT_MOST_ONE_OF_ALLOWED`,{first:`amount0`,second:`amount1`});e.amount0!==void 0&&l(e.amount0,`amount0`),e.amount1!==void 0&&l(e.amount1,`amount1`);let[i,a]=t.flipped?[e.amount1,e.amount0]:[e.amount0,e.amount1];return T({token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:r.tickLower,tickUpper:r.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey),withdrawalQuantityToken0:i,withdrawalQuantityToken1:a})}async submitRemoveLiquidity(e){x(`RemoveLiquidity`,e);let t=e.withdrawalQuantityToken0===void 0&&e.withdrawalQuantityToken1===void 0;return this.submit(`RemoveLiquidity`,e,{kind:t?`removeFull`:`removePartial`,identity:M(e)})}async collectPositionFees(e){return this.submitCollectPositionFees(await this.buildCollectPositionFees(e))}async buildCollectPositionFees(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),n=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);return b(n.tickLower,n.tickUpper,e.fee),C({token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:n.tickLower,tickUpper:n.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey)})}async submitCollectPositionFees(e){return x(`CollectPositionFees`,e),this.submit(`CollectPositionFees`,e,{kind:`collect`,identity:M(e)})}async createPool(e){return this.submitCreatePool(await this.buildCreatePool(e))}async buildCreatePool(e){let t=e.startingPrice!==void 0;if(t===(e.startingSqrtPrice!==void 0))throw new n(`EXACTLY_ONE_OF_REQUIRED`,{first:`startingPrice`,second:`startingSqrtPrice`});c(e.fee);let[r,i]=await Promise.all([this.resolveCreateToken(e.token0,e.token0Symbol),this.resolveCreateToken(e.token1,e.token1Symbol)]),a=r.symbol>i.symbol,[o,s]=a?[i,r]:[r,i],l=t?e.startingPrice:e.startingSqrtPrice;this.rejectNumber(l,t?`startingPrice`:`startingSqrtPrice`);let u=new j(l);if(!u.isFinite()||u.isLessThanOrEqualTo(0))throw new n(`INVALID_STARTING_PRICE`,{value:String(l)});let d=a?new j(1).dividedBy(u):u,f={token0Key:o.classKey,token1Key:s.classKey,token0Symbol:o.symbol,token1Symbol:s.symbol,fee:e.fee,uniqueKey:this.uniqueKeyFor(e.uniqueKey),name:e.name,isPrivate:e.isPrivate,privateAccess:e.privateAccess};return w(t?{...f,startingPrice:d}:{...f,startingSqrtPrice:d})}async submitCreatePool(e){x(`CreatePool`,e);let t=await this.submit(`CreatePool`,e,{kind:`createPool`,token0:e.token0Symbol,token1:e.token1Symbol,fee:e.fee});return this.symbols.invalidate?.(),t}async submit(e,t,r){if(this.signer===void 0)throw n.noSignerError();let i=await A(this.signer,e,t),a=this.walletAddress===void 0?{}:{walletAddress:this.walletAddress},o=this.walletAddress,s=await this.buildPositionConfirmation(r,o),c={...a,...s===void 0?{}:{positionConfirmation:s}};return this.gateway.submit(e,i,c)}async buildPositionConfirmation(e,t){if(e===void 0)return;if(e.kind===`createPool`){let{token0:t,token1:n,fee:r}=e;return async e=>await this.getNullable(`/pool`,{token0:t,token1:n,fee:`${r}`},e)===null?{confirmed:!1}:{confirmed:!0,position:null}}if(t===void 0)return;let{kind:n,identity:r}=e,i=e=>({liquidity:new j(e?.liquidity??0),fees:new j(e?.fees0??0).plus(new j(e?.fees1??0))}),a;if(n!==`removeFull`)try{a=i(await this.getPosition({...r,owner:t}))}catch{a=void 0}return async e=>{let o=await this.getPosition({...r,owner:t},e);if(a===void 0)return a=i(o),n===`removeFull`&&o===null?{confirmed:!0,position:null}:{confirmed:!1};switch(n){case`add`:return o!==null&&new j(o.liquidity).isGreaterThan(a.liquidity)?{confirmed:!0,position:o}:{confirmed:!1};case`removePartial`:return o!==null&&new j(o.liquidity).isLessThan(a.liquidity)?{confirmed:!0,position:o}:{confirmed:!1};case`removeFull`:return o===null?{confirmed:!0,position:null}:{confirmed:!1};case`collect`:{if(o===null)return{confirmed:!1};let e=new j(o.fees0??0).plus(new j(o.fees1??0));return e.isLessThan(a.fees)||a.fees.isZero()&&e.isZero()?{confirmed:!0,position:o}:{confirmed:!1}}}}}async get(e,t,n){return this.http.sendGetRequest(this.gateway.dexBackendBaseUrl,`/v2/trade`,e,t,n===void 0?void 0:{signal:n})}async getNullable(e,t,n){try{return await this.get(e,t,n)}catch(e){if(this.isNotFound(e))return null;throw e}}isNotFound(e){return r(e)&&e.status===404}canonicalTicks(e,t,n){return n?{tickLower:-t,tickUpper:-e}:{tickLower:e,tickUpper:t}}tickSpacing(t){let r=i[t];if(r===void 0)throw new n(`INVALID_FEE`,{field:`fee`,value:t,allowed:e});return r}rejectNumber(e,t){if(typeof e==`number`)throw new n(`AMOUNT_IS_JS_NUMBER`,{field:t})}uniqueKeyFor(e){return e===void 0?O(this.uniqueKeyPrefix):(E(e),e)}orderPair(e,t){return g(`${_(e)}/${_(t)}`,()=>this.symbols.orderPair(e,t))}async resolveCreateToken(e,t){try{let r=typeof e==`object`?D(e):e,i=await g(_(e),()=>this.symbols.resolve(r));if(t!==void 0&&t!==``&&t!==i.symbol)throw new n(`SYMBOL_DISAGREES_WITH_REGISTRY`,{token:_(e),suppliedSymbol:t,registeredSymbol:i.symbol});let a=this.tryParseClassKey(e);if(a===void 0&&i.collection===``)throw new n(`CREATE_POOL_NEEDS_CLASS_KEY`,{token:_(e)});return{symbol:i.symbol,classKey:a??h({collection:i.collection,category:i.category,type:i.type,additionalKey:i.additionalKey})}}catch(i){if(!r(i,`UNKNOWN_TOKEN`))throw i;let a;try{a=h(e)}catch{throw i}if(t===void 0||t===``)throw new n(`TOKEN_SYMBOL_NOT_REGISTERED`,{token:_(e)});if(!o(t))throw new n(`INVALID_TRADING_SYMBOL`,{symbol:t});return{symbol:t,classKey:a}}}tryParseClassKey(e){try{return h(e)}catch{return}}};const P=[`token0Symbol`,`token1Symbol`,`owner`,`liquidity`,`amount0`,`amount1`],F=[`fee`,`tickLower`,`tickUpper`],I=[`token0CompositeKey`,`token1CompositeKey`,`token0Image`,`token1Image`,`sqrtPrice`,`fees0`,`fees1`];function L(e){let t=d(e);if(t===void 0)return p(`the row is not an object`);for(let e of P)if(typeof t[e]!=`string`)return p(`${e} is not a string`);for(let e of F){let n=t[e];if(typeof n!=`number`||!Number.isFinite(n))return p(`${e} is not a number`)}if(typeof t.inRange!=`boolean`)return p(`inRange is not a boolean`);for(let e of I)if(t[e]!==void 0&&typeof t[e]!=`string`)return p(`${e} is not a string`);let n=t.currentTick;if(n!==void 0&&(typeof n!=`number`||!Number.isFinite(n)))return p(`currentTick is not a number`);let r=t.poolRef??t.pool??``;if(typeof r!=`string`)return p(`pool is not a string`);let i=Object.fromEntries([...I,`currentTick`].flatMap(e=>t[e]===void 0?[]:[[e,t[e]]]));return f({token0Symbol:t.token0Symbol,token1Symbol:t.token1Symbol,fee:t.fee,tickLower:t.tickLower,tickUpper:t.tickUpper,liquidity:t.liquidity,amount0:t.amount0,amount1:t.amount1,inRange:t.inRange,pool:r,owner:t.owner,...i})}function R(e){let t=L(e);if(t.ok)return t.value;throw new n(`INVALID_POSITION_RESPONSE`,{reason:t.reason},{body:e,write:!1})}export{N as Positions};
|
|
1
|
+
import{ALLOWED_FEE_TIERS_TEXT as e}from"./gswap_error_catalog.js";import t from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as n,isGSwapError as r}from"./gswap_sdk_error.js";import{TICK_SPACING_BY_FEE as i}from"../types/fees.js";import{tickFromPrice as a}from"../utils/tick_math.js";import{isProposableTradingSymbol as o,userRef as s,validateFee as c,validateNumericAmount as l}from"../utils/validation.js";import{DEX_CONTRACT_PATH as u}from"../utils/chain_contract.js";import{HttpClient as d}from"./http_client.js";import{asEntryRecord as f,entryOk as p,entryRejected as m,readEntries as h}from"../utils/lenient.js";import{parseTokenClassKey as g}from"../utils/ordering.js";import{resolvePreSend as _}from"../utils/resolve_pre_send.js";import{rawTokenOf as v}from"./symbols.js";import{alignTickDown as y,alignTickUp as b,assertTickRange as x}from"../utils/ticks.js";import{assertCanonicalV2Dto as S,buildAddLiquidityDto as C,buildCollectPositionFeesDto as w,buildCreatePoolDto as T,buildRemoveLiquidityDto as E}from"../utils/dto_builders.js";import{assertUniqueKey as D,compositeKeyOf as O,createUniqueKey as k,resolveUniqueKeyPrefix as A,signPreSend as j}from"@gala-chain/gala-core-sdk";import M from"bignumber.js";function N(e){return{token0:e.token0,token1:e.token1,fee:e.fee,tickLower:e.tickLower,tickUpper:e.tickUpper}}var P=class{constructor(e,n,r,i,a={}){this.gateway=e,this.symbols=n,this.signer=r,t(this,`walletAddress`,void 0),t(this,`http`,void 0),t(this,`uniqueKeyPrefix`,void 0),t(this,`onInvalidEntry`,void 0),this.walletAddress=i===void 0?void 0:s(i,`walletAddress`),this.http=new d(e.httpRequestor,e.requestTimeoutMs??3e4,e.wire),this.uniqueKeyPrefix=A(a.uniqueKeyPrefix),this.onInvalidEntry=a.onInvalidEntry}async getUserPositions(e){let t=await this.get(`/positions`,{user:s(e,`owner`)});return h(`positions`,t.data,R,this.onInvalidEntry)}async getPosition(e,t){let n=await this.getNullable(`/position`,await this.positionParams(e),t);return n===null?null:z(n.data)}async readPosition(e,t){try{let n=await this.getPosition(e,t);return n===null?{kind:`not_found`}:{kind:`found`,data:n}}catch(e){if(t?.aborted===!0)throw e;return{kind:`unknown`,error:r(e)?e:new n(`REQUEST_FAILED`,{operation:`position`},{cause:e,write:!1})}}}async positionParams(e){let t=s(e.owner,`owner`);if(this.symbols.passthrough===!0)return{token0:v(e.token0),token1:v(e.token1),fee:`${e.fee}`,owner:t,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`};let n=await this.orderPair(e.token0,e.token1),r=this.canonicalTicks(e.tickLower,e.tickUpper,n.flipped);return{token0:n.token0.symbol,token1:n.token1.symbol,fee:`${e.fee}`,owner:t,tickLower:`${r.tickLower}`,tickUpper:`${r.tickUpper}`}}async estimateAddLiquidity(e){return l(e.amount,`amount`),(await this.get(`/add-liq-estimate`,{token0:v(e.token0),token1:v(e.token1),fee:`${e.fee}`,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`,amount:new M(e.amount).toFixed(),amountIsToken0:String(e.amountIsToken0)})).data}async estimateRemoveLiquidity(e){return l(e.liquidity,`liquidity`),(await this.get(`/remove-liq-estimate`,{token0:v(e.token0),token1:v(e.token1),fee:`${e.fee}`,tickLower:`${e.tickLower}`,tickUpper:`${e.tickUpper}`,liquidity:new M(e.liquidity).toFixed()})).data}async addLiquidityByTicks(e){return this.submitAddLiquidity(await this.buildAddLiquidity(e))}async buildAddLiquidity(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),n=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);x(n.tickLower,n.tickUpper,e.fee),l(e.amount,`amount`);let r={token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:n.tickLower,tickUpper:n.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey)};return t.flipped===e.amountIsToken0?C({...r,depositQuantityToken1:e.amount}):C({...r,depositQuantityToken0:e.amount})}async submitAddLiquidity(e){return S(`AddLiquidity`,e),this.submit(`AddLiquidity`,e,{kind:`add`,identity:N(e)})}async addLiquidityByPrice(e){c(e.fee),this.rejectNumber(e.minPrice,`minPrice`),this.rejectNumber(e.maxPrice,`maxPrice`);let t=new M(e.minPrice),r=new M(e.maxPrice);if(!t.isFinite()||!r.isFinite()||t.isLessThanOrEqualTo(0)||r.isLessThanOrEqualTo(0))throw new n(`INVALID_PRICE_BOUNDS`,{minPrice:String(e.minPrice),maxPrice:String(e.maxPrice)});if(t.isGreaterThan(r))throw new n(`PRICE_BOUNDS_ORDER`,{minPrice:String(e.minPrice),maxPrice:String(e.maxPrice)});let i=this.tickSpacing(e.fee),o=y(a(t),i),s=b(a(r),i);return this.addLiquidityByTicks({token0:e.token0,token1:e.token1,fee:e.fee,tickLower:o,tickUpper:s,amount:e.amount,amountIsToken0:e.amountIsToken0,uniqueKey:e.uniqueKey})}async removeLiquidity(e){return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(e))}async buildRemoveLiquidity(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),r=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);if(x(r.tickLower,r.tickUpper,e.fee),e.amount0!==void 0&&e.amount1!==void 0)throw new n(`AT_MOST_ONE_OF_ALLOWED`,{first:`amount0`,second:`amount1`});e.amount0!==void 0&&l(e.amount0,`amount0`),e.amount1!==void 0&&l(e.amount1,`amount1`);let[i,a]=t.flipped?[e.amount1,e.amount0]:[e.amount0,e.amount1];return E({token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:r.tickLower,tickUpper:r.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey),withdrawalQuantityToken0:i,withdrawalQuantityToken1:a})}async submitRemoveLiquidity(e){S(`RemoveLiquidity`,e);let t=e.withdrawalQuantityToken0===void 0&&e.withdrawalQuantityToken1===void 0;return this.submit(`RemoveLiquidity`,e,{kind:t?`removeFull`:`removePartial`,identity:N(e)})}async collectPositionFees(e){return this.submitCollectPositionFees(await this.buildCollectPositionFees(e))}async buildCollectPositionFees(e){c(e.fee);let t=await this.orderPair(e.token0,e.token1),n=this.canonicalTicks(e.tickLower,e.tickUpper,t.flipped);return x(n.tickLower,n.tickUpper,e.fee),w({token0:t.token0.symbol,token1:t.token1.symbol,fee:e.fee,tickLower:n.tickLower,tickUpper:n.tickUpper,uniqueKey:this.uniqueKeyFor(e.uniqueKey)})}async submitCollectPositionFees(e){return S(`CollectPositionFees`,e),this.submit(`CollectPositionFees`,e,{kind:`collect`,identity:N(e)})}async createPool(e){return this.submitCreatePool(await this.buildCreatePool(e))}async buildCreatePool(e){let t=e.startingPrice!==void 0;if(t===(e.startingSqrtPrice!==void 0))throw new n(`EXACTLY_ONE_OF_REQUIRED`,{first:`startingPrice`,second:`startingSqrtPrice`});c(e.fee);let[r,i]=await Promise.all([this.resolveCreateToken(e.token0,e.token0Symbol),this.resolveCreateToken(e.token1,e.token1Symbol)]),a=r.symbol>i.symbol,[o,s]=a?[i,r]:[r,i],l=t?e.startingPrice:e.startingSqrtPrice;this.rejectNumber(l,t?`startingPrice`:`startingSqrtPrice`);let u=new M(l);if(!u.isFinite()||u.isLessThanOrEqualTo(0))throw new n(`INVALID_STARTING_PRICE`,{value:String(l)});let d=a?new M(1).dividedBy(u):u,f={token0Key:o.classKey,token1Key:s.classKey,token0Symbol:o.symbol,token1Symbol:s.symbol,fee:e.fee,uniqueKey:this.uniqueKeyFor(e.uniqueKey),name:e.name,isPrivate:e.isPrivate,privateAccess:e.privateAccess};return T(t?{...f,startingPrice:d}:{...f,startingSqrtPrice:d})}async submitCreatePool(e){S(`CreatePool`,e);let t=await this.submit(`CreatePool`,e,{kind:`createPool`,token0:e.token0Symbol,token1:e.token1Symbol,fee:e.fee});return this.symbols.invalidate?.(),t}async submit(e,t,r){if(this.signer===void 0)throw n.noSignerError();let i=await j(this.signer,u,e,t),a=this.walletAddress===void 0?{}:{walletAddress:this.walletAddress},o=this.walletAddress,s=await this.buildPositionConfirmation(r,o),c={...a,...s===void 0?{}:{positionConfirmation:s}};return this.gateway.submit(e,i,c)}async buildPositionConfirmation(e,t){if(e===void 0)return;if(e.kind===`createPool`){let{token0:t,token1:n,fee:r}=e;return async e=>await this.getNullable(`/pool`,{token0:t,token1:n,fee:`${r}`},e)===null?{confirmed:!1}:{confirmed:!0,position:null}}if(t===void 0)return;let{kind:n,identity:r}=e,i=e=>({liquidity:new M(e?.liquidity??0),fees:new M(e?.fees0??0).plus(new M(e?.fees1??0))}),a;if(n!==`removeFull`)try{a=i(await this.getPosition({...r,owner:t}))}catch{a=void 0}return async e=>{let o=await this.getPosition({...r,owner:t},e);if(a===void 0)return a=i(o),n===`removeFull`&&o===null?{confirmed:!0,position:null}:{confirmed:!1};switch(n){case`add`:return o!==null&&new M(o.liquidity).isGreaterThan(a.liquidity)?{confirmed:!0,position:o}:{confirmed:!1};case`removePartial`:return o!==null&&new M(o.liquidity).isLessThan(a.liquidity)?{confirmed:!0,position:o}:{confirmed:!1};case`removeFull`:return o===null?{confirmed:!0,position:null}:{confirmed:!1};case`collect`:{if(o===null)return{confirmed:!1};let e=new M(o.fees0??0).plus(new M(o.fees1??0));return e.isLessThan(a.fees)||a.fees.isZero()&&e.isZero()?{confirmed:!0,position:o}:{confirmed:!1}}}}}async get(e,t,n){return this.http.sendGetRequest(this.gateway.dexBackendBaseUrl,`/v2/trade`,e,t,n===void 0?void 0:{signal:n})}async getNullable(e,t,n){try{return await this.get(e,t,n)}catch(e){if(this.isNotFound(e))return null;throw e}}isNotFound(e){return r(e)&&e.status===404}canonicalTicks(e,t,n){return n?{tickLower:-t,tickUpper:-e}:{tickLower:e,tickUpper:t}}tickSpacing(t){let r=i[t];if(r===void 0)throw new n(`INVALID_FEE`,{field:`fee`,value:t,allowed:e});return r}rejectNumber(e,t){if(typeof e==`number`)throw new n(`AMOUNT_IS_JS_NUMBER`,{field:t})}uniqueKeyFor(e){return e===void 0?k(this.uniqueKeyPrefix):(D(e),e)}orderPair(e,t){return _(`${v(e)}/${v(t)}`,()=>this.symbols.orderPair(e,t))}async resolveCreateToken(e,t){try{let r=typeof e==`object`?O(e):e,i=await _(v(e),()=>this.symbols.resolve(r));if(t!==void 0&&t!==``&&t!==i.symbol)throw new n(`SYMBOL_DISAGREES_WITH_REGISTRY`,{token:v(e),suppliedSymbol:t,registeredSymbol:i.symbol});let a=this.tryParseClassKey(e);if(a===void 0&&i.collection===``)throw new n(`CREATE_POOL_NEEDS_CLASS_KEY`,{token:v(e)});return{symbol:i.symbol,classKey:a??g({collection:i.collection,category:i.category,type:i.type,additionalKey:i.additionalKey})}}catch(i){if(!r(i,`UNKNOWN_TOKEN`))throw i;let a;try{a=g(e)}catch{throw i}if(t===void 0||t===``)throw new n(`TOKEN_SYMBOL_NOT_REGISTERED`,{token:v(e)});if(!o(t))throw new n(`INVALID_TRADING_SYMBOL`,{symbol:t});return{symbol:t,classKey:a}}}tryParseClassKey(e){try{return g(e)}catch{return}}};const F=[`token0Symbol`,`token1Symbol`,`owner`,`liquidity`,`amount0`,`amount1`],I=[`fee`,`tickLower`,`tickUpper`],L=[`token0CompositeKey`,`token1CompositeKey`,`token0Image`,`token1Image`,`sqrtPrice`,`fees0`,`fees1`];function R(e){let t=f(e);if(t===void 0)return m(`the row is not an object`);for(let e of F)if(typeof t[e]!=`string`)return m(`${e} is not a string`);for(let e of I){let n=t[e];if(typeof n!=`number`||!Number.isFinite(n))return m(`${e} is not a number`)}if(typeof t.inRange!=`boolean`)return m(`inRange is not a boolean`);for(let e of L)if(t[e]!==void 0&&typeof t[e]!=`string`)return m(`${e} is not a string`);let n=t.currentTick;if(n!==void 0&&(typeof n!=`number`||!Number.isFinite(n)))return m(`currentTick is not a number`);let r=t.poolRef??t.pool??``;if(typeof r!=`string`)return m(`pool is not a string`);let i=Object.fromEntries([...L,`currentTick`].flatMap(e=>t[e]===void 0?[]:[[e,t[e]]]));return p({token0Symbol:t.token0Symbol,token1Symbol:t.token1Symbol,fee:t.fee,tickLower:t.tickLower,tickUpper:t.tickUpper,liquidity:t.liquidity,amount0:t.amount0,amount1:t.amount1,inRange:t.inRange,pool:r,owner:t.owner,...i})}function z(e){let t=R(e);if(t.ok)return t.value;throw new n(`INVALID_POSITION_RESPONSE`,{reason:t.reason},{body:e,write:!1})}export{P as Positions};
|
|
2
2
|
//# sourceMappingURL=positions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"positions.js","names":["_defineProperty","BigNumber","identityOf","dto","Positions","gateway","symbols","signer","walletAddress","userRef","HttpClient","resolveUniqueKeyPrefix","options","response","owner","readEntries","parsePosition","args","signal","readPositionBody","position","error","isGSwapError","GSwapSDKError","rawTokenOf","pair","ticks","validateNumericAmount","validateFee","assertTickRange","base","buildAddLiquidityDto","assertCanonicalV2Dto","minPrice","maxPrice","spacing","tickLower","alignTickDown","tickFromPrice","tickUpper","alignTickUp","canonical0","canonical1","buildRemoveLiquidityDto","isFullClose","buildCollectPositionFeesDto","hasPrice","tokenA","tokenB","flipped","token0","token1","sourcePriceInput","sourcePrice","canonicalPrice","shared","buildCreatePoolDto","transaction","signed","signPreSend","method","submitOptions","positionConfirmation","confirmation","fee","toBaseline","current","baseline","kind","identity","currentFees","endpoint","params","TICK_SPACING_BY_FEE","ALLOWED_FEE_TIERS_TEXT","value","parameterName","supplied","createUniqueKey","assertUniqueKey","resolvePreSend","a","b","lookupRef","ref","compositeKeyOf","resolved","symbolOverride","suppliedClassKey","parseTokenClassKey","classKey","isProposableTradingSymbol","REQUIRED_POSITION_STRINGS","REQUIRED_POSITION_NUMBERS","OPTIONAL_POSITION_STRINGS","wire","asEntryRecord","entryRejected","key","number","\"inRange\"","currentTick","\"currentTick\"","pool","\"poolRef\"","\"pool\"","optional","entryOk","\"token0Symbol\"","\"token1Symbol\"","\"fee\"","\"tickLower\"","\"tickUpper\"","\"liquidity\"","\"amount0\"","\"amount1\"","\"owner\"","parsed","data"],"sources":["../../../src/classes/positions.ts"],"sourcesContent":["import {\n assertUniqueKey,\n compositeKeyOf,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n signPreSend,\n type GalaChainSigner,\n type UniqueKeyOptions,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './gswap_error_catalog.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport type { ChainGateway, ChainSubmitOptions } from './gateway.js';\nimport type { PositionConfirmationResult, SubmittedTransaction } from './submitted_transaction.js';\nimport { HttpClient } from './http_client.js';\nimport { 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 {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { type TokenRef, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend } from '../utils/resolve_pre_send.js';\nimport {\n isProposableTradingSymbol,\n validateFee,\n userRef,\n validateNumericAmount,\n} from '../utils/validation.js';\nimport { tickFromPrice } from '../utils/tick_math.js';\nimport { alignTickDown, alignTickUp, assertTickRange } from '../utils/ticks.js';\nimport {\n assertCanonicalV2Dto,\n buildAddLiquidityDto,\n buildCollectPositionFeesDto,\n buildCreatePoolDto,\n buildRemoveLiquidityDto,\n} from '../utils/dto_builders.js';\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 walletAddress?: string,\n options: PositionsOptions = {},\n ) {\n this.walletAddress =\n walletAddress === undefined ? undefined : userRef(walletAddress, 'walletAddress');\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 /** The signing wallet in the gateway's spelling (`eth|<EIP-55>` or `client|<id>`). */\n private readonly walletAddress: string | undefined;\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: userRef(owner, 'owner') });\n return readEntries('positions', response.data, parsePosition, this.onInvalidEntry);\n }\n\n /**\n * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.\n * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.\n *\n * @param args - Pair, owner, fee, and position tick range.\n * @returns The position, or `null` when the backend returns 404.\n * @example\n * ```typescript\n * const position = await gSwap.positions.getPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async getPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<Position | null> {\n const response = await this.getNullable<unknown>(\n '/position',\n await this.positionParams(args),\n signal,\n );\n return response === null ? null : readPositionBody(response.data);\n }\n\n /**\n * Reads one position and classifies the outcome instead of throwing: `found` with the position\n * (fees included), `not_found` (the backend's HTTP 404, which it sends only when the chain\n * itself has no such position) or `unknown` (any other failure, carried as `error`). Use it\n * to confirm a write: `unknown` is \"no evidence either way\", never a confirmed absence.\n *\n * Only the caller's own abort rethrows. With a pass-through resolver ({@link CanonicalSymbols})\n * the pair and ticks go to the backend exactly as given and the backend orients them.\n *\n * @example\n * ```typescript\n * const read = await gSwap.positions.readPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * if (read.kind === 'found') console.log(read.data.fees0);\n * ```\n */\n async readPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<PositionRead> {\n try {\n const position = await this.getPosition(args, signal);\n return position === null ? { kind: 'not_found' } : { kind: 'found', data: position };\n } catch (error: unknown) {\n if (signal?.aborted === true) throw error;\n return {\n kind: 'unknown',\n error: isGSwapError(error)\n ? error\n : new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'position' },\n { cause: error, write: false },\n ),\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 // The backend matches `owner` against the chain's position owner with strict equality, so\n // only the chain's own spelling (`eth|<EIP-55>`) finds a position.\n const owner = userRef(args.owner, 'owner');\n if (this.symbols.passthrough === true) {\n return {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n owner,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n };\n }\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n return {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: `${args.fee}`,\n owner,\n tickLower: `${ticks.tickLower}`,\n tickUpper: `${ticks.tickUpper}`,\n };\n }\n\n /**\n * Estimates the other token amount and resulting liquidity for a deposit.\n *\n * @param args - Pair, tick range, deposit amount, and the amount's caller-side token index.\n * @returns Backend liquidity estimate.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async estimateAddLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n amountIsToken0: boolean;\n }): Promise<AddLiquidityEstimate> {\n validateNumericAmount(args.amount, 'amount');\n const response = await this.get<AddLiquidityEstimateWire>('/add-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n amount: new BigNumber(args.amount).toFixed(),\n amountIsToken0: String(args.amountIsToken0),\n });\n return response.data;\n }\n\n /**\n * Estimates token amounts released by burning liquidity.\n *\n * @param args - Pair, tick range, fee tier, and liquidity quantity.\n * @returns Estimated token0 and token1 quantities.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateRemoveLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, liquidity: '1000',\n * });\n * ```\n */\n async estimateRemoveLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n liquidity: NumericAmount;\n }): Promise<RemoveLiquidityEstimate> {\n validateNumericAmount(args.liquidity, 'liquidity');\n const response = await this.get<RemoveLiquidityEstimateWire>('/remove-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n liquidity: new BigNumber(args.liquidity).toFixed(),\n });\n return response.data;\n }\n\n /**\n * Adds liquidity using an explicit tick range. Exactly one canonical deposit field is emitted.\n *\n * @param args - Pair, fee, range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByTicks({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * await tx.confirm();\n * ```\n */\n async addLiquidityByTicks(args: AddLiquidityArgs) {\n return this.submitAddLiquidity(await this.buildAddLiquidity(args));\n }\n\n /**\n * Builds the AddLiquidity DTO that {@link addLiquidityByTicks} would sign, without signing or\n * sending it: to show in an approval popup, or to sign elsewhere. Submit exactly this DTO with\n * {@link submitAddLiquidity}. The pure counterpart, with canonical inputs and no resolution,\n * is `buildAddLiquidityDto`.\n *\n * @example\n * ```typescript\n * const dto = await gSwap.positions.buildAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async buildAddLiquidity(args: AddLiquidityArgs): Promise<AddLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n // Caller-facing checks first, so a refusal names the caller's own argument (`amount`).\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n validateNumericAmount(args.amount, 'amount');\n const base = {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n };\n return pair.flipped !== args.amountIsToken0\n ? buildAddLiquidityDto({ ...base, depositQuantityToken0: args.amount })\n : buildAddLiquidityDto({ ...base, depositQuantityToken1: args.amount });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildAddLiquidity} or `buildAddLiquidityDto`; it must\n * be exactly what the builder produces. The returned transaction confirms by proving the\n * position's liquidity grew.\n */\n async submitAddLiquidity(dto: AddLiquidityDTO) {\n assertCanonicalV2Dto('AddLiquidity', dto);\n return this.submit('AddLiquidity', dto, { kind: 'add', identity: identityOf(dto) });\n }\n\n /**\n * Adds liquidity from prices, flooring the lower tick and ceiling the upper tick to fee spacing.\n * The resulting range is therefore no narrower than the requested price interval.\n *\n * @param args - Pair, fee, price range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByPrice({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * minPrice: '0.14', maxPrice: '0.16', amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async addLiquidityByPrice(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n minPrice: PriceIn;\n maxPrice: PriceIn;\n amount: NumericAmount;\n amountIsToken0: boolean;\n /** The attempt's `uniqueKey`; default a fresh one (see {@link AddLiquidityArgs.uniqueKey}). */\n uniqueKey?: string | undefined;\n }) {\n validateFee(args.fee);\n this.rejectNumber(args.minPrice, 'minPrice');\n this.rejectNumber(args.maxPrice, 'maxPrice');\n const minPrice = new BigNumber(args.minPrice);\n const maxPrice = new BigNumber(args.maxPrice);\n if (\n !minPrice.isFinite() ||\n !maxPrice.isFinite() ||\n minPrice.isLessThanOrEqualTo(0) ||\n maxPrice.isLessThanOrEqualTo(0)\n ) {\n throw new GSwapSDKError('INVALID_PRICE_BOUNDS', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError('PRICE_BOUNDS_ORDER', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n const spacing = this.tickSpacing(args.fee);\n const tickLower = alignTickDown(tickFromPrice(minPrice), spacing);\n const tickUpper = alignTickUp(tickFromPrice(maxPrice), spacing);\n return this.addLiquidityByTicks({\n token0: args.token0,\n token1: args.token1,\n fee: args.fee,\n tickLower,\n tickUpper,\n amount: args.amount,\n amountIsToken0: args.amountIsToken0,\n uniqueKey: args.uniqueKey,\n });\n }\n\n /**\n * Removes liquidity by withdrawing at most one canonical token quantity.\n * Omitting both amounts closes the position and sweeps all accrued fees.\n *\n * @param args - Pair, fee, range, and optional caller-side withdrawal amount.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.removeLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async removeLiquidity(args: RemoveLiquidityArgs) {\n return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(args));\n }\n\n /**\n * Builds the RemoveLiquidity DTO that {@link removeLiquidity} would sign, without signing or\n * sending it. Submit exactly this DTO with {@link submitRemoveLiquidity}. The pure counterpart\n * is `buildRemoveLiquidityDto`.\n */\n async buildRemoveLiquidity(args: RemoveLiquidityArgs): Promise<RemoveLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n if (args.amount0 !== undefined && args.amount1 !== undefined) {\n throw new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: 'amount0', second: 'amount1' });\n }\n if (args.amount0 !== undefined) validateNumericAmount(args.amount0, 'amount0');\n if (args.amount1 !== undefined) validateNumericAmount(args.amount1, 'amount1');\n // The caller's amount0 / amount1 follow the caller's pair; the DTO's follow the canonical one.\n const [canonical0, canonical1] = pair.flipped\n ? [args.amount1, args.amount0]\n : [args.amount0, args.amount1];\n return buildRemoveLiquidityDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n withdrawalQuantityToken0: canonical0,\n withdrawalQuantityToken1: canonical1,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildRemoveLiquidity} or `buildRemoveLiquidityDto`;\n * it must be exactly what the builder produces. A DTO with no withdrawal quantity closes the\n * position, and the returned transaction then confirms by proving the position is gone.\n */\n async submitRemoveLiquidity(dto: RemoveLiquidityDTO) {\n assertCanonicalV2Dto('RemoveLiquidity', dto);\n const isFullClose =\n dto.withdrawalQuantityToken0 === undefined && dto.withdrawalQuantityToken1 === undefined;\n return this.submit('RemoveLiquidity', dto, {\n kind: isFullClose ? 'removeFull' : 'removePartial',\n identity: identityOf(dto),\n });\n }\n\n /**\n * Collects all accrued fees for a position; the contract does not support partial collection.\n *\n * @param args - Pair, fee, and tick range identifying the position.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.collectPositionFees({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async collectPositionFees(args: CollectPositionFeesArgs) {\n return this.submitCollectPositionFees(await this.buildCollectPositionFees(args));\n }\n\n /**\n * Builds the CollectPositionFees DTO that {@link collectPositionFees} would sign, without\n * signing or sending it. Submit exactly this DTO with {@link submitCollectPositionFees}. The\n * pure counterpart is `buildCollectPositionFeesDto`.\n */\n async buildCollectPositionFees(args: CollectPositionFeesArgs): Promise<CollectPositionFeesDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n return buildCollectPositionFeesDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCollectPositionFees} or\n * `buildCollectPositionFeesDto`; it must be exactly what the builder produces.\n */\n async submitCollectPositionFees(dto: CollectPositionFeesDTO) {\n assertCanonicalV2Dto('CollectPositionFees', dto);\n return this.submit('CollectPositionFees', dto, { kind: 'collect', identity: identityOf(dto) });\n }\n\n /**\n * Creates a pool, resolving registered trading symbols.\n * Reversed symbol order inverts the supplied starting price or square-root price.\n *\n * A token class key carries no symbol, so for a token being proposed into the v2\n * trading-symbol registry for the first time (no existing pool has registered it yet) the\n * caller MUST pass `token0Symbol`/`token1Symbol` (the token class's symbol, from the token\n * list or FetchTokenClasses). The SDK never derives a symbol from the key, and throws a\n * TOKEN_SYMBOL_NOT_REGISTERED error when an unregistered token has none. For an already-registered token a\n * supplied symbol must match the registered one.\n *\n * @param args - Token class keys or references, fee, exactly one starting price field, and privacy options.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.createPool({\n * token0: 'GALA|Unit|none|none', token1: 'GUSDC|Unit|none|none', fee: 3000,\n * startingPrice: '0.15',\n * });\n * ```\n */\n async createPool(args: CreatePoolArgs) {\n return this.submitCreatePool(await this.buildCreatePool(args));\n }\n\n /**\n * Builds the CreatePool DTO that {@link createPool} would sign, without signing or sending it:\n * symbols resolved or proposed, the pair put in canonical order and the price inverted when it\n * was reversed. Submit exactly this DTO with {@link submitCreatePool}. The pure counterpart,\n * with canonical inputs, is `buildCreatePoolDto`.\n */\n async buildCreatePool(args: CreatePoolArgs): Promise<CreatePoolDTO> {\n const hasPrice = args.startingPrice !== undefined;\n const hasSqrtPrice = args.startingSqrtPrice !== undefined;\n if (hasPrice === hasSqrtPrice) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n validateFee(args.fee);\n const [tokenA, tokenB] = await Promise.all([\n this.resolveCreateToken(args.token0, args.token0Symbol),\n this.resolveCreateToken(args.token1, args.token1Symbol),\n ]);\n const flipped = tokenA.symbol > tokenB.symbol;\n const [token0, token1] = flipped ? [tokenB, tokenA] : [tokenA, tokenB];\n const sourcePriceInput = hasPrice\n ? (args.startingPrice as NumericAmount)\n : (args.startingSqrtPrice as NumericAmount);\n this.rejectNumber(sourcePriceInput, hasPrice ? 'startingPrice' : 'startingSqrtPrice');\n const sourcePrice = new BigNumber(sourcePriceInput);\n if (!sourcePrice.isFinite() || sourcePrice.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(sourcePriceInput) });\n }\n const canonicalPrice = flipped ? new BigNumber(1).dividedBy(sourcePrice) : sourcePrice;\n const shared = {\n token0Key: token0.classKey,\n token1Key: token1.classKey,\n token0Symbol: token0.symbol,\n token1Symbol: token1.symbol,\n fee: args.fee,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n name: args.name,\n isPrivate: args.isPrivate,\n privateAccess: args.privateAccess,\n };\n return hasPrice\n ? buildCreatePoolDto({ ...shared, startingPrice: canonicalPrice })\n : buildCreatePoolDto({ ...shared, startingSqrtPrice: canonicalPrice });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCreatePool} or `buildCreatePoolDto`; it must be\n * exactly what the builder produces. The returned transaction confirms by the pool existing, and\n * the cached symbol registry is dropped, since the pool may have registered new symbols.\n */\n async submitCreatePool(dto: CreatePoolDTO) {\n assertCanonicalV2Dto('CreatePool', dto);\n const transaction = await this.submit('CreatePool', dto, {\n kind: 'createPool',\n token0: dto.token0Symbol,\n token1: dto.token1Symbol,\n fee: dto.fee,\n });\n this.symbols.invalidate?.();\n return transaction;\n }\n\n private async submit(\n method: string,\n dto: Record<string, unknown>,\n confirmation?: PositionSubmitConfirmation,\n ) {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const signed = await signPreSend(this.signer, method, dto);\n const submitOptions =\n this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n const owner = this.walletAddress;\n const positionConfirmation = await 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 read here, before the write is sent. Liquidity writes execute\n * synchronously, so by the time `confirm()` first polls the effect has already landed: a\n * baseline taken on that first poll would already include it, and an add or partial remove\n * would never be seen to change and would time out. Only a full close needs no baseline\n * (it waits for the position to disappear). If the baseline read fails the write is still\n * sent and the closure falls back to taking the baseline on its first poll.\n */\n private async buildPositionConfirmation(\n confirmation: PositionSubmitConfirmation | undefined,\n owner: string | undefined,\n ): Promise<((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 const toBaseline = (current: Position | null) => ({\n liquidity: new BigNumber(current?.liquidity ?? 0),\n fees: new BigNumber(current?.fees0 ?? 0).plus(new BigNumber(current?.fees1 ?? 0)),\n });\n let baseline: { liquidity: BigNumber; fees: BigNumber } | undefined;\n if (kind !== 'removeFull') {\n try {\n baseline = toBaseline(await this.getPosition({ ...identity, owner }));\n } catch {\n baseline = undefined;\n }\n }\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 = toBaseline(current);\n // A full close starting from \"already gone\" (e.g. a retried confirm after the position\n // was already swept) is confirmed immediately rather than waiting for a change that\n // already happened.\n return kind === 'removeFull' && current === null\n ? { confirmed: true, position: null }\n : { confirmed: false };\n }\n\n switch (kind) {\n case 'add':\n return current !== null &&\n new BigNumber(current.liquidity).isGreaterThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removePartial':\n return current !== null && new BigNumber(current.liquidity).isLessThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removeFull':\n return current === null ? { confirmed: true, position: null } : { confirmed: false };\n case 'collect': {\n if (current === null) return { confirmed: false };\n const currentFees = new BigNumber(current.fees0 ?? 0).plus(\n new BigNumber(current.fees1 ?? 0),\n );\n if (currentFees.isLessThan(baseline.fees)) return { confirmed: true, position: current };\n // Nothing to sweep in the first place — a legitimate no-op collect never moves\n // fees, so \"still zero\" is the confirmed outcome, not an unconfirmed one.\n if (baseline.fees.isZero() && currentFees.isZero())\n return { confirmed: true, position: current };\n return { confirmed: false };\n }\n }\n };\n }\n\n private async get<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData>> {\n return this.http.sendGetRequest<BackendEnvelope<TData>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n signal === undefined ? undefined : { signal },\n );\n }\n\n private async getNullable<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData> | null> {\n try {\n return await this.get<TData>(endpoint, params, signal);\n } catch (error: unknown) {\n if (this.isNotFound(error)) return null;\n throw error;\n }\n }\n\n private isNotFound(error: unknown): boolean {\n return isGSwapError(error) && error.status === 404;\n }\n\n private canonicalTicks(tickLower: number, tickUpper: number, flipped: boolean) {\n return flipped ? { tickLower: -tickUpper, tickUpper: -tickLower } : { tickLower, tickUpper };\n }\n\n private tickSpacing(fee: number): number {\n const spacing = (TICK_SPACING_BY_FEE as Record<number, number>)[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n }\n\n /** The caller's `uniqueKey` (validated), else a fresh one. */\n private uniqueKeyFor(supplied: string | undefined): string {\n if (supplied === undefined) return createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(supplied);\n return supplied;\n }\n\n /**\n * The pair in canonical order. A resolver failure that is not an SDK error (an app's own\n * resolver, an app requestor's rejection during the registry read) is `TOKEN_RESOLUTION_FAILED`.\n */\n private orderPair(a: TokenRef, b: TokenRef) {\n return resolvePreSend(`${rawTokenOf(a)}/${rawTokenOf(b)}`, () => this.symbols.orderPair(a, b));\n }\n\n private async resolveCreateToken(\n ref: TokenRef,\n symbolOverride?: string,\n ): Promise<ResolvedCreateToken> {\n try {\n const lookupRef = typeof ref === 'object' ? compositeKeyOf(ref) : ref;\n const resolved = await resolvePreSend(rawTokenOf(ref), () => this.symbols.resolve(lookupRef));\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError('SYMBOL_DISAGREES_WITH_REGISTRY', {\n token: rawTokenOf(ref),\n suppliedSymbol: symbolOverride,\n registeredSymbol: resolved.symbol,\n });\n }\n const suppliedClassKey = this.tryParseClassKey(ref);\n if (suppliedClassKey === undefined && resolved.collection === '') {\n // An offline resolver knows a bare symbol but not its class key; a pool needs the key.\n throw new GSwapSDKError('CREATE_POOL_NEEDS_CLASS_KEY', { token: rawTokenOf(ref) });\n }\n return {\n symbol: resolved.symbol,\n classKey:\n suppliedClassKey ??\n parseTokenClassKey({\n collection: resolved.collection,\n category: resolved.category,\n type: resolved.type,\n additionalKey: resolved.additionalKey,\n }),\n };\n } catch (error: unknown) {\n if (!isGSwapError(error, 'UNKNOWN_TOKEN')) {\n throw error;\n }\n let classKey: ReturnType<typeof parseTokenClassKey>;\n try {\n classKey = parseTokenClassKey(ref);\n } catch {\n throw error;\n }\n // First-time registration: a class key carries NO symbol (collection and symbol disagree\n // for many tokens, launchpad tokens all share collection `Token`, and some collections\n // contain `$`), so the symbol to propose must be supplied by the caller from the token\n // class / registry. Never derive it from the key.\n if (symbolOverride === undefined || symbolOverride === '') {\n throw new GSwapSDKError('TOKEN_SYMBOL_NOT_REGISTERED', { token: rawTokenOf(ref) });\n }\n if (!isProposableTradingSymbol(symbolOverride)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol: symbolOverride });\n }\n return { symbol: symbolOverride, classKey };\n }\n }\n\n private tryParseClassKey(ref: TokenRef): ReturnType<typeof parseTokenClassKey> | undefined {\n try {\n return parseTokenClassKey(ref);\n } catch {\n return undefined;\n }\n }\n}\n\nconst REQUIRED_POSITION_STRINGS = [\n 'token0Symbol',\n 'token1Symbol',\n 'owner',\n 'liquidity',\n 'amount0',\n 'amount1',\n] as const;\nconst REQUIRED_POSITION_NUMBERS = ['fee', 'tickLower', 'tickUpper'] as const;\nconst OPTIONAL_POSITION_STRINGS = [\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'sqrtPrice',\n 'fees0',\n 'fees1',\n] as const;\n\n/**\n * Reads one position row of `/positions` or `/position`: the pair, owner, range, liquidity and\n * amounts must be usable; the composite keys, token images, current tick and price, and the\n * escrowed fees are carried when present. `pool` is the pool reference (`poolRef` wins over\n * `pool`; `''` when the row names neither).\n */\nfunction parsePosition(value: unknown): EntryParse<Position> {\n const wire = asEntryRecord(value);\n if (wire === undefined) return entryRejected('the row is not an object');\n for (const key of REQUIRED_POSITION_STRINGS) {\n if (typeof wire[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n for (const key of REQUIRED_POSITION_NUMBERS) {\n const number = wire[key];\n if (typeof number !== 'number' || !Number.isFinite(number)) {\n return entryRejected(`${key} is not a number`);\n }\n }\n if (typeof wire['inRange'] !== 'boolean') return entryRejected('inRange is not a boolean');\n for (const key of OPTIONAL_POSITION_STRINGS) {\n if (wire[key] !== undefined && typeof wire[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n const currentTick = wire['currentTick'];\n if (\n currentTick !== undefined &&\n (typeof currentTick !== 'number' || !Number.isFinite(currentTick))\n ) {\n return entryRejected('currentTick is not a number');\n }\n const pool = wire['poolRef'] ?? wire['pool'] ?? '';\n if (typeof pool !== 'string') return entryRejected('pool is not a string');\n const optional = Object.fromEntries(\n [...OPTIONAL_POSITION_STRINGS, 'currentTick' as const].flatMap((key) =>\n wire[key] === undefined ? [] : [[key, wire[key]]],\n ),\n );\n return entryOk({\n token0Symbol: wire['token0Symbol'] as string,\n token1Symbol: wire['token1Symbol'] as string,\n fee: wire['fee'] as number,\n tickLower: wire['tickLower'] as number,\n tickUpper: wire['tickUpper'] as number,\n liquidity: wire['liquidity'] as string,\n amount0: wire['amount0'] as string,\n amount1: wire['amount1'] as string,\n inRange: wire['inRange'],\n pool,\n owner: wire['owner'] as string,\n ...optional,\n });\n}\n\n/** The position inside a `/position` answer, or `INVALID_CHAIN_RESPONSE` when it is not one. */\nfunction readPositionBody(data: unknown): Position {\n const parsed = parsePosition(data);\n if (parsed.ok) return parsed.value;\n throw new GSwapSDKError(\n 'INVALID_POSITION_RESPONSE',\n { reason: parsed.reason },\n { body: data, write: false },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"positions.js","names":["_defineProperty","BigNumber","identityOf","dto","Positions","gateway","symbols","signer","walletAddress","userRef","HttpClient","resolveUniqueKeyPrefix","options","response","owner","readEntries","parsePosition","args","signal","readPositionBody","position","error","isGSwapError","GSwapSDKError","rawTokenOf","pair","ticks","validateNumericAmount","validateFee","assertTickRange","base","buildAddLiquidityDto","assertCanonicalV2Dto","minPrice","maxPrice","spacing","tickLower","alignTickDown","tickFromPrice","tickUpper","alignTickUp","canonical0","canonical1","buildRemoveLiquidityDto","isFullClose","buildCollectPositionFeesDto","hasPrice","tokenA","tokenB","flipped","token0","token1","sourcePriceInput","sourcePrice","canonicalPrice","shared","buildCreatePoolDto","transaction","signed","signPreSend","DEX_CONTRACT_PATH","method","submitOptions","positionConfirmation","confirmation","fee","toBaseline","current","baseline","kind","identity","currentFees","endpoint","params","TICK_SPACING_BY_FEE","ALLOWED_FEE_TIERS_TEXT","value","parameterName","supplied","createUniqueKey","assertUniqueKey","resolvePreSend","a","b","lookupRef","ref","compositeKeyOf","resolved","symbolOverride","suppliedClassKey","parseTokenClassKey","classKey","isProposableTradingSymbol","REQUIRED_POSITION_STRINGS","REQUIRED_POSITION_NUMBERS","OPTIONAL_POSITION_STRINGS","wire","asEntryRecord","entryRejected","key","number","\"inRange\"","currentTick","\"currentTick\"","pool","\"poolRef\"","\"pool\"","optional","entryOk","\"token0Symbol\"","\"token1Symbol\"","\"fee\"","\"tickLower\"","\"tickUpper\"","\"liquidity\"","\"amount0\"","\"amount1\"","\"owner\"","parsed","data"],"sources":["../../../src/classes/positions.ts"],"sourcesContent":["import {\n assertUniqueKey,\n compositeKeyOf,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n signPreSend,\n type GalaChainSigner,\n type UniqueKeyOptions,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport { DEX_CONTRACT_PATH } from '../utils/chain_contract.js';\nimport BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './gswap_error_catalog.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport type { ChainGateway, ChainSubmitOptions } from './gateway.js';\nimport type { PositionConfirmationResult, SubmittedTransaction } from './submitted_transaction.js';\nimport { HttpClient } from './http_client.js';\nimport { 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 {\n asEntryRecord,\n entryOk,\n entryRejected,\n readEntries,\n type EntryParse,\n type InvalidEntryHandler,\n} from '../utils/lenient.js';\nimport { type TokenRef, parseTokenClassKey } from '../utils/ordering.js';\nimport { resolvePreSend } from '../utils/resolve_pre_send.js';\nimport {\n isProposableTradingSymbol,\n validateFee,\n userRef,\n validateNumericAmount,\n} from '../utils/validation.js';\nimport { tickFromPrice } from '../utils/tick_math.js';\nimport { alignTickDown, alignTickUp, assertTickRange } from '../utils/ticks.js';\nimport {\n assertCanonicalV2Dto,\n buildAddLiquidityDto,\n buildCollectPositionFeesDto,\n buildCreatePoolDto,\n buildRemoveLiquidityDto,\n} from '../utils/dto_builders.js';\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 walletAddress?: string,\n options: PositionsOptions = {},\n ) {\n this.walletAddress =\n walletAddress === undefined ? undefined : userRef(walletAddress, 'walletAddress');\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 /** The signing wallet in the gateway's spelling (`eth|<EIP-55>` or `client|<id>`). */\n private readonly walletAddress: string | undefined;\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: userRef(owner, 'owner') });\n return readEntries('positions', response.data, parsePosition, this.onInvalidEntry);\n }\n\n /**\n * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.\n * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.\n *\n * @param args - Pair, owner, fee, and position tick range.\n * @returns The position, or `null` when the backend returns 404.\n * @example\n * ```typescript\n * const position = await gSwap.positions.getPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async getPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<Position | null> {\n const response = await this.getNullable<unknown>(\n '/position',\n await this.positionParams(args),\n signal,\n );\n return response === null ? null : readPositionBody(response.data);\n }\n\n /**\n * Reads one position and classifies the outcome instead of throwing: `found` with the position\n * (fees included), `not_found` (the backend's HTTP 404, which it sends only when the chain\n * itself has no such position) or `unknown` (any other failure, carried as `error`). Use it\n * to confirm a write: `unknown` is \"no evidence either way\", never a confirmed absence.\n *\n * Only the caller's own abort rethrows. With a pass-through resolver ({@link CanonicalSymbols})\n * the pair and ticks go to the backend exactly as given and the backend orients them.\n *\n * @example\n * ```typescript\n * const read = await gSwap.positions.readPosition({\n * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',\n * fee: 3000, tickLower: -19200, tickUpper: 12000,\n * });\n * if (read.kind === 'found') console.log(read.data.fees0);\n * ```\n */\n async readPosition(\n args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n owner: string;\n tickLower: number;\n tickUpper: number;\n },\n signal?: AbortSignal,\n ): Promise<PositionRead> {\n try {\n const position = await this.getPosition(args, signal);\n return position === null ? { kind: 'not_found' } : { kind: 'found', data: position };\n } catch (error: unknown) {\n if (signal?.aborted === true) throw error;\n return {\n kind: 'unknown',\n error: isGSwapError(error)\n ? error\n : new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'position' },\n { cause: error, write: false },\n ),\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 // The backend matches `owner` against the chain's position owner with strict equality, so\n // only the chain's own spelling (`eth|<EIP-55>`) finds a position.\n const owner = userRef(args.owner, 'owner');\n if (this.symbols.passthrough === true) {\n return {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n owner,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n };\n }\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n return {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: `${args.fee}`,\n owner,\n tickLower: `${ticks.tickLower}`,\n tickUpper: `${ticks.tickUpper}`,\n };\n }\n\n /**\n * Estimates the other token amount and resulting liquidity for a deposit.\n *\n * @param args - Pair, tick range, deposit amount, and the amount's caller-side token index.\n * @returns Backend liquidity estimate.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async estimateAddLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n amount: NumericAmount;\n amountIsToken0: boolean;\n }): Promise<AddLiquidityEstimate> {\n validateNumericAmount(args.amount, 'amount');\n const response = await this.get<AddLiquidityEstimateWire>('/add-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n amount: new BigNumber(args.amount).toFixed(),\n amountIsToken0: String(args.amountIsToken0),\n });\n return response.data;\n }\n\n /**\n * Estimates token amounts released by burning liquidity.\n *\n * @param args - Pair, tick range, fee tier, and liquidity quantity.\n * @returns Estimated token0 and token1 quantities.\n * @example\n * ```typescript\n * const estimate = await gSwap.positions.estimateRemoveLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, liquidity: '1000',\n * });\n * ```\n */\n async estimateRemoveLiquidity(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n tickLower: number;\n tickUpper: number;\n liquidity: NumericAmount;\n }): Promise<RemoveLiquidityEstimate> {\n validateNumericAmount(args.liquidity, 'liquidity');\n const response = await this.get<RemoveLiquidityEstimateWire>('/remove-liq-estimate', {\n token0: rawTokenOf(args.token0),\n token1: rawTokenOf(args.token1),\n fee: `${args.fee}`,\n tickLower: `${args.tickLower}`,\n tickUpper: `${args.tickUpper}`,\n liquidity: new BigNumber(args.liquidity).toFixed(),\n });\n return response.data;\n }\n\n /**\n * Adds liquidity using an explicit tick range. Exactly one canonical deposit field is emitted.\n *\n * @param args - Pair, fee, range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByTicks({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * await tx.confirm();\n * ```\n */\n async addLiquidityByTicks(args: AddLiquidityArgs) {\n return this.submitAddLiquidity(await this.buildAddLiquidity(args));\n }\n\n /**\n * Builds the AddLiquidity DTO that {@link addLiquidityByTicks} would sign, without signing or\n * sending it: to show in an approval popup, or to sign elsewhere. Submit exactly this DTO with\n * {@link submitAddLiquidity}. The pure counterpart, with canonical inputs and no resolution,\n * is `buildAddLiquidityDto`.\n *\n * @example\n * ```typescript\n * const dto = await gSwap.positions.buildAddLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async buildAddLiquidity(args: AddLiquidityArgs): Promise<AddLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n // Caller-facing checks first, so a refusal names the caller's own argument (`amount`).\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n validateNumericAmount(args.amount, 'amount');\n const base = {\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n };\n return pair.flipped !== args.amountIsToken0\n ? buildAddLiquidityDto({ ...base, depositQuantityToken0: args.amount })\n : buildAddLiquidityDto({ ...base, depositQuantityToken1: args.amount });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildAddLiquidity} or `buildAddLiquidityDto`; it must\n * be exactly what the builder produces. The returned transaction confirms by proving the\n * position's liquidity grew.\n */\n async submitAddLiquidity(dto: AddLiquidityDTO) {\n assertCanonicalV2Dto('AddLiquidity', dto);\n return this.submit('AddLiquidity', dto, { kind: 'add', identity: identityOf(dto) });\n }\n\n /**\n * Adds liquidity from prices, flooring the lower tick and ceiling the upper tick to fee spacing.\n * The resulting range is therefore no narrower than the requested price interval.\n *\n * @param args - Pair, fee, price range, deposit amount, and caller-side token index.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.addLiquidityByPrice({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * minPrice: '0.14', maxPrice: '0.16', amount: '100', amountIsToken0: true,\n * });\n * ```\n */\n async addLiquidityByPrice(args: {\n token0: TokenRef;\n token1: TokenRef;\n fee: FEE_TIER;\n minPrice: PriceIn;\n maxPrice: PriceIn;\n amount: NumericAmount;\n amountIsToken0: boolean;\n /** The attempt's `uniqueKey`; default a fresh one (see {@link AddLiquidityArgs.uniqueKey}). */\n uniqueKey?: string | undefined;\n }) {\n validateFee(args.fee);\n this.rejectNumber(args.minPrice, 'minPrice');\n this.rejectNumber(args.maxPrice, 'maxPrice');\n const minPrice = new BigNumber(args.minPrice);\n const maxPrice = new BigNumber(args.maxPrice);\n if (\n !minPrice.isFinite() ||\n !maxPrice.isFinite() ||\n minPrice.isLessThanOrEqualTo(0) ||\n maxPrice.isLessThanOrEqualTo(0)\n ) {\n throw new GSwapSDKError('INVALID_PRICE_BOUNDS', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n if (minPrice.isGreaterThan(maxPrice)) {\n throw new GSwapSDKError('PRICE_BOUNDS_ORDER', {\n minPrice: String(args.minPrice),\n maxPrice: String(args.maxPrice),\n });\n }\n const spacing = this.tickSpacing(args.fee);\n const tickLower = alignTickDown(tickFromPrice(minPrice), spacing);\n const tickUpper = alignTickUp(tickFromPrice(maxPrice), spacing);\n return this.addLiquidityByTicks({\n token0: args.token0,\n token1: args.token1,\n fee: args.fee,\n tickLower,\n tickUpper,\n amount: args.amount,\n amountIsToken0: args.amountIsToken0,\n uniqueKey: args.uniqueKey,\n });\n }\n\n /**\n * Removes liquidity by withdrawing at most one canonical token quantity.\n * Omitting both amounts closes the position and sweeps all accrued fees.\n *\n * @param args - Pair, fee, range, and optional caller-side withdrawal amount.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.removeLiquidity({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async removeLiquidity(args: RemoveLiquidityArgs) {\n return this.submitRemoveLiquidity(await this.buildRemoveLiquidity(args));\n }\n\n /**\n * Builds the RemoveLiquidity DTO that {@link removeLiquidity} would sign, without signing or\n * sending it. Submit exactly this DTO with {@link submitRemoveLiquidity}. The pure counterpart\n * is `buildRemoveLiquidityDto`.\n */\n async buildRemoveLiquidity(args: RemoveLiquidityArgs): Promise<RemoveLiquidityDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n if (args.amount0 !== undefined && args.amount1 !== undefined) {\n throw new GSwapSDKError('AT_MOST_ONE_OF_ALLOWED', { first: 'amount0', second: 'amount1' });\n }\n if (args.amount0 !== undefined) validateNumericAmount(args.amount0, 'amount0');\n if (args.amount1 !== undefined) validateNumericAmount(args.amount1, 'amount1');\n // The caller's amount0 / amount1 follow the caller's pair; the DTO's follow the canonical one.\n const [canonical0, canonical1] = pair.flipped\n ? [args.amount1, args.amount0]\n : [args.amount0, args.amount1];\n return buildRemoveLiquidityDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n withdrawalQuantityToken0: canonical0,\n withdrawalQuantityToken1: canonical1,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildRemoveLiquidity} or `buildRemoveLiquidityDto`;\n * it must be exactly what the builder produces. A DTO with no withdrawal quantity closes the\n * position, and the returned transaction then confirms by proving the position is gone.\n */\n async submitRemoveLiquidity(dto: RemoveLiquidityDTO) {\n assertCanonicalV2Dto('RemoveLiquidity', dto);\n const isFullClose =\n dto.withdrawalQuantityToken0 === undefined && dto.withdrawalQuantityToken1 === undefined;\n return this.submit('RemoveLiquidity', dto, {\n kind: isFullClose ? 'removeFull' : 'removePartial',\n identity: identityOf(dto),\n });\n }\n\n /**\n * Collects all accrued fees for a position; the contract does not support partial collection.\n *\n * @param args - Pair, fee, and tick range identifying the position.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.collectPositionFees({\n * token0: 'GALA', token1: 'GUSDC', fee: 3000,\n * tickLower: -19200, tickUpper: 12000,\n * });\n * ```\n */\n async collectPositionFees(args: CollectPositionFeesArgs) {\n return this.submitCollectPositionFees(await this.buildCollectPositionFees(args));\n }\n\n /**\n * Builds the CollectPositionFees DTO that {@link collectPositionFees} would sign, without\n * signing or sending it. Submit exactly this DTO with {@link submitCollectPositionFees}. The\n * pure counterpart is `buildCollectPositionFeesDto`.\n */\n async buildCollectPositionFees(args: CollectPositionFeesArgs): Promise<CollectPositionFeesDTO> {\n validateFee(args.fee);\n const pair = await this.orderPair(args.token0, args.token1);\n const ticks = this.canonicalTicks(args.tickLower, args.tickUpper, pair.flipped);\n assertTickRange(ticks.tickLower, ticks.tickUpper, args.fee);\n return buildCollectPositionFeesDto({\n token0: pair.token0.symbol,\n token1: pair.token1.symbol,\n fee: args.fee,\n tickLower: ticks.tickLower,\n tickUpper: ticks.tickUpper,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCollectPositionFees} or\n * `buildCollectPositionFeesDto`; it must be exactly what the builder produces.\n */\n async submitCollectPositionFees(dto: CollectPositionFeesDTO) {\n assertCanonicalV2Dto('CollectPositionFees', dto);\n return this.submit('CollectPositionFees', dto, { kind: 'collect', identity: identityOf(dto) });\n }\n\n /**\n * Creates a pool, resolving registered trading symbols.\n * Reversed symbol order inverts the supplied starting price or square-root price.\n *\n * A token class key carries no symbol, so for a token being proposed into the v2\n * trading-symbol registry for the first time (no existing pool has registered it yet) the\n * caller MUST pass `token0Symbol`/`token1Symbol` (the token class's symbol, from the token\n * list or FetchTokenClasses). The SDK never derives a symbol from the key, and throws a\n * TOKEN_SYMBOL_NOT_REGISTERED error when an unregistered token has none. For an already-registered token a\n * supplied symbol must match the registered one.\n *\n * @param args - Token class keys or references, fee, exactly one starting price field, and privacy options.\n * @returns The synchronously submitted transaction.\n * @example\n * ```typescript\n * const tx = await gSwap.positions.createPool({\n * token0: 'GALA|Unit|none|none', token1: 'GUSDC|Unit|none|none', fee: 3000,\n * startingPrice: '0.15',\n * });\n * ```\n */\n async createPool(args: CreatePoolArgs) {\n return this.submitCreatePool(await this.buildCreatePool(args));\n }\n\n /**\n * Builds the CreatePool DTO that {@link createPool} would sign, without signing or sending it:\n * symbols resolved or proposed, the pair put in canonical order and the price inverted when it\n * was reversed. Submit exactly this DTO with {@link submitCreatePool}. The pure counterpart,\n * with canonical inputs, is `buildCreatePoolDto`.\n */\n async buildCreatePool(args: CreatePoolArgs): Promise<CreatePoolDTO> {\n const hasPrice = args.startingPrice !== undefined;\n const hasSqrtPrice = args.startingSqrtPrice !== undefined;\n if (hasPrice === hasSqrtPrice) {\n throw new GSwapSDKError('EXACTLY_ONE_OF_REQUIRED', {\n first: 'startingPrice',\n second: 'startingSqrtPrice',\n });\n }\n validateFee(args.fee);\n const [tokenA, tokenB] = await Promise.all([\n this.resolveCreateToken(args.token0, args.token0Symbol),\n this.resolveCreateToken(args.token1, args.token1Symbol),\n ]);\n const flipped = tokenA.symbol > tokenB.symbol;\n const [token0, token1] = flipped ? [tokenB, tokenA] : [tokenA, tokenB];\n const sourcePriceInput = hasPrice\n ? (args.startingPrice as NumericAmount)\n : (args.startingSqrtPrice as NumericAmount);\n this.rejectNumber(sourcePriceInput, hasPrice ? 'startingPrice' : 'startingSqrtPrice');\n const sourcePrice = new BigNumber(sourcePriceInput);\n if (!sourcePrice.isFinite() || sourcePrice.isLessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_STARTING_PRICE', { value: String(sourcePriceInput) });\n }\n const canonicalPrice = flipped ? new BigNumber(1).dividedBy(sourcePrice) : sourcePrice;\n const shared = {\n token0Key: token0.classKey,\n token1Key: token1.classKey,\n token0Symbol: token0.symbol,\n token1Symbol: token1.symbol,\n fee: args.fee,\n uniqueKey: this.uniqueKeyFor(args.uniqueKey),\n name: args.name,\n isPrivate: args.isPrivate,\n privateAccess: args.privateAccess,\n };\n return hasPrice\n ? buildCreatePoolDto({ ...shared, startingPrice: canonicalPrice })\n : buildCreatePoolDto({ ...shared, startingSqrtPrice: canonicalPrice });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildCreatePool} or `buildCreatePoolDto`; it must be\n * exactly what the builder produces. The returned transaction confirms by the pool existing, and\n * the cached symbol registry is dropped, since the pool may have registered new symbols.\n */\n async submitCreatePool(dto: CreatePoolDTO) {\n assertCanonicalV2Dto('CreatePool', dto);\n const transaction = await this.submit('CreatePool', dto, {\n kind: 'createPool',\n token0: dto.token0Symbol,\n token1: dto.token1Symbol,\n fee: dto.fee,\n });\n this.symbols.invalidate?.();\n return transaction;\n }\n\n private async submit(\n method: string,\n dto: Record<string, unknown>,\n confirmation?: PositionSubmitConfirmation,\n ) {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const signed = await signPreSend(this.signer, DEX_CONTRACT_PATH, method, dto);\n const submitOptions =\n this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n const owner = this.walletAddress;\n const positionConfirmation = await 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 read here, before the write is sent. Liquidity writes execute\n * synchronously, so by the time `confirm()` first polls the effect has already landed: a\n * baseline taken on that first poll would already include it, and an add or partial remove\n * would never be seen to change and would time out. Only a full close needs no baseline\n * (it waits for the position to disappear). If the baseline read fails the write is still\n * sent and the closure falls back to taking the baseline on its first poll.\n */\n private async buildPositionConfirmation(\n confirmation: PositionSubmitConfirmation | undefined,\n owner: string | undefined,\n ): Promise<((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 const toBaseline = (current: Position | null) => ({\n liquidity: new BigNumber(current?.liquidity ?? 0),\n fees: new BigNumber(current?.fees0 ?? 0).plus(new BigNumber(current?.fees1 ?? 0)),\n });\n let baseline: { liquidity: BigNumber; fees: BigNumber } | undefined;\n if (kind !== 'removeFull') {\n try {\n baseline = toBaseline(await this.getPosition({ ...identity, owner }));\n } catch {\n baseline = undefined;\n }\n }\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 = toBaseline(current);\n // A full close starting from \"already gone\" (e.g. a retried confirm after the position\n // was already swept) is confirmed immediately rather than waiting for a change that\n // already happened.\n return kind === 'removeFull' && current === null\n ? { confirmed: true, position: null }\n : { confirmed: false };\n }\n\n switch (kind) {\n case 'add':\n return current !== null &&\n new BigNumber(current.liquidity).isGreaterThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removePartial':\n return current !== null && new BigNumber(current.liquidity).isLessThan(baseline.liquidity)\n ? { confirmed: true, position: current }\n : { confirmed: false };\n case 'removeFull':\n return current === null ? { confirmed: true, position: null } : { confirmed: false };\n case 'collect': {\n if (current === null) return { confirmed: false };\n const currentFees = new BigNumber(current.fees0 ?? 0).plus(\n new BigNumber(current.fees1 ?? 0),\n );\n if (currentFees.isLessThan(baseline.fees)) return { confirmed: true, position: current };\n // Nothing to sweep in the first place — a legitimate no-op collect never moves\n // fees, so \"still zero\" is the confirmed outcome, not an unconfirmed one.\n if (baseline.fees.isZero() && currentFees.isZero())\n return { confirmed: true, position: current };\n return { confirmed: false };\n }\n }\n };\n }\n\n private async get<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData>> {\n return this.http.sendGetRequest<BackendEnvelope<TData>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n endpoint,\n params,\n signal === undefined ? undefined : { signal },\n );\n }\n\n private async getNullable<TData>(\n endpoint: string,\n params: Record<string, string>,\n signal?: AbortSignal,\n ): Promise<BackendEnvelope<TData> | null> {\n try {\n return await this.get<TData>(endpoint, params, signal);\n } catch (error: unknown) {\n if (this.isNotFound(error)) return null;\n throw error;\n }\n }\n\n private isNotFound(error: unknown): boolean {\n return isGSwapError(error) && error.status === 404;\n }\n\n private canonicalTicks(tickLower: number, tickUpper: number, flipped: boolean) {\n return flipped ? { tickLower: -tickUpper, tickUpper: -tickLower } : { tickLower, tickUpper };\n }\n\n private tickSpacing(fee: number): number {\n const spacing = (TICK_SPACING_BY_FEE as Record<number, number>)[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n return spacing;\n }\n\n private rejectNumber(value: unknown, parameterName: string): void {\n if (typeof value === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n }\n\n /** The caller's `uniqueKey` (validated), else a fresh one. */\n private uniqueKeyFor(supplied: string | undefined): string {\n if (supplied === undefined) return createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(supplied);\n return supplied;\n }\n\n /**\n * The pair in canonical order. A resolver failure that is not an SDK error (an app's own\n * resolver, an app requestor's rejection during the registry read) is `TOKEN_RESOLUTION_FAILED`.\n */\n private orderPair(a: TokenRef, b: TokenRef) {\n return resolvePreSend(`${rawTokenOf(a)}/${rawTokenOf(b)}`, () => this.symbols.orderPair(a, b));\n }\n\n private async resolveCreateToken(\n ref: TokenRef,\n symbolOverride?: string,\n ): Promise<ResolvedCreateToken> {\n try {\n const lookupRef = typeof ref === 'object' ? compositeKeyOf(ref) : ref;\n const resolved = await resolvePreSend(rawTokenOf(ref), () => this.symbols.resolve(lookupRef));\n if (\n symbolOverride !== undefined &&\n symbolOverride !== '' &&\n symbolOverride !== resolved.symbol\n ) {\n throw new GSwapSDKError('SYMBOL_DISAGREES_WITH_REGISTRY', {\n token: rawTokenOf(ref),\n suppliedSymbol: symbolOverride,\n registeredSymbol: resolved.symbol,\n });\n }\n const suppliedClassKey = this.tryParseClassKey(ref);\n if (suppliedClassKey === undefined && resolved.collection === '') {\n // An offline resolver knows a bare symbol but not its class key; a pool needs the key.\n throw new GSwapSDKError('CREATE_POOL_NEEDS_CLASS_KEY', { token: rawTokenOf(ref) });\n }\n return {\n symbol: resolved.symbol,\n classKey:\n suppliedClassKey ??\n parseTokenClassKey({\n collection: resolved.collection,\n category: resolved.category,\n type: resolved.type,\n additionalKey: resolved.additionalKey,\n }),\n };\n } catch (error: unknown) {\n if (!isGSwapError(error, 'UNKNOWN_TOKEN')) {\n throw error;\n }\n let classKey: ReturnType<typeof parseTokenClassKey>;\n try {\n classKey = parseTokenClassKey(ref);\n } catch {\n throw error;\n }\n // First-time registration: a class key carries NO symbol (collection and symbol disagree\n // for many tokens, launchpad tokens all share collection `Token`, and some collections\n // contain `$`), so the symbol to propose must be supplied by the caller from the token\n // class / registry. Never derive it from the key.\n if (symbolOverride === undefined || symbolOverride === '') {\n throw new GSwapSDKError('TOKEN_SYMBOL_NOT_REGISTERED', { token: rawTokenOf(ref) });\n }\n if (!isProposableTradingSymbol(symbolOverride)) {\n throw new GSwapSDKError('INVALID_TRADING_SYMBOL', { symbol: symbolOverride });\n }\n return { symbol: symbolOverride, classKey };\n }\n }\n\n private tryParseClassKey(ref: TokenRef): ReturnType<typeof parseTokenClassKey> | undefined {\n try {\n return parseTokenClassKey(ref);\n } catch {\n return undefined;\n }\n }\n}\n\nconst REQUIRED_POSITION_STRINGS = [\n 'token0Symbol',\n 'token1Symbol',\n 'owner',\n 'liquidity',\n 'amount0',\n 'amount1',\n] as const;\nconst REQUIRED_POSITION_NUMBERS = ['fee', 'tickLower', 'tickUpper'] as const;\nconst OPTIONAL_POSITION_STRINGS = [\n 'token0CompositeKey',\n 'token1CompositeKey',\n 'token0Image',\n 'token1Image',\n 'sqrtPrice',\n 'fees0',\n 'fees1',\n] as const;\n\n/**\n * Reads one position row of `/positions` or `/position`: the pair, owner, range, liquidity and\n * amounts must be usable; the composite keys, token images, current tick and price, and the\n * escrowed fees are carried when present. `pool` is the pool reference (`poolRef` wins over\n * `pool`; `''` when the row names neither).\n */\nfunction parsePosition(value: unknown): EntryParse<Position> {\n const wire = asEntryRecord(value);\n if (wire === undefined) return entryRejected('the row is not an object');\n for (const key of REQUIRED_POSITION_STRINGS) {\n if (typeof wire[key] !== 'string') return entryRejected(`${key} is not a string`);\n }\n for (const key of REQUIRED_POSITION_NUMBERS) {\n const number = wire[key];\n if (typeof number !== 'number' || !Number.isFinite(number)) {\n return entryRejected(`${key} is not a number`);\n }\n }\n if (typeof wire['inRange'] !== 'boolean') return entryRejected('inRange is not a boolean');\n for (const key of OPTIONAL_POSITION_STRINGS) {\n if (wire[key] !== undefined && typeof wire[key] !== 'string') {\n return entryRejected(`${key} is not a string`);\n }\n }\n const currentTick = wire['currentTick'];\n if (\n currentTick !== undefined &&\n (typeof currentTick !== 'number' || !Number.isFinite(currentTick))\n ) {\n return entryRejected('currentTick is not a number');\n }\n const pool = wire['poolRef'] ?? wire['pool'] ?? '';\n if (typeof pool !== 'string') return entryRejected('pool is not a string');\n const optional = Object.fromEntries(\n [...OPTIONAL_POSITION_STRINGS, 'currentTick' as const].flatMap((key) =>\n wire[key] === undefined ? [] : [[key, wire[key]]],\n ),\n );\n return entryOk({\n token0Symbol: wire['token0Symbol'] as string,\n token1Symbol: wire['token1Symbol'] as string,\n fee: wire['fee'] as number,\n tickLower: wire['tickLower'] as number,\n tickUpper: wire['tickUpper'] as number,\n liquidity: wire['liquidity'] as string,\n amount0: wire['amount0'] as string,\n amount1: wire['amount1'] as string,\n inRange: wire['inRange'],\n pool,\n owner: wire['owner'] as string,\n ...optional,\n });\n}\n\n/** The position inside a `/position` answer, or `INVALID_CHAIN_RESPONSE` when it is not one. */\nfunction readPositionBody(data: unknown): Position {\n const parsed = parsePosition(data);\n if (parsed.ok) return parsed.value;\n throw new GSwapSDKError(\n 'INVALID_POSITION_RESPONSE',\n { reason: parsed.reason },\n { body: data, write: false },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{readServerMessage as e}from"../utils/server_message.js";import{ALLOWED_FEE_TIERS_TEXT as t}from"./gswap_error_catalog.js";import n from"../_virtual/_@oxc-project_runtime@0.
|
|
1
|
+
import{readServerMessage as e}from"../utils/server_message.js";import{ALLOWED_FEE_TIERS_TEXT as t}from"./gswap_error_catalog.js";import n from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as r,isGSwapError as i}from"./gswap_sdk_error.js";import{ALL_FEE_TIERS as a}from"../types/fees.js";import{validateNumericAmount as o}from"../utils/validation.js";import{HttpClient as s}from"./http_client.js";import{queryTokenOf as c}from"./symbols.js";import l from"bignumber.js";var u=class{constructor(e,t){this.gateway=e,this.symbols=t,n(this,`http`,void 0),this.http=new s(e.httpRequestor,e.requestTimeoutMs??3e4,e.wire)}async quoteExactInput(e,t,n,r){return o(n,`amountIn`),this.quote(e,t,{amountIn:x(n)},r)}async quoteExactOutput(e,t,n,r){return o(n,`amountOut`),this.quote(e,t,{amountOut:x(n)},r)}async quote(e,t,n,r){b(r);let i={tokenIn:await c(this.symbols,e),tokenOut:await c(this.symbols,t),...n};r!==void 0&&(i.fee=String(r));try{return d((await this.http.sendGetRequest(this.gateway.dexBackendBaseUrl,`/v2/trade`,`/quote`,i)).data)}catch(n){throw y(n,e,t,r,{tokenIn:i.tokenIn??``,tokenOut:i.tokenOut??``})}}};function d(e){if(!m(e))throw new r(`INVALID_CHAIN_RESPONSE`,{resource:`quote`},{body:e,write:!1});let t=e,n=t.currentPrice===void 0?p(t.currentSqrtPrice,t.tokenInIsToken0):new l(t.currentPrice),i=t.newPrice===void 0?p(t.newSqrtPrice,t.tokenInIsToken0):new l(t.newPrice),a=i.minus(n).dividedBy(n);return{contractVersion:t.contractVersion,fee:t.fee,amountIn:t.amountIn,amountOut:t.amountOut,...t.currentSqrtPrice===void 0?{}:{currentSqrtPrice:t.currentSqrtPrice},...t.newSqrtPrice===void 0?{}:{newSqrtPrice:t.newSqrtPrice},feeTier:t.fee,newTick:t.newTick,tradingFees:t.tradingFees,protocolFees:t.protocolFees,totalFees:t.totalFees,feeTokenSymbol:t.feeTokenSymbol,token0Symbol:t.token0Symbol,token1Symbol:t.token1Symbol,tokenInIsToken0:t.tokenInIsToken0,currentPrice:n,newPrice:i,priceImpact:a}}const f=l.clone({DECIMAL_PLACES:60});function p(e,t){let n=new f(e).pow(2);return t?n:new f(1).dividedBy(n)}function m(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.contractVersion===`v2`&&typeof t.fee==`number`&&Number.isFinite(t.fee)&&[`amountIn`,`amountOut`,`tradingFees`,`protocolFees`,`totalFees`,`feeTokenSymbol`,`token0Symbol`,`token1Symbol`].every(e=>typeof t[e]==`string`)&&typeof t.newTick==`number`&&Number.isInteger(t.newTick)&&typeof t.tokenInIsToken0==`boolean`&&h(t.currentSqrtPrice)&&h(t.newSqrtPrice)&&h(t.currentPrice)&&h(t.newPrice)&&(t.currentSqrtPrice!==void 0||t.currentPrice!==void 0)&&(t.newSqrtPrice!==void 0||t.newPrice!==void 0)}function h(e){if(e===void 0)return!0;if(typeof e!=`string`)return!1;try{let t=new l(e);return t.isFinite()&&t.isGreaterThan(0)}catch{return!1}}const g=/no pool|no pools|pool does not exist/iu,_=/Token (\S+) has no trading symbol on the new DEX contract/u;function v(e,t,n,r){return e===t.tokenIn?n:e===t.tokenOut?r:e}function y(t,n,a,o,s){if(i(t)){let i=e(t)??``,c=_.exec(i)?.[1];return c===void 0?t.status===404||g.test(i)?r.noPoolAvailableError(n,a,o,t):t.status===400&&/insufficient liquidity/iu.test(i)?r.insufficientLiquidityError(n,a,o,t):t:r.unknownTokenError(v(c,s,n,a),t)}return new r(`REQUEST_FAILED`,{operation:`quote`},{cause:t,write:!1})}function b(e){if(e!==void 0&&!a.some(t=>Number(t)===Number(e)))throw new r(`INVALID_FEE`,{field:`fee`,value:Number(e),allowed:t})}function x(e){return new l(e).toFixed()}export{u as Quoting};
|
|
2
2
|
//# sourceMappingURL=quoting.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quoting.js","names":["_defineProperty","BigNumber","Quoting","gateway","symbols","HttpClient","validateNumericAmount","amountIn","tokenIn","tokenOut","toDecimalString","fee","amountOut","validateOptionalFee","params","queryTokenOf","amount","\"fee\"","mapQuote","error","mapQuoteError","\"tokenIn\"","\"tokenOut\"","isQuoteWire","value","GSwapSDKError","wire","currentPrice","orientPrice","newPrice","priceImpact","HighPrecision","poolPrice","sqrtPrice","tokenInIsToken0","\"contractVersion\"","key","\"newTick\"","\"tokenInIsToken0\"","optionalPositiveDecimal","\"currentSqrtPrice\"","\"newSqrtPrice\"","\"currentPrice\"","\"newPrice\"","decimal","NO_MARKET_MESSAGE","NO_SYMBOL_MESSAGE","unknownTokenOf","echoed","queried","isGSwapError","message","readServerMessage","unregistered","ALL_FEE_TIERS","tier","ALLOWED_FEE_TIERS_TEXT"],"sources":["../../../src/classes/quoting.ts"],"sourcesContent":["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 '@gala-chain/gala-core-sdk';\nimport type { ChainGateway } from './gateway.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './gswap_error_catalog.js';\nimport { readServerMessage } from '../utils/server_message.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, type TokenResolver } from './symbols.js';\n\ninterface QuoteWire {\n contractVersion: 'v2';\n fee: number;\n amountIn: string;\n amountOut: string;\n currentSqrtPrice?: string;\n newSqrtPrice?: string;\n currentPrice?: string;\n newPrice?: string;\n newTick: number;\n tradingFees: string;\n protocolFees: string;\n totalFees: string;\n feeTokenSymbol: string;\n token0Symbol: string;\n token1Symbol: string;\n tokenInIsToken0: boolean;\n}\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\n/** The transport a quote service reads through: the same shape `Pools` and `Symbols` take. */\ntype QuoteGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** Read-only quote service backed by the v2 offline quote engine. */\nexport class Quoting {\n /**\n * Creates a quote service.\n *\n * @example\n * ```ts\n * const quoting = new Quoting(gateway, symbols); // a ChainGateway, or any { dexBackendBaseUrl, httpRequestor }\n * ```\n */\n constructor(\n private readonly gateway: QuoteGateway,\n private readonly symbols: TokenResolver,\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Quotes the output for a positive exact-input amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactInput('GALA', 'GUSDC', '100');\n * console.log(quote.amountOut);\n * ```\n */\n public async quoteExactInput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountIn: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountIn, 'amountIn');\n return this.quote(tokenIn, tokenOut, { amountIn: toDecimalString(amountIn) }, fee);\n }\n\n /**\n * Quotes the input for a positive exact-output amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactOutput('GALA', 'GUSDC', '10', 3000);\n * console.log(quote.amountIn);\n * ```\n */\n public async quoteExactOutput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountOut: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountOut, 'amountOut');\n return this.quote(tokenIn, tokenOut, { amountOut: toDecimalString(amountOut) }, fee);\n }\n\n private async quote(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amount: { amountIn: string } | { amountOut: string },\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateOptionalFee(fee);\n\n const params: Record<string, string> = {\n tokenIn: await queryTokenOf(this.symbols, tokenIn),\n tokenOut: await queryTokenOf(this.symbols, tokenOut),\n ...amount,\n };\n if (fee !== undefined) params['fee'] = String(fee);\n\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<QuoteWire>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/quote',\n params,\n );\n return mapQuote(response.data);\n } catch (error: unknown) {\n throw mapQuoteError(error, tokenIn, tokenOut, fee, {\n tokenIn: params['tokenIn'] ?? '',\n tokenOut: params['tokenOut'] ?? '',\n });\n }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: 'quote' },\n { body: value, write: false },\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: no pool at ANY fee tier (\"No pools found\n * with sufficient liquidity\") or a missing pool (\"Pool does not exist on the new DEX contract\").\n * A pool that exists but is too thin says \"Insufficient liquidity: ...\" instead.\n */\nconst NO_MARKET_MESSAGE = /no pool|no pools|pool does not exist/iu;\n\n/**\n * A token the DEX contract never registered: the backend's symbol registry answers\n * `Token <token> has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`\n * with an HTTP 400, naming the token exactly as the quote request sent it. That is a different\n * fact from \"no pool for this pair\" (the token itself is unknown), so it is `UNKNOWN_TOKEN` with\n * the token, not `NO_POOL_AVAILABLE`. Token class keys and symbols contain no whitespace.\n */\nconst NO_SYMBOL_MESSAGE = /Token (\\S+) has no trading symbol on the new DEX contract/u;\n\n/** The token the quote request named in the form the caller gave it, else as the backend echoed it. */\nfunction unknownTokenOf(\n echoed: string,\n queried: { tokenIn: string; tokenOut: string },\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n): TokenRef {\n if (echoed === queried.tokenIn) return tokenIn;\n if (echoed === queried.tokenOut) return tokenOut;\n return echoed;\n}\n\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n queried: { tokenIn: string; tokenOut: string },\n): GSwapSDKError {\n if (isGSwapError(error)) {\n // The backend's own English is read ONLY to classify its answer; it is never surfaced. The\n // SDK's generated `message` is never matched: its templates are not a contract.\n const message = readServerMessage(error) ?? '';\n const unregistered = NO_SYMBOL_MESSAGE.exec(message)?.[1];\n if (unregistered !== undefined) {\n return GSwapSDKError.unknownTokenError(\n unknownTokenOf(unregistered, queried, tokenIn, tokenOut),\n error,\n );\n }\n if (error.status === 404 || NO_MARKET_MESSAGE.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee, error);\n }\n if (error.status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee, error);\n }\n return error;\n }\n return new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'quote' },\n { cause: error, write: false },\n );\n}\n\nfunction validateOptionalFee(fee: FEE_TIER | undefined): void {\n if (fee !== undefined && !ALL_FEE_TIERS.some((tier) => Number(tier) === Number(fee))) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: Number(fee),\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"quoting.js","names":["_defineProperty","BigNumber","Quoting","gateway","symbols","HttpClient","validateNumericAmount","amountIn","tokenIn","tokenOut","toDecimalString","fee","amountOut","validateOptionalFee","params","queryTokenOf","amount","\"fee\"","mapQuote","error","mapQuoteError","\"tokenIn\"","\"tokenOut\"","isQuoteWire","value","GSwapSDKError","wire","currentPrice","orientPrice","newPrice","priceImpact","HighPrecision","poolPrice","sqrtPrice","tokenInIsToken0","\"contractVersion\"","key","\"newTick\"","\"tokenInIsToken0\"","optionalPositiveDecimal","\"currentSqrtPrice\"","\"newSqrtPrice\"","\"currentPrice\"","\"newPrice\"","decimal","NO_MARKET_MESSAGE","NO_SYMBOL_MESSAGE","unknownTokenOf","echoed","queried","isGSwapError","message","readServerMessage","unregistered","ALL_FEE_TIERS","tier","ALLOWED_FEE_TIERS_TEXT"],"sources":["../../../src/classes/quoting.ts"],"sourcesContent":["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 '@gala-chain/gala-core-sdk';\nimport type { ChainGateway } from './gateway.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from './gswap_error_catalog.js';\nimport { readServerMessage } from '../utils/server_message.js';\nimport { GSwapSDKError, isGSwapError } from './gswap_sdk_error.js';\nimport { HttpClient } from './http_client.js';\nimport { queryTokenOf, type TokenResolver } from './symbols.js';\n\ninterface QuoteWire {\n contractVersion: 'v2';\n fee: number;\n amountIn: string;\n amountOut: string;\n currentSqrtPrice?: string;\n newSqrtPrice?: string;\n currentPrice?: string;\n newPrice?: string;\n newTick: number;\n tradingFees: string;\n protocolFees: string;\n totalFees: string;\n feeTokenSymbol: string;\n token0Symbol: string;\n token1Symbol: string;\n tokenInIsToken0: boolean;\n}\n\ninterface BackendEnvelope<T> {\n data: T;\n}\n\n/** The transport a quote service reads through: the same shape `Pools` and `Symbols` take. */\ntype QuoteGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {\n requestTimeoutMs?: number | undefined;\n wire?: WireOptions | undefined;\n};\n\n/** Read-only quote service backed by the v2 offline quote engine. */\nexport class Quoting {\n /**\n * Creates a quote service.\n *\n * @example\n * ```ts\n * const quoting = new Quoting(gateway, symbols); // a ChainGateway, or any { dexBackendBaseUrl, httpRequestor }\n * ```\n */\n constructor(\n private readonly gateway: QuoteGateway,\n private readonly symbols: TokenResolver,\n ) {\n this.http = new HttpClient(\n gateway.httpRequestor,\n gateway.requestTimeoutMs ?? 30_000,\n gateway.wire,\n );\n }\n\n private readonly http: HttpClient;\n\n /**\n * Quotes the output for a positive exact-input amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactInput('GALA', 'GUSDC', '100');\n * console.log(quote.amountOut);\n * ```\n */\n public async quoteExactInput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountIn: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountIn, 'amountIn');\n return this.quote(tokenIn, tokenOut, { amountIn: toDecimalString(amountIn) }, fee);\n }\n\n /**\n * Quotes the input for a positive exact-output amount.\n *\n * @example\n * ```ts\n * const quote = await quoting.quoteExactOutput('GALA', 'GUSDC', '10', 3000);\n * console.log(quote.amountIn);\n * ```\n */\n public async quoteExactOutput(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amountOut: NumericAmount,\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateNumericAmount(amountOut, 'amountOut');\n return this.quote(tokenIn, tokenOut, { amountOut: toDecimalString(amountOut) }, fee);\n }\n\n private async quote(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n amount: { amountIn: string } | { amountOut: string },\n fee?: FEE_TIER,\n ): Promise<QuoteResult> {\n validateOptionalFee(fee);\n\n const params: Record<string, string> = {\n tokenIn: await queryTokenOf(this.symbols, tokenIn),\n tokenOut: await queryTokenOf(this.symbols, tokenOut),\n ...amount,\n };\n if (fee !== undefined) params['fee'] = String(fee);\n\n try {\n const response = await this.http.sendGetRequest<BackendEnvelope<QuoteWire>>(\n this.gateway.dexBackendBaseUrl,\n '/v2/trade',\n '/quote',\n params,\n );\n return mapQuote(response.data);\n } catch (error: unknown) {\n throw mapQuoteError(error, tokenIn, tokenOut, fee, {\n tokenIn: params['tokenIn'] ?? '',\n tokenOut: params['tokenOut'] ?? '',\n });\n }\n }\n}\n\nfunction mapQuote(value: unknown): QuoteResult {\n if (!isQuoteWire(value)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: 'quote' },\n { body: value, write: false },\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: no pool at ANY fee tier (\"No pools found\n * with sufficient liquidity\") or a missing pool (\"Pool does not exist on the new DEX contract\").\n * A pool that exists but is too thin says \"Insufficient liquidity: ...\" instead.\n */\nconst NO_MARKET_MESSAGE = /no pool|no pools|pool does not exist/iu;\n\n/**\n * A token the DEX contract never registered: the backend's symbol registry answers\n * `Token <token> has no trading symbol on the new DEX contract (no gcdex pool includes it yet).`\n * with an HTTP 400, naming the token exactly as the quote request sent it. That is a different\n * fact from \"no pool for this pair\" (the token itself is unknown), so it is `UNKNOWN_TOKEN` with\n * the token, not `NO_POOL_AVAILABLE`. Token class keys and symbols contain no whitespace.\n */\nconst NO_SYMBOL_MESSAGE = /Token (\\S+) has no trading symbol on the new DEX contract/u;\n\n/** The token the quote request named in the form the caller gave it, else as the backend echoed it. */\nfunction unknownTokenOf(\n echoed: string,\n queried: { tokenIn: string; tokenOut: string },\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n): TokenRef {\n if (echoed === queried.tokenIn) return tokenIn;\n if (echoed === queried.tokenOut) return tokenOut;\n return echoed;\n}\n\nfunction mapQuoteError(\n error: unknown,\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER | undefined,\n queried: { tokenIn: string; tokenOut: string },\n): GSwapSDKError {\n if (isGSwapError(error)) {\n // The backend's own English is read ONLY to classify its answer; it is never surfaced. The\n // SDK's generated `message` is never matched: its templates are not a contract.\n const message = readServerMessage(error) ?? '';\n const unregistered = NO_SYMBOL_MESSAGE.exec(message)?.[1];\n if (unregistered !== undefined) {\n return GSwapSDKError.unknownTokenError(\n unknownTokenOf(unregistered, queried, tokenIn, tokenOut),\n error,\n );\n }\n if (error.status === 404 || NO_MARKET_MESSAGE.test(message)) {\n return GSwapSDKError.noPoolAvailableError(tokenIn, tokenOut, fee, error);\n }\n if (error.status === 400 && /insufficient liquidity/iu.test(message)) {\n return GSwapSDKError.insufficientLiquidityError(tokenIn, tokenOut, fee, error);\n }\n return error;\n }\n return new GSwapSDKError(\n 'REQUEST_FAILED',\n { operation: 'quote' },\n { cause: error, write: false },\n );\n}\n\nfunction validateOptionalFee(fee: FEE_TIER | undefined): void {\n if (fee !== undefined && !ALL_FEE_TIERS.some((tier) => Number(tier) === Number(fee))) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: Number(fee),\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\nfunction toDecimalString(amount: NumericAmount): string {\n return new BigNumber(amount).toFixed();\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shadow_submit.js","names":["SHADOW_SUBMIT_CODES","SHADOW_FAILURE_KINDS","classifyShadowSubmitStatus","status","classifyShadowSubmitError","code","readShadowSubmitOutcome","result","envelope","asRecord","body","httpStatus","\"error\"","data","\"data\"","rawTransactionId","\"transactionId\"","method","requestedKey","signedBody","\"uniqueKey\"","\"mode\"","GSwapSDKError","kind","getStringProperty","value"],"sources":["../../../src/classes/shadow_submit.ts"],"sourcesContent":["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 the swap backend returns in a shadow failure body (`{ code, message }`, with\n * no `statusCode`; the HTTP status carries the number).\n *\n * - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back\n * silently to a public swap.\n * - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.\n * - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;\n * `message` is the gateway's verbatim string.\n */\nexport const SHADOW_SUBMIT_CODES = [\n 'SHADOW_UNAVAILABLE',\n 'SHADOW_UNSUPPORTED_TYPE',\n 'SHADOW_RELAY_REJECTED',\n] as const;\n\n/** One member of {@link SHADOW_SUBMIT_CODES}. */\nexport type ShadowSubmitCode = (typeof SHADOW_SUBMIT_CODES)[number];\n\n/**\n * Every `kind` of a failed {@link ShadowSubmitOutcome}, for an app that maps each to its own text\n * (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled` (the shadow route\n * answered 400: the request is not a dark-swappable one, e.g. `SHADOW_UNSUPPORTED_TYPE`; Shadow\n * Swaps themselves are enabled in every environment), `rejected` (carries the gateway's `message`)\n * and `unknown`.\n */\nexport const SHADOW_FAILURE_KINDS = ['unavailable', 'disabled', 'rejected', 'unknown'] as const;\n\n/** One member of {@link SHADOW_FAILURE_KINDS}. */\nexport type ShadowFailureKind = (typeof SHADOW_FAILURE_KINDS)[number];\n\n/** A RequestTrade the gateway queued: the handle to confirm it with `confirmAppliedTrade`. */\nexport interface ShadowQueuedRequest {\n uniqueKey: string;\n requestTransactionId: string | null;\n}\n\n/** A shadow write the gateway refused or did not answer: `kind` says why (see {@link SHADOW_FAILURE_KINDS}). */\nexport type ShadowSubmitFailure =\n | { ok: false; kind: 'unavailable'; retryable: true }\n | { ok: false; kind: 'disabled'; retryable: false }\n | { ok: false; kind: 'rejected'; retryable: false; message: string }\n | { ok: false; kind: 'unknown'; retryable: false };\n\n/**\n * The normalized outcome of a shadow RequestTrade (a dark swap). A success (`ok: true`) ALWAYS\n * carries `queued`, the exact key the gateway acknowledged: a RequestTrade answer that does not\n * queue the signed key is not an outcome but a thrown `SHADOW_NOT_QUEUED`. So after `if (outcome.ok)`\n * the app reads `outcome.queued` with no `undefined` branch.\n */\nexport type ShadowSubmitOutcome =\n | {\n ok: true;\n /** The request transaction id (`''` when the gateway gave none). */\n bundleId: string;\n /** Confirm with `confirmAppliedTrade`. */\n queued: ShadowQueuedRequest;\n }\n | ShadowSubmitFailure;\n\n/**\n * The success of a shadow write that is NOT a RequestTrade and executed synchronously\n * (`mode: 'sync'`, a liquidity write): there is nothing queued to confirm, so `queued` is absent.\n */\nexport interface ShadowSyncSuccess {\n ok: true;\n /** The transaction id (`''` when the gateway gave none). */\n bundleId: string;\n queued?: undefined;\n}\n\n/** Maps an HTTP status to a failure kind: 503 retryable, 400 disabled, anything else unknown. */\nexport function classifyShadowSubmitStatus(status: number): ShadowFailureKind {\n if (status === 503) return 'unavailable';\n if (status === 400) return 'disabled';\n return 'unknown';\n}\n\n/**\n * Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.\n * `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway\n * rejection; `SHADOW_UNSUPPORTED_TYPE` and any other 400 map to \"disabled\".\n */\nexport function classifyShadowSubmitError(status: number, code?: string): ShadowFailureKind {\n if (code === 'SHADOW_UNAVAILABLE') return 'unavailable';\n if (code === 'SHADOW_RELAY_REJECTED') return 'rejected';\n if (code === 'SHADOW_UNSUPPORTED_TYPE') return 'disabled';\n return classifyShadowSubmitStatus(status);\n}\n\n/**\n * Normalizes a shadow write's raw answer. For `'RequestTrade'` the result is a\n * {@link ShadowSubmitOutcome}, whose success always has `queued`; any other method may also be a\n * {@link ShadowSyncSuccess} (no `queued`).\n *\n * A 2xx envelope with `error === false` is a success when it is a queued RequestTrade that\n * acknowledges the EXACT signed `uniqueKey`, or a synchronous (`mode: 'sync'`) liquidity write.\n * Everything else is classified as a failure from the status and the body's `code`.\n *\n * @throws GSwapSDKError SHADOW_NOT_QUEUED when a RequestTrade success does not queue the\n * signed `uniqueKey` (a synchronous or mismatched answer must never be accepted as a swap).\n */\nexport function readShadowSubmitOutcome(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess {\n const { httpStatus, body } = result;\n const envelope = asRecord(body);\n if (httpStatus >= 200 && httpStatus < 300 && envelope?.['error'] === false) {\n const data = asRecord(envelope['data']);\n const rawTransactionId =\n typeof data?.['transactionId'] === 'string' ? data['transactionId'] : undefined;\n if (method === 'RequestTrade') {\n const requestedKey = signedBody['uniqueKey'];\n if (\n data?.['mode'] !== 'queued' ||\n typeof requestedKey !== 'string' ||\n data['uniqueKey'] !== requestedKey\n ) {\n throw new GSwapSDKError(\n 'SHADOW_NOT_QUEUED',\n {},\n {\n status: httpStatus,\n body,\n shadow: true,\n ...(typeof requestedKey === 'string' ? { uniqueKey: requestedKey } : {}),\n },\n );\n }\n return {\n ok: true,\n bundleId: rawTransactionId ?? '',\n queued: { uniqueKey: requestedKey, requestTransactionId: rawTransactionId ?? null },\n };\n }\n if (data?.['mode'] === 'sync') return { ok: true, bundleId: rawTransactionId ?? '' };\n }\n\n const kind = classifyShadowSubmitError(httpStatus, getStringProperty(body, 'code'));\n if (kind === 'rejected') {\n return {\n ok: false,\n kind: 'rejected',\n retryable: false,\n message: getStringProperty(body, 'message') ?? '',\n };\n }\n return kind === 'unavailable'\n ? { ok: false, kind, retryable: true }\n : { ok: false, kind, retryable: false };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":"4EAmBA,MAAaA,EAAsB,CACjC,qBACA,0BACA,uBACF,EAYaC,EAAuB,CAAC,cAAe,WAAY,WAAY,SAAS,EA8CrF,SAAgBC,EAA2B,EAAmC,CAG5E,OAFIC,IAAW,IAAY,cACvBA,IAAW,IAAY,WACpB,SACT,CAOA,SAAgBC,EAA0B,EAAgB,EAAkC,CAI1F,OAHIC,IAAS,qBAA6B,cACtCA,IAAS,wBAAgC,WACzCA,IAAS,0BAAkC,WACxCH,EAA2BC,CAAM,CAC1C,CAwBA,SAAgBG,EACd,EACA,EACA,EACyC,CACzC,GAAM,CAAE,aAAY,QAASC,EACvBC,EAAWC,EAASC,CAAI,EAC9B,GAAIC,GAAc,KAAOA,EAAa,KAAOH,GAAWI,QAAa,GAAO,CAC1E,IAAMC,EAAOJ,EAASD,EAASM,IAAO,EAChCC,EACJ,OAAOF,GAAOG,eAAqB,SAAWH,EAAKG,cAAmB,IAAA,GACxE,GAAIC,IAAW,eAAgB,CAC7B,IAAMC,EAAeC,EAAWC,UAChC,GACEP,GAAOQ,OAAY,UACnB,OAAOH,GAAiB,UACxBL,EAAKO,YAAiBF,EAEtB,MAAM,IAAII,EACR,oBACA,CAAC,EACD,CACE,OAAQX,EACR,OACA,OAAQ,GACR,GAAI,OAAOO,GAAiB,SAAW,CAAE,UAAWA,CAAa,EAAI,CAAC,CACxE,CACF,EAEF,MAAO,CACL,GAAI,GACJ,SAAUH,GAAoB,GAC9B,OAAQ,CAAE,UAAWG,EAAc,qBAAsBH,GAAoB,IAAK,CACpF,CACF,CACA,GAAIF,GAAOQ,OAAY,OAAQ,MAAO,CAAE,GAAI,GAAM,SAAUN,GAAoB,EAAG,CACrF,CAEA,IAAMQ,EAAOnB,EAA0BO,EAAYa,EAAkBd,EAAM,MAAM,CAAC,EASlF,OARIa,IAAS,WACJ,CACL,GAAI,GACJ,KAAM,WACN,UAAW,GACX,QAASC,EAAkBd,EAAM,SAAS,GAAK,EACjD,EAEKa,IAAS,cACZ,CAAE,GAAI,GAAO,OAAM,UAAW,EAAK,EACnC,CAAE,GAAI,GAAO,OAAM,UAAW,EAAM,CAC1C,CAEA,SAASd,EAAS,EAAqD,CACrE,OAAO,OAAOgB,GAAU,UAAYA,EAC/BA,EACD,IAAA,EACN"}
|
|
1
|
+
{"version":3,"file":"shadow_submit.js","names":["SHADOW_SUBMIT_CODES","SHADOW_FAILURE_KINDS","classifyShadowSubmitStatus","status","classifyShadowSubmitError","code","readShadowSubmitOutcome","result","envelope","asRecord","body","httpStatus","\"error\"","data","\"data\"","rawTransactionId","\"transactionId\"","method","requestedKey","signedBody","\"uniqueKey\"","\"mode\"","GSwapSDKError","kind","getStringProperty","value"],"sources":["../../../src/classes/shadow_submit.ts"],"sourcesContent":["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 the swap backend returns in a shadow failure body (`{ code, message }`, with\n * no `statusCode`; the HTTP status carries the number).\n *\n * - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back\n * silently to a public swap.\n * - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.\n * - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;\n * `message` is the gateway's verbatim string.\n */\nexport const SHADOW_SUBMIT_CODES = [\n 'SHADOW_UNAVAILABLE',\n 'SHADOW_UNSUPPORTED_TYPE',\n 'SHADOW_RELAY_REJECTED',\n] as const;\n\n/** One member of {@link SHADOW_SUBMIT_CODES}. */\nexport type ShadowSubmitCode = (typeof SHADOW_SUBMIT_CODES)[number];\n\n/**\n * Every `kind` of a failed {@link ShadowSubmitOutcome}, for an app that maps each to its own text\n * (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled` (the shadow route\n * answered 400: the request is not a dark-swappable one, e.g. `SHADOW_UNSUPPORTED_TYPE`; Shadow\n * Swaps themselves are enabled in every environment), `rejected` (carries the gateway's `message`)\n * and `unknown`.\n */\nexport const SHADOW_FAILURE_KINDS = ['unavailable', 'disabled', 'rejected', 'unknown'] as const;\n\n/** One member of {@link SHADOW_FAILURE_KINDS}. */\nexport type ShadowFailureKind = (typeof SHADOW_FAILURE_KINDS)[number];\n\n/** A RequestTrade the gateway queued: the handle to confirm it with `confirmAppliedTrade`. */\nexport interface ShadowQueuedRequest {\n uniqueKey: string;\n requestTransactionId: string | null;\n}\n\n/** A shadow write the gateway refused or did not answer: `kind` says why (see {@link SHADOW_FAILURE_KINDS}). */\nexport type ShadowSubmitFailure =\n | { ok: false; kind: 'unavailable'; retryable: true }\n | { ok: false; kind: 'disabled'; retryable: false }\n | { ok: false; kind: 'rejected'; retryable: false; message: string }\n | { ok: false; kind: 'unknown'; retryable: false };\n\n/**\n * The normalized outcome of a shadow RequestTrade (a dark swap). A success (`ok: true`) ALWAYS\n * carries `queued`, the exact key the gateway acknowledged: a RequestTrade answer that does not\n * queue the signed key is not an outcome but a thrown `SHADOW_NOT_QUEUED`. So after `if (outcome.ok)`\n * the app reads `outcome.queued` with no `undefined` branch.\n */\nexport type ShadowSubmitOutcome =\n | {\n ok: true;\n /** The request transaction id (`''` when the gateway gave none). */\n bundleId: string;\n /** Confirm with `confirmAppliedTrade`. */\n queued: ShadowQueuedRequest;\n }\n | ShadowSubmitFailure;\n\n/**\n * The success of a shadow write that is NOT a RequestTrade and executed synchronously\n * (`mode: 'sync'`, a liquidity write): there is nothing queued to confirm, so `queued` is absent.\n */\nexport interface ShadowSyncSuccess {\n ok: true;\n /** The transaction id (`''` when the gateway gave none). */\n bundleId: string;\n queued?: undefined;\n}\n\n/** Maps an HTTP status to a failure kind: 503 retryable, 400 disabled, anything else unknown. */\nexport function classifyShadowSubmitStatus(status: number): ShadowFailureKind {\n if (status === 503) return 'unavailable';\n if (status === 400) return 'disabled';\n return 'unknown';\n}\n\n/**\n * Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.\n * `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway\n * rejection; `SHADOW_UNSUPPORTED_TYPE` and any other 400 map to \"disabled\".\n */\nexport function classifyShadowSubmitError(status: number, code?: string): ShadowFailureKind {\n if (code === 'SHADOW_UNAVAILABLE') return 'unavailable';\n if (code === 'SHADOW_RELAY_REJECTED') return 'rejected';\n if (code === 'SHADOW_UNSUPPORTED_TYPE') return 'disabled';\n return classifyShadowSubmitStatus(status);\n}\n\n/**\n * Normalizes a shadow write's raw answer. For `'RequestTrade'` the result is a\n * {@link ShadowSubmitOutcome}, whose success always has `queued`; any other method may also be a\n * {@link ShadowSyncSuccess} (no `queued`).\n *\n * A 2xx envelope with `error === false` is a success when it is a queued RequestTrade that\n * acknowledges the EXACT signed `uniqueKey`, or a synchronous (`mode: 'sync'`) liquidity write.\n * Everything else is classified as a failure from the status and the body's `code`.\n *\n * @throws GSwapSDKError SHADOW_NOT_QUEUED when a RequestTrade success does not queue the\n * signed `uniqueKey` (a synchronous or mismatched answer must never be accepted as a swap).\n */\nexport function readShadowSubmitOutcome(\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess;\nexport function readShadowSubmitOutcome(\n method: string,\n signedBody: Record<string, unknown>,\n result: ShadowSubmitResult,\n): ShadowSubmitOutcome | ShadowSyncSuccess {\n const { httpStatus, body } = result;\n const envelope = asRecord(body);\n if (httpStatus >= 200 && httpStatus < 300 && envelope?.['error'] === false) {\n const data = asRecord(envelope['data']);\n const rawTransactionId =\n typeof data?.['transactionId'] === 'string' ? data['transactionId'] : undefined;\n if (method === 'RequestTrade') {\n const requestedKey = signedBody['uniqueKey'];\n if (\n data?.['mode'] !== 'queued' ||\n typeof requestedKey !== 'string' ||\n data['uniqueKey'] !== requestedKey\n ) {\n throw new GSwapSDKError(\n 'SHADOW_NOT_QUEUED',\n {},\n {\n status: httpStatus,\n body,\n shadow: true,\n ...(typeof requestedKey === 'string' ? { uniqueKey: requestedKey } : {}),\n },\n );\n }\n return {\n ok: true,\n bundleId: rawTransactionId ?? '',\n queued: { uniqueKey: requestedKey, requestTransactionId: rawTransactionId ?? null },\n };\n }\n if (data?.['mode'] === 'sync') return { ok: true, bundleId: rawTransactionId ?? '' };\n }\n\n const kind = classifyShadowSubmitError(httpStatus, getStringProperty(body, 'code'));\n if (kind === 'rejected') {\n return {\n ok: false,\n kind: 'rejected',\n retryable: false,\n message: getStringProperty(body, 'message') ?? '',\n };\n }\n return kind === 'unavailable'\n ? { ok: false, kind, retryable: true }\n : { ok: false, kind, retryable: false };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n"],"mappings":"A,4EAmBA,MAAaA,EAAsB,CACjC,qBACA,0BACA,uBACF,EAYaC,EAAuB,CAAC,cAAe,WAAY,WAAY,SAAS,EA8CrF,SAAgBC,EAA2B,EAAmC,CAG5E,OAFIC,IAAW,IAAY,cACvBA,IAAW,IAAY,WACpB,SACT,CAOA,SAAgBC,EAA0B,EAAgB,EAAkC,CAI1F,OAHIC,IAAS,qBAA6B,cACtCA,IAAS,wBAAgC,WACzCA,IAAS,0BAAkC,WACxCH,EAA2BC,CAAM,CAC1C,CAwBA,SAAgBG,EACd,EACA,EACA,EACyC,CACzC,GAAM,CAAE,aAAY,QAASC,EACvBC,EAAWC,EAASC,CAAI,EAC9B,GAAIC,GAAc,KAAOA,EAAa,KAAOH,GAAWI,QAAa,GAAO,CAC1E,IAAMC,EAAOJ,EAASD,EAASM,IAAO,EAChCC,EACJ,OAAOF,GAAOG,eAAqB,SAAWH,EAAKG,cAAmB,IAAA,GACxE,GAAIC,IAAW,eAAgB,CAC7B,IAAMC,EAAeC,EAAWC,UAChC,GACEP,GAAOQ,OAAY,UACnB,OAAOH,GAAiB,UACxBL,EAAKO,YAAiBF,EAEtB,MAAM,IAAII,EACR,oBACA,CAAC,EACD,CACE,OAAQX,EACR,OACA,OAAQ,GACR,GAAI,OAAOO,GAAiB,SAAW,CAAE,UAAWA,CAAa,EAAI,CAAC,CACxE,CACF,EAEF,MAAO,CACL,GAAI,GACJ,SAAUH,GAAoB,GAC9B,OAAQ,CAAE,UAAWG,EAAc,qBAAsBH,GAAoB,IAAK,CACpF,CACF,CACA,GAAIF,GAAOQ,OAAY,OAAQ,MAAO,CAAE,GAAI,GAAM,SAAUN,GAAoB,EAAG,CACrF,CAEA,IAAMQ,EAAOnB,EAA0BO,EAAYa,EAAkBd,EAAM,MAAM,CAAC,EASlF,OARIa,IAAS,WACJ,CACL,GAAI,GACJ,KAAM,WACN,UAAW,GACX,QAASC,EAAkBd,EAAM,SAAS,GAAK,EACjD,EAEKa,IAAS,cACZ,CAAE,GAAI,GAAO,OAAM,UAAW,EAAK,EACnC,CAAE,GAAI,GAAO,OAAM,UAAW,EAAM,CAC1C,CAEA,SAASd,EAAS,EAAqD,CACrE,OAAO,OAAOgB,GAAU,UAAYA,EAC/BA,EACD,IAAA,EACN,C"}
|