@gala-chain/gswap-sdk 2.0.0 → 2.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +2 -2
  2. package/dist/browser/classes/apply_results.js.map +1 -1
  3. package/dist/browser/classes/assets.js.map +1 -1
  4. package/dist/browser/classes/dex_fees.js +1 -1
  5. package/dist/browser/classes/dex_fees.js.map +1 -1
  6. package/dist/browser/classes/gateway.js +1 -1
  7. package/dist/browser/classes/gateway.js.map +1 -1
  8. package/dist/browser/classes/gdex_stream.js +1 -1
  9. package/dist/browser/classes/gdex_stream.js.map +1 -1
  10. package/dist/browser/classes/gswap.js +1 -1
  11. package/dist/browser/classes/gswap.js.map +1 -1
  12. package/dist/browser/classes/gswap_error_catalog.js.map +1 -1
  13. package/dist/browser/classes/gswap_error_phase_table.js.map +1 -1
  14. package/dist/browser/classes/gswap_sdk_error.js +1 -1
  15. package/dist/browser/classes/gswap_sdk_error.js.map +1 -1
  16. package/dist/browser/classes/http_client.js.map +1 -1
  17. package/dist/browser/classes/leaderboard.js.map +1 -1
  18. package/dist/browser/classes/market.js.map +1 -1
  19. package/dist/browser/classes/onramper.js.map +1 -1
  20. package/dist/browser/classes/pending_swap_fate.js.map +1 -1
  21. package/dist/browser/classes/pending_swaps.js +1 -1
  22. package/dist/browser/classes/pending_swaps.js.map +1 -1
  23. package/dist/browser/classes/pools.js +1 -1
  24. package/dist/browser/classes/pools.js.map +1 -1
  25. package/dist/browser/classes/positions.js +1 -1
  26. package/dist/browser/classes/positions.js.map +1 -1
  27. package/dist/browser/classes/quoting.js +1 -1
  28. package/dist/browser/classes/quoting.js.map +1 -1
  29. package/dist/browser/classes/shadow_submit.js.map +1 -1
  30. package/dist/browser/classes/storage_adapters.js.map +1 -1
  31. package/dist/browser/classes/submitted_transaction.js +1 -1
  32. package/dist/browser/classes/submitted_transaction.js.map +1 -1
  33. package/dist/browser/classes/swaps.js +1 -1
  34. package/dist/browser/classes/swaps.js.map +1 -1
  35. package/dist/browser/classes/symbols.js +1 -1
  36. package/dist/browser/classes/symbols.js.map +1 -1
  37. package/dist/browser/types/env.js.map +1 -1
  38. package/dist/browser/types/fees.js.map +1 -1
  39. package/dist/browser/types/market.js.map +1 -1
  40. package/dist/browser/utils/chain_contract.js +2 -0
  41. package/dist/browser/utils/chain_contract.js.map +1 -0
  42. package/dist/browser/utils/classification.js.map +1 -1
  43. package/dist/browser/utils/confirmation_schedule.js.map +1 -1
  44. package/dist/browser/utils/confirmation_state.js.map +1 -1
  45. package/dist/browser/utils/debug.js.map +1 -1
  46. package/dist/browser/utils/dto_builders.js.map +1 -1
  47. package/dist/browser/utils/failure_classification.js.map +1 -1
  48. package/dist/browser/utils/failure_guards.js.map +1 -1
  49. package/dist/browser/utils/lenient.js.map +1 -1
  50. package/dist/browser/utils/ordering.js.map +1 -1
  51. package/dist/browser/utils/reconnection.js +1 -1
  52. package/dist/browser/utils/reconnection.js.map +1 -1
  53. package/dist/browser/utils/resolve_pre_send.js.map +1 -1
  54. package/dist/browser/utils/server_message.js.map +1 -1
  55. package/dist/browser/utils/shadow_errors.js.map +1 -1
  56. package/dist/browser/utils/submit_state.js.map +1 -1
  57. package/dist/browser/utils/tick_align.js.map +1 -1
  58. package/dist/browser/utils/tick_math.js.map +1 -1
  59. package/dist/browser/utils/tick_range.js.map +1 -1
  60. package/dist/browser/utils/ticks.js.map +1 -1
  61. package/dist/browser/utils/validation.js.map +1 -1
  62. package/dist/index.cjs +14 -6
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +2 -2
  65. package/dist/index.d.ts +2 -2
  66. package/dist/index.mjs +14 -6
  67. package/dist/index.mjs.map +1 -1
  68. package/package.json +3 -3
  69. /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/defineProperty.js +0 -0
  70. /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/toPrimitive.js +0 -0
  71. /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/toPropertyKey.js +0 -0
  72. /package/dist/browser/_virtual/{_@oxc-project_runtime@0.153.0 → _@oxc-project_runtime@0.154.0}/helpers/esm/typeof.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"failure_guards.js","names":["isUniqueKeyConsumed","view","toFailureView","error","UNPROVEN_ACKNOWLEDGEMENT_CODES","isUnprovenAcknowledgement","hasCodeIn","isCodeIn","codes","known","code","RELAYABLE_REFUSAL_CODES","isRelayableRefusal","isUninterpretedAnswer","chainErrorKeyOf","errorKey","stringParamOf","NO_MARKET_CODES","isNoMarket","isWriteView"],"sources":["../../../src/utils/failure_guards.ts"],"sourcesContent":["import { isWriteView, stringParamOf, toFailureView } from '@gala-chain/gala-core-sdk';\nimport type { GSwapErrorCode } from '../classes/gswap_error_catalog.js';\nimport type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/**\n * The yes/no questions an app asks about a failure from its CODE alone. They read only the failure\n * view and a short list of codes: no table of every code (that is `classifyFailure`'s, in\n * `failure_classification.ts`), no error class and no catalog (the imports above are types, erased\n * at build time). An app shell that imports one of them pays for this module and nothing else.\n */\n\n/**\n * True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a\n * `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied\n * (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting\n * again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&\n * error.status === 409` and the regex on \"already saved\". Accepts an SDK error or a plain-object\n * view ({@link FailureView}: `code` and `status`); every other value is `false`.\n *\n * @example\n * ```ts\n * if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);\n * ```\n */\nexport function isUniqueKeyConsumed(error: unknown): boolean {\n const view = toFailureView(error);\n return view?.code === 'CHAIN_DISPATCH_FAILED' && view.status === 409;\n}\n\nconst UNPROVEN_ACKNOWLEDGEMENT_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_DATA_MISSING',\n 'GATEWAY_MODE_INVALID',\n 'GATEWAY_SYNC_REQUEST_TRADE',\n 'MISSING_UNIQUE_KEY',\n 'UNIQUE_KEY_MISMATCH',\n];\n\n/**\n * True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no\n * `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.\n * The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an\n * app shows is one line for all five (\"the backend did not confirm it queued the request\"), so\n * the app asks this instead of keeping its own list of the codes. A gateway that says\n * `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.\n *\n * @example\n * ```ts\n * if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);\n * ```\n */\nexport function isUnprovenAcknowledgement(error: unknown): boolean {\n return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);\n}\n\n/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */\nfunction isCodeIn(code: string, codes: readonly GSwapErrorCode[]): boolean {\n return codes.some((known) => known === code);\n}\n\n/**\n * True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose\n * `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet\n * error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.\n */\nfunction hasCodeIn(error: unknown, codes: readonly GSwapErrorCode[]): boolean {\n const view = toFailureView(error);\n // `codes` holds catalog codes only, so membership already means \"a catalog code\": no table needed.\n return view !== undefined && isCodeIn(view.code, codes);\n}\n\n/**\n * The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app\n * may show as it is (and falls back to its own line when it is empty): a refusal the gateway made\n * (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the\n * SDK knows, and `GATEWAY_REJECTED` for one it does not).\n */\nconst RELAYABLE_REFUSAL_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_REPORTED_ERROR',\n 'METHOD_NOT_ALLOWED',\n 'SIGNATURE_INVALID',\n 'SIGNER_MISMATCH',\n 'DTO_INVALID',\n 'BOUNDS_VIOLATION',\n 'SYMBOL_CONFLICT',\n 'RATE_LIMITED',\n 'CHAIN_DISPATCH_FAILED',\n 'GATEWAY_REJECTED',\n];\n\n/**\n * True when the error is a gateway refusal whose `params.serverMessage` an app may relay to the\n * person as the gateway sent it: `GATEWAY_REPORTED_ERROR`, the gateway bounces (`METHOD_NOT_ALLOWED`,\n * `SIGNATURE_INVALID`, `SIGNER_MISMATCH`, `DTO_INVALID`, `BOUNDS_VIOLATION`, `SYMBOL_CONFLICT`,\n * `RATE_LIMITED`, `GATEWAY_REJECTED`) and `CHAIN_DISPATCH_FAILED`. The app shows `serverMessage` when\n * it is not empty and its own line when it is; the SDK's English `message` is never what to show.\n *\n * It accepts a plain-object view of an SDK error too ({@link FailureView}: an app's wrapper with a\n * `code`), and decides from the code in the same way. It narrows to `GSwapSDKError<...>` ONLY when\n * called with an SDK error; with an `unknown` or a view it answers `boolean` (narrow with\n * `isGSwapError` first, or read the view's own `params`).\n *\n * It is a test on the code alone, so it also holds for `CHAIN_DISPATCH_FAILED` with HTTP 409\n * (the `uniqueKey` was already consumed; `classifyFailure` says `unknown`): an app that words that\n * case itself (\"already submitted\", then confirm the key) checks `error.status === 409` BEFORE\n * relaying. It is false for `CHAIN_REJECTED` (the chain's verdict, worded by where it is shown: the\n * submit and confirm screens differ), for `HTTP_ERROR` (a proxy's page, not an answer to this\n * write) and for the five unproven acknowledgements (`isUnprovenAcknowledgement`: they carry no\n * server text).\n *\n * @example\n * ```ts\n * if (isRelayableRefusal(error)) show(error.params.serverMessage || t('swap.requestFailed'));\n * ```\n */\nexport function isRelayableRefusal(error: GSwapSDKError): error is GSwapSDKError<RelayableCode>;\nexport function isRelayableRefusal(error: unknown): boolean;\nexport function isRelayableRefusal(error: unknown): boolean {\n return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);\n}\n\n/** The codes {@link isRelayableRefusal} is true for. */\nexport type RelayableCode =\n | 'GATEWAY_REPORTED_ERROR'\n | 'METHOD_NOT_ALLOWED'\n | 'SIGNATURE_INVALID'\n | 'SIGNER_MISMATCH'\n | 'DTO_INVALID'\n | 'BOUNDS_VIOLATION'\n | 'SYMBOL_CONFLICT'\n | 'RATE_LIMITED'\n | 'CHAIN_DISPATCH_FAILED'\n | 'GATEWAY_REJECTED';\n\n/**\n * True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in\n * `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements\n * (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).\n * The outcome is `unknown` for all six. It replaces the app's own\n * `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.\n */\nexport function isUninterpretedAnswer(error: unknown): boolean {\n return isUnprovenAcknowledgement(error) || hasCodeIn(error, ['GATEWAY_REPORTED_ERROR']);\n}\n\n/**\n * The chain's own machine-readable `ErrorKey` of a failure (`'TOKEN_NOT_FOUND'`,\n * `'NOT_ENOUGH_LIQUIDITY'`, ...), for an app that maps a chain refusal to its own copy: the\n * `params.errorKey` of a `CHAIN_REJECTED` (an apply result, or a body that carries the chain's\n * error) and of a `CHAIN_DISPATCH_FAILED` (the gateway adds the chain's key to the body it\n * answered). `undefined` when the failure is neither, or when it carries no key (the gateway sent\n * none: the SDK writes `''`, which is not a key). Map the KEY, never the message text.\n *\n * Accepts an SDK error or a plain-object view ({@link FailureView}: `code` and `params`); every\n * other value is `undefined`. Other codes are `undefined` even when they have an `errorKey`-named\n * param, so a stray field cannot pass for a chain verdict.\n *\n * @example\n * ```ts\n * const key = chainErrorKeyOf(error);\n * if (key === 'NOT_ENOUGH_LIQUIDITY') showTooThin(); else showGeneric(error);\n * ```\n */\nexport function chainErrorKeyOf(error: unknown): string | undefined {\n const view = toFailureView(error);\n if (view === undefined) return undefined;\n if (view.code !== 'CHAIN_REJECTED' && view.code !== 'CHAIN_DISPATCH_FAILED') return undefined;\n const errorKey = stringParamOf(view, 'errorKey');\n return errorKey === undefined || errorKey === '' ? undefined : errorKey;\n}\n\n/** Codes that mean \"there is no market for this\" however the app reached them. */\nconst NO_MARKET_CODES: readonly GSwapErrorCode[] = [\n 'NO_POOL_AVAILABLE',\n 'INSUFFICIENT_LIQUIDITY',\n 'UNKNOWN_TOKEN',\n];\n\n/**\n * True when a failure means \"there is no market to trade this pair\": `NO_POOL_AVAILABLE` (no pool\n * at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX\n * has no trading symbol for the token), or a READ that was answered 404 (a quote the backend\n * cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||\n * notFound` list, so the empty-state (\"No market for this pair\") has one definition.\n *\n * A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing\n * market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every\n * other value is `false`.\n *\n * @example\n * ```ts\n * if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);\n * ```\n */\nexport function isNoMarket(error: unknown): boolean {\n const view = toFailureView(error);\n if (view === undefined) return false;\n if (isCodeIn(view.code, NO_MARKET_CODES)) return true;\n return !isWriteView(view) && (view.notFound === true || view.status === 404);\n}\n"],"mappings":"8FAwBA,SAAgBA,EAAoB,EAAyB,CAC3D,IAAMC,EAAOC,EAAcC,CAAK,EAChC,OAAOF,GAAM,OAAS,yBAA2BA,EAAK,SAAW,GACnE,CAEA,MAAMG,EAA4D,CAChE,uBACA,uBACA,6BACA,qBACA,qBACF,EAeA,SAAgBC,EAA0B,EAAyB,CACjE,OAAOC,EAAUH,EAAOC,CAA8B,CACxD,CAGA,SAASG,EAAS,EAAc,EAA2C,CACzE,OAAOC,EAAM,KAAM,GAAUC,IAAUC,CAAI,CAC7C,CAOA,SAASJ,EAAU,EAAgB,EAA2C,CAC5E,IAAML,EAAOC,EAAcC,CAAK,EAEhC,OAAOF,IAAS,IAAA,IAAaM,EAASN,EAAK,KAAMO,CAAK,CACxD,CAQA,MAAMG,EAAqD,CACzD,yBACA,qBACA,oBACA,kBACA,cACA,mBACA,kBACA,eACA,wBACA,kBACF,EA6BA,SAAgBC,EAAmB,EAAyB,CAC1D,OAAON,EAAUH,EAAOQ,CAAuB,CACjD,CAsBA,SAAgBE,EAAsB,EAAyB,CAC7D,OAAOR,EAA0BF,CAAK,GAAKG,EAAUH,EAAO,CAAC,wBAAwB,CAAC,CACxF,CAoBA,SAAgBW,EAAgB,EAAoC,CAClE,IAAMb,EAAOC,EAAcC,CAAK,EAEhC,GADIF,IAAS,IAAA,IACTA,EAAK,OAAS,kBAAoBA,EAAK,OAAS,wBAAyB,OAC7E,IAAMc,EAAWC,EAAcf,EAAM,UAAU,EAC/C,OAAOc,IAAa,IAAA,IAAaA,IAAa,GAAK,IAAA,GAAYA,CACjE,CAGA,MAAME,EAA6C,CACjD,oBACA,yBACA,eACF,EAkBA,SAAgBC,EAAW,EAAyB,CAClD,IAAMjB,EAAOC,EAAcC,CAAK,EAGhC,OAFIF,IAAS,IAAA,GAAkB,GAC3BM,EAASN,EAAK,KAAMgB,CAAe,EAAU,GAC1C,CAACE,EAAYlB,CAAI,IAAMA,EAAK,WAAa,IAAQA,EAAK,SAAW,IAC1E"}
