@gala-chain/gswap-sdk 2.1.0-beta.5 → 2.1.0-beta.7
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 +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/positions.js +1 -1
- package/dist/browser/classes/positions.js.map +1 -1
- package/dist/browser/classes/swaps.js +1 -1
- package/dist/browser/classes/swaps.js.map +1 -1
- package/dist/index.cjs +4 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ See [Signing and Identity](./docs/other/signing-and-identity.md).
|
|
|
33
33
|
npm install @gala-chain/gswap-sdk@next @gala-chain/gala-core-sdk@next
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
`@gala-chain/gala-core-sdk` is a peer dependency (range <!-- docs:var peer:@gala-chain/gala-core-sdk -->>=1.1.0-beta.
|
|
36
|
+
`@gala-chain/gala-core-sdk` is a peer dependency (range <!-- docs:var peer:@gala-chain/gala-core-sdk -->>=1.1.0-beta.9 <2<!-- /docs:var -->):
|
|
37
37
|
install it next to the SDK. Pin exact versions for a wallet or app build.
|
|
38
38
|
|
|
39
39
|
## 2.0: signing moved to @gala-chain/gala-core-sdk
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as t}from"./gswap_sdk_error.js";import{buildRequestHeaders as n,createUniqueKey as r,fetchRequestor as i,readResponseBody as a,requestWithTimeout as o,
|
|
1
|
+
import e from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as t}from"./gswap_sdk_error.js";import{buildRequestHeaders as n,createUniqueKey as r,fetchRequestor as i,readResponseBody as a,requestWithTimeout as o,signPreSendFor as s}from"@gala-chain/gala-core-sdk";const c=[`Swap`,`RequestTrade`,`AddLiquidity`,`RemoveLiquidity`,`CollectPositionFees`,`CreatePool`],l=`DryRun`,u=`galaconnect-operation-`;function d(e){return typeof e==`string`&&c.includes(e)}function f(e,t){return d(t)&&typeof e?.token0==`string`&&typeof e.token1==`string`}function p(e){return e.replace(/(?:\/+|\/api\/v1(?=\/|$))+$/u,``)}function m(e){let t={...e};for(let e of[`signature`,`prefix`,`types`,`domain`,`dtoOperation`,`trace`])delete t[e];return t}function h(e,t,n,i,a=u,o=`asset/dexv3-contract`){return s(e,o,l,{callerPublicKey:t,method:n,dto:m(i),uniqueKey:r(a)})}var g=class{constructor(t,n){this.signer=n,e(this,`requestor`,void 0),e(this,`baseUrl`,void 0),e(this,`requestTimeoutMs`,void 0),e(this,`wire`,void 0),this.requestor=t.httpRequestor??i,this.baseUrl=p(t.dexBackendBaseUrl),this.requestTimeoutMs=t.requestTimeoutMs??3e4,this.wire=t.wire}async quote(e,r,i,s={}){if(this.signer===void 0)throw t.noSignerError();let c=s.channel??`asset`,l=s.contract??`dexv3-contract`,u=await h(this.signer,e,r,m(i),void 0,`${c}/${l}`),d=`${this.baseUrl}/api/v1/wallet/connect/galachain/api/${encodeURIComponent(c)}/${encodeURIComponent(l)}/${encodeURIComponent(r)}/fee`,f,p,g;try{let e=await o(this.requestor,d,{method:`POST`,headers:n(this.wire,{json:!0,defaults:{Accept:`application/json`}}),body:JSON.stringify(u)},this.requestTimeoutMs);f=e.status,p=e.ok,g=p?await a(e):void 0}catch{return null}return p?_(g):l===`dex-contract`&&f===403?{source:`default`,fees:[{feeInGala:`0`}]}:null}};function _(e){if(typeof e!=`object`||!e)return null;let t=e.fees;return!Array.isArray(t)||typeof t[0]?.feeInGala!=`string`?null:e}export{c as DEX_FEE_METHODS,l as DRY_RUN_METHOD,u as DRY_RUN_UNIQUE_KEY_PREFIX,g as DexFees,h as buildDryRunWrapper,p as dexBackendRoot,f as isCurrentContractDexMessage,d as isDexFeeMethod,m as toChainDto};
|
|
2
2
|
//# sourceMappingURL=dex_fees.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dex_fees.js","names":["_defineProperty","DEX_FEE_METHODS","DRY_RUN_METHOD","DRY_RUN_UNIQUE_KEY_PREFIX","isDexFeeMethod","method","isCurrentContractDexMessage","message","\"token0\"","\"token1\"","dexBackendRoot","base","toChainDto","chainDto","field","buildDryRunWrapper","signPreSend","signer","contractPath","dto","createUniqueKey","uniqueKeyPrefix","DexFees","client","fetchRequestor","GSwapSDKError","channel","options","contract","wrapper","callerPublicKey","url","status","ok","body","response","requestWithTimeout","buildRequestHeaders","readResponseBody","readQuote","fees"],"sources":["../../../src/classes/dex_fees.ts"],"sourcesContent":["import {\n buildRequestHeaders,\n createUniqueKey,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n signPreSend,\n type ChainContractPath,\n type GalaChainSigner,\n type HttpRequestor,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\n/** DEX methods the backend accepts a fee quote for (its allow-list enumerates the same six). */\nexport const DEX_FEE_METHODS = [\n 'Swap',\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n 'CreatePool',\n] as const;\n/** A chain method whose network fee `DexFees.quote` can price (see `isDexFeeMethod`). */\nexport type DexFeeMethod = (typeof DEX_FEE_METHODS)[number];\n\n/** Which pool contract the DTO being quoted targets: legacy (V3) or current (GalaChainDex). */\nexport type DexFeeContract = 'dexv3-contract' | 'dex-contract';\n\n/** The chain method name the signed DryRun wrapper is signed under. */\nexport const DRY_RUN_METHOD = 'DryRun';\n\n/** `uniqueKey` prefix of the DryRun WRAPPER (distinct from the inner DTO's key). */\nexport const DRY_RUN_UNIQUE_KEY_PREFIX = 'galaconnect-operation-';\n\n/** True when `method` is a DEX method a fee can be quoted for. */\nexport function isDexFeeMethod(method: unknown): method is DexFeeMethod {\n return typeof method === 'string' && (DEX_FEE_METHODS as readonly string[]).includes(method);\n}\n\n/** Current-contract typed DEX messages use trading symbols instead of TokenClassKey objects. */\nexport function isCurrentContractDexMessage(\n message: Record<string, unknown> | null | undefined,\n method: unknown,\n): boolean {\n return (\n isDexFeeMethod(method) &&\n typeof message?.['token0'] === 'string' &&\n typeof message['token1'] === 'string'\n );\n}\n\n/**\n * The backend's response. It ALWAYS carries a usable `fees[0].feeInGala`: the backend decides what\n * to serve when the chain cannot price the operation, so the client never invents a fee.\n *\n * `source` is informational: `'dry-run'` is simulated on chain and authoritative (possibly a\n * legitimate `'0'`), `'default'` means the chain could not price it and the platform default was\n * served.\n */\nexport interface DexFeeQuote {\n fees: Array<{ feeInGala: string }>;\n source: 'dry-run' | 'default';\n}\n\n/** The wallet-connect proxy's fee route, below the backend root (stage, 2026-11-02: only this prefix exists). */\nconst FEE_ROUTE_PREFIX = '/api/v1/wallet/connect/galachain/api';\n\n/**\n * The backend root a fee quote is built on: `base` without trailing slashes and without a trailing\n * `/api/v1` (the wallet passes the versioned base, the SDK presets the host root). Idempotent.\n *\n * @example\n * ```typescript\n * dexBackendRoot('https://swap-backend.stage.defi.ovh.gala.com/api/v1/'); // 'https://swap-backend.stage.defi.ovh.gala.com'\n * ```\n */\nexport function dexBackendRoot(base: string): string {\n return base.replace(/(?:\\/+|\\/api\\/v1(?=\\/|$))+$/u, '');\n}\n\n/**\n * Reduces an EIP-712 approval `message` to the DTO the chain actually receives: drops the signing\n * envelope (`signature`, `prefix`, `types`, `domain`), the `dtoOperation` it was signed to call (a\n * DryRun runs the DTO inside a wrapper signed for `DryRun`; left inside, the chain refuses it:\n * \"signed to call ...:RequestTrade, but the current operation is ...:DryRun\") and transport\n * metadata (`trace`).\n */\nexport function toChainDto(message: Record<string, unknown>): Record<string, unknown> {\n const chainDto: Record<string, unknown> = { ...message };\n for (const field of ['signature', 'prefix', 'types', 'domain', 'dtoOperation', 'trace']) {\n delete chainDto[field];\n }\n return chainDto;\n}\n\n/**\n * Signs the DryRun WRAPPER the gateway accepts for every contract:\n * `{ callerPublicKey, method, dto: <inner DTO object>, uniqueKey, signature }`. The inner DTO\n * travels unsigned and as an object; no `signerPublicKey` is sent because the signature already\n * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own\n * `uniqueKey`, distinct from the DTO's, and its own `dtoOperation` (`<Contract>:DryRun`); the inner DTO\n * carries none of the signing envelope or the `dtoOperation` of the call it simulates (see\n * {@link toChainDto}), whatever the caller passes, so a signed DTO can be handed in as is.\n */\nexport function buildDryRunWrapper(\n signer: GalaChainSigner,\n callerPublicKey: string,\n method: string,\n dto: Record<string, unknown>,\n uniqueKeyPrefix: string = DRY_RUN_UNIQUE_KEY_PREFIX,\n contractPath: ChainContractPath = 'asset/dexv3-contract',\n): Promise<Record<string, unknown>> {\n return signPreSend(signer, contractPath, DRY_RUN_METHOD, {\n callerPublicKey,\n method,\n dto: toChainDto(dto),\n // Core's RN-safe mint (`getRandomValues`, never `randomUUID`, which Hermes lacks).\n uniqueKey: createUniqueKey(uniqueKeyPrefix),\n });\n}\n\n/** The transport and backend a fee quote reads from. */\nexport interface DexFeesClient {\n /**\n * Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com`. A base that already ends in\n * `/api/v1` (what the wallet passes) and trailing slashes are accepted: the request goes to the\n * same URL either way (see {@link dexBackendRoot}).\n */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-request timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /**\n * Request headers of the fee POST (`userAgent`, `headers`); see {@link WireOptions}. The SDK's\n * `Accept: application/json` is a default that `wire.headers` may replace.\n */\n wire?: WireOptions | undefined;\n}\n\n/** Options for a single quote. */\nexport interface DexFeeQuoteOptions {\n /** GalaChain channel. Default `asset`. */\n channel?: string | undefined;\n /**\n * Contract the DTO targets. Default `dexv3-contract` (what every legacy caller quotes against);\n * a current-contract operation must pass `dex-contract` explicitly.\n */\n contract?: DexFeeContract | undefined;\n}\n\n/**\n * Network-fee quote for GalaChain DEX methods, derived from a server-side DryRun.\n *\n * The client only SIGNS the DryRun wrapper (with whatever {@link GalaChainSigner} it is given) and\n * the backend forwards it to the gateway, where the simulated writes carry the fee; the backend\n * never holds a key. Intended for wallets: the DTO quoted is the typed message a dApp handed over.\n *\n * @example\n * ```ts\n * const fees = new DexFees({ dexBackendBaseUrl }, new PrivateKeySigner(sessionKey));\n * const quote = await fees.quote(publicKey, 'RequestTrade', toChainDto(message), {\n * contract: 'dex-contract',\n * });\n * const feeInGala = quote?.fees[0]?.feeInGala;\n * ```\n */\nexport class DexFees {\n private readonly requestor: HttpRequestor;\n private readonly baseUrl: string;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n\n constructor(\n client: DexFeesClient,\n private readonly signer: GalaChainSigner | undefined,\n ) {\n this.requestor = client.httpRequestor ?? fetchRequestor;\n this.baseUrl = dexBackendRoot(client.dexBackendBaseUrl);\n this.requestTimeoutMs = client.requestTimeoutMs ?? 30_000;\n this.wire = client.wire;\n }\n\n /**\n * Quotes the network fee for `method` applied to `message`. The message is reduced with\n * {@link toChainDto} first, so an EIP-712 approval message can be passed as is.\n *\n * Resolves `null` when the BACKEND could not be reached or answered unusably (offline, 4xx/5xx,\n * malformed body): a transport outcome, not a fee. Deciding what to charge when the chain is\n * silent is the backend's job (it serves `source: 'default'`), so the client never substitutes\n * a fee of its own, with ONE exception that mirrors the wallet: a `dex-contract` quote answered\n * 403 means the contract has no fee route yet and resolves `{ source: 'default', '0' }`. A 404 is\n * a wrong path, not \"no fee route\": it resolves `null`, never a default. The request always goes\n * to `<root>/api/v1/wallet/connect/galachain/api/{channel}/{contract}/{method}/fee`, whether the\n * client's base URL is the host root or already ends in `/api/v1`.\n * Never throws on transport, so a fee lookup cannot block or break a signing screen.\n *\n * @throws GSwapSDKError NO_SIGNER when constructed without a signer; `SIGNING_FAILED` or\n * `KEY_PROVIDER_FAILED` (a pre-send error, the original as `cause`) when the signer fails, for\n * example a locked wallet.\n */\n public async quote(\n callerPublicKey: string,\n method: DexFeeMethod,\n message: Record<string, unknown>,\n options: DexFeeQuoteOptions = {},\n ): Promise<DexFeeQuote | null> {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const channel = options.channel ?? 'asset';\n const contract = options.contract ?? 'dexv3-contract';\n const wrapper = await buildDryRunWrapper(\n this.signer,\n callerPublicKey,\n method,\n toChainDto(message),\n undefined,\n `asset/${contract}`,\n );\n const url = `${this.baseUrl}${FEE_ROUTE_PREFIX}/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;\n\n let status: number;\n let ok: boolean;\n let body: unknown;\n try {\n const response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers: buildRequestHeaders(this.wire, {\n json: true,\n defaults: { Accept: 'application/json' },\n }),\n body: JSON.stringify(wrapper),\n },\n this.requestTimeoutMs,\n );\n status = response.status;\n ok = response.ok;\n body = ok ? await readResponseBody(response) : undefined;\n } catch {\n return null;\n }\n\n if (!ok) {\n // 403: the contract has no fee route yet (the route exists, the backend refuses the path). A 404 is\n // NOT that: it is a wrong path (stage, 2026-11-02: the host root answered 404 and every quote became a\n // silent 0), so it resolves null like any other backend failure.\n if (contract === 'dex-contract' && status === 403) {\n return { source: 'default', fees: [{ feeInGala: '0' }] };\n }\n return null;\n }\n // Accept whatever fee the backend served: 'default' is as usable as 'dry-run'. Only a body\n // missing the fee outright is unusable.\n return readQuote(body);\n }\n}\n\nfunction readQuote(body: unknown): DexFeeQuote | null {\n if (typeof body !== 'object' || body === null) return null;\n const fees = (body as { fees?: unknown }).fees;\n if (\n !Array.isArray(fees) ||\n typeof (fees[0] as { feeInGala?: unknown } | undefined)?.feeInGala !== 'string'\n ) {\n return null;\n }\n return body as DexFeeQuote;\n}\n"],"mappings":"A,oTAeA,MAAaC,EAAkB,CAC7B,OACA,eACA,eACA,kBACA,sBACA,YACF,EAQaC,EAAiB,SAGjBC,EAA4B,yBAGzC,SAAgBC,EAAe,EAAyC,CACtE,OAAO,OAAOC,GAAW,UAAaJ,EAAsC,SAASI,CAAM,CAC7F,CAGA,SAAgBC,EACd,EACA,EACS,CACT,OACEF,EAAeC,CAAM,GACrB,OAAOE,GAAUC,QAAc,UAC/B,OAAOD,EAAQE,QAAc,QAEjC,CA2BA,SAAgBC,EAAe,EAAsB,CACnD,OAAOC,EAAK,QAAQ,+BAAgC,EAAE,CACxD,CASA,SAAgBC,EAAW,EAA2D,CACpF,IAAMC,EAAoC,CAAE,GAAGN,CAAQ,EACvD,IAAK,IAAMO,IAAS,CAAC,YAAa,SAAU,QAAS,SAAU,eAAgB,OAAO,EACpF,OAAOD,EAASC,GAElB,OAAOD,CACT,CAWA,SAAgBE,EACd,EACA,EACA,EACA,EACA,EAA0BZ,EAC1B,EAAkC,uBACA,CAClC,OAAOa,EAAYC,EAAQC,EAAchB,EAAgB,CACvD,kBACA,SACA,IAAKU,EAAWO,CAAG,EAEnB,UAAWC,EAAgBC,CAAe,CAC5C,CAAC,CACH,CAgDA,IAAaC,EAAb,KAAqB,CAMnB,YACE,EACA,EACA,CADiB,KAAA,OAAAL,EAPFjB,EAAA,KAAA,YAAA,IAAA,EAAA,EACAA,EAAA,KAAA,UAAA,IAAA,EAAA,EACAA,EAAA,KAAA,mBAAA,IAAA,EAAA,EACAA,EAAA,KAAA,OAAA,IAAA,EAAA,EAMf,KAAK,UAAYuB,EAAO,eAAiBC,EACzC,KAAK,QAAUd,EAAea,EAAO,iBAAiB,EACtD,KAAK,iBAAmBA,EAAO,kBAAoB,IACnD,KAAK,KAAOA,EAAO,IACrB,CAoBA,MAAa,MACX,EACA,EACA,EACA,EAA8B,CAAC,EACF,CAC7B,GAAI,KAAK,SAAW,IAAA,GAAW,MAAME,EAAc,cAAc,EACjE,IAAMC,EAAUC,EAAQ,SAAW,QAC7BC,EAAWD,EAAQ,UAAY,iBAC/BE,EAAU,MAAMd,EACpB,KAAK,OACLe,EACAzB,EACAO,EAAWL,CAAO,EAClB,IAAA,GACA,SAASqB,GACX,EACMG,EAAM,GAAG,KAAK,+CAA8B,mBAAmBL,CAAO,EAAE,GAAG,mBAAmBE,CAAQ,EAAE,GAAG,mBAAmBvB,CAAM,EAAE,MAExI2B,EACAC,EACAC,EACJ,GAAI,CACF,IAAMC,EAAW,MAAMC,EACrB,KAAK,UACLL,EACA,CACE,OAAQ,OACR,QAASM,EAAoB,KAAK,KAAM,CACtC,KAAM,GACN,SAAU,CAAE,OAAQ,kBAAmB,CACzC,CAAC,EACD,KAAM,KAAK,UAAUR,CAAO,CAC9B,EACA,KAAK,gBACP,EACA,EAASM,EAAS,OAClB,EAAKA,EAAS,GACd,EAAOF,EAAK,MAAMK,EAAiBH,CAAQ,EAAI,IAAA,EACjD,MAAQ,CACN,OAAO,IACT,CAaA,OAXKF,EAWEM,EAAUL,CAAI,EAPfN,IAAa,gBAAkBI,IAAW,IACrC,CAAE,OAAQ,UAAW,KAAM,CAAC,CAAE,UAAW,GAAI,CAAC,CAAE,EAElD,IAKX,CACF,EAEA,SAASO,EAAU,EAAmC,CACpD,GAAI,OAAOL,GAAS,WAAYA,EAAe,OAAO,KACtD,IAAMM,EAAQN,EAA4B,KAO1C,MALE,CAAC,MAAM,QAAQM,CAAI,GACnB,OAAQA,EAAK,EAAE,EAA0C,WAAc,SAEhE,KAEFN,CACT,C"}
|
|
1
|
+
{"version":3,"file":"dex_fees.js","names":["_defineProperty","DEX_FEE_METHODS","DRY_RUN_METHOD","DRY_RUN_UNIQUE_KEY_PREFIX","isDexFeeMethod","method","isCurrentContractDexMessage","message","\"token0\"","\"token1\"","dexBackendRoot","base","toChainDto","chainDto","field","buildDryRunWrapper","signPreSendFor","signer","contractPath","dto","createUniqueKey","uniqueKeyPrefix","DexFees","client","fetchRequestor","GSwapSDKError","channel","options","contract","wrapper","callerPublicKey","url","status","ok","body","response","requestWithTimeout","buildRequestHeaders","readResponseBody","readQuote","fees"],"sources":["../../../src/classes/dex_fees.ts"],"sourcesContent":["import {\n buildRequestHeaders,\n createUniqueKey,\n fetchRequestor,\n readResponseBody,\n requestWithTimeout,\n signPreSendFor,\n type ChainContractPath,\n type GalaChainSigner,\n type HttpRequestor,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\n\n/** DEX methods the backend accepts a fee quote for (its allow-list enumerates the same six). */\nexport const DEX_FEE_METHODS = [\n 'Swap',\n 'RequestTrade',\n 'AddLiquidity',\n 'RemoveLiquidity',\n 'CollectPositionFees',\n 'CreatePool',\n] as const;\n/** A chain method whose network fee `DexFees.quote` can price (see `isDexFeeMethod`). */\nexport type DexFeeMethod = (typeof DEX_FEE_METHODS)[number];\n\n/** Which pool contract the DTO being quoted targets: legacy (V3) or current (GalaChainDex). */\nexport type DexFeeContract = 'dexv3-contract' | 'dex-contract';\n\n/** The chain method name the signed DryRun wrapper is signed under. */\nexport const DRY_RUN_METHOD = 'DryRun';\n\n/** `uniqueKey` prefix of the DryRun WRAPPER (distinct from the inner DTO's key). */\nexport const DRY_RUN_UNIQUE_KEY_PREFIX = 'galaconnect-operation-';\n\n/** True when `method` is a DEX method a fee can be quoted for. */\nexport function isDexFeeMethod(method: unknown): method is DexFeeMethod {\n return typeof method === 'string' && (DEX_FEE_METHODS as readonly string[]).includes(method);\n}\n\n/** Current-contract typed DEX messages use trading symbols instead of TokenClassKey objects. */\nexport function isCurrentContractDexMessage(\n message: Record<string, unknown> | null | undefined,\n method: unknown,\n): boolean {\n return (\n isDexFeeMethod(method) &&\n typeof message?.['token0'] === 'string' &&\n typeof message['token1'] === 'string'\n );\n}\n\n/**\n * The backend's response. It ALWAYS carries a usable `fees[0].feeInGala`: the backend decides what\n * to serve when the chain cannot price the operation, so the client never invents a fee.\n *\n * `source` is informational: `'dry-run'` is simulated on chain and authoritative (possibly a\n * legitimate `'0'`), `'default'` means the chain could not price it and the platform default was\n * served.\n */\nexport interface DexFeeQuote {\n fees: Array<{ feeInGala: string }>;\n source: 'dry-run' | 'default';\n}\n\n/** The wallet-connect proxy's fee route, below the backend root (stage, 2026-11-02: only this prefix exists). */\nconst FEE_ROUTE_PREFIX = '/api/v1/wallet/connect/galachain/api';\n\n/**\n * The backend root a fee quote is built on: `base` without trailing slashes and without a trailing\n * `/api/v1` (the wallet passes the versioned base, the SDK presets the host root). Idempotent.\n *\n * @example\n * ```typescript\n * dexBackendRoot('https://swap-backend.stage.defi.ovh.gala.com/api/v1/'); // 'https://swap-backend.stage.defi.ovh.gala.com'\n * ```\n */\nexport function dexBackendRoot(base: string): string {\n return base.replace(/(?:\\/+|\\/api\\/v1(?=\\/|$))+$/u, '');\n}\n\n/**\n * Reduces an EIP-712 approval `message` to the DTO the chain actually receives: drops the signing\n * envelope (`signature`, `prefix`, `types`, `domain`), the `dtoOperation` it was signed to call (a\n * DryRun runs the DTO inside a wrapper signed for `DryRun`; left inside, the chain refuses it:\n * \"signed to call ...:RequestTrade, but the current operation is ...:DryRun\") and transport\n * metadata (`trace`).\n */\nexport function toChainDto(message: Record<string, unknown>): Record<string, unknown> {\n const chainDto: Record<string, unknown> = { ...message };\n for (const field of ['signature', 'prefix', 'types', 'domain', 'dtoOperation', 'trace']) {\n delete chainDto[field];\n }\n return chainDto;\n}\n\n/**\n * Signs the DryRun WRAPPER the gateway accepts for every contract:\n * `{ callerPublicKey, method, dto: <inner DTO object>, uniqueKey, signature }`. The inner DTO\n * travels unsigned and as an object; no `signerPublicKey` is sent because the signature already\n * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own\n * `uniqueKey`, distinct from the DTO's, and its own `dtoOperation` (`<Contract>:DryRun`); the inner DTO\n * carries none of the signing envelope or the `dtoOperation` of the call it simulates (see\n * {@link toChainDto}), whatever the caller passes, so a signed DTO can be handed in as is.\n */\nexport function buildDryRunWrapper(\n signer: GalaChainSigner,\n callerPublicKey: string,\n method: string,\n dto: Record<string, unknown>,\n uniqueKeyPrefix: string = DRY_RUN_UNIQUE_KEY_PREFIX,\n contractPath: ChainContractPath = 'asset/dexv3-contract',\n): Promise<Record<string, unknown>> {\n return signPreSendFor(signer, contractPath, DRY_RUN_METHOD, {\n callerPublicKey,\n method,\n dto: toChainDto(dto),\n // Core's RN-safe mint (`getRandomValues`, never `randomUUID`, which Hermes lacks).\n uniqueKey: createUniqueKey(uniqueKeyPrefix),\n });\n}\n\n/** The transport and backend a fee quote reads from. */\nexport interface DexFeesClient {\n /**\n * Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com`. A base that already ends in\n * `/api/v1` (what the wallet passes) and trailing slashes are accepted: the request goes to the\n * same URL either way (see {@link dexBackendRoot}).\n */\n dexBackendBaseUrl: string;\n /** Defaults to the global `fetch`. */\n httpRequestor?: HttpRequestor | undefined;\n /** Per-request timeout in milliseconds (default 30 000). */\n requestTimeoutMs?: number | undefined;\n /**\n * Request headers of the fee POST (`userAgent`, `headers`); see {@link WireOptions}. The SDK's\n * `Accept: application/json` is a default that `wire.headers` may replace.\n */\n wire?: WireOptions | undefined;\n}\n\n/** Options for a single quote. */\nexport interface DexFeeQuoteOptions {\n /** GalaChain channel. Default `asset`. */\n channel?: string | undefined;\n /**\n * Contract the DTO targets. Default `dexv3-contract` (what every legacy caller quotes against);\n * a current-contract operation must pass `dex-contract` explicitly.\n */\n contract?: DexFeeContract | undefined;\n}\n\n/**\n * Network-fee quote for GalaChain DEX methods, derived from a server-side DryRun.\n *\n * The client only SIGNS the DryRun wrapper (with whatever {@link GalaChainSigner} it is given) and\n * the backend forwards it to the gateway, where the simulated writes carry the fee; the backend\n * never holds a key. Intended for wallets: the DTO quoted is the typed message a dApp handed over.\n *\n * @example\n * ```ts\n * const fees = new DexFees({ dexBackendBaseUrl }, new PrivateKeySigner(sessionKey));\n * const quote = await fees.quote(publicKey, 'RequestTrade', toChainDto(message), {\n * contract: 'dex-contract',\n * });\n * const feeInGala = quote?.fees[0]?.feeInGala;\n * ```\n */\nexport class DexFees {\n private readonly requestor: HttpRequestor;\n private readonly baseUrl: string;\n private readonly requestTimeoutMs: number;\n private readonly wire: WireOptions | undefined;\n\n constructor(\n client: DexFeesClient,\n private readonly signer: GalaChainSigner | undefined,\n ) {\n this.requestor = client.httpRequestor ?? fetchRequestor;\n this.baseUrl = dexBackendRoot(client.dexBackendBaseUrl);\n this.requestTimeoutMs = client.requestTimeoutMs ?? 30_000;\n this.wire = client.wire;\n }\n\n /**\n * Quotes the network fee for `method` applied to `message`. The message is reduced with\n * {@link toChainDto} first, so an EIP-712 approval message can be passed as is.\n *\n * Resolves `null` when the BACKEND could not be reached or answered unusably (offline, 4xx/5xx,\n * malformed body): a transport outcome, not a fee. Deciding what to charge when the chain is\n * silent is the backend's job (it serves `source: 'default'`), so the client never substitutes\n * a fee of its own, with ONE exception that mirrors the wallet: a `dex-contract` quote answered\n * 403 means the contract has no fee route yet and resolves `{ source: 'default', '0' }`. A 404 is\n * a wrong path, not \"no fee route\": it resolves `null`, never a default. The request always goes\n * to `<root>/api/v1/wallet/connect/galachain/api/{channel}/{contract}/{method}/fee`, whether the\n * client's base URL is the host root or already ends in `/api/v1`.\n * Never throws on transport, so a fee lookup cannot block or break a signing screen.\n *\n * @throws GSwapSDKError NO_SIGNER when constructed without a signer; `SIGNING_FAILED` or\n * `KEY_PROVIDER_FAILED` (a pre-send error, the original as `cause`) when the signer fails, for\n * example a locked wallet.\n */\n public async quote(\n callerPublicKey: string,\n method: DexFeeMethod,\n message: Record<string, unknown>,\n options: DexFeeQuoteOptions = {},\n ): Promise<DexFeeQuote | null> {\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n const channel = options.channel ?? 'asset';\n const contract = options.contract ?? 'dexv3-contract';\n const wrapper = await buildDryRunWrapper(\n this.signer,\n callerPublicKey,\n method,\n toChainDto(message),\n undefined,\n // The wrapper's operation comes from the SAME `<channel>/<contract>` the fee URL below is built\n // from, so the two can never disagree (an unknown pair is refused before signing).\n `${channel}/${contract}` as ChainContractPath,\n );\n const url = `${this.baseUrl}${FEE_ROUTE_PREFIX}/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;\n\n let status: number;\n let ok: boolean;\n let body: unknown;\n try {\n const response = await requestWithTimeout(\n this.requestor,\n url,\n {\n method: 'POST',\n headers: buildRequestHeaders(this.wire, {\n json: true,\n defaults: { Accept: 'application/json' },\n }),\n body: JSON.stringify(wrapper),\n },\n this.requestTimeoutMs,\n );\n status = response.status;\n ok = response.ok;\n body = ok ? await readResponseBody(response) : undefined;\n } catch {\n return null;\n }\n\n if (!ok) {\n // 403: the contract has no fee route yet (the route exists, the backend refuses the path). A 404 is\n // NOT that: it is a wrong path (stage, 2026-11-02: the host root answered 404 and every quote became a\n // silent 0), so it resolves null like any other backend failure.\n if (contract === 'dex-contract' && status === 403) {\n return { source: 'default', fees: [{ feeInGala: '0' }] };\n }\n return null;\n }\n // Accept whatever fee the backend served: 'default' is as usable as 'dry-run'. Only a body\n // missing the fee outright is unusable.\n return readQuote(body);\n }\n}\n\nfunction readQuote(body: unknown): DexFeeQuote | null {\n if (typeof body !== 'object' || body === null) return null;\n const fees = (body as { fees?: unknown }).fees;\n if (\n !Array.isArray(fees) ||\n typeof (fees[0] as { feeInGala?: unknown } | undefined)?.feeInGala !== 'string'\n ) {\n return null;\n }\n return body as DexFeeQuote;\n}\n"],"mappings":"A,uTAeA,MAAaC,EAAkB,CAC7B,OACA,eACA,eACA,kBACA,sBACA,YACF,EAQaC,EAAiB,SAGjBC,EAA4B,yBAGzC,SAAgBC,EAAe,EAAyC,CACtE,OAAO,OAAOC,GAAW,UAAaJ,EAAsC,SAASI,CAAM,CAC7F,CAGA,SAAgBC,EACd,EACA,EACS,CACT,OACEF,EAAeC,CAAM,GACrB,OAAOE,GAAUC,QAAc,UAC/B,OAAOD,EAAQE,QAAc,QAEjC,CA2BA,SAAgBC,EAAe,EAAsB,CACnD,OAAOC,EAAK,QAAQ,+BAAgC,EAAE,CACxD,CASA,SAAgBC,EAAW,EAA2D,CACpF,IAAMC,EAAoC,CAAE,GAAGN,CAAQ,EACvD,IAAK,IAAMO,IAAS,CAAC,YAAa,SAAU,QAAS,SAAU,eAAgB,OAAO,EACpF,OAAOD,EAASC,GAElB,OAAOD,CACT,CAWA,SAAgBE,EACd,EACA,EACA,EACA,EACA,EAA0BZ,EAC1B,EAAkC,uBACA,CAClC,OAAOa,EAAeC,EAAQC,EAAchB,EAAgB,CAC1D,kBACA,SACA,IAAKU,EAAWO,CAAG,EAEnB,UAAWC,EAAgBC,CAAe,CAC5C,CAAC,CACH,CAgDA,IAAaC,EAAb,KAAqB,CAMnB,YACE,EACA,EACA,CADiB,KAAA,OAAAL,EAPFjB,EAAA,KAAA,YAAA,IAAA,EAAA,EACAA,EAAA,KAAA,UAAA,IAAA,EAAA,EACAA,EAAA,KAAA,mBAAA,IAAA,EAAA,EACAA,EAAA,KAAA,OAAA,IAAA,EAAA,EAMf,KAAK,UAAYuB,EAAO,eAAiBC,EACzC,KAAK,QAAUd,EAAea,EAAO,iBAAiB,EACtD,KAAK,iBAAmBA,EAAO,kBAAoB,IACnD,KAAK,KAAOA,EAAO,IACrB,CAoBA,MAAa,MACX,EACA,EACA,EACA,EAA8B,CAAC,EACF,CAC7B,GAAI,KAAK,SAAW,IAAA,GAAW,MAAME,EAAc,cAAc,EACjE,IAAMC,EAAUC,EAAQ,SAAW,QAC7BC,EAAWD,EAAQ,UAAY,iBAC/BE,EAAU,MAAMd,EACpB,KAAK,OACLe,EACAzB,EACAO,EAAWL,CAAO,EAClB,IAAA,GAGA,GAAGmB,EAAQ,GAAGE,GAChB,EACMG,EAAM,GAAG,KAAK,+CAA8B,mBAAmBL,CAAO,EAAE,GAAG,mBAAmBE,CAAQ,EAAE,GAAG,mBAAmBvB,CAAM,EAAE,MAExI2B,EACAC,EACAC,EACJ,GAAI,CACF,IAAMC,EAAW,MAAMC,EACrB,KAAK,UACLL,EACA,CACE,OAAQ,OACR,QAASM,EAAoB,KAAK,KAAM,CACtC,KAAM,GACN,SAAU,CAAE,OAAQ,kBAAmB,CACzC,CAAC,EACD,KAAM,KAAK,UAAUR,CAAO,CAC9B,EACA,KAAK,gBACP,EACA,EAASM,EAAS,OAClB,EAAKA,EAAS,GACd,EAAOF,EAAK,MAAMK,EAAiBH,CAAQ,EAAI,IAAA,EACjD,MAAQ,CACN,OAAO,IACT,CAaA,OAXKF,EAWEM,EAAUL,CAAI,EAPfN,IAAa,gBAAkBI,IAAW,IACrC,CAAE,OAAQ,UAAW,KAAM,CAAC,CAAE,UAAW,GAAI,CAAC,CAAE,EAElD,IAKX,CACF,EAEA,SAASO,EAAU,EAAmC,CACpD,GAAI,OAAOL,GAAS,WAAYA,EAAe,OAAO,KACtD,IAAMM,EAAQN,EAA4B,KAO1C,MALE,CAAC,MAAM,QAAQM,CAAI,GACnB,OAAQA,EAAK,EAAE,EAA0C,WAAc,SAEhE,KAEFN,CACT,C"}
|
|
@@ -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.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};
|
|
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,signPreSendFor 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","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
|
+
{"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","signPreSendFor","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 signPreSendFor,\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 signPreSendFor(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 e from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as t}from"./gswap_sdk_error.js";import{assertCanonicalPair as n,userRef as r,validateFee as i}from"../utils/validation.js";import{DEX_CONTRACT_PATH as a}from"../utils/chain_contract.js";import{shadowFailures as o}from"../utils/shadow_errors.js";import{SubmittedTransaction as s}from"./submitted_transaction.js";import{orderSymbols as c,readOrderedSymbols as l}from"../utils/ordering.js";import{tradingSymbolOf as u}from"./symbols.js";import{assertCanonicalV2Dto as d,buildRequestTradeDto as f}from"../utils/dto_builders.js";import{readShadowSubmitOutcome as p}from"./shadow_submit.js";import{assertUniqueKey as m,createUniqueKey as h,resolveUniqueKeyPrefix as g,
|
|
1
|
+
import e from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";import{GSwapSDKError as t}from"./gswap_sdk_error.js";import{assertCanonicalPair as n,userRef as r,validateFee as i}from"../utils/validation.js";import{DEX_CONTRACT_PATH as a}from"../utils/chain_contract.js";import{shadowFailures as o}from"../utils/shadow_errors.js";import{SubmittedTransaction as s}from"./submitted_transaction.js";import{orderSymbols as c,readOrderedSymbols as l}from"../utils/ordering.js";import{tradingSymbolOf as u}from"./symbols.js";import{assertCanonicalV2Dto as d,buildRequestTradeDto as f}from"../utils/dto_builders.js";import{readShadowSubmitOutcome as p}from"./shadow_submit.js";import{assertUniqueKey as m,createUniqueKey as h,resolveUniqueKeyPrefix as g,signPreSendFor as _}from"@gala-chain/gala-core-sdk";function v(e){i(e.fee),n(e.token0Symbol,e.token1Symbol);let[t,r]=e.tokenInIsToken0?[e.token0Symbol,e.token1Symbol]:[e.token1Symbol,e.token0Symbol];return{tokenIn:t,tokenOut:r,fee:e.fee,pool:{token0:e.token0Symbol,token1:e.token1Symbol}}}var y=class{constructor(t,n,i,a,o={}){this.gateway=t,this.symbols=n,this.signer=i,e(this,`walletAddress`,void 0),e(this,`uniqueKeyPrefix`,void 0),this.walletAddress=a===void 0?void 0:r(a,`walletAddress`),this.uniqueKeyPrefix=g(o.uniqueKeyPrefix)}async swap(e,t,n,r,i){return this.submitSwap(await this.buildSwap(e,t,n,r,i))}async swapShadow(e,t,n,r,i){return o(async()=>this.submitSwapShadow(await this.buildSwap(e,t,n,r,i)))}async buildSwap(e,t,n,r,a){i(n);let o=a?.uniqueKey??h(this.uniqueKeyPrefix);m(o);let s=await u(this.symbols,e),c=await u(this.symbols,t),l=this.orientPool(s,c,a?.pool);return f({token0:l.token0,token1:l.token1,fee:n,tokenInIsToken0:s===l.token0,uniqueKey:o,...r})}async submitSwap(e){let t=await this.signRequestTrade(e);return this.gateway.submit(`RequestTrade`,t,this.submitOptions())}async submitSwapShadow(e){return o(async()=>{let t=await this.signRequestTrade(e),n=await this.gateway.submitShadow(`RequestTrade`,t,this.submitOptions());return p(`RequestTrade`,t,n)})}submitOptions(){return this.walletAddress===void 0?{}:{walletAddress:this.walletAddress}}async signRequestTrade(e){if(d(`RequestTrade`,e),this.signer===void 0)throw t.noSignerError();return _(this.signer,a,`RequestTrade`,e)}orientPool(e,n,r){if(r===void 0)return l(c(e,n));if(!(e===r.token0&&n===r.token1||e===r.token1&&n===r.token0))throw new t(`POOL_MISMATCH`,{tokenIn:e,tokenOut:n,poolToken0:r.token0,poolToken1:r.token1});return{token0:r.token0,token1:r.token1}}async confirmSwap(e,t){return m(e),new s({method:`RequestTrade`,uniqueKey:e,transactionId:null,mode:`queued`,result:void 0,dexBackendBaseUrl:this.gateway.dexBackendBaseUrl,httpRequestor:this.gateway.httpRequestor,requestTimeoutMs:this.gateway.requestTimeoutMs,wire:this.gateway.wire}).confirm({initialDelayMs:0,...t})}};export{y as Swaps,v as swapRouteFromQuote};
|
|
2
2
|
//# sourceMappingURL=swaps.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"swaps.js","names":["_defineProperty","swapRouteFromQuote","validateFee","quote","assertCanonicalPair","tokenIn","tokenOut","Swaps","gateway","symbols","signer","walletAddress","userRef","resolveUniqueKeyPrefix","options","fee","amount","shadowFailures","uniqueKey","createUniqueKey","assertUniqueKey","tokenInSymbol","tradingSymbolOf","tokenOutSymbol","ordered","buildRequestTradeDto","signed","dto","result","readShadowSubmitOutcome","assertCanonicalV2Dto","GSwapSDKError","signPreSend","DEX_CONTRACT_PATH","pool","readOrderedSymbols","orderSymbols","SubmittedTransaction"],"sources":["../../../src/classes/swaps.ts"],"sourcesContent":["import {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n signPreSend,\n type GalaChainSigner,\n type HttpRequestor,\n type UniqueKeyOptions,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport type { SwapAmount } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport { assertCanonicalV2Dto, buildRequestTradeDto } from '../utils/dto_builders.js';\nimport { DEX_CONTRACT_PATH } from '../utils/chain_contract.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport { assertCanonicalPair, userRef, validateFee } from '../utils/validation.js';\nimport type { ChainSubmitOptions } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport {\n readShadowSubmitOutcome,\n type ShadowSubmitOutcome,\n type ShadowSubmitResult,\n} from './shadow_submit.js';\nimport { SubmittedTransaction } from './submitted_transaction.js';\nimport type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { RequestTradeDTO } from '../types/v2_dtos.js';\nimport type { AppliedTrade, QuoteResult } from '../types/v2_results.js';\nimport { tradingSymbolOf, type TokenResolver } from './symbols.js';\n\ninterface SwapGateway {\n submit: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<AppliedTrade>>;\n submitShadow: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<ShadowSubmitResult>;\n readonly dexBackendBaseUrl: string;\n readonly httpRequestor: HttpRequestor;\n readonly requestTimeoutMs: number;\n readonly wire?: WireOptions | undefined;\n}\n\n/** The canonical pool a swap trades in, as a quote names it. */\nexport interface SwapPool {\n token0: string;\n token1: string;\n}\n\n/** Options of a swap. */\nexport interface SwapOptions {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing (to remember it, to\n * show it), or to retry the SAME attempt after a lost response; never reuse it for another trade.\n */\n uniqueKey?: string | undefined;\n /**\n * Pin the pool: take `token0` / `token1` verbatim from the quote the user saw, instead of\n * ordering `tokenIn` / `tokenOut` by string comparison. `tokenIn` and `tokenOut` must be exactly\n * these two symbols, and `token0` must sort before `token1`. See {@link swapRouteFromQuote}.\n */\n pool?: SwapPool | undefined;\n}\n\n/** Everything {@link Swaps.swap} needs to trade in the pool a quote priced. */\nexport interface SwapRoute {\n tokenIn: string;\n tokenOut: string;\n fee: FEE_TIER;\n pool: SwapPool;\n}\n\n/**\n * The route of a quote: its fee tier and pool, with `tokenIn` / `tokenOut` taken from\n * `tokenInIsToken0`, nothing re-derived. Use it to swap in exactly the pool a quote priced:\n *\n * @example\n * ```ts\n * const route = swapRouteFromQuote(quote);\n * await swaps.swap(route.tokenIn, route.tokenOut, route.fee, { exactIn: '100' }, { pool: route.pool });\n * ```\n */\nexport function swapRouteFromQuote(\n quote: Pick<QuoteResult, 'token0Symbol' | 'token1Symbol' | 'tokenInIsToken0' | 'fee'>,\n): SwapRoute {\n validateFee(quote.fee);\n assertCanonicalPair(quote.token0Symbol, quote.token1Symbol);\n const [tokenIn, tokenOut] = quote.tokenInIsToken0\n ? [quote.token0Symbol, quote.token1Symbol]\n : [quote.token1Symbol, quote.token0Symbol];\n return {\n tokenIn,\n tokenOut,\n fee: quote.fee,\n pool: { token0: quote.token0Symbol, token1: quote.token1Symbol },\n };\n}\n\n/** Executes queued current-contract RequestTrade operations through the Chain Gateway. */\nexport class Swaps {\n /**\n * Creates a swap service.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, symbols, signer, 'client|alice');\n * ```\n */\n constructor(\n private readonly gateway: SwapGateway,\n private readonly symbols: TokenResolver,\n private readonly signer?: GalaChainSigner,\n walletAddress?: string,\n options: UniqueKeyOptions = {},\n ) {\n this.walletAddress =\n walletAddress === undefined ? undefined : userRef(walletAddress, 'walletAddress');\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\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 uniqueKeyPrefix: string;\n\n /**\n * Signs and submits an exact-input or exact-output RequestTrade DTO. The returned transaction\n * is QUEUED; call `await tx.confirm()` to obtain the executed trade or chain rejection.\n *\n * @example\n * ```ts\n * const submitted = await swaps.swap('GALA', 'GUSDC', 3000, {\n * exactIn: '100',\n * amountOutMinimum: '14',\n * });\n * ```\n */\n public async swap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>> {\n return this.submitSwap(await this.buildSwap(tokenIn, tokenOut, fee, amount, options));\n }\n\n /**\n * Signs and submits a SHADOW (dark) swap: the same RequestTrade as {@link swap}, relayed with\n * `X-Shadow: true` so the swap backend marks it private before it reaches the contract. Requires a\n * `walletAddress`. Resolves the normalized outcome instead of throwing on a gateway refusal:\n * `ok: false` carries `unavailable` (retryable), `disabled`, `rejected` (with the gateway's\n * message) or `unknown`. A success carries `queued`, to be confirmed with\n * `confirmSwap(queued.uniqueKey)`; never fall back to a public swap on failure. Whatever this\n * THROWS (a validation error, the signer, a lost connection, `SHADOW_NOT_QUEUED`) has\n * `error.shadow === true` (`isShadowError`), so an app can apply its dark-swap policy to it.\n *\n * @example\n * ```ts\n * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * if (outcome.ok) await swaps.confirmSwap(outcome.queued.uniqueKey);\n * ```\n */\n public async swapShadow(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () =>\n this.submitSwapShadow(await this.buildSwap(tokenIn, tokenOut, fee, amount, options)),\n );\n }\n\n /**\n * Builds the RequestTrade DTO that {@link swap} would sign, without signing or sending it: to\n * show in an approval popup, to remember its `uniqueKey`, or to sign elsewhere. Submit exactly\n * this DTO with {@link submitSwap}. The pure counterpart, with canonical inputs and no\n * resolution, is `buildRequestTradeDto`.\n *\n * @example\n * ```ts\n * const dto = await swaps.buildSwap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * showApproval(dto);\n * const submitted = await swaps.submitSwap(dto);\n * ```\n */\n public async buildSwap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<RequestTradeDTO> {\n validateFee(fee);\n const uniqueKey = options?.uniqueKey ?? createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(uniqueKey);\n const tokenInSymbol = await tradingSymbolOf(this.symbols, tokenIn);\n const tokenOutSymbol = await tradingSymbolOf(this.symbols, tokenOut);\n const ordered = this.orientPool(tokenInSymbol, tokenOutSymbol, options?.pool);\n return buildRequestTradeDto({\n token0: ordered.token0,\n token1: ordered.token1,\n fee,\n tokenInIsToken0: tokenInSymbol === ordered.token0,\n uniqueKey,\n ...amount,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildSwap} or `buildRequestTradeDto`. The DTO must be\n * exactly what the builder produces (no signature, canonical decimals, builder key order), so\n * what an app showed is what gets signed.\n *\n * @example\n * ```ts\n * const submitted = await swaps.submitSwap(dto);\n * const applied = await submitted.confirm();\n * ```\n */\n public async submitSwap(dto: RequestTradeDTO): Promise<SubmittedTransaction<AppliedTrade>> {\n const signed = await this.signRequestTrade(dto);\n return this.gateway.submit('RequestTrade', signed, this.submitOptions());\n }\n\n /** Signs and shadow-submits a DTO built by {@link buildSwap}; see {@link swapShadow}. */\n public async submitSwapShadow(dto: RequestTradeDTO): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () => {\n const signed = await this.signRequestTrade(dto);\n const result = await this.gateway.submitShadow('RequestTrade', signed, this.submitOptions());\n return readShadowSubmitOutcome('RequestTrade', signed, result);\n });\n }\n\n private submitOptions(): ChainSubmitOptions {\n return this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n }\n\n private async signRequestTrade(dto: RequestTradeDTO): Promise<Record<string, unknown>> {\n assertCanonicalV2Dto('RequestTrade', dto);\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n return signPreSend(this.signer, DEX_CONTRACT_PATH, 'RequestTrade', dto);\n }\n\n /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */\n private orientPool(\n tokenInSymbol: string,\n tokenOutSymbol: string,\n pool: SwapPool | undefined,\n ): SwapPool {\n if (pool === undefined) {\n return readOrderedSymbols(orderSymbols(tokenInSymbol, tokenOutSymbol));\n }\n const sameSet =\n (tokenInSymbol === pool.token0 && tokenOutSymbol === pool.token1) ||\n (tokenInSymbol === pool.token1 && tokenOutSymbol === pool.token0);\n if (!sameSet) {\n throw new GSwapSDKError('POOL_MISMATCH', {\n tokenIn: tokenInSymbol,\n tokenOut: tokenOutSymbol,\n poolToken0: pool.token0,\n poolToken1: pool.token1,\n });\n }\n return { token0: pool.token0, token1: pool.token1 };\n }\n\n /**\n * Confirm a swap by its durable `uniqueKey` without resubmitting it. This is the recovery\n * path after a `CONFIRMATION_TIMEOUT`, a `SUBMISSION_OUTCOME_UNKNOWN`, a `409` replay\n * conflict, or a process restart: it reads the same apply-results record that\n * `SubmittedTransaction.confirm()` reads (retained for 7 days) and resolves the applied trade\n * or throws the chain's rejection. The first read happens immediately unless\n * `initialDelayMs` is given.\n *\n * @example\n * ```ts\n * const applied = await swaps.confirmSwap('galaswap-operation-2f1c…');\n * ```\n */\n public async confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade> {\n assertUniqueKey(uniqueKey);\n const transaction = new SubmittedTransaction<AppliedTrade>({\n method: 'RequestTrade',\n uniqueKey,\n transactionId: null,\n mode: 'queued',\n result: undefined,\n dexBackendBaseUrl: this.gateway.dexBackendBaseUrl,\n httpRequestor: this.gateway.httpRequestor,\n requestTimeoutMs: this.gateway.requestTimeoutMs,\n wire: this.gateway.wire,\n });\n return transaction.confirm({ initialDelayMs: 0, ...options });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"swaps.js","names":["_defineProperty","swapRouteFromQuote","validateFee","quote","assertCanonicalPair","tokenIn","tokenOut","Swaps","gateway","symbols","signer","walletAddress","userRef","resolveUniqueKeyPrefix","options","fee","amount","shadowFailures","uniqueKey","createUniqueKey","assertUniqueKey","tokenInSymbol","tradingSymbolOf","tokenOutSymbol","ordered","buildRequestTradeDto","signed","dto","result","readShadowSubmitOutcome","assertCanonicalV2Dto","GSwapSDKError","signPreSendFor","DEX_CONTRACT_PATH","pool","readOrderedSymbols","orderSymbols","SubmittedTransaction"],"sources":["../../../src/classes/swaps.ts"],"sourcesContent":["import {\n assertUniqueKey,\n createUniqueKey,\n resolveUniqueKeyPrefix,\n signPreSendFor,\n type GalaChainSigner,\n type HttpRequestor,\n type UniqueKeyOptions,\n type WireOptions,\n} from '@gala-chain/gala-core-sdk';\nimport type { SwapAmount } from '../types/amounts.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { orderSymbols, readOrderedSymbols, type TokenRef } from '../utils/ordering.js';\nimport { assertCanonicalV2Dto, buildRequestTradeDto } from '../utils/dto_builders.js';\nimport { DEX_CONTRACT_PATH } from '../utils/chain_contract.js';\nimport { shadowFailures } from '../utils/shadow_errors.js';\nimport { assertCanonicalPair, userRef, validateFee } from '../utils/validation.js';\nimport type { ChainSubmitOptions } from './gateway.js';\nimport { GSwapSDKError } from './gswap_sdk_error.js';\nimport {\n readShadowSubmitOutcome,\n type ShadowSubmitOutcome,\n type ShadowSubmitResult,\n} from './shadow_submit.js';\nimport { SubmittedTransaction } from './submitted_transaction.js';\nimport type { ConfirmOptions } from '../types/confirm_options.js';\nimport type { RequestTradeDTO } from '../types/v2_dtos.js';\nimport type { AppliedTrade, QuoteResult } from '../types/v2_results.js';\nimport { tradingSymbolOf, type TokenResolver } from './symbols.js';\n\ninterface SwapGateway {\n submit: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<SubmittedTransaction<AppliedTrade>>;\n submitShadow: (\n method: 'RequestTrade',\n signedBody: Record<string, unknown>,\n options?: ChainSubmitOptions,\n ) => Promise<ShadowSubmitResult>;\n readonly dexBackendBaseUrl: string;\n readonly httpRequestor: HttpRequestor;\n readonly requestTimeoutMs: number;\n readonly wire?: WireOptions | undefined;\n}\n\n/** The canonical pool a swap trades in, as a quote names it. */\nexport interface SwapPool {\n token0: string;\n token1: string;\n}\n\n/** Options of a swap. */\nexport interface SwapOptions {\n /**\n * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh\n * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing (to remember it, to\n * show it), or to retry the SAME attempt after a lost response; never reuse it for another trade.\n */\n uniqueKey?: string | undefined;\n /**\n * Pin the pool: take `token0` / `token1` verbatim from the quote the user saw, instead of\n * ordering `tokenIn` / `tokenOut` by string comparison. `tokenIn` and `tokenOut` must be exactly\n * these two symbols, and `token0` must sort before `token1`. See {@link swapRouteFromQuote}.\n */\n pool?: SwapPool | undefined;\n}\n\n/** Everything {@link Swaps.swap} needs to trade in the pool a quote priced. */\nexport interface SwapRoute {\n tokenIn: string;\n tokenOut: string;\n fee: FEE_TIER;\n pool: SwapPool;\n}\n\n/**\n * The route of a quote: its fee tier and pool, with `tokenIn` / `tokenOut` taken from\n * `tokenInIsToken0`, nothing re-derived. Use it to swap in exactly the pool a quote priced:\n *\n * @example\n * ```ts\n * const route = swapRouteFromQuote(quote);\n * await swaps.swap(route.tokenIn, route.tokenOut, route.fee, { exactIn: '100' }, { pool: route.pool });\n * ```\n */\nexport function swapRouteFromQuote(\n quote: Pick<QuoteResult, 'token0Symbol' | 'token1Symbol' | 'tokenInIsToken0' | 'fee'>,\n): SwapRoute {\n validateFee(quote.fee);\n assertCanonicalPair(quote.token0Symbol, quote.token1Symbol);\n const [tokenIn, tokenOut] = quote.tokenInIsToken0\n ? [quote.token0Symbol, quote.token1Symbol]\n : [quote.token1Symbol, quote.token0Symbol];\n return {\n tokenIn,\n tokenOut,\n fee: quote.fee,\n pool: { token0: quote.token0Symbol, token1: quote.token1Symbol },\n };\n}\n\n/** Executes queued current-contract RequestTrade operations through the Chain Gateway. */\nexport class Swaps {\n /**\n * Creates a swap service.\n *\n * @example\n * ```ts\n * const swaps = new Swaps(gateway, symbols, signer, 'client|alice');\n * ```\n */\n constructor(\n private readonly gateway: SwapGateway,\n private readonly symbols: TokenResolver,\n private readonly signer?: GalaChainSigner,\n walletAddress?: string,\n options: UniqueKeyOptions = {},\n ) {\n this.walletAddress =\n walletAddress === undefined ? undefined : userRef(walletAddress, 'walletAddress');\n this.uniqueKeyPrefix = resolveUniqueKeyPrefix(options.uniqueKeyPrefix);\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 uniqueKeyPrefix: string;\n\n /**\n * Signs and submits an exact-input or exact-output RequestTrade DTO. The returned transaction\n * is QUEUED; call `await tx.confirm()` to obtain the executed trade or chain rejection.\n *\n * @example\n * ```ts\n * const submitted = await swaps.swap('GALA', 'GUSDC', 3000, {\n * exactIn: '100',\n * amountOutMinimum: '14',\n * });\n * ```\n */\n public async swap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<SubmittedTransaction<AppliedTrade>> {\n return this.submitSwap(await this.buildSwap(tokenIn, tokenOut, fee, amount, options));\n }\n\n /**\n * Signs and submits a SHADOW (dark) swap: the same RequestTrade as {@link swap}, relayed with\n * `X-Shadow: true` so the swap backend marks it private before it reaches the contract. Requires a\n * `walletAddress`. Resolves the normalized outcome instead of throwing on a gateway refusal:\n * `ok: false` carries `unavailable` (retryable), `disabled`, `rejected` (with the gateway's\n * message) or `unknown`. A success carries `queued`, to be confirmed with\n * `confirmSwap(queued.uniqueKey)`; never fall back to a public swap on failure. Whatever this\n * THROWS (a validation error, the signer, a lost connection, `SHADOW_NOT_QUEUED`) has\n * `error.shadow === true` (`isShadowError`), so an app can apply its dark-swap policy to it.\n *\n * @example\n * ```ts\n * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * if (outcome.ok) await swaps.confirmSwap(outcome.queued.uniqueKey);\n * ```\n */\n public async swapShadow(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () =>\n this.submitSwapShadow(await this.buildSwap(tokenIn, tokenOut, fee, amount, options)),\n );\n }\n\n /**\n * Builds the RequestTrade DTO that {@link swap} would sign, without signing or sending it: to\n * show in an approval popup, to remember its `uniqueKey`, or to sign elsewhere. Submit exactly\n * this DTO with {@link submitSwap}. The pure counterpart, with canonical inputs and no\n * resolution, is `buildRequestTradeDto`.\n *\n * @example\n * ```ts\n * const dto = await swaps.buildSwap('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * showApproval(dto);\n * const submitted = await swaps.submitSwap(dto);\n * ```\n */\n public async buildSwap(\n tokenIn: TokenRef,\n tokenOut: TokenRef,\n fee: FEE_TIER,\n amount: SwapAmount,\n options?: SwapOptions,\n ): Promise<RequestTradeDTO> {\n validateFee(fee);\n const uniqueKey = options?.uniqueKey ?? createUniqueKey(this.uniqueKeyPrefix);\n assertUniqueKey(uniqueKey);\n const tokenInSymbol = await tradingSymbolOf(this.symbols, tokenIn);\n const tokenOutSymbol = await tradingSymbolOf(this.symbols, tokenOut);\n const ordered = this.orientPool(tokenInSymbol, tokenOutSymbol, options?.pool);\n return buildRequestTradeDto({\n token0: ordered.token0,\n token1: ordered.token1,\n fee,\n tokenInIsToken0: tokenInSymbol === ordered.token0,\n uniqueKey,\n ...amount,\n });\n }\n\n /**\n * Signs and submits a DTO built by {@link buildSwap} or `buildRequestTradeDto`. The DTO must be\n * exactly what the builder produces (no signature, canonical decimals, builder key order), so\n * what an app showed is what gets signed.\n *\n * @example\n * ```ts\n * const submitted = await swaps.submitSwap(dto);\n * const applied = await submitted.confirm();\n * ```\n */\n public async submitSwap(dto: RequestTradeDTO): Promise<SubmittedTransaction<AppliedTrade>> {\n const signed = await this.signRequestTrade(dto);\n return this.gateway.submit('RequestTrade', signed, this.submitOptions());\n }\n\n /** Signs and shadow-submits a DTO built by {@link buildSwap}; see {@link swapShadow}. */\n public async submitSwapShadow(dto: RequestTradeDTO): Promise<ShadowSubmitOutcome> {\n return shadowFailures(async () => {\n const signed = await this.signRequestTrade(dto);\n const result = await this.gateway.submitShadow('RequestTrade', signed, this.submitOptions());\n return readShadowSubmitOutcome('RequestTrade', signed, result);\n });\n }\n\n private submitOptions(): ChainSubmitOptions {\n return this.walletAddress === undefined ? {} : { walletAddress: this.walletAddress };\n }\n\n private async signRequestTrade(dto: RequestTradeDTO): Promise<Record<string, unknown>> {\n assertCanonicalV2Dto('RequestTrade', dto);\n if (this.signer === undefined) throw GSwapSDKError.noSignerError();\n return signPreSendFor(this.signer, DEX_CONTRACT_PATH, 'RequestTrade', dto);\n }\n\n /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */\n private orientPool(\n tokenInSymbol: string,\n tokenOutSymbol: string,\n pool: SwapPool | undefined,\n ): SwapPool {\n if (pool === undefined) {\n return readOrderedSymbols(orderSymbols(tokenInSymbol, tokenOutSymbol));\n }\n const sameSet =\n (tokenInSymbol === pool.token0 && tokenOutSymbol === pool.token1) ||\n (tokenInSymbol === pool.token1 && tokenOutSymbol === pool.token0);\n if (!sameSet) {\n throw new GSwapSDKError('POOL_MISMATCH', {\n tokenIn: tokenInSymbol,\n tokenOut: tokenOutSymbol,\n poolToken0: pool.token0,\n poolToken1: pool.token1,\n });\n }\n return { token0: pool.token0, token1: pool.token1 };\n }\n\n /**\n * Confirm a swap by its durable `uniqueKey` without resubmitting it. This is the recovery\n * path after a `CONFIRMATION_TIMEOUT`, a `SUBMISSION_OUTCOME_UNKNOWN`, a `409` replay\n * conflict, or a process restart: it reads the same apply-results record that\n * `SubmittedTransaction.confirm()` reads (retained for 7 days) and resolves the applied trade\n * or throws the chain's rejection. The first read happens immediately unless\n * `initialDelayMs` is given.\n *\n * @example\n * ```ts\n * const applied = await swaps.confirmSwap('galaswap-operation-2f1c…');\n * ```\n */\n public async confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade> {\n assertUniqueKey(uniqueKey);\n const transaction = new SubmittedTransaction<AppliedTrade>({\n method: 'RequestTrade',\n uniqueKey,\n transactionId: null,\n mode: 'queued',\n result: undefined,\n dexBackendBaseUrl: this.gateway.dexBackendBaseUrl,\n httpRequestor: this.gateway.httpRequestor,\n requestTimeoutMs: this.gateway.requestTimeoutMs,\n wire: this.gateway.wire,\n });\n return transaction.confirm({ initialDelayMs: 0, ...options });\n }\n}\n"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -1773,7 +1773,7 @@ function toChainDto(message) {
|
|
|
1773
1773
|
* {@link toChainDto}), whatever the caller passes, so a signed DTO can be handed in as is.
|
|
1774
1774
|
*/
|
|
1775
1775
|
function buildDryRunWrapper(signer, callerPublicKey, method, dto, uniqueKeyPrefix = DRY_RUN_UNIQUE_KEY_PREFIX, contractPath = "asset/dexv3-contract") {
|
|
1776
|
-
return (0, _gala_chain_gala_core_sdk.
|
|
1776
|
+
return (0, _gala_chain_gala_core_sdk.signPreSendFor)(signer, contractPath, DRY_RUN_METHOD, {
|
|
1777
1777
|
callerPublicKey,
|
|
1778
1778
|
method,
|
|
1779
1779
|
dto: toChainDto(dto),
|
|
@@ -1831,7 +1831,7 @@ var DexFees = class {
|
|
|
1831
1831
|
if (this.signer === void 0) throw GSwapSDKError.noSignerError();
|
|
1832
1832
|
const channel = options.channel ?? "asset";
|
|
1833
1833
|
const contract = options.contract ?? "dexv3-contract";
|
|
1834
|
-
const wrapper = await buildDryRunWrapper(this.signer, callerPublicKey, method, toChainDto(message), void 0,
|
|
1834
|
+
const wrapper = await buildDryRunWrapper(this.signer, callerPublicKey, method, toChainDto(message), void 0, `${channel}/${contract}`);
|
|
1835
1835
|
const url = `${this.baseUrl}${FEE_ROUTE_PREFIX}/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;
|
|
1836
1836
|
let status;
|
|
1837
1837
|
let ok;
|
|
@@ -5015,7 +5015,7 @@ var Positions = class {
|
|
|
5015
5015
|
}
|
|
5016
5016
|
async submit(method, dto, confirmation) {
|
|
5017
5017
|
if (this.signer === void 0) throw GSwapSDKError.noSignerError();
|
|
5018
|
-
const signed = await (0, _gala_chain_gala_core_sdk.
|
|
5018
|
+
const signed = await (0, _gala_chain_gala_core_sdk.signPreSendFor)(this.signer, DEX_CONTRACT_PATH, method, dto);
|
|
5019
5019
|
const submitOptions = this.walletAddress === void 0 ? {} : { walletAddress: this.walletAddress };
|
|
5020
5020
|
const owner = this.walletAddress;
|
|
5021
5021
|
const positionConfirmation = await this.buildPositionConfirmation(confirmation, owner);
|
|
@@ -5676,7 +5676,7 @@ var Swaps = class {
|
|
|
5676
5676
|
async signRequestTrade(dto) {
|
|
5677
5677
|
assertCanonicalV2Dto("RequestTrade", dto);
|
|
5678
5678
|
if (this.signer === void 0) throw GSwapSDKError.noSignerError();
|
|
5679
|
-
return (0, _gala_chain_gala_core_sdk.
|
|
5679
|
+
return (0, _gala_chain_gala_core_sdk.signPreSendFor)(this.signer, DEX_CONTRACT_PATH, "RequestTrade", dto);
|
|
5680
5680
|
}
|
|
5681
5681
|
/** The pool's two symbols in contract order: the quote's own when pinned, else string order. */
|
|
5682
5682
|
orientPool(tokenInSymbol, tokenOutSymbol, pool) {
|