1
+ {"version":3,"file":"failure_guards.js","names":["isUniqueKeyConsumed","view","toFailureView","error","UNPROVEN_ACKNOWLEDGEMENT_CODES","isUnprovenAcknowledgement","hasCodeIn","isCodeIn","codes","known","code","RELAYABLE_REFUSAL_CODES","isRelayableRefusal","isUninterpretedAnswer","chainErrorKeyOf","errorKey","stringParamOf","NO_MARKET_CODES","isNoMarket","isWriteView"],"sources":["../../../src/utils/failure_guards.ts"],"sourcesContent":["import { isWriteView, stringParamOf, toFailureView } from '@gala-chain/gala-core-sdk';\nimport type { GSwapErrorCode } from '../classes/gswap_error_catalog.js';\nimport type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/**\n * The yes/no questions an app asks about a failure from its CODE alone. They read only the failure\n * view and a short list of codes: no table of every code (that is `classifyFailure`'s, in\n * `failure_classification.ts`), no error class and no catalog (the imports above are types, erased\n * at build time). An app shell that imports one of them pays for this module and nothing else.\n */\n\n/**\n * True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a\n * `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied\n * (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting\n * again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&\n * error.status === 409` and the regex on \"already saved\". Accepts an SDK error or a plain-object\n * view ({@link FailureView}: `code` and `status`); every other value is `false`.\n *\n * @example\n * ```ts\n * if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);\n * ```\n */\nexport function isUniqueKeyConsumed(error: unknown): boolean {\n const view = toFailureView(error);\n return view?.code === 'CHAIN_DISPATCH_FAILED' && view.status === 409;\n}\n\nconst UNPROVEN_ACKNOWLEDGEMENT_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_DATA_MISSING',\n 'GATEWAY_MODE_INVALID',\n 'GATEWAY_SYNC_REQUEST_TRADE',\n 'MISSING_UNIQUE_KEY',\n 'UNIQUE_KEY_MISMATCH',\n];\n\n/**\n * True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no\n * `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.\n * The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an\n * app shows is one line for all five (\"the backend did not confirm it queued the request\"), so\n * the app asks this instead of keeping its own list of the codes. A gateway that says\n * `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.\n *\n * @example\n * ```ts\n * if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);\n * ```\n */\nexport function isUnprovenAcknowledgement(error: unknown): boolean {\n return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);\n}\n\n/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */\nfunction isCodeIn(code: string, codes: readonly GSwapErrorCode[]): boolean {\n return codes.some((known) => known === code);\n}\n\n/**\n * True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose\n * `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet\n * error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.\n */\nfunction hasCodeIn(error: unknown, codes: readonly GSwapErrorCode[]): boolean {\n const view = toFailureView(error);\n // `codes` holds catalog codes only, so membership already means \"a catalog code\": no table needed.\n return view !== undefined && isCodeIn(view.code, codes);\n}\n\n/**\n * The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app\n * may show as it is (and falls back to its own line when it is empty): a refusal the gateway made\n * (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the\n * SDK knows, and `GATEWAY_REJECTED` for one it does not).\n */\nconst RELAYABLE_REFUSAL_CODES: readonly GSwapErrorCode[] = [\n 'GATEWAY_REPORTED_ERROR',\n 'METHOD_NOT_ALLOWED',\n 'SIGNATURE_INVALID',\n 'SIGNER_MISMATCH',\n 'DTO_INVALID',\n 'BOUNDS_VIOLATION',\n 'SYMBOL_CONFLICT',\n 'RATE_LIMITED',\n 'CHAIN_DISPATCH_FAILED',\n 'GATEWAY_REJECTED',\n];\n\n/**\n * True when the error is a gateway refusal whose `params.serverMessage` an app may relay to the\n * person as the gateway sent it: `GATEWAY_REPORTED_ERROR`, the gateway bounces (`METHOD_NOT_ALLOWED`,\n * `SIGNATURE_INVALID`, `SIGNER_MISMATCH`, `DTO_INVALID`, `BOUNDS_VIOLATION`, `SYMBOL_CONFLICT`,\n * `RATE_LIMITED`, `GATEWAY_REJECTED`) and `CHAIN_DISPATCH_FAILED`. The app shows `serverMessage` when\n * it is not empty and its own line when it is; the SDK's English `message` is never what to show.\n *\n * It accepts a plain-object view of an SDK error too ({@link FailureView}: an app's wrapper with a\n * `code`), and decides from the code in the same way. It narrows to `GSwapSDKError<...>` ONLY when\n * called with an SDK error; with an `unknown` or a view it answers `boolean` (narrow with\n * `isGSwapError` first, or read the view's own `params`).\n *\n * It is a test on the code alone, so it also holds for `CHAIN_DISPATCH_FAILED` with HTTP 409\n * (the `uniqueKey` was already consumed; `classifyFailure` says `unknown`): an app that words that\n * case itself (\"already submitted\", then confirm the key) checks `error.status === 409` BEFORE\n * relaying. It is false for `CHAIN_REJECTED` (the chain's verdict, worded by where it is shown: the\n * submit and confirm screens differ), for `HTTP_ERROR` (a proxy's page, not an answer to this\n * write) and for the five unproven acknowledgements (`isUnprovenAcknowledgement`: they carry no\n * server text).\n *\n * @example\n * ```ts\n * if (isRelayableRefusal(error)) show(error.params.serverMessage || t('swap.requestFailed'));\n * ```\n */\nexport function isRelayableRefusal(error: GSwapSDKError): error is GSwapSDKError<RelayableCode>;\nexport function isRelayableRefusal(error: unknown): boolean;\nexport function isRelayableRefusal(error: unknown): boolean {\n return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);\n}\n\n/** The codes {@link isRelayableRefusal} is true for. */\nexport type RelayableCode =\n | 'GATEWAY_REPORTED_ERROR'\n | 'METHOD_NOT_ALLOWED'\n | 'SIGNATURE_INVALID'\n | 'SIGNER_MISMATCH'\n | 'DTO_INVALID'\n | 'BOUNDS_VIOLATION'\n | 'SYMBOL_CONFLICT'\n | 'RATE_LIMITED'\n | 'CHAIN_DISPATCH_FAILED'\n | 'GATEWAY_REJECTED';\n\n/**\n * True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in\n * `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements\n * (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).\n * The outcome is `unknown` for all six. It replaces the app's own\n * `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.\n */\nexport function isUninterpretedAnswer(error: unknown): boolean {\n return isUnprovenAcknowledgement(error) || hasCodeIn(error, ['GATEWAY_REPORTED_ERROR']);\n}\n\n/**\n * The chain's own machine-readable `ErrorKey` of a failure (`'TOKEN_NOT_FOUND'`,\n * `'NOT_ENOUGH_LIQUIDITY'`, ...), for an app that maps a chain refusal to its own copy: the\n * `params.errorKey` of a `CHAIN_REJECTED` (an apply result, or a body that carries the chain's\n * error) and of a `CHAIN_DISPATCH_FAILED` (the gateway adds the chain's key to the body it\n * answered). `undefined` when the failure is neither, or when it carries no key (the gateway sent\n * none: the SDK writes `''`, which is not a key). Map the KEY, never the message text.\n *\n * Accepts an SDK error or a plain-object view ({@link FailureView}: `code` and `params`); every\n * other value is `undefined`. Other codes are `undefined` even when they have an `errorKey`-named\n * param, so a stray field cannot pass for a chain verdict.\n *\n * @example\n * ```ts\n * const key = chainErrorKeyOf(error);\n * if (key === 'NOT_ENOUGH_LIQUIDITY') showTooThin(); else showGeneric(error);\n * ```\n */\nexport function chainErrorKeyOf(error: unknown): string | undefined {\n const view = toFailureView(error);\n if (view === undefined) return undefined;\n if (view.code !== 'CHAIN_REJECTED' && view.code !== 'CHAIN_DISPATCH_FAILED') return undefined;\n const errorKey = stringParamOf(view, 'errorKey');\n return errorKey === undefined || errorKey === '' ? undefined : errorKey;\n}\n\n/** Codes that mean \"there is no market for this\" however the app reached them. */\nconst NO_MARKET_CODES: readonly GSwapErrorCode[] = [\n 'NO_POOL_AVAILABLE',\n 'INSUFFICIENT_LIQUIDITY',\n 'UNKNOWN_TOKEN',\n];\n\n/**\n * True when a failure means \"there is no market to trade this pair\": `NO_POOL_AVAILABLE` (no pool\n * at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX\n * has no trading symbol for the token), or a READ that was answered 404 (a quote the backend\n * cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||\n * notFound` list, so the empty-state (\"No market for this pair\") has one definition.\n *\n * A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing\n * market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every\n * other value is `false`.\n *\n * @example\n * ```ts\n * if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);\n * ```\n */\nexport function isNoMarket(error: unknown): boolean {\n const view = toFailureView(error);\n if (view === undefined) return false;\n if (isCodeIn(view.code, NO_MARKET_CODES)) return true;\n return !isWriteView(view) && (view.notFound === true || view.status === 404);\n}\n"],"mappings":"A,8FAwBA,SAAgBA,EAAoB,EAAyB,CAC3D,IAAMC,EAAOC,EAAcC,CAAK,EAChC,OAAOF,GAAM,OAAS,yBAA2BA,EAAK,SAAW,GACnE,CAEA,MAAMG,EAA4D,CAChE,uBACA,uBACA,6BACA,qBACA,qBACF,EAeA,SAAgBC,EAA0B,EAAyB,CACjE,OAAOC,EAAUH,EAAOC,CAA8B,CACxD,CAGA,SAASG,EAAS,EAAc,EAA2C,CACzE,OAAOC,EAAM,KAAM,GAAUC,IAAUC,CAAI,CAC7C,CAOA,SAASJ,EAAU,EAAgB,EAA2C,CAC5E,IAAML,EAAOC,EAAcC,CAAK,EAEhC,OAAOF,IAAS,IAAA,IAAaM,EAASN,EAAK,KAAMO,CAAK,CACxD,CAQA,MAAMG,EAAqD,CACzD,yBACA,qBACA,oBACA,kBACA,cACA,mBACA,kBACA,eACA,wBACA,kBACF,EA6BA,SAAgBC,EAAmB,EAAyB,CAC1D,OAAON,EAAUH,EAAOQ,CAAuB,CACjD,CAsBA,SAAgBE,EAAsB,EAAyB,CAC7D,OAAOR,EAA0BF,CAAK,GAAKG,EAAUH,EAAO,CAAC,wBAAwB,CAAC,CACxF,CAoBA,SAAgBW,EAAgB,EAAoC,CAClE,IAAMb,EAAOC,EAAcC,CAAK,EAEhC,GADIF,IAAS,IAAA,IACTA,EAAK,OAAS,kBAAoBA,EAAK,OAAS,wBAAyB,OAC7E,IAAMc,EAAWC,EAAcf,EAAM,UAAU,EAC/C,OAAOc,IAAa,IAAA,IAAaA,IAAa,GAAK,IAAA,GAAYA,CACjE,CAGA,MAAME,EAA6C,CACjD,oBACA,yBACA,eACF,EAkBA,SAAgBC,EAAW,EAAyB,CAClD,IAAMjB,EAAOC,EAAcC,CAAK,EAGhC,OAFIF,IAAS,IAAA,GAAkB,GAC3BM,EAASN,EAAK,KAAMgB,CAAe,EAAU,GAC1C,CAACE,EAAYlB,CAAI,IAAMA,EAAK,WAAa,IAAQA,EAAK,SAAW,IAC1E,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"lenient.js","names":["entryOk","entryRejected","readEntries","data","GSwapSDKError","source","rows","parsed","parse","entry","onInvalidEntry","asEntryRecord","value","finiteNumberOf"],"sources":["../../../src/utils/lenient.ts"],"sourcesContent":["import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** One row of a list answer that the SDK skipped because it was not usable. */\nexport interface InvalidEntry {\n /** Which read the row came from. */\n source: 'pools' | 'symbols' | 'positions' | 'prices' | 'priceSeries' | 'seasons' | 'leaderboard';\n /**\n * Position of the row in the answer's array; for `prices` (an answer keyed by token), the\n * position of the token in the list asked for.\n */\n index: number;\n /** The row exactly as the backend sent it. */\n entry: unknown;\n /** Why it was skipped, in words. */\n reason: string;\n}\n\n/**\n * Called once per skipped row, in order, before the read resolves. It is a diagnostics hook: what it\n * does, or throws, never changes the result of the read.\n */\nexport type InvalidEntryHandler = (invalid: InvalidEntry) => void;\n\n/** The outcome of reading one row. */\nexport type EntryParse<T> = { ok: true; value: T } | { ok: false; reason: string };\n\n/** A usable row. */\nexport function entryOk<T>(value: T): EntryParse<T> {\n return { ok: true, value };\n}\n\n/** An unusable row, with the reason it is reported under. */\nexport function entryRejected<T>(reason: string): EntryParse<T> {\n return { ok: false, reason };\n}\n\n/**\n * Reads a list answer row by row: a row that cannot be used is skipped and reported, instead of\n * rejecting the whole list because of one bad row. An answer that is not a list at all is still\n * `INVALID_CHAIN_RESPONSE` (a read's: `write: false`): nothing in it can be trusted.\n */\nexport function readEntries<T>(\n source: InvalidEntry['source'],\n data: unknown,\n parse: (entry: unknown) => EntryParse<T>,\n onInvalidEntry?: InvalidEntryHandler,\n): T[] {\n if (!Array.isArray(data)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: `${source} list` },\n { body: data, write: false },\n );\n }\n const rows: T[] = [];\n (data as unknown[]).forEach((entry, index) => {\n const parsed = parse(entry);\n if (parsed.ok) {\n rows.push(parsed.value);\n return;\n }\n try {\n onInvalidEntry?.({ source, index, entry, reason: parsed.reason });\n } catch {\n // A diagnostics hook must not turn a lenient read into a failed one.\n }\n });\n return rows;\n}\n\n/** A plain JSON object (not null, not an array). */\nexport function asEntryRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** A finite number, or a non-empty numeric string, as a number; otherwise `undefined`. */\nexport function finiteNumberOf(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined;\n if (typeof value === 'string' && value.trim() !== '') {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n"],"mappings":"8DA2BA,SAAgBA,EAAW,EAAyB,CAClD,MAAO,CAAE,GAAI,GAAM,OAAM,CAC3B,CAGA,SAAgBC,EAAiB,EAA+B,CAC9D,MAAO,CAAE,GAAI,GAAO,QAAO,CAC7B,CAOA,SAAgBC,EACd,EACA,EACA,EACA,EACK,CACL,GAAI,CAAC,MAAM,QAAQC,CAAI,EACrB,MAAM,IAAIC,EACR,yBACA,CAAE,SAAU,GAAGC,EAAO,MAAO,EAC7B,CAAE,KAAMF,EAAM,MAAO,EAAM,CAC7B,EAEF,IAAMG,EAAY,CAAC,EAanB,OAZAH,EAAoB,SAAS,EAAO,IAAU,CAC5C,IAAMI,EAASC,EAAMC,CAAK,EAC1B,GAAIF,EAAO,GACTD,EAAK,KAAKC,EAAO,KAAK,OAGxB,GAAI,CACFG,IAAiB,CAAE,SAAQ,QAAO,QAAO,OAAQH,EAAO,MAAO,CAAC,CAClE,MAAQ,CAER,CACF,CAAC,EACMD,CACT,CAGA,SAAgBK,EAAc,EAAqD,CACjF,OAAO,OAAOC,GAAU,UAAYA,GAAkB,CAAC,MAAM,QAAQA,CAAK,EACrEA,EACD,IAAA,EACN,CAGA,SAAgBC,EAAe,EAAoC,CACjE,GAAI,OAAOD,GAAU,SAAU,OAAO,OAAO,SAASA,CAAK,EAAIA,EAAQ,IAAA,GACvE,GAAI,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAAI,CACpD,IAAML,EAAS,OAAOK,CAAK,EAC3B,OAAO,OAAO,SAASL,CAAM,EAAIA,EAAS,IAAA,EAC5C,CAEF"}
1
+ {"version":3,"file":"lenient.js","names":["entryOk","entryRejected","readEntries","data","GSwapSDKError","source","rows","parsed","parse","entry","onInvalidEntry","asEntryRecord","value","finiteNumberOf"],"sources":["../../../src/utils/lenient.ts"],"sourcesContent":["import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** One row of a list answer that the SDK skipped because it was not usable. */\nexport interface InvalidEntry {\n /** Which read the row came from. */\n source: 'pools' | 'symbols' | 'positions' | 'prices' | 'priceSeries' | 'seasons' | 'leaderboard';\n /**\n * Position of the row in the answer's array; for `prices` (an answer keyed by token), the\n * position of the token in the list asked for.\n */\n index: number;\n /** The row exactly as the backend sent it. */\n entry: unknown;\n /** Why it was skipped, in words. */\n reason: string;\n}\n\n/**\n * Called once per skipped row, in order, before the read resolves. It is a diagnostics hook: what it\n * does, or throws, never changes the result of the read.\n */\nexport type InvalidEntryHandler = (invalid: InvalidEntry) => void;\n\n/** The outcome of reading one row. */\nexport type EntryParse<T> = { ok: true; value: T } | { ok: false; reason: string };\n\n/** A usable row. */\nexport function entryOk<T>(value: T): EntryParse<T> {\n return { ok: true, value };\n}\n\n/** An unusable row, with the reason it is reported under. */\nexport function entryRejected<T>(reason: string): EntryParse<T> {\n return { ok: false, reason };\n}\n\n/**\n * Reads a list answer row by row: a row that cannot be used is skipped and reported, instead of\n * rejecting the whole list because of one bad row. An answer that is not a list at all is still\n * `INVALID_CHAIN_RESPONSE` (a read's: `write: false`): nothing in it can be trusted.\n */\nexport function readEntries<T>(\n source: InvalidEntry['source'],\n data: unknown,\n parse: (entry: unknown) => EntryParse<T>,\n onInvalidEntry?: InvalidEntryHandler,\n): T[] {\n if (!Array.isArray(data)) {\n throw new GSwapSDKError(\n 'INVALID_CHAIN_RESPONSE',\n { resource: `${source} list` },\n { body: data, write: false },\n );\n }\n const rows: T[] = [];\n (data as unknown[]).forEach((entry, index) => {\n const parsed = parse(entry);\n if (parsed.ok) {\n rows.push(parsed.value);\n return;\n }\n try {\n onInvalidEntry?.({ source, index, entry, reason: parsed.reason });\n } catch {\n // A diagnostics hook must not turn a lenient read into a failed one.\n }\n });\n return rows;\n}\n\n/** A plain JSON object (not null, not an array). */\nexport function asEntryRecord(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** A finite number, or a non-empty numeric string, as a number; otherwise `undefined`. */\nexport function finiteNumberOf(value: unknown): number | undefined {\n if (typeof value === 'number') return Number.isFinite(value) ? value : undefined;\n if (typeof value === 'string' && value.trim() !== '') {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n}\n"],"mappings":"A,8DA2BA,SAAgBA,EAAW,EAAyB,CAClD,MAAO,CAAE,GAAI,GAAM,OAAM,CAC3B,CAGA,SAAgBC,EAAiB,EAA+B,CAC9D,MAAO,CAAE,GAAI,GAAO,QAAO,CAC7B,CAOA,SAAgBC,EACd,EACA,EACA,EACA,EACK,CACL,GAAI,CAAC,MAAM,QAAQC,CAAI,EACrB,MAAM,IAAIC,EACR,yBACA,CAAE,SAAU,GAAGC,EAAO,MAAO,EAC7B,CAAE,KAAMF,EAAM,MAAO,EAAM,CAC7B,EAEF,IAAMG,EAAY,CAAC,EAanB,OAZAH,EAAoB,SAAS,EAAO,IAAU,CAC5C,IAAMI,EAASC,EAAMC,CAAK,EAC1B,GAAIF,EAAO,GACTD,EAAK,KAAKC,EAAO,KAAK,OAGxB,GAAI,CACFG,IAAiB,CAAE,SAAQ,QAAO,QAAO,OAAQH,EAAO,MAAO,CAAC,CAClE,MAAQ,CAER,CACF,CAAC,EACMD,CACT,CAGA,SAAgBK,EAAc,EAAqD,CACjF,OAAO,OAAOC,GAAU,UAAYA,GAAkB,CAAC,MAAM,QAAQA,CAAK,EACrEA,EACD,IAAA,EACN,CAGA,SAAgBC,EAAe,EAAoC,CACjE,GAAI,OAAOD,GAAU,SAAU,OAAO,OAAO,SAASA,CAAK,EAAIA,EAAQ,IAAA,GACvE,GAAI,OAAOA,GAAU,UAAYA,EAAM,KAAK,IAAM,GAAI,CACpD,IAAML,EAAS,OAAOK,CAAK,EAC3B,OAAO,OAAO,SAASL,CAAM,EAAIA,EAAS,IAAA,EAC5C,CAEF,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ordering.js","names":["orderSymbols","a","b","readOrderedSymbols","value","token0","token1","record","\"token0\"","\"token1\"","GSwapSDKError","parseTokenClassKey","tokenClassKey","parsed","splitClassKey"],"sources":["../../../src/utils/ordering.ts"],"sourcesContent":["import { splitClassKey, type GalaChainTokenClassKey } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** A symbol or a GalaChain token class key accepted by v2 operations. */\nexport type TokenRef = string | GalaChainTokenClassKey;\n\n/** Return two trading symbols in the contract's plain-string order. */\nexport function orderSymbols(a: string, b: string): [string, string] {\n return a < b ? [a, b] : [b, a];\n}\n\n/** Read an ordered symbol pair from a tuple or object returned by a boundary helper.\n *\n * @example\n * ```ts\n * const pair = readOrderedSymbols(['GALA', 'GUSDC']);\n * console.log(pair.token0);\n * ```\n */\nexport function readOrderedSymbols(value: unknown): { token0: string; token1: string } {\n if (Array.isArray(value) && value.length >= 2) {\n const token0 = (value as unknown[])[0];\n const token1 = (value as unknown[])[1];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n if (typeof value === 'object' && value !== null) {\n const record = value as Record<string, unknown>;\n const token0 = record['token0'];\n const token1 = record['token1'];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n throw new GSwapSDKError('UNORDERABLE_SYMBOLS', {\n received: Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value,\n });\n}\n\n/**\n * Parse a pipe- or dollar-separated token class key.\n *\n * The LAST three segments are always `category`, `type` and `additionalKey`; everything before\n * them is the `collection`. Parsing from the right is required because real collections contain\n * the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`\n * shifts every field. Nothing here says anything about the token's symbol: a class key carries\n * no symbol, which must come from the token class or trading-symbol registry.\n *\n * @example\n * ```ts\n * parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'\n * ```\n */\nexport function parseTokenClassKey(tokenClassKey: TokenRef): GalaChainTokenClassKey {\n if (typeof tokenClassKey === 'object') {\n return {\n collection: tokenClassKey.collection,\n category: tokenClassKey.category,\n type: tokenClassKey.type,\n additionalKey: tokenClassKey.additionalKey,\n };\n }\n\n const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes('|') ? '|' : '$');\n if (parsed === undefined) throw new GSwapSDKError('INVALID_TOKEN_CLASS_KEY', { tokenClassKey });\n return parsed;\n}\n"],"mappings":"wHAOA,SAAgBA,EAAa,EAAW,EAA6B,CACnE,OAAOC,EAAIC,EAAI,CAACD,EAAGC,CAAC,EAAI,CAACA,EAAGD,CAAC,CAC/B,CAUA,SAAgBE,EAAmB,EAAoD,CACrF,GAAI,MAAM,QAAQC,CAAK,GAAKA,EAAM,QAAU,EAAG,CAC7C,IAAMC,EAAUD,EAAoB,GAC9BE,EAAUF,EAAoB,GACpC,GAAI,OAAOC,GAAW,UAAY,OAAOC,GAAW,SAAU,MAAO,CAAE,SAAQ,QAAO,CACxF,CACA,GAAI,OAAOF,GAAU,UAAYA,EAAgB,CAC/C,IAAMG,EAASH,EACTC,EAASE,EAAOC,OAChBF,EAASC,EAAOE,OACtB,GAAI,OAAOJ,GAAW,UAAY,OAAOC,GAAW,SAAU,MAAO,CAAE,SAAQ,QAAO,CACxF,CACA,MAAM,IAAII,EAAc,sBAAuB,CAC7C,SAAU,MAAM,QAAQN,CAAK,EAAI,QAAUA,IAAU,KAAO,OAAS,OAAOA,CAC9E,CAAC,CACH,CAgBA,SAAgBO,EAAmB,EAAiD,CAClF,GAAI,OAAOC,GAAkB,SAC3B,MAAO,CACL,WAAYA,EAAc,WAC1B,SAAUA,EAAc,SACxB,KAAMA,EAAc,KACpB,cAAeA,EAAc,aAC/B,EAGF,IAAMC,EAASC,EAAcF,EAAeA,EAAc,SAAS,GAAG,EAAI,IAAM,GAAG,EACnF,GAAIC,IAAW,IAAA,GAAW,MAAM,IAAIH,EAAc,0BAA2B,CAAE,eAAc,CAAC,EAC9F,OAAOG,CACT"}
1
+ {"version":3,"file":"ordering.js","names":["orderSymbols","a","b","readOrderedSymbols","value","token0","token1","record","\"token0\"","\"token1\"","GSwapSDKError","parseTokenClassKey","tokenClassKey","parsed","splitClassKey"],"sources":["../../../src/utils/ordering.ts"],"sourcesContent":["import { splitClassKey, type GalaChainTokenClassKey } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/** A symbol or a GalaChain token class key accepted by v2 operations. */\nexport type TokenRef = string | GalaChainTokenClassKey;\n\n/** Return two trading symbols in the contract's plain-string order. */\nexport function orderSymbols(a: string, b: string): [string, string] {\n return a < b ? [a, b] : [b, a];\n}\n\n/** Read an ordered symbol pair from a tuple or object returned by a boundary helper.\n *\n * @example\n * ```ts\n * const pair = readOrderedSymbols(['GALA', 'GUSDC']);\n * console.log(pair.token0);\n * ```\n */\nexport function readOrderedSymbols(value: unknown): { token0: string; token1: string } {\n if (Array.isArray(value) && value.length >= 2) {\n const token0 = (value as unknown[])[0];\n const token1 = (value as unknown[])[1];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n if (typeof value === 'object' && value !== null) {\n const record = value as Record<string, unknown>;\n const token0 = record['token0'];\n const token1 = record['token1'];\n if (typeof token0 === 'string' && typeof token1 === 'string') return { token0, token1 };\n }\n throw new GSwapSDKError('UNORDERABLE_SYMBOLS', {\n received: Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value,\n });\n}\n\n/**\n * Parse a pipe- or dollar-separated token class key.\n *\n * The LAST three segments are always `category`, `type` and `additionalKey`; everything before\n * them is the `collection`. Parsing from the right is required because real collections contain\n * the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`\n * shifts every field. Nothing here says anything about the token's symbol: a class key carries\n * no symbol, which must come from the token class or trading-symbol registry.\n *\n * @example\n * ```ts\n * parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'\n * ```\n */\nexport function parseTokenClassKey(tokenClassKey: TokenRef): GalaChainTokenClassKey {\n if (typeof tokenClassKey === 'object') {\n return {\n collection: tokenClassKey.collection,\n category: tokenClassKey.category,\n type: tokenClassKey.type,\n additionalKey: tokenClassKey.additionalKey,\n };\n }\n\n const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes('|') ? '|' : '$');\n if (parsed === undefined) throw new GSwapSDKError('INVALID_TOKEN_CLASS_KEY', { tokenClassKey });\n return parsed;\n}\n"],"mappings":"A,wHAOA,SAAgBA,EAAa,EAAW,EAA6B,CACnE,OAAOC,EAAIC,EAAI,CAACD,EAAGC,CAAC,EAAI,CAACA,EAAGD,CAAC,CAC/B,CAUA,SAAgBE,EAAmB,EAAoD,CACrF,GAAI,MAAM,QAAQC,CAAK,GAAKA,EAAM,QAAU,EAAG,CAC7C,IAAMC,EAAUD,EAAoB,GAC9BE,EAAUF,EAAoB,GACpC,GAAI,OAAOC,GAAW,UAAY,OAAOC,GAAW,SAAU,MAAO,CAAE,SAAQ,QAAO,CACxF,CACA,GAAI,OAAOF,GAAU,UAAYA,EAAgB,CAC/C,IAAMG,EAASH,EACTC,EAASE,EAAOC,OAChBF,EAASC,EAAOE,OACtB,GAAI,OAAOJ,GAAW,UAAY,OAAOC,GAAW,SAAU,MAAO,CAAE,SAAQ,QAAO,CACxF,CACA,MAAM,IAAII,EAAc,sBAAuB,CAC7C,SAAU,MAAM,QAAQN,CAAK,EAAI,QAAUA,IAAU,KAAO,OAAS,OAAOA,CAC9E,CAAC,CACH,CAgBA,SAAgBO,EAAmB,EAAiD,CAClF,GAAI,OAAOC,GAAkB,SAC3B,MAAO,CACL,WAAYA,EAAc,WAC1B,SAAUA,EAAc,SACxB,KAAMA,EAAc,KACpB,cAAeA,EAAc,aAC/B,EAGF,IAAMC,EAASC,EAAcF,EAAeA,EAAc,SAAS,GAAG,EAAI,IAAM,GAAG,EACnF,GAAIC,IAAW,IAAA,GAAW,MAAM,IAAIH,EAAc,0BAA2B,CAAE,eAAc,CAAC,EAC9F,OAAOG,CACT,C"}
@@ -1,2 +1,2 @@
1
- import e from"../_virtual/_@oxc-project_runtime@0.153.0/helpers/esm/defineProperty.js";var t=class{constructor(t){this.options=t,e(this,`attempts`,0),e(this,`delayMs`,void 0),e(this,`maxDelayMs`,void 0),this.delayMs=t.baseDelayMs,this.maxDelayMs=t.maxDelayMs??3e4}shouldRetry(){return this.attempts<this.options.maxAttempts}nextDelayMs(){return this.delayMs}recordAttempt(){this.attempts+=1,this.delayMs=Math.min(this.delayMs*2,this.maxDelayMs)}reset(){this.attempts=0,this.delayMs=this.options.baseDelayMs}get attemptCount(){return this.attempts}get maxAttempts(){return this.options.maxAttempts}};export{t as ReconnectionBackoff};
1
+ import e from"../_virtual/_@oxc-project_runtime@0.154.0/helpers/esm/defineProperty.js";var t=class{constructor(t){this.options=t,e(this,`attempts`,0),e(this,`delayMs`,void 0),e(this,`maxDelayMs`,void 0),this.delayMs=t.baseDelayMs,this.maxDelayMs=t.maxDelayMs??3e4}shouldRetry(){return this.attempts<this.options.maxAttempts}nextDelayMs(){return this.delayMs}recordAttempt(){this.attempts+=1,this.delayMs=Math.min(this.delayMs*2,this.maxDelayMs)}reset(){this.attempts=0,this.delayMs=this.options.baseDelayMs}get attemptCount(){return this.attempts}get maxAttempts(){return this.options.maxAttempts}};export{t as ReconnectionBackoff};
2
2
  //# sourceMappingURL=reconnection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reconnection.js","names":["_defineProperty","ReconnectionBackoff","options"],"sources":["../../../src/utils/reconnection.ts"],"sourcesContent":["/** Options for {@link ReconnectionBackoff}. */\nexport interface ReconnectionBackoffOptions {\n /** Attempts allowed before giving up. */\n maxAttempts: number;\n /** Delay before the first attempt, in milliseconds. */\n baseDelayMs: number;\n /** Ceiling the doubling delay never exceeds, in milliseconds. */\n maxDelayMs?: number;\n}\n\n/** Counts reconnect attempts and doubles the delay between them, up to a ceiling. */\nexport class ReconnectionBackoff {\n private attempts = 0;\n private delayMs: number;\n private readonly maxDelayMs: number;\n\n constructor(private readonly options: ReconnectionBackoffOptions) {\n this.delayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? 30_000;\n }\n\n /** Whether another attempt is allowed. */\n shouldRetry(): boolean {\n return this.attempts < this.options.maxAttempts;\n }\n\n /** The delay to wait before the next attempt. */\n nextDelayMs(): number {\n return this.delayMs;\n }\n\n /** Record that an attempt is being made, and double the next delay. */\n recordAttempt(): void {\n this.attempts += 1;\n this.delayMs = Math.min(this.delayMs * 2, this.maxDelayMs);\n }\n\n /** Forget every attempt: the connection is healthy again. */\n reset(): void {\n this.attempts = 0;\n this.delayMs = this.options.baseDelayMs;\n }\n\n get attemptCount(): number {\n return this.attempts;\n }\n\n get maxAttempts(): number {\n return this.options.maxAttempts;\n }\n}\n"],"mappings":"uFAWA,IAAaC,EAAb,KAAiC,CAK/B,YAAY,EAAsD,CAArC,KAAA,QAAAC,EAJrBF,EAAA,KAAA,WAAW,CAAA,EACXA,EAAA,KAAA,UAAA,IAAA,EAAA,EACSA,EAAA,KAAA,aAAA,IAAA,EAAA,EAGf,KAAK,QAAUE,EAAQ,YACvB,KAAK,WAAaA,EAAQ,YAAc,GAC1C,CAGA,aAAuB,CACrB,OAAO,KAAK,SAAW,KAAK,QAAQ,WACtC,CAGA,aAAsB,CACpB,OAAO,KAAK,OACd,CAGA,eAAsB,CACpB,KAAK,UAAY,EACjB,KAAK,QAAU,KAAK,IAAI,KAAK,QAAU,EAAG,KAAK,UAAU,CAC3D,CAGA,OAAc,CACZ,KAAK,SAAW,EAChB,KAAK,QAAU,KAAK,QAAQ,WAC9B,CAEA,IAAI,cAAuB,CACzB,OAAO,KAAK,QACd,CAEA,IAAI,aAAsB,CACxB,OAAO,KAAK,QAAQ,WACtB,CACF"}
1
+ {"version":3,"file":"reconnection.js","names":["_defineProperty","ReconnectionBackoff","options"],"sources":["../../../src/utils/reconnection.ts"],"sourcesContent":["/** Options for {@link ReconnectionBackoff}. */\nexport interface ReconnectionBackoffOptions {\n /** Attempts allowed before giving up. */\n maxAttempts: number;\n /** Delay before the first attempt, in milliseconds. */\n baseDelayMs: number;\n /** Ceiling the doubling delay never exceeds, in milliseconds. */\n maxDelayMs?: number;\n}\n\n/** Counts reconnect attempts and doubles the delay between them, up to a ceiling. */\nexport class ReconnectionBackoff {\n private attempts = 0;\n private delayMs: number;\n private readonly maxDelayMs: number;\n\n constructor(private readonly options: ReconnectionBackoffOptions) {\n this.delayMs = options.baseDelayMs;\n this.maxDelayMs = options.maxDelayMs ?? 30_000;\n }\n\n /** Whether another attempt is allowed. */\n shouldRetry(): boolean {\n return this.attempts < this.options.maxAttempts;\n }\n\n /** The delay to wait before the next attempt. */\n nextDelayMs(): number {\n return this.delayMs;\n }\n\n /** Record that an attempt is being made, and double the next delay. */\n recordAttempt(): void {\n this.attempts += 1;\n this.delayMs = Math.min(this.delayMs * 2, this.maxDelayMs);\n }\n\n /** Forget every attempt: the connection is healthy again. */\n reset(): void {\n this.attempts = 0;\n this.delayMs = this.options.baseDelayMs;\n }\n\n get attemptCount(): number {\n return this.attempts;\n }\n\n get maxAttempts(): number {\n return this.options.maxAttempts;\n }\n}\n"],"mappings":"A,uFAWA,IAAaC,EAAb,KAAiC,CAK/B,YAAY,EAAsD,CAArC,KAAA,QAAAC,EAJrBF,EAAA,KAAA,WAAW,CAAA,EACXA,EAAA,KAAA,UAAA,IAAA,EAAA,EACSA,EAAA,KAAA,aAAA,IAAA,EAAA,EAGf,KAAK,QAAUE,EAAQ,YACvB,KAAK,WAAaA,EAAQ,YAAc,GAC1C,CAGA,aAAuB,CACrB,OAAO,KAAK,SAAW,KAAK,QAAQ,WACtC,CAGA,aAAsB,CACpB,OAAO,KAAK,OACd,CAGA,eAAsB,CACpB,KAAK,UAAY,EACjB,KAAK,QAAU,KAAK,IAAI,KAAK,QAAU,EAAG,KAAK,UAAU,CAC3D,CAGA,OAAc,CACZ,KAAK,SAAW,EAChB,KAAK,QAAU,KAAK,QAAQ,WAC9B,CAEA,IAAI,cAAuB,CACzB,OAAO,KAAK,QACd,CAEA,IAAI,aAAsB,CACxB,OAAO,KAAK,QAAQ,WACtB,CACF,E"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolve_pre_send.js","names":["resolvePreSend","run","cause","isGalaError","GSwapSDKError"],"sources":["../../../src/utils/resolve_pre_send.ts"],"sourcesContent":["import { isGalaError } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/**\n * Runs a token-resolution step (a resolver's `resolve` / `orderPair`, which may read the registry\n * through the app's HTTP stack) on the \"nothing was sent\" boundary, like core's `signPreSend` does\n * for the signer. A failure that is not an SDK error is `TOKEN_RESOLUTION_FAILED` (`token` names\n * what was being resolved, the original is `cause`); an SDK error of any product (every one is a\n * `GalaSDKError`, core's transport errors included) passes through.\n *\n * @throws GSwapSDKError TOKEN_RESOLUTION_FAILED, or the SDK error the step itself threw.\n */\nexport async function resolvePreSend<T>(token: string, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause: unknown) {\n throw isGalaError(cause)\n ? cause\n : new GSwapSDKError('TOKEN_RESOLUTION_FAILED', { token }, { cause });\n }\n}\n"],"mappings":"sHAYA,eAAsBA,EAAkB,EAAe,EAAmC,CACxF,GAAI,CACF,OAAO,MAAMC,EAAI,CACnB,OAASC,EAAgB,CACvB,MAAMC,EAAYD,CAAK,EACnBA,EACA,IAAIE,EAAc,0BAA2B,CAAE,OAAM,EAAG,CAAE,OAAM,CAAC,CACvE,CACF"}
1
+ {"version":3,"file":"resolve_pre_send.js","names":["resolvePreSend","run","cause","isGalaError","GSwapSDKError"],"sources":["../../../src/utils/resolve_pre_send.ts"],"sourcesContent":["import { isGalaError } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\n/**\n * Runs a token-resolution step (a resolver's `resolve` / `orderPair`, which may read the registry\n * through the app's HTTP stack) on the \"nothing was sent\" boundary, like core's `signPreSend` does\n * for the signer. A failure that is not an SDK error is `TOKEN_RESOLUTION_FAILED` (`token` names\n * what was being resolved, the original is `cause`); an SDK error of any product (every one is a\n * `GalaSDKError`, core's transport errors included) passes through.\n *\n * @throws GSwapSDKError TOKEN_RESOLUTION_FAILED, or the SDK error the step itself threw.\n */\nexport async function resolvePreSend<T>(token: string, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause: unknown) {\n throw isGalaError(cause)\n ? cause\n : new GSwapSDKError('TOKEN_RESOLUTION_FAILED', { token }, { cause });\n }\n}\n"],"mappings":"A,sHAYA,eAAsBA,EAAkB,EAAe,EAAmC,CACxF,GAAI,CACF,OAAO,MAAMC,EAAI,CACnB,OAASC,EAAgB,CACvB,MAAMC,EAAYD,CAAK,EACnBA,EACA,IAAIE,EAAc,0BAA2B,CAAE,OAAM,EAAG,CAAE,OAAM,CAAC,CACvE,CACF,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"server_message.js","names":["nonEmptyString","value","field","property","serverMessageOfBody","nested","body","\"error\"","readServerMessage","fromParams","error","\"serverMessage\"","fromBody"],"sources":["../../../src/utils/server_message.ts"],"sourcesContent":["import type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nfunction nonEmptyString(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const field = (value as Record<string, unknown>)[property];\n return typeof field === 'string' && field !== '' ? field : undefined;\n}\n\n/**\n * The human message a failing JSON body carries, as the server wrote it: the first non-empty\n * string of `message`, `Message`, `error.message`, `error.Message` (NestJS, the gateway filter\n * and the chain each use one of these shapes), else `''`. A body that is not JSON (an HTML 502\n * page, an empty body), or whose `message` is not a string (a validation error's list), has no\n * message. This is the single reader behind every `serverMessage` param.\n *\n * The text is DATA from the server, not SDK text: it is English, unstable, and may be empty. The\n * SDK exposes it so an app can relay it or ignore it; it is never part of `error.message`.\n */\nexport function serverMessageOfBody(body: unknown): string {\n const nested =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)['error']\n : undefined;\n return (\n nonEmptyString(body, 'message') ??\n nonEmptyString(body, 'Message') ??\n nonEmptyString(nested, 'message') ??\n nonEmptyString(nested, 'Message') ??\n ''\n );\n}\n\n/**\n * The message the server put in a failing answer: the `serverMessage` param of a code that relays\n * it, else the message of the JSON body ({@link serverMessageOfBody}). Internal: the SDK reads it\n * ONLY to classify a failure (a quote that says \"no pools\"); it is English from the server, never\n * part of the SDK's own `message`, and not exported from the package.\n */\nexport function readServerMessage(error: GSwapSDKError): string | undefined {\n const params: Readonly<Record<string, string | number | boolean>> = error.params;\n const fromParams = params['serverMessage'];\n if (typeof fromParams === 'string' && fromParams !== '') return fromParams;\n const fromBody = serverMessageOfBody(error.body);\n return fromBody === '' ? undefined : fromBody;\n}\n"],"mappings":"AAEA,SAASA,EAAe,EAAgB,EAAsC,CAC5E,GAAI,OAAOC,GAAU,WAAYA,EAAgB,OACjD,IAAMC,EAASD,EAAkCE,GACjD,OAAO,OAAOD,GAAU,UAAYA,IAAU,GAAKA,EAAQ,IAAA,EAC7D,CAYA,SAAgBE,EAAoB,EAAuB,CACzD,IAAMC,EACJ,OAAOC,GAAS,UAAYA,EACvBA,EAAiCC,MAClC,IAAA,GACN,OACEP,EAAeM,EAAM,SAAS,GAC9BN,EAAeM,EAAM,SAAS,GAC9BN,EAAeK,EAAQ,SAAS,GAChCL,EAAeK,EAAQ,SAAS,GAChC,EAEJ,CAQA,SAAgBG,EAAkB,EAA0C,CAE1E,IAAMC,EAD8DC,EAAM,OAChDC,cAC1B,GAAI,OAAOF,GAAe,UAAYA,IAAe,GAAI,OAAOA,EAChE,IAAMG,EAAWR,EAAoBM,EAAM,IAAI,EAC/C,OAAOE,IAAa,GAAK,IAAA,GAAYA,CACvC"}
1
+ {"version":3,"file":"server_message.js","names":["nonEmptyString","value","field","property","serverMessageOfBody","nested","body","\"error\"","readServerMessage","fromParams","error","\"serverMessage\"","fromBody"],"sources":["../../../src/utils/server_message.ts"],"sourcesContent":["import type { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nfunction nonEmptyString(value: unknown, property: string): string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const field = (value as Record<string, unknown>)[property];\n return typeof field === 'string' && field !== '' ? field : undefined;\n}\n\n/**\n * The human message a failing JSON body carries, as the server wrote it: the first non-empty\n * string of `message`, `Message`, `error.message`, `error.Message` (NestJS, the gateway filter\n * and the chain each use one of these shapes), else `''`. A body that is not JSON (an HTML 502\n * page, an empty body), or whose `message` is not a string (a validation error's list), has no\n * message. This is the single reader behind every `serverMessage` param.\n *\n * The text is DATA from the server, not SDK text: it is English, unstable, and may be empty. The\n * SDK exposes it so an app can relay it or ignore it; it is never part of `error.message`.\n */\nexport function serverMessageOfBody(body: unknown): string {\n const nested =\n typeof body === 'object' && body !== null\n ? (body as Record<string, unknown>)['error']\n : undefined;\n return (\n nonEmptyString(body, 'message') ??\n nonEmptyString(body, 'Message') ??\n nonEmptyString(nested, 'message') ??\n nonEmptyString(nested, 'Message') ??\n ''\n );\n}\n\n/**\n * The message the server put in a failing answer: the `serverMessage` param of a code that relays\n * it, else the message of the JSON body ({@link serverMessageOfBody}). Internal: the SDK reads it\n * ONLY to classify a failure (a quote that says \"no pools\"); it is English from the server, never\n * part of the SDK's own `message`, and not exported from the package.\n */\nexport function readServerMessage(error: GSwapSDKError): string | undefined {\n const params: Readonly<Record<string, string | number | boolean>> = error.params;\n const fromParams = params['serverMessage'];\n if (typeof fromParams === 'string' && fromParams !== '') return fromParams;\n const fromBody = serverMessageOfBody(error.body);\n return fromBody === '' ? undefined : fromBody;\n}\n"],"mappings":"AAEA,SAASA,EAAe,EAAgB,EAAsC,CAC5E,GAAI,OAAOC,GAAU,WAAYA,EAAgB,OACjD,IAAMC,EAASD,EAAkCE,GACjD,OAAO,OAAOD,GAAU,UAAYA,IAAU,GAAKA,EAAQ,IAAA,EAC7D,CAYA,SAAgBE,EAAoB,EAAuB,CACzD,IAAMC,EACJ,OAAOC,GAAS,UAAYA,EACvBA,EAAiCC,MAClC,IAAA,GACN,OACEP,EAAeM,EAAM,SAAS,GAC9BN,EAAeM,EAAM,SAAS,GAC9BN,EAAeK,EAAQ,SAAS,GAChCL,EAAeK,EAAQ,SAAS,GAChC,EAEJ,CAQA,SAAgBG,EAAkB,EAA0C,CAE1E,IAAMC,EAD8DC,EAAM,OAChDC,cAC1B,GAAI,OAAOF,GAAe,UAAYA,IAAe,GAAI,OAAOA,EAChE,IAAMG,EAAWR,EAAoBM,EAAM,IAAI,EAC/C,OAAOE,IAAa,GAAK,IAAA,GAAYA,CACvC,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"shadow_errors.js","names":["shadowRejections","isShadowError","isGSwapError","value","toFailureView","asShadowError","error","copy","GSwapSDKError","shadowFailures","run"],"sources":["../../../src/utils/shadow_errors.ts"],"sourcesContent":["import { toFailureView } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\n\n/**\n * Failures of the shadow (dark) path carry that fact, so an app can apply its own policy (no\n * Retry, no public fallback) without tracking which call it made. An SDK error gets `shadow: true`;\n * a non-SDK object that escapes the path (an app requestor's own rejection) is remembered in a\n * WeakSet, which `isShadowError` reads. Nothing here changes what an error means, only where it\n * came from.\n */\nconst shadowRejections = new WeakSet<object>();\n\n/**\n * True when `value` is a failure of the shadow (dark) path: an SDK error with `shadow: true`, a\n * plain-object view of one (`{ code, shadow: true }`, see `FailureView`), or a non-SDK object (a requestor's own rejection) that escaped `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`. A primitive that was thrown (`throw 'x'`) cannot be remembered, so\n * it is never shadow; an app that cares tracks the call it made.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { retryable } = classifyFailure(error);\n * offerRetry(retryable && !isShadowError(error)); // never retry a dark swap in public\n * }\n * ```\n */\nexport function isShadowError(value: unknown): boolean {\n if (isGSwapError(value)) return value.shadow;\n if (toFailureView(value)?.shadow === true) return true;\n return typeof value === 'object' && value !== null && shadowRejections.has(value);\n}\n\n/**\n * The same failure, marked as shadow. An SDK error is COPIED (same code, params, status, body,\n * url, ids, cause, phase, read/write, wallet code and stack), never mutated: one error object can\n * be shared by several callers (a registry read many swaps wait on), and only the shadow caller's\n * copy is shadow. Everything the deciders read is carried over, so the copy classifies exactly as\n * the original (a failed READ stays a read, never a \"maybe queued\" write).\n */\nfunction asShadowError(error: unknown): unknown {\n if (isGSwapError(error)) {\n if (error.shadow) return error;\n const copy = new GSwapSDKError(error.code, error.params, {\n status: error.status,\n body: error.body ?? error.bodyText,\n url: error.url,\n uniqueKey: error.uniqueKey,\n requestTransactionId: error.requestTransactionId,\n applyTransactionId: error.applyTransactionId,\n blockNumber: error.blockNumber,\n retryAfterMs: error.retryAfterMs,\n cause: error.cause,\n phase: error.phase,\n write: error.write,\n walletCode: error.walletCode,\n shadow: true,\n });\n if (error.stack !== undefined) copy.stack = error.stack;\n return copy;\n }\n if (typeof error === 'object' && error !== null) shadowRejections.add(error);\n return error;\n}\n\n/** Runs one shadow operation and marks whatever it throws as shadow (see {@link isShadowError}). */\nexport async function shadowFailures<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error: unknown) {\n throw asShadowError(error);\n }\n}\n"],"mappings":"0IAUA,MAAMA,kBAAmB,IAAI,QAkB7B,SAAgBC,EAAc,EAAyB,CAGrD,OAFIC,EAAaC,CAAK,EAAUA,EAAM,OAClCC,EAAcD,CAAK,CAAC,EAAE,SAAW,IAC9B,OAAOA,GAAU,YAAYA,GAAkBH,EAAiB,IAAIG,CAAK,CAClF,CASA,SAASE,EAAc,EAAyB,CAC9C,GAAIH,EAAaI,CAAK,EAAG,CACvB,GAAIA,EAAM,OAAQ,OAAOA,EACzB,IAAMC,EAAO,IAAIC,EAAcF,EAAM,KAAMA,EAAM,OAAQ,CACvD,OAAQA,EAAM,OACd,KAAMA,EAAM,MAAQA,EAAM,SAC1B,IAAKA,EAAM,IACX,UAAWA,EAAM,UACjB,qBAAsBA,EAAM,qBAC5B,mBAAoBA,EAAM,mBAC1B,YAAaA,EAAM,YACnB,aAAcA,EAAM,aACpB,MAAOA,EAAM,MACb,MAAOA,EAAM,MACb,MAAOA,EAAM,MACb,WAAYA,EAAM,WAClB,OAAQ,EACV,CAAC,EAED,OADIA,EAAM,QAAU,IAAA,KAAW,EAAK,MAAQA,EAAM,OAC3CC,CACT,CAEA,OADI,OAAOD,GAAU,UAAYA,GAAgBN,EAAiB,IAAIM,CAAK,EACpEA,CACT,CAGA,eAAsBG,EAAkB,EAAmC,CACzE,GAAI,CACF,OAAO,MAAMC,EAAI,CACnB,OAASJ,EAAgB,CACvB,MAAMD,EAAcC,CAAK,CAC3B,CACF"}
1
+ {"version":3,"file":"shadow_errors.js","names":["shadowRejections","isShadowError","isGSwapError","value","toFailureView","asShadowError","error","copy","GSwapSDKError","shadowFailures","run"],"sources":["../../../src/utils/shadow_errors.ts"],"sourcesContent":["import { toFailureView } from '@gala-chain/gala-core-sdk';\nimport { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\n\n/**\n * Failures of the shadow (dark) path carry that fact, so an app can apply its own policy (no\n * Retry, no public fallback) without tracking which call it made. An SDK error gets `shadow: true`;\n * a non-SDK object that escapes the path (an app requestor's own rejection) is remembered in a\n * WeakSet, which `isShadowError` reads. Nothing here changes what an error means, only where it\n * came from.\n */\nconst shadowRejections = new WeakSet<object>();\n\n/**\n * True when `value` is a failure of the shadow (dark) path: an SDK error with `shadow: true`, a\n * plain-object view of one (`{ code, shadow: true }`, see `FailureView`), or a non-SDK object (a requestor's own rejection) that escaped `swapShadow`, `submitSwapShadow` or\n * `ChainGateway.submitShadow`. A primitive that was thrown (`throw 'x'`) cannot be remembered, so\n * it is never shadow; an app that cares tracks the call it made.\n *\n * @example\n * ```ts\n * try {\n * await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });\n * } catch (error) {\n * const { retryable } = classifyFailure(error);\n * offerRetry(retryable && !isShadowError(error)); // never retry a dark swap in public\n * }\n * ```\n */\nexport function isShadowError(value: unknown): boolean {\n if (isGSwapError(value)) return value.shadow;\n if (toFailureView(value)?.shadow === true) return true;\n return typeof value === 'object' && value !== null && shadowRejections.has(value);\n}\n\n/**\n * The same failure, marked as shadow. An SDK error is COPIED (same code, params, status, body,\n * url, ids, cause, phase, read/write, wallet code and stack), never mutated: one error object can\n * be shared by several callers (a registry read many swaps wait on), and only the shadow caller's\n * copy is shadow. Everything the deciders read is carried over, so the copy classifies exactly as\n * the original (a failed READ stays a read, never a \"maybe queued\" write).\n */\nfunction asShadowError(error: unknown): unknown {\n if (isGSwapError(error)) {\n if (error.shadow) return error;\n const copy = new GSwapSDKError(error.code, error.params, {\n status: error.status,\n body: error.body ?? error.bodyText,\n url: error.url,\n uniqueKey: error.uniqueKey,\n requestTransactionId: error.requestTransactionId,\n applyTransactionId: error.applyTransactionId,\n blockNumber: error.blockNumber,\n retryAfterMs: error.retryAfterMs,\n cause: error.cause,\n phase: error.phase,\n write: error.write,\n walletCode: error.walletCode,\n shadow: true,\n });\n if (error.stack !== undefined) copy.stack = error.stack;\n return copy;\n }\n if (typeof error === 'object' && error !== null) shadowRejections.add(error);\n return error;\n}\n\n/** Runs one shadow operation and marks whatever it throws as shadow (see {@link isShadowError}). */\nexport async function shadowFailures<T>(run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (error: unknown) {\n throw asShadowError(error);\n }\n}\n"],"mappings":"A,0IAUA,MAAMA,kBAAmB,IAAI,QAkB7B,SAAgBC,EAAc,EAAyB,CAGrD,OAFIC,EAAaC,CAAK,EAAUA,EAAM,OAClCC,EAAcD,CAAK,CAAC,EAAE,SAAW,IAC9B,OAAOA,GAAU,YAAYA,GAAkBH,EAAiB,IAAIG,CAAK,CAClF,CASA,SAASE,EAAc,EAAyB,CAC9C,GAAIH,EAAaI,CAAK,EAAG,CACvB,GAAIA,EAAM,OAAQ,OAAOA,EACzB,IAAMC,EAAO,IAAIC,EAAcF,EAAM,KAAMA,EAAM,OAAQ,CACvD,OAAQA,EAAM,OACd,KAAMA,EAAM,MAAQA,EAAM,SAC1B,IAAKA,EAAM,IACX,UAAWA,EAAM,UACjB,qBAAsBA,EAAM,qBAC5B,mBAAoBA,EAAM,mBAC1B,YAAaA,EAAM,YACnB,aAAcA,EAAM,aACpB,MAAOA,EAAM,MACb,MAAOA,EAAM,MACb,MAAOA,EAAM,MACb,WAAYA,EAAM,WAClB,OAAQ,EACV,CAAC,EAED,OADIA,EAAM,QAAU,IAAA,KAAW,EAAK,MAAQA,EAAM,OAC3CC,CACT,CAEA,OADI,OAAOD,GAAU,UAAYA,GAAgBN,EAAiB,IAAIM,CAAK,EACpEA,CACT,CAGA,eAAsBG,EAAkB,EAAmC,CACzE,GAAI,CACF,OAAO,MAAMC,EAAI,CACnB,OAASJ,EAAgB,CACvB,MAAMD,EAAcC,CAAK,CAC3B,CACF,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"submit_state.js","names":["modeOf","data","envelope","\"data\"","\"mode\"","recordOf","value","isSubmitRejected","\"error\"","isSubmitExecuted","record","isSubmitQueued","\"uniqueKey\"","classifySubmitEnvelope"],"sources":["../../../src/utils/submit_state.ts"],"sourcesContent":["/**\n * What a write's gateway answer says about the write, as one vocabulary for every app.\n *\n * The gateway answers `{ status, message, error, data }`. `data.mode` is `'sync'` for a liquidity\n * write (its executed chain result is in `data.result`) and `'queued'` for a RequestTrade\n * acknowledgement (accepted, NOT executed: the outcome is read from apply-results with\n * `confirm()`). `error: true` is the gateway refusing the write.\n *\n * A {@link SubmittedTransaction} only exists for an answer the SDK accepted, so its\n * {@link SubmitStatus} is `'executed'` or `'queued'`; a refused answer is a thrown\n * {@link GSwapSDKError}. The predicates below classify a RAW envelope instead, for an app that\n * holds one (`SubmittedTransaction.envelope`, `GSwapSDKError.body`, a stored answer) and for the\n * answers that never became a transaction, so an app does not need its own copies of the\n * success, queued and rejected checks.\n */\n\n/** The state of an accepted write: executed on chain (`mode: 'sync'`) or queued (`mode: 'queued'`). */\nexport type SubmitStatus = 'executed' | 'queued';\n\n/**\n * How a raw gateway envelope classifies:\n *\n * - `'executed'`: `error === false` and `data.mode === 'sync'` (the executed result came back).\n * - `'queued'`: `error === false`, `data.mode === 'queued'` and `data.uniqueKey` is a string.\n * - `'rejected'`: no envelope at all, or `error === true`: a DEFINITE failure.\n * - `'unconfirmed'`: anything else (`error: false` with another or no `mode`, a queued answer\n * with no `uniqueKey`, an envelope with no boolean `error`): accepted, outcome not known. It is\n * NOT a rejection and must not be shown as one.\n *\n * The four are mutually exclusive and exhaustive.\n */\nexport type SubmitClassification = SubmitStatus | 'rejected' | 'unconfirmed';\n\n/** The `mode` of `envelope.data`, or `undefined` when there is no such field. */\nfunction modeOf(envelope: Record<string, unknown>): unknown {\n const data = envelope['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)['mode']\n : undefined;\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** True when the envelope is a definite failure: absent, or `error === true`. */\nexport function isSubmitRejected(envelope: unknown): boolean {\n if (!envelope) return true;\n return recordOf(envelope)?.['error'] === true;\n}\n\n/**\n * True when the envelope carries an executed result: `error === false` and `data.mode === 'sync'`.\n * A queued RequestTrade acknowledgement is deliberately NOT executed: its outcome is not known\n * until apply-results resolves.\n */\nexport function isSubmitExecuted(envelope: unknown): boolean {\n const record = recordOf(envelope);\n return record?.['error'] === false && modeOf(record) === 'sync';\n}\n\n/** True when the envelope acknowledges a `uniqueKey` as queued (`data.mode === 'queued'`). */\nexport function isSubmitQueued(envelope: unknown): boolean {\n const record = recordOf(envelope);\n if (record?.['error'] !== false || modeOf(record) !== 'queued') return false;\n return typeof recordOf(record['data'])?.['uniqueKey'] === 'string';\n}\n\n/** Classifies a raw gateway envelope; see {@link SubmitClassification}. */\nexport function classifySubmitEnvelope(envelope: unknown): SubmitClassification {\n if (isSubmitRejected(envelope)) return 'rejected';\n if (isSubmitExecuted(envelope)) return 'executed';\n if (isSubmitQueued(envelope)) return 'queued';\n return 'unconfirmed';\n}\n"],"mappings":"AAkCA,SAASA,EAAO,EAA4C,CAC1D,IAAMC,EAAOC,EAASC,KACtB,OAAO,OAAOF,GAAS,UAAYA,EAC9BA,EAAiCG,KAClC,IAAA,EACN,CAEA,SAASC,EAAS,EAAqD,CACrE,OAAO,OAAOC,GAAU,UAAYA,EAC/BA,EACD,IAAA,EACN,CAGA,SAAgBC,EAAiB,EAA4B,CAE3D,MADA,CAAKL,GACEG,EAASH,CAAQ,CAAC,EAAGM,QAAa,EAC3C,CAOA,SAAgBC,EAAiB,EAA4B,CAC3D,IAAMC,EAASL,EAASH,CAAQ,EAChC,OAAOQ,GAASF,QAAa,IAASR,EAAOU,CAAM,IAAM,MAC3D,CAGA,SAAgBC,EAAe,EAA4B,CACzD,IAAMD,EAASL,EAASH,CAAQ,EAEhC,OADIQ,GAASF,QAAa,IAASR,EAAOU,CAAM,IAAM,SAAiB,GAChE,OAAOL,EAASK,EAAOP,IAAO,CAAC,EAAGS,WAAiB,QAC5D,CAGA,SAAgBC,EAAuB,EAAyC,CAI9E,OAHIN,EAAiBL,CAAQ,EAAU,WACnCO,EAAiBP,CAAQ,EAAU,WACnCS,EAAeT,CAAQ,EAAU,SAC9B,aACT"}
1
+ {"version":3,"file":"submit_state.js","names":["modeOf","data","envelope","\"data\"","\"mode\"","recordOf","value","isSubmitRejected","\"error\"","isSubmitExecuted","record","isSubmitQueued","\"uniqueKey\"","classifySubmitEnvelope"],"sources":["../../../src/utils/submit_state.ts"],"sourcesContent":["/**\n * What a write's gateway answer says about the write, as one vocabulary for every app.\n *\n * The gateway answers `{ status, message, error, data }`. `data.mode` is `'sync'` for a liquidity\n * write (its executed chain result is in `data.result`) and `'queued'` for a RequestTrade\n * acknowledgement (accepted, NOT executed: the outcome is read from apply-results with\n * `confirm()`). `error: true` is the gateway refusing the write.\n *\n * A {@link SubmittedTransaction} only exists for an answer the SDK accepted, so its\n * {@link SubmitStatus} is `'executed'` or `'queued'`; a refused answer is a thrown\n * {@link GSwapSDKError}. The predicates below classify a RAW envelope instead, for an app that\n * holds one (`SubmittedTransaction.envelope`, `GSwapSDKError.body`, a stored answer) and for the\n * answers that never became a transaction, so an app does not need its own copies of the\n * success, queued and rejected checks.\n */\n\n/** The state of an accepted write: executed on chain (`mode: 'sync'`) or queued (`mode: 'queued'`). */\nexport type SubmitStatus = 'executed' | 'queued';\n\n/**\n * How a raw gateway envelope classifies:\n *\n * - `'executed'`: `error === false` and `data.mode === 'sync'` (the executed result came back).\n * - `'queued'`: `error === false`, `data.mode === 'queued'` and `data.uniqueKey` is a string.\n * - `'rejected'`: no envelope at all, or `error === true`: a DEFINITE failure.\n * - `'unconfirmed'`: anything else (`error: false` with another or no `mode`, a queued answer\n * with no `uniqueKey`, an envelope with no boolean `error`): accepted, outcome not known. It is\n * NOT a rejection and must not be shown as one.\n *\n * The four are mutually exclusive and exhaustive.\n */\nexport type SubmitClassification = SubmitStatus | 'rejected' | 'unconfirmed';\n\n/** The `mode` of `envelope.data`, or `undefined` when there is no such field. */\nfunction modeOf(envelope: Record<string, unknown>): unknown {\n const data = envelope['data'];\n return typeof data === 'object' && data !== null\n ? (data as Record<string, unknown>)['mode']\n : undefined;\n}\n\nfunction recordOf(value: unknown): Record<string, unknown> | undefined {\n return typeof value === 'object' && value !== null\n ? (value as Record<string, unknown>)\n : undefined;\n}\n\n/** True when the envelope is a definite failure: absent, or `error === true`. */\nexport function isSubmitRejected(envelope: unknown): boolean {\n if (!envelope) return true;\n return recordOf(envelope)?.['error'] === true;\n}\n\n/**\n * True when the envelope carries an executed result: `error === false` and `data.mode === 'sync'`.\n * A queued RequestTrade acknowledgement is deliberately NOT executed: its outcome is not known\n * until apply-results resolves.\n */\nexport function isSubmitExecuted(envelope: unknown): boolean {\n const record = recordOf(envelope);\n return record?.['error'] === false && modeOf(record) === 'sync';\n}\n\n/** True when the envelope acknowledges a `uniqueKey` as queued (`data.mode === 'queued'`). */\nexport function isSubmitQueued(envelope: unknown): boolean {\n const record = recordOf(envelope);\n if (record?.['error'] !== false || modeOf(record) !== 'queued') return false;\n return typeof recordOf(record['data'])?.['uniqueKey'] === 'string';\n}\n\n/** Classifies a raw gateway envelope; see {@link SubmitClassification}. */\nexport function classifySubmitEnvelope(envelope: unknown): SubmitClassification {\n if (isSubmitRejected(envelope)) return 'rejected';\n if (isSubmitExecuted(envelope)) return 'executed';\n if (isSubmitQueued(envelope)) return 'queued';\n return 'unconfirmed';\n}\n"],"mappings":"AAkCA,SAASA,EAAO,EAA4C,CAC1D,IAAMC,EAAOC,EAASC,KACtB,OAAO,OAAOF,GAAS,UAAYA,EAC9BA,EAAiCG,KAClC,IAAA,EACN,CAEA,SAASC,EAAS,EAAqD,CACrE,OAAO,OAAOC,GAAU,UAAYA,EAC/BA,EACD,IAAA,EACN,CAGA,SAAgBC,EAAiB,EAA4B,CAE3D,MADA,CAAKL,GACEG,EAASH,CAAQ,CAAC,EAAGM,QAAa,EAC3C,CAOA,SAAgBC,EAAiB,EAA4B,CAC3D,IAAMC,EAASL,EAASH,CAAQ,EAChC,OAAOQ,GAASF,QAAa,IAASR,EAAOU,CAAM,IAAM,MAC3D,CAGA,SAAgBC,EAAe,EAA4B,CACzD,IAAMD,EAASL,EAASH,CAAQ,EAEhC,OADIQ,GAASF,QAAa,IAASR,EAAOU,CAAM,IAAM,SAAiB,GAChE,OAAOL,EAASK,EAAOP,IAAO,CAAC,EAAGS,WAAiB,QAC5D,CAGA,SAAgBC,EAAuB,EAAyC,CAI9E,OAHIN,EAAiBL,CAAQ,EAAU,WACnCO,EAAiBP,CAAQ,EAAU,WACnCS,EAAeT,CAAQ,EAAU,SAC9B,aACT,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"tick_align.js","names":["hasValidSpacing","spacing","alignTickDownOrNaN","tick","alignTickUpOrNaN"],"sources":["../../../src/utils/tick_align.ts"],"sourcesContent":["/**\n * Aligning a tick to a pool's tick spacing without throwing. This module imports nothing, so an\n * app shell (a price input that snaps to a tick) pays for a few dozen bytes, not for the error\n * class and catalog that `alignTickDown` and `alignTickUp` (in `ticks.ts`) carry because they\n * throw `INVALID_TICK_SPACING` for a spacing that is not a positive integer.\n */\n\n/** True for a tick spacing the contract can use: a positive integer. The one definition. */\nexport function hasValidSpacing(spacing: number): boolean {\n return Number.isInteger(spacing) && spacing > 0;\n}\n\n/**\n * {@link alignTickDown} that answers `NaN` instead of throwing: the greatest multiple of `spacing`\n * that is no greater than `tick`, or `NaN` when `spacing` is not a positive integer (a pool whose\n * spacing has not loaded yet) or `tick` is not a number. For an app shell and for a drag handler,\n * which must not throw while the spacing is missing. `alignTickDown` (the SDK's own call sites use\n * it) gives the same value and throws for the bad spacing.\n *\n * @example\n * ```ts\n * alignTickDownOrNaN(-61, 60); // -120: it floors, it does not truncate toward zero\n * alignTickDownOrNaN(100, 0); // NaN\n * ```\n */\nexport function alignTickDownOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.floor(tick / spacing) * spacing : Number.NaN;\n}\n\n/**\n * {@link alignTickUp} that answers `NaN` instead of throwing: the least multiple of `spacing` that\n * is no less than `tick`, or `NaN` for a spacing that is not a positive integer. See\n * {@link alignTickDownOrNaN}.\n */\nexport function alignTickUpOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.ceil(tick / spacing) * spacing : Number.NaN;\n}\n"],"mappings":"AAQA,SAAgBA,EAAgB,EAA0B,CACxD,OAAO,OAAO,UAAUC,CAAO,GAAKA,EAAU,CAChD,CAeA,SAAgBC,EAAmB,EAAc,EAAyB,CACxE,OAAOF,EAAgBC,CAAO,EAAI,KAAK,MAAME,EAAOF,CAAO,EAAIA,EAAU,GAC3E,CAOA,SAAgBG,EAAiB,EAAc,EAAyB,CACtE,OAAOJ,EAAgBC,CAAO,EAAI,KAAK,KAAKE,EAAOF,CAAO,EAAIA,EAAU,GAC1E"}
1
+ {"version":3,"file":"tick_align.js","names":["hasValidSpacing","spacing","alignTickDownOrNaN","tick","alignTickUpOrNaN"],"sources":["../../../src/utils/tick_align.ts"],"sourcesContent":["/**\n * Aligning a tick to a pool's tick spacing without throwing. This module imports nothing, so an\n * app shell (a price input that snaps to a tick) pays for a few dozen bytes, not for the error\n * class and catalog that `alignTickDown` and `alignTickUp` (in `ticks.ts`) carry because they\n * throw `INVALID_TICK_SPACING` for a spacing that is not a positive integer.\n */\n\n/** True for a tick spacing the contract can use: a positive integer. The one definition. */\nexport function hasValidSpacing(spacing: number): boolean {\n return Number.isInteger(spacing) && spacing > 0;\n}\n\n/**\n * {@link alignTickDown} that answers `NaN` instead of throwing: the greatest multiple of `spacing`\n * that is no greater than `tick`, or `NaN` when `spacing` is not a positive integer (a pool whose\n * spacing has not loaded yet) or `tick` is not a number. For an app shell and for a drag handler,\n * which must not throw while the spacing is missing. `alignTickDown` (the SDK's own call sites use\n * it) gives the same value and throws for the bad spacing.\n *\n * @example\n * ```ts\n * alignTickDownOrNaN(-61, 60); // -120: it floors, it does not truncate toward zero\n * alignTickDownOrNaN(100, 0); // NaN\n * ```\n */\nexport function alignTickDownOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.floor(tick / spacing) * spacing : Number.NaN;\n}\n\n/**\n * {@link alignTickUp} that answers `NaN` instead of throwing: the least multiple of `spacing` that\n * is no less than `tick`, or `NaN` for a spacing that is not a positive integer. See\n * {@link alignTickDownOrNaN}.\n */\nexport function alignTickUpOrNaN(tick: number, spacing: number): number {\n return hasValidSpacing(spacing) ? Math.ceil(tick / spacing) * spacing : Number.NaN;\n}\n"],"mappings":"AAQA,SAAgBA,EAAgB,EAA0B,CACxD,OAAO,OAAO,UAAUC,CAAO,GAAKA,EAAU,CAChD,CAeA,SAAgBC,EAAmB,EAAc,EAAyB,CACxE,OAAOF,EAAgBC,CAAO,EAAI,KAAK,MAAME,EAAOF,CAAO,EAAIA,EAAU,GAC3E,CAOA,SAAgBG,EAAiB,EAAc,EAAyB,CACtE,OAAOJ,EAAgBC,CAAO,EAAI,KAAK,KAAKE,EAAOF,CAAO,EAAIA,EAAU,GAC1E,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"tick_math.js","names":["BigNumber","GC_MIN_TICK","GC_MAX_TICK","DexMath","DexDecimal","Decimal","tickToSqrtPrice","tick","sqrtPriceToTick","value","sqrtPrice","approximate","tickToPrice","isSqrtPriceInRange","isTickInRange","tickLower","tickUpper","tickFromPrice","priceText","price","exact","options"],"sources":["../../../src/utils/tick_math.ts"],"sourcesContent":["import BigNumber from 'bignumber.js';\nimport { Decimal } from 'decimal.js';\nimport { isTickInRange, type TickInput } from './tick_range.js';\n\n/**\n * Tick and price arithmetic that never throws an SDK error: the contract's tick bounds, the\n * conversions between ticks and prices, and nothing that validates a range. It imports only the\n * two number libraries it computes with, never the `GSwapSDKError` class or the error catalog\n * (functions that must throw, `alignTickDown` and `assertTickRange`, are in `ticks.ts`), so an\n * app shell that prices a tick pays for the libraries and these few functions, not for ~25 kB of\n * error templates. A value that cannot be computed is `NaN`, never an exception.\n */\n\n/** Minimum tick supported by GalaChainDex. */\nexport const GC_MIN_TICK = -887272;\n/** Maximum tick supported by GalaChainDex. */\nexport const GC_MAX_TICK = 887272;\n\nconst DexMath = BigNumber.clone({\n DECIMAL_PLACES: 60,\n ROUNDING_MODE: BigNumber.ROUND_DOWN,\n});\n/** `decimal.js` at the 60 significant digits the contract's price math is exact to. */\nexport const DexDecimal = Decimal.clone({ precision: 60 });\n\n/** Convert a tick to the corresponding square-root price. */\nexport function tickToSqrtPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick / 2).toString());\n}\n\n/** Return the greatest tick whose square-root price is no greater than the input. */\nexport function sqrtPriceToTick(sqrtPrice: BigNumber.Value): number {\n let value: BigNumber;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this function's contract is to signal an invalid input via NaN, not\n // to throw, so an unparseable value is just another case for the guard below.\n value = new DexMath(sqrtPrice);\n } catch {\n return Number.NaN;\n }\n if (!value.isFinite() || value.isLessThanOrEqualTo(0)) return Number.NaN;\n\n const approximate = Math.log(value.toNumber() ** 2) / Math.log(1.0001);\n if (!Number.isFinite(approximate)) return Number.NaN;\n // Clamp the seed before the correction loops below — an unclamped seed derived from an\n // out-of-range sqrtPrice (extreme but finite, e.g. 1e20) leaves the loops running past\n // GC_MIN_TICK/GC_MAX_TICK for a long time; an infinite (overflowed) seed would never\n // enter the increasing loop and never terminate the decreasing one.\n let tick = Math.min(GC_MAX_TICK, Math.max(GC_MIN_TICK, Math.floor(approximate)));\n while (tick < GC_MAX_TICK && tickToSqrtPrice(tick + 1).isLessThanOrEqualTo(value)) tick += 1;\n while (tick > GC_MIN_TICK && tickToSqrtPrice(tick).isGreaterThan(value)) tick -= 1;\n return tick;\n}\n\n/**\n * The token1/token0 price at `tick`: `1.0001 ** tick`, exact to 60 significant digits (the lower\n * edge of the tick's price range; `tickToSqrtPrice(tick) ** 2`). A tick outside the contract's\n * bounds is still computed; ask `assertTickRange` first when that matters. A non-integer tick is\n * computed as given.\n *\n * Use `.toNumber()` for a display value (it differs from `Math.exp(tick * Math.log(1.0001))` in\n * the last digits of a double: that expression multiplies in floating point first).\n */\nexport function tickToPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick).toString());\n}\n\n/**\n * {@link isTickInRange} for a pool's square-root price instead of its tick (a position row that\n * carries `sqrtPrice`, `tickLower` and `tickUpper`). The tick is derived from the price exactly as\n * the contract does (`sqrtPriceToTick`: the greatest tick whose square-root price is no greater\n * than the price, exact to 60 digits), then the contract's rule applies: lower tick inclusive,\n * upper tick exclusive. So a pool sitting exactly on `tickLower`'s price is in range, and exactly\n * on `tickUpper`'s price is not, and no float rounding can flip either.\n *\n * `false` for a price that is not positive and finite (not loaded, zero, `NaN`): it says nothing\n * about the position, so an app that must show a neutral state checks for the missing price\n * itself first. `tickLower` and `tickUpper` follow {@link isTickInRange}.\n *\n * @example\n * ```ts\n * const inRange = isSqrtPriceInRange(position.sqrtPrice, position.tickLower, position.tickUpper);\n * ```\n */\nexport function isSqrtPriceInRange(\n sqrtPrice: BigNumber.Value,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n return isTickInRange(sqrtPriceToTick(sqrtPrice), tickLower, tickUpper);\n}\n\n/** How {@link tickFromPrice} turns the exact logarithm into an integer tick. */\nexport interface TickFromPriceOptions {\n /**\n * `'floor'` (default): the greatest tick whose price is no greater than `price`, which is how\n * the contract places a price. `'nearest'`: the closest tick, a half rounding away from zero.\n * That is what a price INPUT wants (a person types a price, the field snaps to the nearest\n * tick), and it differs from `'floor'` for any price in the upper half of a tick's range.\n */\n rounding?: 'floor' | 'nearest' | undefined;\n}\n\n/**\n * Return the integer tick for a token1/token0 `price`: by default the greatest tick whose price\n * is no greater than `price`; `{ rounding: 'nearest' }` the closest tick. `NaN` for a price that\n * is not positive and finite.\n */\nexport function tickFromPrice(price: BigNumber.Value, options: TickFromPriceOptions = {}): number {\n const priceText =\n typeof price === 'string'\n ? price\n : typeof price === 'number'\n ? price.toString()\n : BigNumber.isBigNumber(price)\n ? price.toString()\n : 'NaN';\n const value = new DexDecimal(priceText);\n if (!value.isFinite() || value.lessThanOrEqualTo(0)) return Number.NaN;\n if (!Number.isFinite(value.toNumber())) return Number.NaN;\n const exact = value.ln().dividedBy(new DexDecimal(1.0001).ln());\n const tick = (options.rounding === 'nearest' ? exact.round() : exact.floor()).toNumber();\n return Number.isFinite(tick) ? tick : Number.NaN;\n}\n"],"mappings":"iHAcA,MAAaC,EAAc,QAEdC,EAAc,OAErBC,EAAUH,EAAU,MAAM,CAC9B,eAAgB,GAChB,cAAeA,EAAU,UAC3B,CAAC,EAEYI,EAAaC,EAAQ,MAAM,CAAE,UAAW,EAAG,CAAC,EAGzD,SAAgBC,EAAgB,EAAyB,CACvD,OAAO,IAAIN,EAAU,IAAII,EAAW,MAAM,CAAC,CAAC,IAAIG,EAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CACtE,CAGA,SAAgBC,EAAgB,EAAoC,CAClE,IAAIC,EACJ,GAAI,CAIF,EAAQ,IAAIN,EAAQO,CAAS,CAC/B,MAAQ,CACN,MAAO,IACT,CACA,GAAI,CAACD,EAAM,SAAS,GAAKA,EAAM,oBAAoB,CAAC,EAAG,MAAO,KAE9D,IAAME,EAAc,KAAK,IAAIF,EAAM,SAAS,GAAK,CAAC,EAAI,KAAK,IAAI,MAAM,EACrE,GAAI,CAAC,OAAO,SAASE,CAAW,EAAG,MAAO,KAK1C,IAAIJ,EAAO,KAAK,IAAIL,EAAa,KAAK,IAAID,EAAa,KAAK,MAAMU,CAAW,CAAC,CAAC,EAC/E,KAAOJ,EAAA,QAAsBD,EAAgBC,EAAO,CAAC,CAAC,CAAC,oBAAoBE,CAAK,GAAG,GAAQ,EAC3F,KAAOF,EAAA,SAAsBD,EAAgBC,CAAI,CAAC,CAAC,cAAcE,CAAK,GAAG,IACzE,OAAOF,CACT,CAWA,SAAgBK,EAAY,EAAyB,CACnD,OAAO,IAAIZ,EAAU,IAAII,EAAW,MAAM,CAAC,CAAC,IAAIG,CAAI,CAAC,CAAC,SAAS,CAAC,CAClE,CAmBA,SAAgBM,EACd,EACA,EACA,EACS,CACT,OAAOC,EAAcN,EAAgBE,CAAS,EAAGK,EAAWC,CAAS,CACvE,CAkBA,SAAgBC,EAAc,EAAwB,EAAgC,CAAC,EAAW,CAChG,IAAMC,EACJ,OAAOC,GAAU,SACbA,EACA,OAAOA,GAAU,UAEfnB,EAAU,YAAYmB,CAAK,EAD3BA,EAAM,SAAS,EAGb,MACJV,EAAQ,IAAIL,EAAWc,CAAS,EAEtC,GADI,CAACT,EAAM,SAAS,GAAKA,EAAM,kBAAkB,CAAC,GAC9C,CAAC,OAAO,SAASA,EAAM,SAAS,CAAC,EAAG,MAAO,KAC/C,IAAMW,EAAQX,EAAM,GAAG,CAAC,CAAC,UAAU,IAAIL,EAAW,MAAM,CAAC,CAAC,GAAG,CAAC,EACxDG,GAAQc,EAAQ,WAAa,UAAYD,EAAM,MAAM,EAAIA,EAAM,MAAM,EAAA,CAAG,SAAS,EACvF,OAAO,OAAO,SAASb,CAAI,EAAIA,EAAO,GACxC"}
1
+ {"version":3,"file":"tick_math.js","names":["BigNumber","GC_MIN_TICK","GC_MAX_TICK","DexMath","DexDecimal","Decimal","tickToSqrtPrice","tick","sqrtPriceToTick","value","sqrtPrice","approximate","tickToPrice","isSqrtPriceInRange","isTickInRange","tickLower","tickUpper","tickFromPrice","priceText","price","exact","options"],"sources":["../../../src/utils/tick_math.ts"],"sourcesContent":["import BigNumber from 'bignumber.js';\nimport { Decimal } from 'decimal.js';\nimport { isTickInRange, type TickInput } from './tick_range.js';\n\n/**\n * Tick and price arithmetic that never throws an SDK error: the contract's tick bounds, the\n * conversions between ticks and prices, and nothing that validates a range. It imports only the\n * two number libraries it computes with, never the `GSwapSDKError` class or the error catalog\n * (functions that must throw, `alignTickDown` and `assertTickRange`, are in `ticks.ts`), so an\n * app shell that prices a tick pays for the libraries and these few functions, not for ~25 kB of\n * error templates. A value that cannot be computed is `NaN`, never an exception.\n */\n\n/** Minimum tick supported by GalaChainDex. */\nexport const GC_MIN_TICK = -887272;\n/** Maximum tick supported by GalaChainDex. */\nexport const GC_MAX_TICK = 887272;\n\nconst DexMath = BigNumber.clone({\n DECIMAL_PLACES: 60,\n ROUNDING_MODE: BigNumber.ROUND_DOWN,\n});\n/** `decimal.js` at the 60 significant digits the contract's price math is exact to. */\nexport const DexDecimal = Decimal.clone({ precision: 60 });\n\n/** Convert a tick to the corresponding square-root price. */\nexport function tickToSqrtPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick / 2).toString());\n}\n\n/** Return the greatest tick whose square-root price is no greater than the input. */\nexport function sqrtPriceToTick(sqrtPrice: BigNumber.Value): number {\n let value: BigNumber;\n try {\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — this function's contract is to signal an invalid input via NaN, not\n // to throw, so an unparseable value is just another case for the guard below.\n value = new DexMath(sqrtPrice);\n } catch {\n return Number.NaN;\n }\n if (!value.isFinite() || value.isLessThanOrEqualTo(0)) return Number.NaN;\n\n const approximate = Math.log(value.toNumber() ** 2) / Math.log(1.0001);\n if (!Number.isFinite(approximate)) return Number.NaN;\n // Clamp the seed before the correction loops below — an unclamped seed derived from an\n // out-of-range sqrtPrice (extreme but finite, e.g. 1e20) leaves the loops running past\n // GC_MIN_TICK/GC_MAX_TICK for a long time; an infinite (overflowed) seed would never\n // enter the increasing loop and never terminate the decreasing one.\n let tick = Math.min(GC_MAX_TICK, Math.max(GC_MIN_TICK, Math.floor(approximate)));\n while (tick < GC_MAX_TICK && tickToSqrtPrice(tick + 1).isLessThanOrEqualTo(value)) tick += 1;\n while (tick > GC_MIN_TICK && tickToSqrtPrice(tick).isGreaterThan(value)) tick -= 1;\n return tick;\n}\n\n/**\n * The token1/token0 price at `tick`: `1.0001 ** tick`, exact to 60 significant digits (the lower\n * edge of the tick's price range; `tickToSqrtPrice(tick) ** 2`). A tick outside the contract's\n * bounds is still computed; ask `assertTickRange` first when that matters. A non-integer tick is\n * computed as given.\n *\n * Use `.toNumber()` for a display value (it differs from `Math.exp(tick * Math.log(1.0001))` in\n * the last digits of a double: that expression multiplies in floating point first).\n */\nexport function tickToPrice(tick: number): BigNumber {\n return new BigNumber(new DexDecimal(1.0001).pow(tick).toString());\n}\n\n/**\n * {@link isTickInRange} for a pool's square-root price instead of its tick (a position row that\n * carries `sqrtPrice`, `tickLower` and `tickUpper`). The tick is derived from the price exactly as\n * the contract does (`sqrtPriceToTick`: the greatest tick whose square-root price is no greater\n * than the price, exact to 60 digits), then the contract's rule applies: lower tick inclusive,\n * upper tick exclusive. So a pool sitting exactly on `tickLower`'s price is in range, and exactly\n * on `tickUpper`'s price is not, and no float rounding can flip either.\n *\n * `false` for a price that is not positive and finite (not loaded, zero, `NaN`): it says nothing\n * about the position, so an app that must show a neutral state checks for the missing price\n * itself first. `tickLower` and `tickUpper` follow {@link isTickInRange}.\n *\n * @example\n * ```ts\n * const inRange = isSqrtPriceInRange(position.sqrtPrice, position.tickLower, position.tickUpper);\n * ```\n */\nexport function isSqrtPriceInRange(\n sqrtPrice: BigNumber.Value,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n return isTickInRange(sqrtPriceToTick(sqrtPrice), tickLower, tickUpper);\n}\n\n/** How {@link tickFromPrice} turns the exact logarithm into an integer tick. */\nexport interface TickFromPriceOptions {\n /**\n * `'floor'` (default): the greatest tick whose price is no greater than `price`, which is how\n * the contract places a price. `'nearest'`: the closest tick, a half rounding away from zero.\n * That is what a price INPUT wants (a person types a price, the field snaps to the nearest\n * tick), and it differs from `'floor'` for any price in the upper half of a tick's range.\n */\n rounding?: 'floor' | 'nearest' | undefined;\n}\n\n/**\n * Return the integer tick for a token1/token0 `price`: by default the greatest tick whose price\n * is no greater than `price`; `{ rounding: 'nearest' }` the closest tick. `NaN` for a price that\n * is not positive and finite.\n */\nexport function tickFromPrice(price: BigNumber.Value, options: TickFromPriceOptions = {}): number {\n const priceText =\n typeof price === 'string'\n ? price\n : typeof price === 'number'\n ? price.toString()\n : BigNumber.isBigNumber(price)\n ? price.toString()\n : 'NaN';\n const value = new DexDecimal(priceText);\n if (!value.isFinite() || value.lessThanOrEqualTo(0)) return Number.NaN;\n if (!Number.isFinite(value.toNumber())) return Number.NaN;\n const exact = value.ln().dividedBy(new DexDecimal(1.0001).ln());\n const tick = (options.rounding === 'nearest' ? exact.round() : exact.floor()).toNumber();\n return Number.isFinite(tick) ? tick : Number.NaN;\n}\n"],"mappings":"A,iHAcA,MAAaC,EAAc,QAEdC,EAAc,OAErBC,EAAUH,EAAU,MAAM,CAC9B,eAAgB,GAChB,cAAeA,EAAU,UAC3B,CAAC,EAEYI,EAAaC,EAAQ,MAAM,CAAE,UAAW,EAAG,CAAC,EAGzD,SAAgBC,EAAgB,EAAyB,CACvD,OAAO,IAAIN,EAAU,IAAII,EAAW,MAAM,CAAC,CAAC,IAAIG,EAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CACtE,CAGA,SAAgBC,EAAgB,EAAoC,CAClE,IAAIC,EACJ,GAAI,CAIF,EAAQ,IAAIN,EAAQO,CAAS,CAC/B,MAAQ,CACN,MAAO,IACT,CACA,GAAI,CAACD,EAAM,SAAS,GAAKA,EAAM,oBAAoB,CAAC,EAAG,MAAO,KAE9D,IAAME,EAAc,KAAK,IAAIF,EAAM,SAAS,GAAK,CAAC,EAAI,KAAK,IAAI,MAAM,EACrE,GAAI,CAAC,OAAO,SAASE,CAAW,EAAG,MAAO,KAK1C,IAAIJ,EAAO,KAAK,IAAIL,EAAa,KAAK,IAAID,EAAa,KAAK,MAAMU,CAAW,CAAC,CAAC,EAC/E,KAAOJ,EAAA,QAAsBD,EAAgBC,EAAO,CAAC,CAAC,CAAC,oBAAoBE,CAAK,GAAG,GAAQ,EAC3F,KAAOF,EAAA,SAAsBD,EAAgBC,CAAI,CAAC,CAAC,cAAcE,CAAK,GAAG,IACzE,OAAOF,CACT,CAWA,SAAgBK,EAAY,EAAyB,CACnD,OAAO,IAAIZ,EAAU,IAAII,EAAW,MAAM,CAAC,CAAC,IAAIG,CAAI,CAAC,CAAC,SAAS,CAAC,CAClE,CAmBA,SAAgBM,EACd,EACA,EACA,EACS,CACT,OAAOC,EAAcN,EAAgBE,CAAS,EAAGK,EAAWC,CAAS,CACvE,CAkBA,SAAgBC,EAAc,EAAwB,EAAgC,CAAC,EAAW,CAChG,IAAMC,EACJ,OAAOC,GAAU,SACbA,EACA,OAAOA,GAAU,UAEfnB,EAAU,YAAYmB,CAAK,EAD3BA,EAAM,SAAS,EAGb,MACJV,EAAQ,IAAIL,EAAWc,CAAS,EAEtC,GADI,CAACT,EAAM,SAAS,GAAKA,EAAM,kBAAkB,CAAC,GAC9C,CAAC,OAAO,SAASA,EAAM,SAAS,CAAC,EAAG,MAAO,KAC/C,IAAMW,EAAQX,EAAM,GAAG,CAAC,CAAC,UAAU,IAAIL,EAAW,MAAM,CAAC,CAAC,GAAG,CAAC,EACxDG,GAAQc,EAAQ,WAAa,UAAYD,EAAM,MAAM,EAAIA,EAAM,MAAM,EAAA,CAAG,SAAS,EACvF,OAAO,OAAO,SAASb,CAAI,EAAIA,EAAO,GACxC,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"tick_range.js","names":["integerTickOf","tick","isTickInRange","current","currentTick","lower","tickLower","upper","tickUpper"],"sources":["../../../src/utils/tick_range.ts"],"sourcesContent":["/**\n * Whether a pool's current tick lies inside a position's range, by the contract's own rule. This\n * module imports nothing, so an app shell (a position badge, a filter) pays for a few dozen bytes.\n */\n\n/** A tick as the chain and the backends write it: a number, or the decimal string of one. */\nexport type TickInput = number | string;\n\nfunction integerTickOf(tick: TickInput): number {\n if (typeof tick === 'string') return tick.trim() === '' ? Number.NaN : Number(tick);\n return tick;\n}\n\n/**\n * True when a position over `[tickLower, tickUpper)` is IN RANGE at `currentTick`: the lower tick\n * is INCLUSIVE and the upper tick is EXCLUSIVE. That is the GalaChainDex contract's rule\n * (`DexV3Pool`: `tickCurrent >= tickLower && tickCurrent < tickUpper` is the case in which a\n * position holds both tokens and earns fees). A pool whose tick equals `tickUpper` is already out\n * of range: the position is entirely token1 there, and a swap through the tick has crossed it.\n *\n * `currentTick` is the pool's tick (`slot0.tick`, the greatest tick whose price is no greater than\n * the pool's price), not a rounded display value. A tick may be a number or the decimal string a\n * backend returns. Anything that is not an integer (`NaN`, `undefined`-like, an empty string, a\n * fraction) makes the answer `false`: an app that must tell \"not loaded yet\" from \"out of range\"\n * checks for the missing value itself first.\n *\n * Do NOT decide range by comparing a price with a tick's price (`tickToPrice`) using `<=` on both\n * ends, or by mixing a square-root price with a price. A price exactly on a tick's boundary is\n * then in range at the upper edge (the contract says it is not), and two representations of the\n * same boundary can round to opposite sides. For a pool price use {@link isSqrtPriceInRange}, which\n * derives the tick the way the contract does and then applies this rule.\n *\n * @example\n * ```ts\n * isTickInRange(-60, -60, 60); // true: the lower tick is inclusive\n * isTickInRange(60, -60, 60); // false: the upper tick is exclusive\n * ```\n */\nexport function isTickInRange(\n currentTick: TickInput,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n const current = integerTickOf(currentTick);\n const lower = integerTickOf(tickLower);\n const upper = integerTickOf(tickUpper);\n if (!Number.isInteger(current) || !Number.isInteger(lower) || !Number.isInteger(upper)) {\n return false;\n }\n return current >= lower && current < upper;\n}\n"],"mappings":"AAQA,SAASA,EAAc,EAAyB,CAE9C,OADI,OAAOC,GAAS,SAAiBA,EAAK,KAAK,IAAM,GAAK,IAAa,OAAOA,CAAI,EAC3EA,CACT,CA2BA,SAAgBC,EACd,EACA,EACA,EACS,CACT,IAAMC,EAAUH,EAAcI,CAAW,EACnCC,EAAQL,EAAcM,CAAS,EAC/BC,EAAQP,EAAcQ,CAAS,EAIrC,MAHI,CAAC,OAAO,UAAUL,CAAO,GAAK,CAAC,OAAO,UAAUE,CAAK,GAAK,CAAC,OAAO,UAAUE,CAAK,EAC5E,GAEFJ,GAAWE,GAASF,EAAUI,CACvC"}
1
+ {"version":3,"file":"tick_range.js","names":["integerTickOf","tick","isTickInRange","current","currentTick","lower","tickLower","upper","tickUpper"],"sources":["../../../src/utils/tick_range.ts"],"sourcesContent":["/**\n * Whether a pool's current tick lies inside a position's range, by the contract's own rule. This\n * module imports nothing, so an app shell (a position badge, a filter) pays for a few dozen bytes.\n */\n\n/** A tick as the chain and the backends write it: a number, or the decimal string of one. */\nexport type TickInput = number | string;\n\nfunction integerTickOf(tick: TickInput): number {\n if (typeof tick === 'string') return tick.trim() === '' ? Number.NaN : Number(tick);\n return tick;\n}\n\n/**\n * True when a position over `[tickLower, tickUpper)` is IN RANGE at `currentTick`: the lower tick\n * is INCLUSIVE and the upper tick is EXCLUSIVE. That is the GalaChainDex contract's rule\n * (`DexV3Pool`: `tickCurrent >= tickLower && tickCurrent < tickUpper` is the case in which a\n * position holds both tokens and earns fees). A pool whose tick equals `tickUpper` is already out\n * of range: the position is entirely token1 there, and a swap through the tick has crossed it.\n *\n * `currentTick` is the pool's tick (`slot0.tick`, the greatest tick whose price is no greater than\n * the pool's price), not a rounded display value. A tick may be a number or the decimal string a\n * backend returns. Anything that is not an integer (`NaN`, `undefined`-like, an empty string, a\n * fraction) makes the answer `false`: an app that must tell \"not loaded yet\" from \"out of range\"\n * checks for the missing value itself first.\n *\n * Do NOT decide range by comparing a price with a tick's price (`tickToPrice`) using `<=` on both\n * ends, or by mixing a square-root price with a price. A price exactly on a tick's boundary is\n * then in range at the upper edge (the contract says it is not), and two representations of the\n * same boundary can round to opposite sides. For a pool price use {@link isSqrtPriceInRange}, which\n * derives the tick the way the contract does and then applies this rule.\n *\n * @example\n * ```ts\n * isTickInRange(-60, -60, 60); // true: the lower tick is inclusive\n * isTickInRange(60, -60, 60); // false: the upper tick is exclusive\n * ```\n */\nexport function isTickInRange(\n currentTick: TickInput,\n tickLower: TickInput,\n tickUpper: TickInput,\n): boolean {\n const current = integerTickOf(currentTick);\n const lower = integerTickOf(tickLower);\n const upper = integerTickOf(tickUpper);\n if (!Number.isInteger(current) || !Number.isInteger(lower) || !Number.isInteger(upper)) {\n return false;\n }\n return current >= lower && current < upper;\n}\n"],"mappings":"AAQA,SAASA,EAAc,EAAyB,CAE9C,OADI,OAAOC,GAAS,SAAiBA,EAAK,KAAK,IAAM,GAAK,IAAa,OAAOA,CAAI,EAC3EA,CACT,CA2BA,SAAgBC,EACd,EACA,EACA,EACS,CACT,IAAMC,EAAUH,EAAcI,CAAW,EACnCC,EAAQL,EAAcM,CAAS,EAC/BC,EAAQP,EAAcQ,CAAS,EAIrC,MAHI,CAAC,OAAO,UAAUL,CAAO,GAAK,CAAC,OAAO,UAAUE,CAAK,GAAK,CAAC,OAAO,UAAUE,CAAK,EAC5E,GAEFJ,GAAWE,GAASF,EAAUI,CACvC,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"ticks.js","names":["alignTickDown","assertSpacing","spacing","alignTickDownOrNaN","tick","alignTickUp","alignTickUpOrNaN","assertTickRange","TICK_SPACING_BY_FEE","fee","GSwapSDKError","ALLOWED_FEE_TIERS_TEXT","lower","upper","GC_MIN_TICK","GC_MAX_TICK","hasValidSpacing","frameSlot0","slot0","inverted","DexDecimal","sqrtPrice","sqrtPriceToTick"],"sources":["../../../src/utils/ticks.ts"],"sourcesContent":["import { ALLOWED_FEE_TIERS_TEXT } from '../classes/gswap_error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\nimport { alignTickDownOrNaN, alignTickUpOrNaN, hasValidSpacing } from './tick_align.js';\nimport { DexDecimal, GC_MAX_TICK, GC_MIN_TICK, sqrtPriceToTick } from './tick_math.js';\n\n/**\n * The tick functions that THROW an SDK error on a bad input (`alignTickDown`, `alignTickUp`,\n * `assertTickRange`, `frameSlot0`). The arithmetic that never throws (`tickToPrice`,\n * `tickFromPrice`, `tickToSqrtPrice`, `sqrtPriceToTick`, the bounds) is in `tick_math.ts`, which\n * does not import the error class or the catalog; import it from the package entry as usual.\n */\n\n/** Align a tick down to the nearest multiple of a positive spacing. */\nexport function alignTickDown(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickDownOrNaN(tick, spacing);\n}\n\n/** Align a tick up to the nearest multiple of a positive spacing. */\nexport function alignTickUp(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickUpOrNaN(tick, spacing);\n}\n\n/** Validate a position range against the global tick bounds and fee-tier spacing. */\nexport function assertTickRange(lower: number, upper: number, fee: FEE_TIER): void {\n const spacing = TICK_SPACING_BY_FEE[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower: lower, tickUpper: upper });\n }\n if (lower >= upper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower: lower, tickUpper: upper });\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower: lower,\n tickUpper: upper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new GSwapSDKError('TICKS_NOT_ALIGNED', {\n tickLower: lower,\n tickUpper: upper,\n spacing,\n });\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!hasValidSpacing(spacing)) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: spacing });\n }\n}\n\n/** A pool's current price in the frame of the request that asked for it. */\nexport interface FramedSlot0 {\n /** The square-root price, token1 per token0 in the REQUESTED order. */\n sqrtPrice: string;\n /** The greatest tick whose square-root price is no greater than `sqrtPrice`. */\n tick: number;\n}\n\n/**\n * Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's\n * canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse\n * order the price is inverted here (at 60 significant digits, so a very large or very small\n * reciprocal keeps its precision) and the tick is re-derived from the inverted price with the\n * contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks\n * (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).\n *\n * @example\n * ```ts\n * const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);\n * const { sqrtPrice, tick } = frameSlot0(slot0);\n * ```\n */\nexport function frameSlot0(slot0: {\n sqrtPrice: string;\n tick: number;\n flippedFromRequest?: boolean | undefined;\n}): FramedSlot0 {\n if (slot0.flippedFromRequest !== true) return { sqrtPrice: slot0.sqrtPrice, tick: slot0.tick };\n const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));\n if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_SQRT_PRICE', { sqrtPrice: slot0.sqrtPrice });\n }\n const sqrtPrice = inverted.toString();\n return { sqrtPrice, tick: sqrtPriceToTick(sqrtPrice) };\n}\n"],"mappings":"mYAeA,SAAgBA,EAAc,EAAc,EAAyB,CAEnE,OADAC,EAAcC,CAAO,EACdC,EAAmBC,EAAMF,CAAO,CACzC,CAGA,SAAgBG,EAAY,EAAc,EAAyB,CAEjE,OADAJ,EAAcC,CAAO,EACdI,EAAiBF,EAAMF,CAAO,CACvC,CAGA,SAAgBK,EAAgB,EAAe,EAAe,EAAqB,CACjF,IAAML,EAAUM,EAAoBC,GACpC,GAAIP,IAAY,IAAA,GACd,MAAM,IAAIQ,EAAc,cAAe,CACrC,MAAO,MACP,MAAOD,EACP,QAASE,CACX,CAAC,EAEH,GAAI,CAAC,OAAO,UAAUC,CAAK,GAAK,CAAC,OAAO,UAAUC,CAAK,EACrD,MAAM,IAAIH,EAAc,qBAAsB,CAAE,UAAWE,EAAO,UAAWC,CAAM,CAAC,EAEtF,GAAID,GAASC,EACX,MAAM,IAAIH,EAAc,qBAAsB,CAAE,UAAWE,EAAO,UAAWC,CAAM,CAAC,EAEtF,GAAID,EAAA,SAAuBC,EAAA,OACzB,MAAM,IAAIH,EAAc,sBAAuB,CAC7C,UAAWE,EACX,UAAWC,EACX,QAASC,EACT,QAASC,CACX,CAAC,EAEH,GAAIH,EAAQV,IAAY,GAAKW,EAAQX,IAAY,EAC/C,MAAM,IAAIQ,EAAc,oBAAqB,CAC3C,UAAWE,EACX,UAAWC,EACX,SACF,CAAC,CAEL,CAEA,SAASZ,EAAc,EAAuB,CAC5C,GAAI,CAACe,EAAgBd,CAAO,EAC1B,MAAM,IAAIQ,EAAc,uBAAwB,CAAE,MAAOR,CAAQ,CAAC,CAEtE,CAwBA,SAAgBe,EAAW,EAIX,CACd,GAAIC,EAAM,qBAAuB,GAAM,MAAO,CAAE,UAAWA,EAAM,UAAW,KAAMA,EAAM,IAAK,EAC7F,IAAMC,EAAW,IAAIC,EAAW,CAAC,CAAC,CAAC,UAAU,IAAIA,EAAWF,EAAM,SAAS,CAAC,EAC5E,GAAI,CAACC,EAAS,SAAS,GAAKA,EAAS,kBAAkB,CAAC,EACtD,MAAM,IAAIT,EAAc,qBAAsB,CAAE,UAAWQ,EAAM,SAAU,CAAC,EAE9E,IAAMG,EAAYF,EAAS,SAAS,EACpC,MAAO,CAAE,YAAW,KAAMG,EAAgBD,CAAS,CAAE,CACvD"}
1
+ {"version":3,"file":"ticks.js","names":["alignTickDown","assertSpacing","spacing","alignTickDownOrNaN","tick","alignTickUp","alignTickUpOrNaN","assertTickRange","TICK_SPACING_BY_FEE","fee","GSwapSDKError","ALLOWED_FEE_TIERS_TEXT","lower","upper","GC_MIN_TICK","GC_MAX_TICK","hasValidSpacing","frameSlot0","slot0","inverted","DexDecimal","sqrtPrice","sqrtPriceToTick"],"sources":["../../../src/utils/ticks.ts"],"sourcesContent":["import { ALLOWED_FEE_TIERS_TEXT } from '../classes/gswap_error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { TICK_SPACING_BY_FEE } from '../types/fees.js';\nimport { alignTickDownOrNaN, alignTickUpOrNaN, hasValidSpacing } from './tick_align.js';\nimport { DexDecimal, GC_MAX_TICK, GC_MIN_TICK, sqrtPriceToTick } from './tick_math.js';\n\n/**\n * The tick functions that THROW an SDK error on a bad input (`alignTickDown`, `alignTickUp`,\n * `assertTickRange`, `frameSlot0`). The arithmetic that never throws (`tickToPrice`,\n * `tickFromPrice`, `tickToSqrtPrice`, `sqrtPriceToTick`, the bounds) is in `tick_math.ts`, which\n * does not import the error class or the catalog; import it from the package entry as usual.\n */\n\n/** Align a tick down to the nearest multiple of a positive spacing. */\nexport function alignTickDown(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickDownOrNaN(tick, spacing);\n}\n\n/** Align a tick up to the nearest multiple of a positive spacing. */\nexport function alignTickUp(tick: number, spacing: number): number {\n assertSpacing(spacing);\n return alignTickUpOrNaN(tick, spacing);\n}\n\n/** Validate a position range against the global tick bounds and fee-tier spacing. */\nexport function assertTickRange(lower: number, upper: number, fee: FEE_TIER): void {\n const spacing = TICK_SPACING_BY_FEE[fee];\n if (spacing === undefined) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n if (!Number.isInteger(lower) || !Number.isInteger(upper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower: lower, tickUpper: upper });\n }\n if (lower >= upper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower: lower, tickUpper: upper });\n }\n if (lower < GC_MIN_TICK || upper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower: lower,\n tickUpper: upper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n if (lower % spacing !== 0 || upper % spacing !== 0) {\n throw new GSwapSDKError('TICKS_NOT_ALIGNED', {\n tickLower: lower,\n tickUpper: upper,\n spacing,\n });\n }\n}\n\nfunction assertSpacing(spacing: number): void {\n if (!hasValidSpacing(spacing)) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: spacing });\n }\n}\n\n/** A pool's current price in the frame of the request that asked for it. */\nexport interface FramedSlot0 {\n /** The square-root price, token1 per token0 in the REQUESTED order. */\n sqrtPrice: string;\n /** The greatest tick whose square-root price is no greater than `sqrtPrice`. */\n tick: number;\n}\n\n/**\n * Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's\n * canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse\n * order the price is inverted here (at 60 significant digits, so a very large or very small\n * reciprocal keeps its precision) and the tick is re-derived from the inverted price with the\n * contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks\n * (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).\n *\n * @example\n * ```ts\n * const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);\n * const { sqrtPrice, tick } = frameSlot0(slot0);\n * ```\n */\nexport function frameSlot0(slot0: {\n sqrtPrice: string;\n tick: number;\n flippedFromRequest?: boolean | undefined;\n}): FramedSlot0 {\n if (slot0.flippedFromRequest !== true) return { sqrtPrice: slot0.sqrtPrice, tick: slot0.tick };\n const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));\n if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) {\n throw new GSwapSDKError('INVALID_SQRT_PRICE', { sqrtPrice: slot0.sqrtPrice });\n }\n const sqrtPrice = inverted.toString();\n return { sqrtPrice, tick: sqrtPriceToTick(sqrtPrice) };\n}\n"],"mappings":"A,mYAeA,SAAgBA,EAAc,EAAc,EAAyB,CAEnE,OADAC,EAAcC,CAAO,EACdC,EAAmBC,EAAMF,CAAO,CACzC,CAGA,SAAgBG,EAAY,EAAc,EAAyB,CAEjE,OADAJ,EAAcC,CAAO,EACdI,EAAiBF,EAAMF,CAAO,CACvC,CAGA,SAAgBK,EAAgB,EAAe,EAAe,EAAqB,CACjF,IAAML,EAAUM,EAAoBC,GACpC,GAAIP,IAAY,IAAA,GACd,MAAM,IAAIQ,EAAc,cAAe,CACrC,MAAO,MACP,MAAOD,EACP,QAASE,CACX,CAAC,EAEH,GAAI,CAAC,OAAO,UAAUC,CAAK,GAAK,CAAC,OAAO,UAAUC,CAAK,EACrD,MAAM,IAAIH,EAAc,qBAAsB,CAAE,UAAWE,EAAO,UAAWC,CAAM,CAAC,EAEtF,GAAID,GAASC,EACX,MAAM,IAAIH,EAAc,qBAAsB,CAAE,UAAWE,EAAO,UAAWC,CAAM,CAAC,EAEtF,GAAID,EAAA,SAAuBC,EAAA,OACzB,MAAM,IAAIH,EAAc,sBAAuB,CAC7C,UAAWE,EACX,UAAWC,EACX,QAASC,EACT,QAASC,CACX,CAAC,EAEH,GAAIH,EAAQV,IAAY,GAAKW,EAAQX,IAAY,EAC/C,MAAM,IAAIQ,EAAc,oBAAqB,CAC3C,UAAWE,EACX,UAAWC,EACX,SACF,CAAC,CAEL,CAEA,SAASZ,EAAc,EAAuB,CAC5C,GAAI,CAACe,EAAgBd,CAAO,EAC1B,MAAM,IAAIQ,EAAc,uBAAwB,CAAE,MAAOR,CAAQ,CAAC,CAEtE,CAwBA,SAAgBe,EAAW,EAIX,CACd,GAAIC,EAAM,qBAAuB,GAAM,MAAO,CAAE,UAAWA,EAAM,UAAW,KAAMA,EAAM,IAAK,EAC7F,IAAMC,EAAW,IAAIC,EAAW,CAAC,CAAC,CAAC,UAAU,IAAIA,EAAWF,EAAM,SAAS,CAAC,EAC5E,GAAI,CAACC,EAAS,SAAS,GAAKA,EAAS,kBAAkB,CAAC,EACtD,MAAM,IAAIT,EAAc,qBAAsB,CAAE,UAAWQ,EAAM,SAAU,CAAC,EAE9E,IAAMG,EAAYF,EAAS,SAAS,EACpC,MAAO,CAAE,YAAW,KAAMG,EAAgBD,CAAS,CAAE,CACvD,C"}
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","names":["BigNumber","validateNumericAmount","amount","GSwapSDKError","parameterName","bnAmount","allowZero","validatePriceValues","spotPrice","lowerPrice","upperPrice","value","parse","bnSpotPrice","bnLowerPrice","bnUpperPrice","validateTokenDecimals","decimals","validateTickRange","tickLower","tickUpper","GC_MIN_TICK","GC_MAX_TICK","validateFee","ALL_FEE_TIERS","tier","fee","ALLOWED_FEE_TIERS_TEXT","validateTickSpacing","tickSpacing","userRef","galaChainUserRef","field","cause","isGalaError","requireUserRef","address","RESERVED_TRADING_SYMBOLS","TRADING_SYMBOL_PATTERN","isProposableTradingSymbol","symbol","assertCanonicalPair","token0","token1"],"sources":["../../../src/utils/validation.ts"],"sourcesContent":["import { galaChainUserRef, isGalaError } from '@gala-chain/gala-core-sdk';\nimport BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from '../classes/gswap_error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { GC_MAX_TICK, GC_MIN_TICK } from './tick_math.js';\n\n/**\n * Validates a decimal amount: a string or `BigNumber`, never a JavaScript number.\n *\n * @param amount - The amount to check.\n * @param parameterName - The field name reported in the error's `params.field`.\n * @param allowZero - Accept zero (default `false`).\n * @throws GSwapSDKError `AMOUNT_IS_JS_NUMBER`, `AMOUNT_NOT_FINITE`, `AMOUNT_NOT_POSITIVE` (zero\n * when `allowZero` is false) or `AMOUNT_NEGATIVE`.\n */\nexport function validateNumericAmount(\n amount: NumericAmount,\n parameterName: string,\n allowZero = false,\n): void {\n if (typeof amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite() check below still catches\n // it and raises the same typed error, instead of a raw exception escaping.\n let bnAmount: BigNumber;\n try {\n bnAmount = BigNumber(amount);\n } catch {\n bnAmount = BigNumber(NaN);\n }\n\n if (!bnAmount.isFinite()) {\n throw new GSwapSDKError('AMOUNT_NOT_FINITE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError('AMOUNT_NOT_POSITIVE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError('AMOUNT_NEGATIVE', { field: parameterName, value: String(amount) });\n }\n}\n\n/**\n * Validates a spot price and a lower/upper price range: none a JavaScript number, all positive and\n * finite (a non-finite upper bound counts as an unbounded `1e18`), and `lowerPrice <= upperPrice`.\n *\n * @throws GSwapSDKError `PRICE_VALUES_IS_JS_NUMBER`, `INVALID_PRICE_VALUES` or `INVALID_PRICE_RANGE`.\n */\nexport function validatePriceValues(\n spotPrice: NumericAmount,\n lowerPrice: NumericAmount,\n upperPrice: NumericAmount,\n): void {\n if ([spotPrice, lowerPrice, upperPrice].some((value) => typeof value === 'number')) {\n throw new GSwapSDKError('PRICE_VALUES_IS_JS_NUMBER', {});\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite()/isPositive() checks below\n // still catch it and raise the same typed error, instead of a raw exception escaping.\n const parse = (value: NumericAmount): BigNumber => {\n try {\n return BigNumber(value);\n } catch {\n return BigNumber(NaN);\n }\n };\n const bnSpotPrice = parse(spotPrice);\n const bnLowerPrice = parse(lowerPrice);\n let bnUpperPrice = parse(upperPrice);\n\n bnUpperPrice = bnUpperPrice.isFinite() ? bnUpperPrice : BigNumber(1e18);\n\n if (\n !bnSpotPrice.isFinite() ||\n !bnLowerPrice.isFinite() ||\n !bnUpperPrice.isFinite() ||\n !bnSpotPrice.isPositive() ||\n !bnLowerPrice.isPositive() ||\n !bnUpperPrice.isPositive()\n ) {\n throw new GSwapSDKError('INVALID_PRICE_VALUES', {\n spotPrice: String(spotPrice),\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError('INVALID_PRICE_RANGE', {\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n}\n\n/**\n * Validates a token's decimals: a non-negative integer.\n *\n * @throws GSwapSDKError `INVALID_TOKEN_DECIMALS` (`params.field` is `parameterName`).\n */\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError('INVALID_TOKEN_DECIMALS', { field: parameterName, value: decimals });\n }\n}\n\n/**\n * Validates a position's tick range: two integers with `tickLower < tickUpper`, both within\n * `GC_MIN_TICK`..`GC_MAX_TICK`. It does not check alignment to a fee tier's spacing (see\n * `assertTickRange`).\n *\n * @throws GSwapSDKError `TICKS_NOT_INTEGERS`, `INVALID_TICK_RANGE` or `TICKS_OUT_OF_BOUNDS`.\n */\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower, tickUpper });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower, tickUpper });\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n}\n\n/**\n * Asserts that `fee` is one of the fee tiers in `ALL_FEE_TIERS` (`0`, `500`, `3000`, `10000`).\n *\n * @throws GSwapSDKError `INVALID_FEE` (`params.field` `'fee'`, `params.allowed` the tiers).\n */\nexport function validateFee(fee: number): asserts fee is FEE_TIER {\n if (!ALL_FEE_TIERS.some((tier) => Number(tier) === fee)) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\n/**\n * Validates a tick spacing: a positive integer.\n *\n * @throws GSwapSDKError `INVALID_TICK_SPACING`.\n */\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: tickSpacing });\n }\n}\n\n/**\n * The GalaChain user reference an owner, user or wallet address names, in the one spelling the\n * gateway and the swap backend accept: `eth|<EIP-55 checksummed digits>` for an Ethereum account\n * (given as `eth|<40 hex>` in any casing, `0x<40 hex>` or bare hex), `client|<id>` as written.\n * `eth|0x<hex>` is not an address form. This is `galaChainUserRef` of\n * `@gala-chain/gala-core-sdk`, the one implementation; only the error for a spelling that is no\n * address at all is this package's. Every place this SDK puts a user identity on the wire goes\n * through it, so what is signed, sent and compared on the backend (`owner === position.owner`,\n * strict) is always the chain's own spelling.\n *\n * @param value - The identity the caller gave.\n * @param field - The field name reported in the error's `params.field`.\n * @throws GalaSDKError core's `INVALID_ETH_USER_REF_PREFIX` (passed through as it is: its message\n * says an `eth|` reference takes the 40 hex digits with no `0x` and names the correct spelling,\n * `params.expected`) for `eth|0x...`; GSwapSDKError `INVALID_WALLET_ADDRESS` for anything else, a\n * mixed-case spelling whose casing is not the EIP-55 checksum included (a typo); nothing is\n * signed or sent.\n */\nexport function userRef(value: unknown, field: string): string {\n try {\n return galaChainUserRef(value, field);\n } catch (cause: unknown) {\n if (isGalaError(cause) && cause.code === 'INVALID_ETH_USER_REF_PREFIX') throw cause;\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field, value: String(value) });\n }\n}\n\n/**\n * {@link userRef} of an address that must be there.\n *\n * @throws GSwapSDKError `MISSING_WALLET_ADDRESS` (undefined) or `INVALID_WALLET_ADDRESS`; core's\n * `INVALID_ETH_USER_REF_PREFIX` for `eth|0x...` (see {@link userRef}).\n */\nexport function requireUserRef(address: string | undefined, field: string): string {\n if (address === undefined) {\n throw new GSwapSDKError('MISSING_WALLET_ADDRESS', {});\n }\n return userRef(address, field);\n}\n\n/** Words the chain gateway refuses as a trading symbol. */\nconst RESERVED_TRADING_SYMBOLS = new Set(['Token', 'Unit', 'none']);\nconst TRADING_SYMBOL_PATTERN = /^[A-Za-z0-9]+$/u;\nconst MAX_TRADING_SYMBOL_LENGTH = 32;\n\n/**\n * True when `symbol` is acceptable to propose into the trading-symbol registry: ASCII letters and\n * digits only, 1 to 32 characters, and not a reserved word (`Token`, `Unit`, `none`) — the rules\n * the chain gateway enforces on a CreatePool symbol.\n */\nexport function isProposableTradingSymbol(symbol: string): boolean {\n return (\n TRADING_SYMBOL_PATTERN.test(symbol) &&\n symbol.length <= MAX_TRADING_SYMBOL_LENGTH &&\n !RESERVED_TRADING_SYMBOLS.has(symbol)\n );\n}\n\n/**\n * Asserts that a pair is in the contract's canonical order (`token0 < token1` by plain string\n * comparison), which every write DTO requires. A pair a caller took from a stale quote or\n * position can be reversed; signing it would sign something other than what was priced.\n *\n * @throws GSwapSDKError `NON_CANONICAL_PAIR` (`params.token0`, `params.token1`) otherwise.\n */\nexport function assertCanonicalPair(token0: string, token1: string): void {\n if (!(token0 < token1)) {\n throw new GSwapSDKError('NON_CANONICAL_PAIR', { token0, token1 });\n }\n}\n"],"mappings":"kWAkBA,SAAgBC,EACd,EACA,EACA,EAAY,GACN,CACN,GAAI,OAAOC,GAAW,SACpB,MAAM,IAAIC,EAAc,sBAAuB,CAAE,MAAOC,CAAc,CAAC,EAKzE,IAAIC,EACJ,GAAI,CACF,EAAWL,EAAUE,CAAM,CAC7B,MAAQ,CACN,EAAWF,EAAU,GAAG,CAC1B,CAEA,GAAI,CAACK,EAAS,SAAS,EACrB,MAAM,IAAIF,EAAc,oBAAqB,CAC3C,MAAOC,EACP,MAAO,OAAOF,CAAM,CACtB,CAAC,EAGH,GAAI,CAACI,GAAaD,EAAS,OAAO,EAChC,MAAM,IAAIF,EAAc,sBAAuB,CAC7C,MAAOC,EACP,MAAO,OAAOF,CAAM,CACtB,CAAC,EAGH,GAAIG,EAAS,WAAW,EACtB,MAAM,IAAIF,EAAc,kBAAmB,CAAE,MAAOC,EAAe,MAAO,OAAOF,CAAM,CAAE,CAAC,CAE9F,CAQA,SAAgBK,EACd,EACA,EACA,EACM,CACN,GAAI,CAACC,EAAWC,EAAYC,CAAU,CAAC,CAAC,KAAM,GAAU,OAAOC,GAAU,QAAQ,EAC/E,MAAM,IAAIR,EAAc,4BAA6B,CAAC,CAAC,EAKzD,IAAMS,EAAS,GAAoC,CACjD,GAAI,CACF,OAAOZ,EAAUW,CAAK,CACxB,MAAQ,CACN,OAAOX,EAAU,GAAG,CACtB,CACF,EACMa,EAAcD,EAAMJ,CAAS,EAC7BM,EAAeF,EAAMH,CAAU,EACjCM,EAAeH,EAAMF,CAAU,EAInC,GAFA,EAAeK,EAAa,SAAS,EAAIA,EAAef,EAAU,iBAAI,EAGpE,CAACa,EAAY,SAAS,GACtB,CAACC,EAAa,SAAS,GACvB,CAACC,EAAa,SAAS,GACvB,CAACF,EAAY,WAAW,GACxB,CAACC,EAAa,WAAW,GACzB,CAACC,EAAa,WAAW,EAEzB,MAAM,IAAIZ,EAAc,uBAAwB,CAC9C,UAAW,OAAOK,CAAS,EAC3B,WAAY,OAAOC,CAAU,EAC7B,WAAY,OAAOC,CAAU,CAC/B,CAAC,EAGH,GAAII,EAAa,cAAcC,CAAY,EACzC,MAAM,IAAIZ,EAAc,sBAAuB,CAC7C,WAAY,OAAOM,CAAU,EAC7B,WAAY,OAAOC,CAAU,CAC/B,CAAC,CAEL,CAOA,SAAgBM,EAAsB,EAAkB,EAA6B,CACnF,GAAIC,EAAW,GAAK,CAAC,OAAO,UAAUA,CAAQ,EAC5C,MAAM,IAAId,EAAc,yBAA0B,CAAE,MAAOC,EAAe,MAAOa,CAAS,CAAC,CAE/F,CASA,SAAgBC,EAAkB,EAAmB,EAAyB,CAC5E,GAAI,CAAC,OAAO,UAAUC,CAAS,GAAK,CAAC,OAAO,UAAUC,CAAS,EAC7D,MAAM,IAAIjB,EAAc,qBAAsB,CAAE,YAAW,WAAU,CAAC,EAGxE,GAAIgB,GAAaC,EACf,MAAM,IAAIjB,EAAc,qBAAsB,CAAE,YAAW,WAAU,CAAC,EAGxE,GAAIgB,EAAA,SAA2BC,EAAA,OAC7B,MAAM,IAAIjB,EAAc,sBAAuB,CAC7C,YACA,YACA,QAASkB,EACT,QAASC,CACX,CAAC,CAEL,CAOA,SAAgBC,EAAY,EAAsC,CAChE,GAAI,CAACC,EAAc,KAAM,GAAS,OAAOC,CAAI,IAAMC,CAAG,EACpD,MAAM,IAAIvB,EAAc,cAAe,CACrC,MAAO,MACP,MAAOuB,EACP,QAASC,CACX,CAAC,CAEL,CAOA,SAAgBC,EAAoB,EAA2B,CAC7D,GAAI,CAAC,OAAO,UAAUC,CAAW,GAAKA,GAAe,EACnD,MAAM,IAAI1B,EAAc,uBAAwB,CAAE,MAAO0B,CAAY,CAAC,CAE1E,CAoBA,SAAgBC,EAAQ,EAAgB,EAAuB,CAC7D,GAAI,CACF,OAAOC,EAAiBpB,EAAOqB,CAAK,CACtC,OAASC,EAAgB,CAEvB,MADIC,EAAYD,CAAK,GAAKA,EAAM,OAAS,8BAAqCA,EACxE,IAAI9B,EAAc,yBAA0B,CAAE,QAAO,MAAO,OAAOQ,CAAK,CAAE,CAAC,CACnF,CACF,CAQA,SAAgBwB,EAAe,EAA6B,EAAuB,CACjF,GAAIC,IAAY,IAAA,GACd,MAAM,IAAIjC,EAAc,yBAA0B,CAAC,CAAC,EAEtD,OAAO2B,EAAQM,EAASJ,CAAK,CAC/B,CAGA,MAAMK,kBAA2B,IAAI,IAAI,CAAC,QAAS,OAAQ,MAAM,CAAC,EAC5DC,EAAyB,kBAQ/B,SAAgBC,EAA0B,EAAyB,CACjE,OACED,EAAuB,KAAKE,CAAM,GAClCA,EAAO,QAAU,IACjB,CAACH,EAAyB,IAAIG,CAAM,CAExC,CASA,SAAgBC,EAAoB,EAAgB,EAAsB,CACxE,GAAI,EAAEC,EAASC,GACb,MAAM,IAAIxC,EAAc,qBAAsB,CAAE,SAAQ,QAAO,CAAC,CAEpE"}
1
+ {"version":3,"file":"validation.js","names":["BigNumber","validateNumericAmount","amount","GSwapSDKError","parameterName","bnAmount","allowZero","validatePriceValues","spotPrice","lowerPrice","upperPrice","value","parse","bnSpotPrice","bnLowerPrice","bnUpperPrice","validateTokenDecimals","decimals","validateTickRange","tickLower","tickUpper","GC_MIN_TICK","GC_MAX_TICK","validateFee","ALL_FEE_TIERS","tier","fee","ALLOWED_FEE_TIERS_TEXT","validateTickSpacing","tickSpacing","userRef","galaChainUserRef","field","cause","isGalaError","requireUserRef","address","RESERVED_TRADING_SYMBOLS","TRADING_SYMBOL_PATTERN","isProposableTradingSymbol","symbol","assertCanonicalPair","token0","token1"],"sources":["../../../src/utils/validation.ts"],"sourcesContent":["import { galaChainUserRef, isGalaError } from '@gala-chain/gala-core-sdk';\nimport BigNumber from 'bignumber.js';\nimport { ALLOWED_FEE_TIERS_TEXT } from '../classes/gswap_error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport type { NumericAmount } from '../types/amounts.js';\nimport { ALL_FEE_TIERS } from '../types/fees.js';\nimport type { FEE_TIER } from '../types/fees.js';\nimport { GC_MAX_TICK, GC_MIN_TICK } from './tick_math.js';\n\n/**\n * Validates a decimal amount: a string or `BigNumber`, never a JavaScript number.\n *\n * @param amount - The amount to check.\n * @param parameterName - The field name reported in the error's `params.field`.\n * @param allowZero - Accept zero (default `false`).\n * @throws GSwapSDKError `AMOUNT_IS_JS_NUMBER`, `AMOUNT_NOT_FINITE`, `AMOUNT_NOT_POSITIVE` (zero\n * when `allowZero` is false) or `AMOUNT_NEGATIVE`.\n */\nexport function validateNumericAmount(\n amount: NumericAmount,\n parameterName: string,\n allowZero = false,\n): void {\n if (typeof amount === 'number') {\n throw new GSwapSDKError('AMOUNT_IS_JS_NUMBER', { field: parameterName });\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite() check below still catches\n // it and raises the same typed error, instead of a raw exception escaping.\n let bnAmount: BigNumber;\n try {\n bnAmount = BigNumber(amount);\n } catch {\n bnAmount = BigNumber(NaN);\n }\n\n if (!bnAmount.isFinite()) {\n throw new GSwapSDKError('AMOUNT_NOT_FINITE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (!allowZero && bnAmount.isZero()) {\n throw new GSwapSDKError('AMOUNT_NOT_POSITIVE', {\n field: parameterName,\n value: String(amount),\n });\n }\n\n if (bnAmount.isNegative()) {\n throw new GSwapSDKError('AMOUNT_NEGATIVE', { field: parameterName, value: String(amount) });\n }\n}\n\n/**\n * Validates a spot price and a lower/upper price range: none a JavaScript number, all positive and\n * finite (a non-finite upper bound counts as an unbounded `1e18`), and `lowerPrice <= upperPrice`.\n *\n * @throws GSwapSDKError `PRICE_VALUES_IS_JS_NUMBER`, `INVALID_PRICE_VALUES` or `INVALID_PRICE_RANGE`.\n */\nexport function validatePriceValues(\n spotPrice: NumericAmount,\n lowerPrice: NumericAmount,\n upperPrice: NumericAmount,\n): void {\n if ([spotPrice, lowerPrice, upperPrice].some((value) => typeof value === 'number')) {\n throw new GSwapSDKError('PRICE_VALUES_IS_JS_NUMBER', {});\n }\n // bignumber.js 11+ throws on an unparseable value instead of constructing a NaN\n // instance — substitute an explicit NaN so the isFinite()/isPositive() checks below\n // still catch it and raise the same typed error, instead of a raw exception escaping.\n const parse = (value: NumericAmount): BigNumber => {\n try {\n return BigNumber(value);\n } catch {\n return BigNumber(NaN);\n }\n };\n const bnSpotPrice = parse(spotPrice);\n const bnLowerPrice = parse(lowerPrice);\n let bnUpperPrice = parse(upperPrice);\n\n bnUpperPrice = bnUpperPrice.isFinite() ? bnUpperPrice : BigNumber(1e18);\n\n if (\n !bnSpotPrice.isFinite() ||\n !bnLowerPrice.isFinite() ||\n !bnUpperPrice.isFinite() ||\n !bnSpotPrice.isPositive() ||\n !bnLowerPrice.isPositive() ||\n !bnUpperPrice.isPositive()\n ) {\n throw new GSwapSDKError('INVALID_PRICE_VALUES', {\n spotPrice: String(spotPrice),\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n\n if (bnLowerPrice.isGreaterThan(bnUpperPrice)) {\n throw new GSwapSDKError('INVALID_PRICE_RANGE', {\n lowerPrice: String(lowerPrice),\n upperPrice: String(upperPrice),\n });\n }\n}\n\n/**\n * Validates a token's decimals: a non-negative integer.\n *\n * @throws GSwapSDKError `INVALID_TOKEN_DECIMALS` (`params.field` is `parameterName`).\n */\nexport function validateTokenDecimals(decimals: number, parameterName: string): void {\n if (decimals < 0 || !Number.isInteger(decimals)) {\n throw new GSwapSDKError('INVALID_TOKEN_DECIMALS', { field: parameterName, value: decimals });\n }\n}\n\n/**\n * Validates a position's tick range: two integers with `tickLower < tickUpper`, both within\n * `GC_MIN_TICK`..`GC_MAX_TICK`. It does not check alignment to a fee tier's spacing (see\n * `assertTickRange`).\n *\n * @throws GSwapSDKError `TICKS_NOT_INTEGERS`, `INVALID_TICK_RANGE` or `TICKS_OUT_OF_BOUNDS`.\n */\nexport function validateTickRange(tickLower: number, tickUpper: number): void {\n if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) {\n throw new GSwapSDKError('TICKS_NOT_INTEGERS', { tickLower, tickUpper });\n }\n\n if (tickLower >= tickUpper) {\n throw new GSwapSDKError('INVALID_TICK_RANGE', { tickLower, tickUpper });\n }\n\n if (tickLower < GC_MIN_TICK || tickUpper > GC_MAX_TICK) {\n throw new GSwapSDKError('TICKS_OUT_OF_BOUNDS', {\n tickLower,\n tickUpper,\n minTick: GC_MIN_TICK,\n maxTick: GC_MAX_TICK,\n });\n }\n}\n\n/**\n * Asserts that `fee` is one of the fee tiers in `ALL_FEE_TIERS` (`0`, `500`, `3000`, `10000`).\n *\n * @throws GSwapSDKError `INVALID_FEE` (`params.field` `'fee'`, `params.allowed` the tiers).\n */\nexport function validateFee(fee: number): asserts fee is FEE_TIER {\n if (!ALL_FEE_TIERS.some((tier) => Number(tier) === fee)) {\n throw new GSwapSDKError('INVALID_FEE', {\n field: 'fee',\n value: fee,\n allowed: ALLOWED_FEE_TIERS_TEXT,\n });\n }\n}\n\n/**\n * Validates a tick spacing: a positive integer.\n *\n * @throws GSwapSDKError `INVALID_TICK_SPACING`.\n */\nexport function validateTickSpacing(tickSpacing: number): void {\n if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) {\n throw new GSwapSDKError('INVALID_TICK_SPACING', { value: tickSpacing });\n }\n}\n\n/**\n * The GalaChain user reference an owner, user or wallet address names, in the one spelling the\n * gateway and the swap backend accept: `eth|<EIP-55 checksummed digits>` for an Ethereum account\n * (given as `eth|<40 hex>` in any casing, `0x<40 hex>` or bare hex), `client|<id>` as written.\n * `eth|0x<hex>` is not an address form. This is `galaChainUserRef` of\n * `@gala-chain/gala-core-sdk`, the one implementation; only the error for a spelling that is no\n * address at all is this package's. Every place this SDK puts a user identity on the wire goes\n * through it, so what is signed, sent and compared on the backend (`owner === position.owner`,\n * strict) is always the chain's own spelling.\n *\n * @param value - The identity the caller gave.\n * @param field - The field name reported in the error's `params.field`.\n * @throws GalaSDKError core's `INVALID_ETH_USER_REF_PREFIX` (passed through as it is: its message\n * says an `eth|` reference takes the 40 hex digits with no `0x` and names the correct spelling,\n * `params.expected`) for `eth|0x...`; GSwapSDKError `INVALID_WALLET_ADDRESS` for anything else, a\n * mixed-case spelling whose casing is not the EIP-55 checksum included (a typo); nothing is\n * signed or sent.\n */\nexport function userRef(value: unknown, field: string): string {\n try {\n return galaChainUserRef(value, field);\n } catch (cause: unknown) {\n if (isGalaError(cause) && cause.code === 'INVALID_ETH_USER_REF_PREFIX') throw cause;\n throw new GSwapSDKError('INVALID_WALLET_ADDRESS', { field, value: String(value) });\n }\n}\n\n/**\n * {@link userRef} of an address that must be there.\n *\n * @throws GSwapSDKError `MISSING_WALLET_ADDRESS` (undefined) or `INVALID_WALLET_ADDRESS`; core's\n * `INVALID_ETH_USER_REF_PREFIX` for `eth|0x...` (see {@link userRef}).\n */\nexport function requireUserRef(address: string | undefined, field: string): string {\n if (address === undefined) {\n throw new GSwapSDKError('MISSING_WALLET_ADDRESS', {});\n }\n return userRef(address, field);\n}\n\n/** Words the chain gateway refuses as a trading symbol. */\nconst RESERVED_TRADING_SYMBOLS = new Set(['Token', 'Unit', 'none']);\nconst TRADING_SYMBOL_PATTERN = /^[A-Za-z0-9]+$/u;\nconst MAX_TRADING_SYMBOL_LENGTH = 32;\n\n/**\n * True when `symbol` is acceptable to propose into the trading-symbol registry: ASCII letters and\n * digits only, 1 to 32 characters, and not a reserved word (`Token`, `Unit`, `none`) — the rules\n * the chain gateway enforces on a CreatePool symbol.\n */\nexport function isProposableTradingSymbol(symbol: string): boolean {\n return (\n TRADING_SYMBOL_PATTERN.test(symbol) &&\n symbol.length <= MAX_TRADING_SYMBOL_LENGTH &&\n !RESERVED_TRADING_SYMBOLS.has(symbol)\n );\n}\n\n/**\n * Asserts that a pair is in the contract's canonical order (`token0 < token1` by plain string\n * comparison), which every write DTO requires. A pair a caller took from a stale quote or\n * position can be reversed; signing it would sign something other than what was priced.\n *\n * @throws GSwapSDKError `NON_CANONICAL_PAIR` (`params.token0`, `params.token1`) otherwise.\n */\nexport function assertCanonicalPair(token0: string, token1: string): void {\n if (!(token0 < token1)) {\n throw new GSwapSDKError('NON_CANONICAL_PAIR', { token0, token1 });\n }\n}\n"],"mappings":"A,kWAkBA,SAAgBC,EACd,EACA,EACA,EAAY,GACN,CACN,GAAI,OAAOC,GAAW,SACpB,MAAM,IAAIC,EAAc,sBAAuB,CAAE,MAAOC,CAAc,CAAC,EAKzE,IAAIC,EACJ,GAAI,CACF,EAAWL,EAAUE,CAAM,CAC7B,MAAQ,CACN,EAAWF,EAAU,GAAG,CAC1B,CAEA,GAAI,CAACK,EAAS,SAAS,EACrB,MAAM,IAAIF,EAAc,oBAAqB,CAC3C,MAAOC,EACP,MAAO,OAAOF,CAAM,CACtB,CAAC,EAGH,GAAI,CAACI,GAAaD,EAAS,OAAO,EAChC,MAAM,IAAIF,EAAc,sBAAuB,CAC7C,MAAOC,EACP,MAAO,OAAOF,CAAM,CACtB,CAAC,EAGH,GAAIG,EAAS,WAAW,EACtB,MAAM,IAAIF,EAAc,kBAAmB,CAAE,MAAOC,EAAe,MAAO,OAAOF,CAAM,CAAE,CAAC,CAE9F,CAQA,SAAgBK,EACd,EACA,EACA,EACM,CACN,GAAI,CAACC,EAAWC,EAAYC,CAAU,CAAC,CAAC,KAAM,GAAU,OAAOC,GAAU,QAAQ,EAC/E,MAAM,IAAIR,EAAc,4BAA6B,CAAC,CAAC,EAKzD,IAAMS,EAAS,GAAoC,CACjD,GAAI,CACF,OAAOZ,EAAUW,CAAK,CACxB,MAAQ,CACN,OAAOX,EAAU,GAAG,CACtB,CACF,EACMa,EAAcD,EAAMJ,CAAS,EAC7BM,EAAeF,EAAMH,CAAU,EACjCM,EAAeH,EAAMF,CAAU,EAInC,GAFA,EAAeK,EAAa,SAAS,EAAIA,EAAef,EAAU,iBAAI,EAGpE,CAACa,EAAY,SAAS,GACtB,CAACC,EAAa,SAAS,GACvB,CAACC,EAAa,SAAS,GACvB,CAACF,EAAY,WAAW,GACxB,CAACC,EAAa,WAAW,GACzB,CAACC,EAAa,WAAW,EAEzB,MAAM,IAAIZ,EAAc,uBAAwB,CAC9C,UAAW,OAAOK,CAAS,EAC3B,WAAY,OAAOC,CAAU,EAC7B,WAAY,OAAOC,CAAU,CAC/B,CAAC,EAGH,GAAII,EAAa,cAAcC,CAAY,EACzC,MAAM,IAAIZ,EAAc,sBAAuB,CAC7C,WAAY,OAAOM,CAAU,EAC7B,WAAY,OAAOC,CAAU,CAC/B,CAAC,CAEL,CAOA,SAAgBM,EAAsB,EAAkB,EAA6B,CACnF,GAAIC,EAAW,GAAK,CAAC,OAAO,UAAUA,CAAQ,EAC5C,MAAM,IAAId,EAAc,yBAA0B,CAAE,MAAOC,EAAe,MAAOa,CAAS,CAAC,CAE/F,CASA,SAAgBC,EAAkB,EAAmB,EAAyB,CAC5E,GAAI,CAAC,OAAO,UAAUC,CAAS,GAAK,CAAC,OAAO,UAAUC,CAAS,EAC7D,MAAM,IAAIjB,EAAc,qBAAsB,CAAE,YAAW,WAAU,CAAC,EAGxE,GAAIgB,GAAaC,EACf,MAAM,IAAIjB,EAAc,qBAAsB,CAAE,YAAW,WAAU,CAAC,EAGxE,GAAIgB,EAAA,SAA2BC,EAAA,OAC7B,MAAM,IAAIjB,EAAc,sBAAuB,CAC7C,YACA,YACA,QAASkB,EACT,QAASC,CACX,CAAC,CAEL,CAOA,SAAgBC,EAAY,EAAsC,CAChE,GAAI,CAACC,EAAc,KAAM,GAAS,OAAOC,CAAI,IAAMC,CAAG,EACpD,MAAM,IAAIvB,EAAc,cAAe,CACrC,MAAO,MACP,MAAOuB,EACP,QAASC,CACX,CAAC,CAEL,CAOA,SAAgBC,EAAoB,EAA2B,CAC7D,GAAI,CAAC,OAAO,UAAUC,CAAW,GAAKA,GAAe,EACnD,MAAM,IAAI1B,EAAc,uBAAwB,CAAE,MAAO0B,CAAY,CAAC,CAE1E,CAoBA,SAAgBC,EAAQ,EAAgB,EAAuB,CAC7D,GAAI,CACF,OAAOC,EAAiBpB,EAAOqB,CAAK,CACtC,OAASC,EAAgB,CAEvB,MADIC,EAAYD,CAAK,GAAKA,EAAM,OAAS,8BAAqCA,EACxE,IAAI9B,EAAc,yBAA0B,CAAE,QAAO,MAAO,OAAOQ,CAAK,CAAE,CAAC,CACnF,CACF,CAQA,SAAgBwB,EAAe,EAA6B,EAAuB,CACjF,GAAIC,IAAY,IAAA,GACd,MAAM,IAAIjC,EAAc,yBAA0B,CAAC,CAAC,EAEtD,OAAO2B,EAAQM,EAASJ,CAAK,CAC/B,CAGA,MAAMK,kBAA2B,IAAI,IAAI,CAAC,QAAS,OAAQ,MAAM,CAAC,EAC5DC,EAAyB,kBAQ/B,SAAgBC,EAA0B,EAAyB,CACjE,OACED,EAAuB,KAAKE,CAAM,GAClCA,EAAO,QAAU,IACjB,CAACH,EAAyB,IAAIG,CAAM,CAExC,CASA,SAAgBC,EAAoB,EAAgB,EAAsB,CACxE,GAAI,EAAEC,EAASC,GACb,MAAM,IAAIxC,EAAc,qBAAsB,CAAE,SAAQ,QAAO,CAAC,CAEpE,C"}
package/dist/index.cjs CHANGED
@@ -1745,8 +1745,8 @@ function toChainDto(message) {
1745
1745
  * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own
1746
1746
  * `uniqueKey`, distinct from the DTO's.
1747
1747
  */
1748
- function buildDryRunWrapper(signer, callerPublicKey, method, dto, uniqueKeyPrefix = DRY_RUN_UNIQUE_KEY_PREFIX) {
1749
- return (0, _gala_chain_gala_core_sdk.signPreSend)(signer, DRY_RUN_METHOD, {
1748
+ function buildDryRunWrapper(signer, callerPublicKey, method, dto, uniqueKeyPrefix = DRY_RUN_UNIQUE_KEY_PREFIX, contractPath = "asset/dexv3-contract") {
1749
+ return (0, _gala_chain_gala_core_sdk.signPreSend)(signer, contractPath, DRY_RUN_METHOD, {
1750
1750
  callerPublicKey,
1751
1751
  method,
1752
1752
  dto,
@@ -1801,7 +1801,7 @@ var DexFees = class {
1801
1801
  if (this.signer === void 0) throw GSwapSDKError.noSignerError();
1802
1802
  const channel = options.channel ?? "asset";
1803
1803
  const contract = options.contract ?? "dexv3-contract";
1804
- const wrapper = await buildDryRunWrapper(this.signer, callerPublicKey, method, toChainDto(message));
1804
+ const wrapper = await buildDryRunWrapper(this.signer, callerPublicKey, method, toChainDto(message), void 0, `asset/${contract}`);
1805
1805
  const url = `${this.baseUrl}/wallet/connect/galachain/api/${encodeURIComponent(channel)}/${encodeURIComponent(contract)}/${encodeURIComponent(method)}/fee`;
1806
1806
  let status;
1807
1807
  let ok;
@@ -1839,6 +1839,14 @@ function readQuote(body) {
1839
1839
  return body;
1840
1840
  }
1841
1841
 
1842
+ //#endregion
1843
+ //#region src/utils/chain_contract.ts
1844
+ /**
1845
+ * The contract every v2 write goes to: its route under `/v1/chain/` and (through core's table) the
1846
+ * `dtoOperation` each DTO is signed with. One constant for both, so they cannot disagree.
1847
+ */
1848
+ const DEX_CONTRACT_PATH = "asset/dex-contract";
1849
+
1842
1850
  //#endregion
1843
1851
  //#region src/utils/shadow_errors.ts
1844
1852
  /**
@@ -2200,7 +2208,7 @@ var ChainGateway = class {
2200
2208
  return (options === null || options === void 0 ? void 0 : options.walletAddress) === void 0 ? this.walletAddress : userRef(options.walletAddress, "walletAddress");
2201
2209
  }
2202
2210
  writeUrl(method) {
2203
- return `${this.dexBackendBaseUrl}/v1/chain/asset/dex-contract/${method}`;
2211
+ return `${this.dexBackendBaseUrl}/v1/chain/${DEX_CONTRACT_PATH}/${method}`;
2204
2212
  }
2205
2213
  /**
2206
2214
  * POSTs a signed body and reads the answer. Neither a timeout nor a transport failure proves the
@@ -4977,7 +4985,7 @@ var Positions = class {
4977
4985
  }
4978
4986
  async submit(method, dto, confirmation) {
4979
4987
  if (this.signer === void 0) throw GSwapSDKError.noSignerError();
4980
- const signed = await (0, _gala_chain_gala_core_sdk.signPreSend)(this.signer, method, dto);
4988
+ const signed = await (0, _gala_chain_gala_core_sdk.signPreSend)(this.signer, DEX_CONTRACT_PATH, method, dto);
4981
4989
  const submitOptions = this.walletAddress === void 0 ? {} : { walletAddress: this.walletAddress };
4982
4990
  const owner = this.walletAddress;
4983
4991
  const positionConfirmation = await this.buildPositionConfirmation(confirmation, owner);
@@ -5638,7 +5646,7 @@ var Swaps = class {
5638
5646
  async signRequestTrade(dto) {
5639
5647
  assertCanonicalV2Dto("RequestTrade", dto);
5640
5648
  if (this.signer === void 0) throw GSwapSDKError.noSignerError();
5641
- return (0, _gala_chain_gala_core_sdk.signPreSend)(this.signer, "RequestTrade", dto);
5649
+ return (0, _gala_chain_gala_core_sdk.signPreSend)(this.signer, DEX_CONTRACT_PATH, "RequestTrade", dto);
5642
5650
  }
5643
5651
  /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */
5644
5652
  orientPool(tokenInSymbol, tokenOutSymbol, pool) {