@gala-chain/gswap-sdk 1.2.0 → 2.0.0-rc.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.
- package/README.md +42 -8
- package/dist/browser/classes/apply_results.js +1 -1
- package/dist/browser/classes/apply_results.js.map +1 -1
- package/dist/browser/classes/assets.js +1 -1
- package/dist/browser/classes/assets.js.map +1 -1
- package/dist/browser/classes/dex_fees.js +1 -1
- package/dist/browser/classes/dex_fees.js.map +1 -1
- package/dist/browser/classes/gateway.js +1 -1
- package/dist/browser/classes/gateway.js.map +1 -1
- package/dist/browser/classes/gdex_stream.js +1 -1
- package/dist/browser/classes/gdex_stream.js.map +1 -1
- package/dist/browser/classes/gswap.js +1 -1
- package/dist/browser/classes/gswap.js.map +1 -1
- package/dist/browser/classes/gswap_error_catalog.js +2 -0
- package/dist/browser/classes/gswap_error_catalog.js.map +1 -0
- package/dist/browser/classes/gswap_error_phase_table.js +2 -0
- package/dist/browser/classes/gswap_error_phase_table.js.map +1 -0
- package/dist/browser/classes/gswap_sdk_error.js +1 -1
- package/dist/browser/classes/gswap_sdk_error.js.map +1 -1
- package/dist/browser/classes/http_client.js +1 -1
- package/dist/browser/classes/http_client.js.map +1 -1
- package/dist/browser/classes/leaderboard.js +2 -0
- package/dist/browser/classes/leaderboard.js.map +1 -0
- package/dist/browser/classes/market.js +2 -0
- package/dist/browser/classes/market.js.map +1 -0
- package/dist/browser/classes/pending_swap_fate.js.map +1 -1
- package/dist/browser/classes/pending_swaps.js +1 -1
- package/dist/browser/classes/pending_swaps.js.map +1 -1
- package/dist/browser/classes/pools.js +1 -1
- package/dist/browser/classes/pools.js.map +1 -1
- package/dist/browser/classes/positions.js +1 -1
- package/dist/browser/classes/positions.js.map +1 -1
- package/dist/browser/classes/quoting.js +1 -1
- package/dist/browser/classes/quoting.js.map +1 -1
- package/dist/browser/classes/shadow_submit.js.map +1 -1
- package/dist/browser/classes/storage_adapters.js.map +1 -1
- package/dist/browser/classes/submitted_transaction.js +1 -1
- package/dist/browser/classes/submitted_transaction.js.map +1 -1
- package/dist/browser/classes/swaps.js +1 -1
- package/dist/browser/classes/swaps.js.map +1 -1
- package/dist/browser/classes/symbols.js +1 -1
- package/dist/browser/classes/symbols.js.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/types/env.js.map +1 -1
- package/dist/browser/types/fees.js.map +1 -1
- package/dist/browser/types/market.js +2 -0
- package/dist/browser/types/market.js.map +1 -0
- package/dist/browser/utils/classification.js.map +1 -1
- package/dist/browser/utils/confirmation_schedule.js.map +1 -1
- package/dist/browser/utils/confirmation_state.js +1 -1
- package/dist/browser/utils/confirmation_state.js.map +1 -1
- package/dist/browser/utils/debug.js.map +1 -1
- package/dist/browser/utils/dto_builders.js +1 -1
- package/dist/browser/utils/dto_builders.js.map +1 -1
- package/dist/browser/utils/failure_classification.js +1 -1
- package/dist/browser/utils/failure_classification.js.map +1 -1
- package/dist/browser/utils/failure_guards.js +1 -1
- package/dist/browser/utils/failure_guards.js.map +1 -1
- package/dist/browser/utils/lenient.js +1 -1
- package/dist/browser/utils/lenient.js.map +1 -1
- package/dist/browser/utils/ordering.js +1 -1
- package/dist/browser/utils/ordering.js.map +1 -1
- package/dist/browser/utils/reconnection.js +1 -1
- package/dist/browser/utils/reconnection.js.map +1 -1
- package/dist/browser/utils/resolve_pre_send.js +2 -0
- package/dist/browser/utils/resolve_pre_send.js.map +1 -0
- package/dist/browser/utils/server_message.js.map +1 -1
- package/dist/browser/utils/shadow_errors.js +1 -1
- package/dist/browser/utils/shadow_errors.js.map +1 -1
- package/dist/browser/utils/submit_state.js.map +1 -1
- package/dist/browser/utils/tick_align.js.map +1 -1
- package/dist/browser/utils/tick_math.js.map +1 -1
- package/dist/browser/utils/tick_range.js.map +1 -1
- package/dist/browser/utils/ticks.js +1 -1
- package/dist/browser/utils/ticks.js.map +1 -1
- package/dist/browser/utils/validation.js +1 -1
- package/dist/browser/utils/validation.js.map +1 -1
- package/dist/index.cjs +1033 -2925
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +439 -1604
- package/dist/index.d.ts +439 -1604
- package/dist/index.mjs +964 -2810
- package/dist/index.mjs.map +1 -1
- package/package.json +36 -60
- package/dist/browser/classes/error_catalog.js +0 -2
- package/dist/browser/classes/error_catalog.js.map +0 -1
- package/dist/browser/classes/error_phase_table.js +0 -2
- package/dist/browser/classes/error_phase_table.js.map +0 -1
- package/dist/browser/classes/error_phases.js +0 -2
- package/dist/browser/classes/error_phases.js.map +0 -1
- package/dist/browser/classes/signers.js +0 -2
- package/dist/browser/classes/signers.js.map +0 -1
- package/dist/browser/utils/axios_requestor.js +0 -2
- package/dist/browser/utils/axios_requestor.js.map +0 -1
- package/dist/browser/utils/chain_dto_signing.js +0 -3
- package/dist/browser/utils/chain_dto_signing.js.map +0 -1
- package/dist/browser/utils/class_key.js +0 -2
- package/dist/browser/utils/class_key.js.map +0 -1
- package/dist/browser/utils/eip712.js +0 -4
- package/dist/browser/utils/eip712.js.map +0 -1
- package/dist/browser/utils/error_brand.js +0 -2
- package/dist/browser/utils/error_brand.js.map +0 -1
- package/dist/browser/utils/ethers_provider.js +0 -2
- package/dist/browser/utils/ethers_provider.js.map +0 -1
- package/dist/browser/utils/failure_outcomes.js +0 -2
- package/dist/browser/utils/failure_outcomes.js.map +0 -1
- package/dist/browser/utils/failure_view.js +0 -2
- package/dist/browser/utils/failure_view.js.map +0 -1
- package/dist/browser/utils/fetch_failure.js +0 -2
- package/dist/browser/utils/fetch_failure.js.map +0 -1
- package/dist/browser/utils/pre_send.js +0 -2
- package/dist/browser/utils/pre_send.js.map +0 -1
- package/dist/browser/utils/signing.js +0 -3
- package/dist/browser/utils/signing.js.map +0 -1
- package/dist/browser/utils/transport.js +0 -2
- package/dist/browser/utils/transport.js.map +0 -1
- package/dist/browser/utils/typed_data.js +0 -2
- package/dist/browser/utils/typed_data.js.map +0 -1
- package/dist/browser/utils/unique_key.js +0 -2
- package/dist/browser/utils/unique_key.js.map +0 -1
- package/dist/browser/utils/unique_key_syntax.js +0 -2
- package/dist/browser/utils/unique_key_syntax.js.map +0 -1
- package/dist/browser/utils/wallet_rejection.js +0 -2
- package/dist/browser/utils/wallet_rejection.js.map +0 -1
- package/dist/browser/version.js +0 -2
- package/dist/browser/version.js.map +0 -1
- package/dist/browser/wallet.js +0 -2
- package/dist/browser/wallet.js.map +0 -1
- package/dist/wallet.cjs +0 -159
- package/dist/wallet.cjs.map +0 -1
- package/dist/wallet.d.cts +0 -74
- package/dist/wallet.d.ts +0 -74
- package/dist/wallet.mjs +0 -156
- package/dist/wallet.mjs.map +0 -1
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/defineProperty.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPrimitive.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/toPropertyKey.js +0 -0
- /package/dist/browser/_virtual/{_@oxc-project_runtime@0.151.0 → _@oxc-project_runtime@0.153.0}/helpers/esm/typeof.js +0 -0
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{GSwapSDKError as e}from"../classes/gswap_sdk_error.js";import{stripEip712DomainType as t}from"./chain_dto_signing.js";function n(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function r(e){return n(e)&&Object.values(e).every(e=>Array.isArray(e)&&e.every(e=>n(e)&&typeof e.name==`string`&&typeof e.type==`string`))}function i(t){return new e(`MALFORMED_WALLET_REQUEST`,{method:t})}function a(e){let a=e?.[1],o;try{o=typeof a==`string`?JSON.parse(a):a}catch{throw i(`eth_signTypedData_v4`)}if(!n(o))throw i(`eth_signTypedData_v4`);let{domain:s,types:c,message:l}=o;if(!n(s)||!r(c)||!n(l))throw i(`eth_signTypedData_v4`);return{domain:s,types:t(c),message:l}}function o(t,n={}){let r=()=>{if(t==null)throw new e(`WALLET_UNAVAILABLE`,{});return t};return{request:async({method:t,params:o})=>{switch(t){case`eth_chainId`:return r().send(`eth_chainId`,[]);case`eth_signTypedData_v4`:{let e=r(),{domain:t,types:n,message:i}=a(o);return(await e.getSigner()).signTypedData(t,n,i)}case`personal_sign`:{let e=o?.[0];if(typeof e!=`string`)throw i(`personal_sign`);return n.personalSign===void 0?(await r().getSigner()).signMessage(e):n.personalSign(e)}default:throw new e(`UNSUPPORTED_WALLET_METHOD`,{method:t})}}}}export{o as eip1193ProviderFromEthers};
|
|
2
|
-
//# sourceMappingURL=ethers_provider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ethers_provider.js","names":[],"sources":["../../../src/utils/ethers_provider.ts"],"sourcesContent":["import type { BrowserWalletProvider } from '../classes/signers.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { stripEip712DomainType } from './chain_dto_signing.js';\n\n/**\n * The part of an ethers v6 signer (`JsonRpcSigner`, `Wallet`) the adapter calls. Declared\n * structurally, so the SDK takes no dependency on ethers and an ethers object satisfies it as is.\n */\nexport interface EthersLikeSigner {\n signTypedData(\n domain: Record<string, unknown>,\n types: Record<string, Array<{ name: string; type: string }>>,\n value: Record<string, unknown>,\n ): Promise<string>;\n signMessage(message: string): Promise<string>;\n}\n\n/** The part of an ethers v6 provider (`BrowserProvider`) the adapter calls. */\nexport interface EthersLikeProvider {\n getSigner(): Promise<EthersLikeSigner>;\n /** The raw JSON-RPC passthrough (`BrowserProvider.send`). */\n send(method: string, params: unknown[]): Promise<unknown>;\n}\n\n/** Options of {@link eip1193ProviderFromEthers}. */\nexport interface EthersEip1193Options {\n /**\n * Signs a `personal_sign` message when the provider cannot or should not: a wallet SDK that\n * signs through its own object (TrustWallet's `web3Wallet.signMessage`). When set it answers\n * every `personal_sign`, and the provider is not touched for it.\n */\n personalSign?: ((message: string) => Promise<string>) | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isTypedDataTypes(\n value: unknown,\n): value is Record<string, Array<{ name: string; type: string }>> {\n return (\n isRecord(value) &&\n Object.values(value).every(\n (fields) =>\n Array.isArray(fields) &&\n fields.every(\n (field) =>\n isRecord(field) &&\n typeof field['name'] === 'string' &&\n typeof field['type'] === 'string',\n ),\n )\n );\n}\n\nfunction malformed(method: string): GSwapSDKError {\n return new GSwapSDKError('MALFORMED_WALLET_REQUEST', { method });\n}\n\n/** Splits `eth_signTypedData_v4` params (`[account, JSON payload]`) into what ethers' signer takes. */\nfunction readTypedDataRequest(params: unknown[] | undefined): {\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n message: Record<string, unknown>;\n} {\n const raw = params?.[1];\n let payload: unknown;\n try {\n payload = typeof raw === 'string' ? JSON.parse(raw) : raw;\n } catch {\n throw malformed('eth_signTypedData_v4');\n }\n if (!isRecord(payload)) throw malformed('eth_signTypedData_v4');\n const { domain, types, message } = payload;\n if (!isRecord(domain) || !isTypedDataTypes(types) || !isRecord(message)) {\n throw malformed('eth_signTypedData_v4');\n }\n // ethers refuses an explicit EIP712Domain type; the JSON-RPC form includes it.\n return { domain, types: stripEip712DomainType(types), message };\n}\n\n/**\n * An EIP-1193 provider over an ethers v6 provider, for {@link BrowserWalletSigner}: apps whose\n * wallet connection is an ethers `BrowserProvider` sign through the very ethers calls they always\n * made, with no hand-written shim.\n *\n * - `eth_chainId` is `provider.send('eth_chainId', [])`: the wallet's LIVE chain. Never\n * `provider.getNetwork()`, which ethers caches and does not invalidate on `chainChanged`, so a\n * user who switches networks after connecting would sign against a stale chainId.\n * - `eth_signTypedData_v4` parses the `[account, JSON]` params and calls\n * `signer.signTypedData(domain, types, message)` with `EIP712Domain` removed from `types`.\n * - `personal_sign` is `options.personalSign(message)` when given, else `signer.signMessage`.\n * - Anything else is `UNSUPPORTED_WALLET_METHOD`; a malformed request is\n * `MALFORMED_WALLET_REQUEST`; a missing provider is `WALLET_UNAVAILABLE`.\n *\n * `provider` may be `null`/`undefined` (nothing connected): a request that needs it then fails\n * with `WALLET_UNAVAILABLE` rather than at construction, so a signer can be built before the\n * connection state is known.\n *\n * @example\n * ```ts\n * const signer = new BrowserWalletSigner(eip1193ProviderFromEthers(browserProvider), account, {\n * scheme: 'eip712',\n * });\n * ```\n */\nexport function eip1193ProviderFromEthers(\n provider: EthersLikeProvider | null | undefined,\n options: EthersEip1193Options = {},\n): BrowserWalletProvider {\n const connected = (): EthersLikeProvider => {\n if (provider === null || provider === undefined) {\n throw new GSwapSDKError('WALLET_UNAVAILABLE', {});\n }\n return provider;\n };\n return {\n request: async ({ method, params }) => {\n switch (method) {\n case 'eth_chainId':\n return connected().send('eth_chainId', []);\n case 'eth_signTypedData_v4': {\n const wallet = connected();\n const { domain, types, message } = readTypedDataRequest(params);\n return (await wallet.getSigner()).signTypedData(domain, types, message);\n }\n case 'personal_sign': {\n const message = params?.[0];\n if (typeof message !== 'string') throw malformed('personal_sign');\n if (options.personalSign !== undefined) return options.personalSign(message);\n return (await connected().getSigner()).signMessage(message);\n }\n default:\n throw new GSwapSDKError('UNSUPPORTED_WALLET_METHOD', { method });\n }\n },\n };\n}\n"],"mappings":"6HAkCA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,GAAkB,CAAC,MAAM,QAAQ,CAAK,CAC5E,CAEA,SAAS,EACP,EACgE,CAChE,OACE,EAAS,CAAK,GACd,OAAO,OAAO,CAAK,CAAC,CAAC,MAClB,GACC,MAAM,QAAQ,CAAM,GACpB,EAAO,MACJ,GACC,EAAS,CAAK,GACd,OAAO,EAAM,MAAY,UACzB,OAAO,EAAM,MAAY,QAC7B,CACJ,CAEJ,CAEA,SAAS,EAAU,EAA+B,CAChD,OAAO,IAAI,EAAc,2BAA4B,CAAE,QAAO,CAAC,CACjE,CAGA,SAAS,EAAqB,EAI5B,CACA,IAAM,EAAM,IAAS,GACjB,EACJ,GAAI,CACF,EAAU,OAAO,GAAQ,SAAW,KAAK,MAAM,CAAG,EAAI,CACxD,MAAQ,CACN,MAAM,EAAU,sBAAsB,CACxC,CACA,GAAI,CAAC,EAAS,CAAO,EAAG,MAAM,EAAU,sBAAsB,EAC9D,GAAM,CAAE,SAAQ,QAAO,WAAY,EACnC,GAAI,CAAC,EAAS,CAAM,GAAK,CAAC,EAAiB,CAAK,GAAK,CAAC,EAAS,CAAO,EACpE,MAAM,EAAU,sBAAsB,EAGxC,MAAO,CAAE,SAAQ,MAAO,EAAsB,CAAK,EAAG,SAAQ,CAChE,CA2BA,SAAgB,EACd,EACA,EAAgC,CAAC,EACV,CACvB,IAAM,MAAsC,CAC1C,GAAI,GAAa,KACf,MAAM,IAAI,EAAc,qBAAsB,CAAC,CAAC,EAElD,OAAO,CACT,EACA,MAAO,CACL,QAAS,MAAO,CAAE,SAAQ,YAAa,CACrC,OAAQ,EAAR,CACE,IAAK,cACH,OAAO,EAAU,CAAC,CAAC,KAAK,cAAe,CAAC,CAAC,EAC3C,IAAK,uBAAwB,CAC3B,IAAM,EAAS,EAAU,EACnB,CAAE,SAAQ,QAAO,WAAY,EAAqB,CAAM,EAC9D,OAAQ,MAAM,EAAO,UAAU,EAAA,CAAG,cAAc,EAAQ,EAAO,CAAO,CACxE,CACA,IAAK,gBAAiB,CACpB,IAAM,EAAU,IAAS,GACzB,GAAI,OAAO,GAAY,SAAU,MAAM,EAAU,eAAe,EAEhE,OADI,EAAQ,eAAiB,IAAA,IACrB,MAAM,EAAU,CAAC,CAAC,UAAU,EAAA,CAAG,YAAY,CAAO,EADX,EAAQ,aAAa,CAAO,CAE7E,CACA,QACE,MAAM,IAAI,EAAc,4BAA6B,CAAE,QAAO,CAAC,CACnE,CACF,CACF,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"failure_outcomes.js","names":[],"sources":["../../../src/utils/failure_outcomes.ts"],"sourcesContent":["/**\n * What a failure means for the operation that raised it, as one vocabulary for every app.\n *\n * - `rejected`: the CHAIN refused the request (a definite no). Nothing was applied, so a NEW\n * request is safe.\n * - `unknown`: the request MAY have been applied (a timeout, a broken connection, an\n * acknowledgement that proves nothing, a failed confirmation). Never submit again under a fresh\n * key: keep `error.uniqueKey` and confirm it.\n * - `not_queued`: the gateway refused the write before queueing it. Nothing is pending.\n * - `not_sent`: the request never left (`error.phase === 'pre_send'`) for a reason outside the\n * call itself: the signer or the wallet failed (locked, unreachable, the person declined), the\n * key provider or the token resolver failed, or no key was available yet. Nothing is pending and\n * nothing was transmitted, so repeating the call is safe and may succeed once the cause (an\n * unlocked wallet) is gone.\n * - `invalid_input`: the call itself cannot work (a bad argument, a missing signer or wallet, an\n * unknown token or pool, a corrupt stored key). Repeating the same call fails the same way.\n * Such an error is also pre-send (`isPreSendError`), but the input is what has to change.\n * - `transient`: a read or connection failed with no state change. Repeating the same call is safe\n * and may succeed.\n *\n * This module has no imports: the failure view (`FailureView.outcome`) and the classifier both\n * read the closed set from here.\n */\nexport const FAILURE_OUTCOMES = [\n 'rejected',\n 'unknown',\n 'not_queued',\n 'not_sent',\n 'invalid_input',\n 'transient',\n] as const;\n\n/** One member of {@link FAILURE_OUTCOMES}. */\nexport type FailureOutcome = (typeof FAILURE_OUTCOMES)[number];\n"],"mappings":"AAuBA,MAAa,EAAmB,CAC9B,WACA,UACA,aACA,WACA,gBACA,WACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{GSWAP_ERROR_PHASES as e}from"../classes/error_phases.js";import{FAILURE_OUTCOMES as t}from"./failure_outcomes.js";function n(e){return typeof e==`object`&&!!e}function r(r){if(!n(r))return;let{code:i,params:a,status:o,phase:s,uniqueKey:c,write:l,outcome:u,retryable:d,shadow:f,notFound:p}=r;if(typeof i==`string`&&i!==``)return{code:i,params:n(a)&&!Array.isArray(a)?a:void 0,status:typeof o==`number`&&Number.isFinite(o)?o:void 0,phase:e.find(e=>e===s),uniqueKey:typeof c==`string`&&c!==``?c:void 0,write:typeof l==`boolean`?l:void 0,outcome:t.find(e=>e===u),retryable:d!==!1&&void 0,shadow:typeof f==`boolean`?f:void 0,notFound:typeof p==`boolean`?p:void 0}}function i(e){return e.uniqueKey!==void 0||e.write!==!1}function a(e,t){let n=e.params?.[t];return typeof n==`string`?n:void 0}function o(e,t){let n=e.params?.[t];return typeof n==`number`&&Number.isFinite(n)?n:void 0}export{i as isWriteView,o as numberParamOf,a as stringParamOf,r as toFailureView};
|
|
2
|
-
//# sourceMappingURL=failure_view.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"failure_view.js","names":[],"sources":["../../../src/utils/failure_view.ts"],"sourcesContent":["import { GSWAP_ERROR_PHASES, type GSwapErrorPhase } from '../classes/error_phases.js';\nimport { FAILURE_OUTCOMES, type FailureOutcome } from './failure_outcomes.js';\n\n/**\n * A failure as a PLAIN OBJECT: the facts the SDK's guards and `classifyFailure` read, and nothing\n * else. A real `GSwapSDKError` is one (every field below is on it); so is the wrapper an app makes\n * from an SDK error to carry through its own layers (frontend_v2's `V2Failure`, the wallet's\n * `WalletSwapError` data), which has a `code` and `params` but is not an `instanceof` anything the\n * SDK owns. `classifyFailure`, `isRelayableRefusal`, `isUnprovenAcknowledgement`,\n * `isUninterpretedAnswer`, `isPreSendError`, `isShadowError`, `isNoMarket` and `mayHaveBeenQueued`\n * all accept such an object wherever they accept an SDK error, and decide from the SAME fields in\n * the same way, so an app never has to keep the original error just to ask.\n *\n * Only `code` is required. A field that is missing, or has the wrong type, reads as absent: a view\n * with no `status` is not a 404. Nothing here is text: the SDK never reads `message` of a view.\n *\n * READ OR WRITE: a view is a WRITE's unless it says it is a read. This fails CLOSED on purpose:\n * a 5xx on a write may have been queued (`unknown`, no retry) and the same 5xx on a read changed\n * nothing (`transient`, retry), so a wrapper that drops its `uniqueKey` must never turn the first\n * into the second. A view is a read ONLY when it states `write: false` and has no `uniqueKey`;\n * `GSwapSDKError.write` is already set that way for every SDK read. {@link isWriteView}\n * is the one definition.\n *\n * APP ERRORS: a code the SDK catalog does not define is `unknown` (the SDK cannot say what\n * happened, and a wrong \"failed\" invites a duplicate), unless the view declares `outcome`.\n */\nexport interface FailureView {\n /** The catalog code (`'HTTP_ERROR'`, `'CHAIN_REJECTED'`, ...). A string the SDK does not know classifies as `unknown`. */\n readonly code: string;\n /** The error's flat params (`status` of an `HTTP_ERROR`, `reason` of a `SIGNING_FAILED`, ...). */\n readonly params?: Readonly<Record<string, unknown>> | undefined;\n /** The HTTP status of the answer the failure was made from. */\n readonly status?: number | undefined;\n /** How far the request got; when absent, the catalog's phase for `code`. */\n readonly phase?: GSwapErrorPhase | undefined;\n /** The `uniqueKey` of the WRITE this is about; its presence makes the failure a write's. */\n readonly uniqueKey?: string | undefined;\n /**\n * `false` says the failed call was a READ (no `uniqueKey` to confirm, nothing pending). Anything\n * else, including absent, is a write: see the note on {@link FailureView}. With a `uniqueKey`\n * the failure is a write whatever this says.\n */\n readonly write?: boolean | undefined;\n /**\n * What an error the APP raised means, for a `code` the SDK catalog does not define (`'POSITION_STALE'`,\n * `'AMOUNT_SIDE'`): `not_sent` for a step that failed before anything was signed or sent, and so\n * on. The SDK honours it ONLY for such a code: for a catalog code the SDK's own table decides, so\n * an app cannot declare a refusal the SDK knows to be unknown as safe. A non-catalog code with no\n * `outcome` stays `unknown`, and `mayHaveBeenQueued` is then `true`.\n */\n readonly outcome?: FailureOutcome | undefined;\n /**\n * WITHHOLD-ONLY: `false` takes Retry away from the declared `outcome` (an app's `DID_NOT_QUEUE`\n * is `{ outcome: 'not_queued', retryable: false }`, the SDK's `NOT_QUEUED_FINAL`). Any other\n * value, `true` included, reads as absent: a view can never GRANT Retry to an outcome that does\n * not have it, and it is read only together with `outcome`, for a code the catalog does not\n * define.\n */\n readonly retryable?: false | undefined;\n /** True when the failure came from the shadow (dark) path. */\n readonly shadow?: boolean | undefined;\n /** True for \"that market does not exist\" (`GSwapSDKError.notFound`). */\n readonly notFound?: boolean | undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/**\n * Reads the failure view of any value: a `GSwapSDKError`, or a plain object with a string `code`\n * (and, optionally, `params`, `status`, `phase`, `uniqueKey`, `shadow`, `notFound`). Anything else\n * (a string, a wallet error with a numeric `code`, `null`) has no view and is `undefined`.\n *\n * Having a view does not mean the SDK knows the code: an ethers error is `{ code:\n * 'ACTION_REJECTED' }` and has a view too. The SDK's guards compare the code with the catalog.\n *\n * @example\n * ```ts\n * const view = toFailureView(error); // an SDK error, or an app's `{ code, params, status }` wrapper\n * if (view?.code === 'CHAIN_REJECTED') showChainRejection(view.params);\n * ```\n */\nexport function toFailureView(value: unknown): FailureView | undefined {\n if (!isRecord(value)) return undefined;\n const { code, params, status, phase, uniqueKey, write, outcome, retryable, shadow, notFound } =\n value;\n if (typeof code !== 'string' || code === '') return undefined;\n return {\n code,\n params: isRecord(params) && !Array.isArray(params) ? params : undefined,\n status: typeof status === 'number' && Number.isFinite(status) ? status : undefined,\n phase: GSWAP_ERROR_PHASES.find((known) => known === phase),\n uniqueKey: typeof uniqueKey === 'string' && uniqueKey !== '' ? uniqueKey : undefined,\n write: typeof write === 'boolean' ? write : undefined,\n outcome: FAILURE_OUTCOMES.find((known) => known === outcome),\n retryable: retryable === false ? false : undefined,\n shadow: typeof shadow === 'boolean' ? shadow : undefined,\n notFound: typeof notFound === 'boolean' ? notFound : undefined,\n };\n}\n\n/**\n * True when a failure is a WRITE's: it names a `uniqueKey`, or it does not say `write: false`.\n * Fail-closed (see {@link FailureView}): only an explicit read is a read.\n */\nexport function isWriteView(view: FailureView): boolean {\n return view.uniqueKey !== undefined || view.write !== false;\n}\n\n/** A param of a view, when it is a string. */\nexport function stringParamOf(view: FailureView, name: string): string | undefined {\n const value = view.params?.[name];\n return typeof value === 'string' ? value : undefined;\n}\n\n/** A param of a view, when it is a finite number. */\nexport function numberParamOf(view: FailureView, name: string): number | undefined {\n const value = view.params?.[name];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n"],"mappings":"yHAiEA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,CACtC,CAgBA,SAAgB,EAAc,EAAyC,CACrE,GAAI,CAAC,EAAS,CAAK,EAAG,OACtB,GAAM,CAAE,OAAM,SAAQ,SAAQ,QAAO,YAAW,QAAO,UAAS,YAAW,SAAQ,YACjF,EACF,GAAI,OAAO,GAAS,UAAY,IAAS,GACzC,MAAO,CACL,OACA,OAAQ,EAAS,CAAM,GAAK,CAAC,MAAM,QAAQ,CAAM,EAAI,EAAS,IAAA,GAC9D,OAAQ,OAAO,GAAW,UAAY,OAAO,SAAS,CAAM,EAAI,EAAS,IAAA,GACzE,MAAO,EAAmB,KAAM,GAAU,IAAU,CAAK,EACzD,UAAW,OAAO,GAAc,UAAY,IAAc,GAAK,EAAY,IAAA,GAC3E,MAAO,OAAO,GAAU,UAAY,EAAQ,IAAA,GAC5C,QAAS,EAAiB,KAAM,GAAU,IAAU,CAAO,EAC3D,UAAW,IAAc,IAAgB,IAAA,GACzC,OAAQ,OAAO,GAAW,UAAY,EAAS,IAAA,GAC/C,SAAU,OAAO,GAAa,UAAY,EAAW,IAAA,EACvD,CACF,CAMA,SAAgB,EAAY,EAA4B,CACtD,OAAO,EAAK,YAAc,IAAA,IAAa,EAAK,QAAU,EACxD,CAGA,SAAgB,EAAc,EAAmB,EAAkC,CACjF,IAAM,EAAQ,EAAK,SAAS,GAC5B,OAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,EAC7C,CAGA,SAAgB,EAAc,EAAmB,EAAkC,CACjF,IAAM,EAAQ,EAAK,SAAS,GAC5B,OAAO,OAAO,GAAU,UAAY,OAAO,SAAS,CAAK,EAAI,EAAQ,IAAA,EACvE"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function e(e){if(typeof e!=`object`||!e)return!1;try{let t=`name`in e?e.name:void 0;return t===`AbortError`||t===`TimeoutError`?!1:e instanceof TypeError||t===`TypeError`||t===`NetworkError`}catch{return!1}}export{e as isFetchTransportFailure};
|
|
2
|
-
//# sourceMappingURL=fetch_failure.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fetch_failure.js","names":[],"sources":["../../../src/utils/fetch_failure.ts"],"sourcesContent":["/**\n * True when a rejection of a `fetch`-based requestor means NO HTTP ANSWER ARRIVED: the network\n * failed, the connection was reset, the host did not resolve, CORS blocked it. For a write that\n * is not a refusal (the request may have been queued), so this is the default\n * `ChainGatewayOptions.isTransportFailure` for a requestor that wraps `fetch` and rejects with\n * its own errors.\n *\n * - Yes: a `TypeError` (what `fetch` rejects with in every engine: `Failed to fetch`, `Load failed`,\n * `NetworkError when attempting to fetch resource`, undici's `fetch failed`), recognised by name\n * too so one from another realm (an extension page, an iframe) still counts, and a\n * `DOMException` named `NetworkError`.\n * - No: an abort (`AbortError`) or a timeout (`TimeoutError`). The SDK's own request layer knows\n * whether its timer or the caller's signal aborted, and reports those itself\n * (`REQUEST_TIMEOUT`, or the caller's own abort unchanged); claiming them here would turn the\n * caller's cancel into \"maybe queued\".\n * - No: anything else, including an SDK error and a value that is not an object.\n *\n * It never throws.\n *\n * @example\n * ```ts\n * new ChainGateway({ dexBackendBaseUrl, httpRequestor: galaFetch, isTransportFailure: isFetchTransportFailure });\n * ```\n */\nexport function isFetchTransportFailure(error: unknown): boolean {\n if (typeof error !== 'object' || error === null) return false;\n try {\n const name: unknown = 'name' in error ? error.name : undefined;\n if (name === 'AbortError' || name === 'TimeoutError') return false;\n return error instanceof TypeError || name === 'TypeError' || name === 'NetworkError';\n } catch {\n // A hostile or revoked object (a Proxy that throws on property access) proves nothing.\n return false;\n }\n}\n"],"mappings":"AAwBA,SAAgB,EAAwB,EAAyB,CAC/D,GAAI,OAAO,GAAU,WAAY,EAAgB,MAAO,GACxD,GAAI,CACF,IAAM,EAAgB,SAAU,EAAQ,EAAM,KAAO,IAAA,GAErD,OADI,IAAS,cAAgB,IAAS,eAAuB,GACtD,aAAiB,WAAa,IAAS,aAAe,IAAS,cACxE,MAAQ,CAEN,MAAO,EACT,CACF"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{GSwapSDKError as e,isGSwapError as t}from"../classes/gswap_sdk_error.js";import{isWalletUserRejection as n,walletDeclineCode as r}from"./wallet_rejection.js";async function i(i,a,o){let s;try{s=await i.signObject(a,o)}catch(i){if(t(i))throw i;let o=n(i)?`user_rejected`:`failed`;throw new e(`SIGNING_FAILED`,{method:a,reason:o},{cause:i,walletCode:r(i)})}if(typeof s!=`object`||!s)throw new e(`SIGNING_FAILED`,{method:a,reason:`failed`},{cause:s});return s}async function a(n,r){try{return await r()}catch(r){throw t(r)?r:new e(`TOKEN_RESOLUTION_FAILED`,{token:n},{cause:r})}}export{a as resolvePreSend,i as signPreSend};
|
|
2
|
-
//# sourceMappingURL=pre_send.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pre_send.js","names":[],"sources":["../../../src/utils/pre_send.ts"],"sourcesContent":["import { GSwapSDKError, isGSwapError } from '../classes/gswap_sdk_error.js';\nimport type { GalaChainSigner, SignedDto } from '../classes/signers.js';\nimport { isWalletUserRejection, walletDeclineCode } from './wallet_rejection.js';\n\n/**\n * The boundary of \"nothing was sent\". Every place where the SDK hands control to code the APP\n * supplied BEFORE the request leaves (the signer, the token resolver) goes through here, so a\n * failure of that code reaches the caller as a catalogued, pre-send SDK error with the original as\n * `cause`, never as a bare value the SDK cannot classify. An SDK error thrown by that code is\n * already catalogued and passes through untouched. Nothing here is used after the request has\n * been sent: an app's own rejection AFTER send stays what it is, because the SDK cannot know what\n * the server did with the write.\n */\n\n/**\n * Signs a DTO with the app's signer. Whatever the signer throws that is not already an SDK error\n * (a locked wallet, an unreachable extension, a wallet that declined) is `SIGNING_FAILED`\n * (`reason` `user_rejected` or `failed`, the original as `cause`), and a signer that returns\n * something other than an object is `SIGNING_FAILED` too: both are pre-send, so a retry is safe.\n *\n * @throws GSwapSDKError SIGNING_FAILED, or the SDK error the signer itself threw.\n */\nexport async function signPreSend<T extends Record<string, unknown>>(\n signer: GalaChainSigner,\n method: string,\n dto: T,\n): Promise<SignedDto<T>> {\n let signed: SignedDto<T>;\n try {\n signed = await signer.signObject(method, dto);\n } catch (cause: unknown) {\n if (isGSwapError(cause)) throw cause;\n const reason = isWalletUserRejection(cause) ? 'user_rejected' : 'failed';\n throw new GSwapSDKError(\n 'SIGNING_FAILED',\n { method, reason },\n { cause, walletCode: walletDeclineCode(cause) },\n );\n }\n if (typeof signed !== 'object' || signed === null) {\n throw new GSwapSDKError('SIGNING_FAILED', { method, reason: 'failed' }, { cause: signed });\n }\n return signed;\n}\n\n/**\n * Runs a token-resolution step (a resolver's `resolve` / `orderPair`, which may read the registry\n * through the app's HTTP stack). A failure that is not an SDK error is `TOKEN_RESOLUTION_FAILED`\n * (`token` names what was being resolved, the original is `cause`); an SDK error passes through.\n *\n * @throws GSwapSDKError TOKEN_RESOLUTION_FAILED, or the SDK error the step itself threw.\n */\nexport async function resolvePreSend<T>(token: string, run: () => Promise<T>): Promise<T> {\n try {\n return await run();\n } catch (cause: unknown) {\n throw isGSwapError(cause)\n ? cause\n : new GSwapSDKError('TOKEN_RESOLUTION_FAILED', { token }, { cause });\n }\n}\n"],"mappings":"qKAsBA,eAAsB,EACpB,EACA,EACA,EACuB,CACvB,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,EAAO,WAAW,EAAQ,CAAG,CAC9C,OAAS,EAAgB,CACvB,GAAI,EAAa,CAAK,EAAG,MAAM,EAC/B,IAAM,EAAS,EAAsB,CAAK,EAAI,gBAAkB,SAChE,MAAM,IAAI,EACR,iBACA,CAAE,SAAQ,QAAO,EACjB,CAAE,QAAO,WAAY,EAAkB,CAAK,CAAE,CAChD,CACF,CACA,GAAI,OAAO,GAAW,WAAY,EAChC,MAAM,IAAI,EAAc,iBAAkB,CAAE,SAAQ,OAAQ,QAAS,EAAG,CAAE,MAAO,CAAO,CAAC,EAE3F,OAAO,CACT,CASA,eAAsB,EAAkB,EAAe,EAAmC,CACxF,GAAI,CACF,OAAO,MAAM,EAAI,CACnB,OAAS,EAAgB,CACvB,MAAM,EAAa,CAAK,EACpB,EACA,IAAI,EAAc,0BAA2B,CAAE,OAAM,EAAG,CAAE,OAAM,CAAC,CACvE,CACF"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{GSwapSDKError as e}from"../classes/gswap_sdk_error.js";import{secp256k1 as t}from"@noble/curves/secp256k1";import{keccak_256 as n}from"@noble/hashes/sha3";import{bytesToHex as r}from"@noble/hashes/utils";const i=new TextEncoder;function a(e){if(e==null)return e;if(e instanceof RegExp)return e.toString();let t=e;return typeof t.toJSON==`function`?Reflect.apply(t.toJSON,e,[]):e}function o(e){let t=a(e);if(t===void 0)return;if(typeof t!=`object`||!t)return JSON.stringify(t);if(Array.isArray(t))return`[${t.map(e=>o(e)??`null`).join(`,`)}]`;let n=t,r=[];for(let e of Object.keys(n).sort()){let t=o(n[e]);t!==void 0&&r.push(`${JSON.stringify(e)}:${t}`)}return`{${r.join(`,`)}}`}function s(e){JSON.stringify(e);let t=o(e);if(t===void 0)throw TypeError(`Cannot serialize a value with no JSON representation.`);return t}function c(e){let{prefix:t,...n}=e;return delete n.signature,delete n.multisig,delete n.trace,(typeof t==`string`?t:``)+s(n)}const l=`Ethereum Signed Message:
|
|
2
|
-
`;function u(e){return l+String(i.encode(e).length)}function d(e){let t={...e};return delete t.prefix,u(s(t))}function f(e){let t={...e};delete t.prefix;let n=i.encode(c(t)).length,r=l+String(n),a=-1;for(;n!==a;)a=n,r=l+String(n),n=i.encode(c({...t,prefix:r})).length;return r}function p(t){return new e(`INVALID_PRIVATE_KEY`,{reason:t})}function m(e){if(!/^[A-Za-z0-9+/]+={0,2}$/u.test(e)||e.length%4!=0)return;let t=e.replace(/=+$/u,``),n=[],r=0,i=0;for(let e of t)r=r<<6|`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`.indexOf(e),i+=6,i>=8&&(i-=8,n.push(r>>i&255));return Uint8Array.from(n)}function h(e){let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n+=1)t[n]=parseInt(e.slice(n*2,n*2+2),16);return t}function g(e){if(typeof e!=`string`){if(!(e instanceof Uint8Array)||e.length!==32)throw p(`wrong_length`);if(!t.utils.isValidSecretKey(e))throw p(`not_on_curve`);return Uint8Array.from(e)}let n=e.startsWith(`0x`)?e.slice(2):e,r;if(/^[0-9a-fA-F]{63,64}$/u.test(n)?r=h(n.length===63?`0${n}`:n):n.length===44&&(r=m(n)),r?.length!==32)throw p(`bad_encoding`);if(!t.utils.isValidSecretKey(r))throw p(`not_on_curve`);return r}function _(n,i){if(i.length!==32)throw new e(`INVALID_SIGNING_HASH_LENGTH`,{length:i.length});let a=t.sign(i,n,{prehash:!1,lowS:!0});return r(a.toBytes(`compact`))+(a.recovery===1?`1c`:`1b`)}function v(e){let i=t.getPublicKey(e,!1);return`0x${r(n(i.slice(1)).slice(-20))}`}function y(e){return n(i.encode(e))}function b(e,t){return _(e,y(t))}function x(e,t){return b(e,c(t))}function S(e,t,n){return _(e,y(t+n))}export{u as calculatePersonalSignPrefix,v as ethAddressOfPrivateKey,f as fixpointPrefixFor,c as getPayloadToSign,y as keccak256Utf8,g as normalizePrivateKey,d as personalSignPrefixFor,s as serialize,_ as signHash,x as signNative,S as signPersonalMessage,b as signSerializedNative};
|
|
3
|
-
//# sourceMappingURL=signing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signing.js","names":[],"sources":["../../../src/utils/signing.ts"],"sourcesContent":["/**\n * SDK-owned signing primitives.\n *\n * Everything the SDK needs to produce a GalaChain signature lives here, with no dependency on\n * `@gala-chain/api` (which drags `secp256k1` native bindings, `reflect-metadata`, `class-validator`\n * and its own `bignumber.js` major into every consumer). The only runtime dependencies are the\n * audited, pure-JS `@noble/curves` (secp256k1) and `@noble/hashes` (keccak256), which run\n * unchanged in browsers, MV3 service workers, Node and React Native/Hermes.\n *\n * Every function here is pinned byte-for-byte to the signatures produced by `@gala-chain/api`\n * (`serialize`, `signatures.getSignature`), `@gala-chain/connect`, the Gala Wallet extension and\n * frontend_v2 by the golden-vector suite in `tests/signing-golden.test.ts`.\n */\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { bytesToHex } from '@noble/hashes/utils';\nimport type { InvalidPrivateKeyReason } from '../classes/error_catalog.js';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\n\nconst textEncoder = new TextEncoder();\n\nfunction toDeterministicNode(node: unknown): unknown {\n if (node === null || node === undefined) return node;\n if (node instanceof RegExp) return node.toString();\n const candidate = node as { toJSON?: unknown };\n return typeof candidate.toJSON === 'function'\n ? (Reflect.apply(candidate.toJSON, node, []) as unknown)\n : node;\n}\n\nfunction deterministicNode(rawNode: unknown): string | undefined {\n const node = toDeterministicNode(rawNode);\n if (node === undefined) return undefined;\n if (typeof node !== 'object' || node === null) return JSON.stringify(node);\n\n if (Array.isArray(node)) {\n const items = (node as unknown[]).map((item) => deterministicNode(item) ?? 'null');\n return `[${items.join(',')}]`;\n }\n\n const record = node as Record<string, unknown>;\n const members: string[] = [];\n for (const key of Object.keys(record).sort()) {\n const value = deterministicNode(record[key]);\n if (value === undefined) continue;\n members.push(`${JSON.stringify(key)}:${value}`);\n }\n return `{${members.join(',')}}`;\n}\n\n/**\n * GalaChain's deterministic JSON: object keys sorted (UTF-16 code-unit order) at every depth, no\n * whitespace, `undefined`/function members dropped, `toJSON()` honored. Byte-identical to\n * `serialize` from `@gala-chain/api` / `json-stringify-deterministic` for every JSON-shaped\n * value, which is all a DTO ever is.\n *\n * @throws TypeError for circular structures and BigInt values (as `JSON.stringify` does) and\n * when the value itself has no JSON representation (`undefined`, a function, a symbol).\n */\nexport function serialize(value: unknown): string {\n // Same cycle/BigInt guard json-stringify-deterministic runs before walking the value.\n JSON.stringify(value);\n const result = deterministicNode(value);\n if (result === undefined) {\n throw new TypeError('Cannot serialize a value with no JSON representation.');\n }\n return result;\n}\n\n/**\n * The exact string GalaChain hashes for a DTO: the (optional, string) `prefix` field PREPENDED to\n * the deterministic serialization of the DTO WITHOUT `signature`, `multisig`, `trace` and `prefix`.\n * Equivalent to `@gala-chain/api` 3.x `getPayloadToSign` for every non-EIP-712 DTO.\n */\nexport function getPayloadToSign(dto: Record<string, unknown>): string {\n const { prefix, ...rest } = dto;\n delete rest['signature'];\n delete rest['multisig'];\n delete rest['trace'];\n const head = typeof prefix === 'string' ? prefix : '';\n return head + serialize(rest);\n}\n\n// Built via String.fromCharCode rather than a literal escape ON PURPOSE: a literal control byte in\n// source is invisible and fragile under editors/diffs/copy-paste; this keeps the source ordinary.\nconst ETHEREUM_SIGNED_MESSAGE = String.fromCharCode(0x19) + 'Ethereum Signed Message:\\n';\n\n/**\n * The EIP-191 header for `message`: `\"\\x19Ethereum Signed Message:\\n\"` + the message's UTF-8 BYTE\n * length. This is what a wallet's `personal_sign` prepends, and what the chain recomputes when it\n * recovers a personal-signed DTO.\n */\nexport function calculatePersonalSignPrefix(message: string): string {\n return ETHEREUM_SIGNED_MESSAGE + String(textEncoder.encode(message).length);\n}\n\n/**\n * The EIP-191 header for `serialize(dto)` (any `prefix` already on the DTO is ignored). This is\n * deliberately the same string the signers hand a wallet to sign, so the header's length can never\n * disagree with the signed message. Wallet-neutral: it is the value both a browser wallet's\n * `personal_sign` and Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepend.\n */\nexport function personalSignPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n return calculatePersonalSignPrefix(serialize(withoutPrefix));\n}\n\n/**\n * The `@gala-chain/connect`-style prefix frontend_v2 puts in the body of an EIP-712 write: the\n * EIP-191 header whose number counts the prefix string ITSELF plus the body (the UTF-8 length of\n * `getPayloadToSign({ ...dto, prefix })`), found by fixpoint because adding the prefix changes the\n * length (a body of 99 bytes settles on 101).\n *\n * It is NOT a personal-sign prefix (a personal-sign write with this value recovers a phantom\n * signer; use `personalSignPrefixFor`). Under EIP-712 the field is an untyped extra that the\n * typed-data hash ignores and defi-backend recomputes, so it only exists to keep the submitted\n * body byte-identical to what frontend_v2 has always sent.\n */\nexport function fixpointPrefixFor(dto: Record<string, unknown>): string {\n const withoutPrefix: Record<string, unknown> = { ...dto };\n delete withoutPrefix['prefix'];\n let payloadLength = textEncoder.encode(getPayloadToSign(withoutPrefix)).length;\n let prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n let previousLength = -1;\n while (payloadLength !== previousLength) {\n previousLength = payloadLength;\n prefix = ETHEREUM_SIGNED_MESSAGE + String(payloadLength);\n payloadLength = textEncoder.encode(getPayloadToSign({ ...withoutPrefix, prefix })).length;\n }\n return prefix;\n}\n\nfunction invalidPrivateKey(reason: InvalidPrivateKeyReason): GSwapSDKError<'INVALID_PRIVATE_KEY'> {\n return new GSwapSDKError('INVALID_PRIVATE_KEY', { reason });\n}\n\nconst BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nfunction decodeBase64(input: string): Uint8Array | undefined {\n if (!/^[A-Za-z0-9+/]+={0,2}$/u.test(input) || input.length % 4 !== 0) return undefined;\n const unpadded = input.replace(/=+$/u, '');\n const bytes: number[] = [];\n let buffer = 0;\n let bits = 0;\n for (const char of unpadded) {\n buffer = (buffer << 6) | BASE64_ALPHABET.indexOf(char);\n bits += 6;\n if (bits >= 8) {\n bits -= 8;\n bytes.push((buffer >> bits) & 0xff);\n }\n }\n return Uint8Array.from(bytes);\n}\n\nfunction decodeHex(input: string): Uint8Array {\n const bytes = new Uint8Array(input.length / 2);\n for (let index = 0; index < bytes.length; index += 1) {\n bytes[index] = parseInt(input.slice(index * 2, index * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Normalizes a secp256k1 private key to a fresh 32-byte array (the caller may zero it). Also\n * accepts 32 raw bytes, which are validated and copied. For strings it accepts what `@gala-chain/api`'s\n * `normalizePrivateKey` accepted for a usable key: 64 hex characters (optionally `0x`-prefixed;\n * a 63-character hex key is left-padded with a zero) or a 44-character base64 string.\n *\n * @throws GSwapSDKError (`INVALID_PRIVATE_KEY`; `params.reason` is one of\n * `INVALID_PRIVATE_KEY_REASONS`: `wrong_length` for raw bytes that are not 32 long,\n * `bad_encoding` for any other string shape, `not_on_curve` for an out-of-range scalar).\n */\nexport function normalizePrivateKey(input: string | Uint8Array): Uint8Array {\n if (typeof input !== 'string') {\n // Raw bytes: validated, then COPIED, so zeroing the result never touches the caller's array.\n if (!(input instanceof Uint8Array) || input.length !== 32) {\n throw invalidPrivateKey('wrong_length');\n }\n if (!secp256k1.utils.isValidSecretKey(input)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return Uint8Array.from(input);\n }\n const withoutPrefix = input.startsWith('0x') ? input.slice(2) : input;\n let key: Uint8Array | undefined;\n if (/^[0-9a-fA-F]{63,64}$/u.test(withoutPrefix)) {\n key = decodeHex(withoutPrefix.length === 63 ? `0${withoutPrefix}` : withoutPrefix);\n } else if (withoutPrefix.length === 44) {\n key = decodeBase64(withoutPrefix);\n }\n if (key?.length !== 32) {\n throw invalidPrivateKey('bad_encoding');\n }\n if (!secp256k1.utils.isValidSecretKey(key)) {\n throw invalidPrivateKey('not_on_curve');\n }\n return key;\n}\n\n/**\n * Signs a 32-byte keccak256 hash and returns GalaChain's recoverable signature: 64 hex `r` +\n * 64 hex `s` + `1b`/`1c` (`v`), lowercase, no `0x`. Deterministic (RFC 6979) and low-S, exactly\n * what `@gala-chain/api` and the Gala Wallet produce. A DER signature carries no recovery byte\n * and cannot be used: the chain RECOVERS the signer from the signature.\n */\nexport function signHash(privateKey: Uint8Array, hash: Uint8Array): string {\n if (hash.length !== 32) {\n throw new GSwapSDKError('INVALID_SIGNING_HASH_LENGTH', { length: hash.length });\n }\n const signature = secp256k1.sign(hash, privateKey, { prehash: false, lowS: true });\n // compact raw bytes are r (32) || s (32); the recovery id becomes v.\n return bytesToHex(signature.toBytes('compact')) + (signature.recovery === 1 ? '1c' : '1b');\n}\n\n/**\n * The lowercase `0x` Ethereum address (last 20 bytes of keccak256 of the uncompressed public key)\n * of a normalized private key. The Gala `eth|` identity of a key is this address.\n */\nexport function ethAddressOfPrivateKey(privateKey: Uint8Array): string {\n const publicKey = secp256k1.getPublicKey(privateKey, false);\n return `0x${bytesToHex(keccak_256(publicKey.slice(1)).slice(-20))}`;\n}\n\n/** keccak256 of a string's UTF-8 bytes. */\nexport function keccak256Utf8(data: string): Uint8Array {\n return keccak_256(textEncoder.encode(data));\n}\n\n/**\n * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes, with no\n * prefix and no signature envelope. The caller owns serialization, so the bytes shown to a user\n * and the bytes signed can never diverge.\n */\nexport function signSerializedNative(privateKey: Uint8Array, serializedDto: string): string {\n return signHash(privateKey, keccak256Utf8(serializedDto));\n}\n\n/**\n * GalaChain NATIVE signature for a DTO: keccak256 of `getPayloadToSign(dto)`, signed with\n * secp256k1. Byte-identical to `signatures.getSignature` from `@gala-chain/api`.\n */\nexport function signNative(privateKey: Uint8Array, dto: Record<string, unknown>): string {\n return signSerializedNative(privateKey, getPayloadToSign(dto));\n}\n\n/**\n * Personal-sign hash and signature: keccak256(`prefix` + `message`), both hashed VERBATIM with no\n * further EIP-191 wrapping. Passing `prefix = calculatePersonalSignPrefix(message)` reproduces a\n * wallet's `personal_sign` of `message`. Gala Wallet's `gala_signChainDto` (personal-sign\n * scheme) hashes `prefix` + the exact string it is handed, which can differ from the bare message\n * (see the `signatureOverPrefixlessBody` vectors); that quirk is why the two inputs stay separate.\n */\nexport function signPersonalMessage(\n privateKey: Uint8Array,\n prefix: string,\n message: string,\n): string {\n return signHash(privateKey, keccak256Utf8(prefix + message));\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{GSwapSDKError as e,parseJson as t}from"../classes/gswap_sdk_error.js";import"../version.js";function n(e,t){if(t===1/0)return()=>void 0;let n=setTimeout(()=>e.abort(),t);return()=>clearTimeout(n)}function r(t,n){if(t===1/0||Number.isFinite(t)&&t>0)return t;throw new e(`INVALID_TIMEOUT`,{field:n,value:t})}const i=/[A-Za-z0-9\-._~!'()*$|:,]/u;function a(e){let t=``;for(let n of e)n===` `?t+=`+`:i.test(n)?t+=n:t+=o(n);return t}function o(e){try{return encodeURIComponent(e)}catch{return`%EF%BF%BD`}}function s(e,t=`standard`){return t===`readable`?Object.entries(e).map(([e,t])=>`${a(e)}=${a(t)}`).join(`&`):new URLSearchParams(e).toString()}function c(e,t={}){let n=/* @__PURE__ */ new Map,r=(e,t=!1)=>{for(let[r,i]of Object.entries(e??{}))t&&n.delete(r.toLowerCase()),n.set(r.toLowerCase(),[r,i])};return e?.userAgent!==!1&&r({"User-Agent":e?.userAgent??`GalaChain-SDK/1.2.0`}),r(t.defaults),r(e?.headers),t.json===!0&&!n.has(`content-type`)&&r({"Content-Type":`application/json`}),r(t.fixed,!0),Object.fromEntries(n.values())}const l=async(t,n)=>{try{return await fetch(t,n)}catch(r){throw n?.signal?.aborted===!0?r:new e(`TRANSPORT_ERROR`,{url:t},{url:t,cause:r})}};async function u(t,r,i,a){let o=new AbortController,s=n(o,a),c=i.signal,l=()=>o.abort();c?.addEventListener(`abort`,l,{once:!0});try{return await t(r,{...i,signal:o.signal})}catch(t){throw c?.aborted===!0?t:o.signal.aborted?new e(`REQUEST_TIMEOUT`,{url:r,timeoutMs:a},{url:r,cause:t}):t}finally{s(),c?.removeEventListener(`abort`,l)}}async function d(e){let n=await e.text();return t(n)??n}function f(e,t){let n=e.headers;if(n===void 0)return;if(h(n)){let e=n.get(t);return e===null||e===``?void 0:e}let r=Object.entries(n).find(([e])=>e.toLowerCase()===t.toLowerCase())?.[1];return r===void 0||r===``?void 0:r}function p(e){let t=f(e,`retry-after`);if(t===void 0)return;let n=Number(t);if(Number.isFinite(n)&&n>=0)return n*1e3;let r=Date.parse(t);return Number.isNaN(r)?void 0:Math.max(0,r-Date.now())}function m(e,t=`x-block-number`){let n=f(e,t);if(n===void 0)return;let r=Number(n);return Number.isInteger(r)&&r>=0?r:void 0}function h(e){return`get`in e&&typeof e.get==`function`}export{n as armTimeout,s as buildQueryString,c as buildRequestHeaders,l as fetchRequestor,m as readBlockNumberHeader,f as readHeader,d as readResponseBody,p as readRetryAfter,u as requestWithTimeout,r as validateTimeoutMs};
|
|
2
|
-
//# sourceMappingURL=transport.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transport.js","names":[],"sources":["../../../src/utils/transport.ts"],"sourcesContent":["import type { HTTPResponse, HttpRequestor } from '../types/http_requestor.js';\nimport type { WireOptions } from '../types/wire.js';\nimport { GSwapSDKError, parseJson } from '../classes/gswap_sdk_error.js';\nimport { SDK_VERSION } from '../version.js';\n\n/**\n * Arms the abort timer for a request. `Infinity` means \"never time out\": `setTimeout` would turn\n * it into 1 ms, so no timer is armed at all. Returns a function that disarms it.\n */\nexport function armTimeout(controller: AbortController, timeoutMs: number): () => void {\n if (timeoutMs === Infinity) return () => undefined;\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n return () => clearTimeout(timer);\n}\n\n/**\n * Validates a request timeout in milliseconds: a positive finite number, or `Infinity` for none.\n *\n * @throws GSwapSDKError `INVALID_TIMEOUT` (`params.field` = `name`) otherwise.\n */\nexport function validateTimeoutMs(timeoutMs: number, name: string): number {\n if (timeoutMs === Infinity || (Number.isFinite(timeoutMs) && timeoutMs > 0)) return timeoutMs;\n throw new GSwapSDKError('INVALID_TIMEOUT', { field: name, value: timeoutMs });\n}\n\nconst READABLE_QUERY_SAFE = /[A-Za-z0-9\\-._~!'()*$|:,]/u;\n\nfunction encodeReadable(text: string): string {\n let out = '';\n for (const char of text) {\n if (char === ' ') out += '+';\n else if (READABLE_QUERY_SAFE.test(char)) out += char;\n else out += encodeScalar(char);\n }\n return out;\n}\n\n/** Percent-encodes one code point; a lone surrogate becomes U+FFFD, as `URLSearchParams` does. */\nfunction encodeScalar(char: string): string {\n try {\n return encodeURIComponent(char);\n } catch {\n return '%EF%BF%BD';\n }\n}\n\n/** Serializes GET parameters, in insertion order, in the encoding the wire options select. */\nexport function buildQueryString(\n params: Record<string, string>,\n encoding: WireOptions['queryEncoding'] = 'standard',\n): string {\n if (encoding === 'readable') {\n return Object.entries(params)\n .map(([key, value]) => `${encodeReadable(key)}=${encodeReadable(value)}`)\n .join('&');\n }\n return new URLSearchParams(params).toString();\n}\n\n/** What an SDK request adds to the headers the wire options describe. */\nexport interface RequestHeaderParts {\n /** The request carries a JSON body: `Content-Type: application/json` unless `wire.headers` sets one. */\n json?: boolean | undefined;\n /** Headers the SDK sends unless `wire.headers` replaces them (for example `Accept`). */\n defaults?: Record<string, string> | undefined;\n /**\n * Headers that carry the request's meaning (`X-Wallet-Address`, `X-Shadow`). They come last and\n * replace a same-named `wire.headers` entry, so an app's static headers can never re-attribute\n * or un-shadow a write.\n */\n fixed?: Record<string, string> | undefined;\n}\n\n/**\n * The request headers for ANY SDK request, GET or POST, from one place so the wire options reach\n * every request alike. Order, which is the order the requestor sees them in: `User-Agent`\n * (`wire.userAgent`, default `GalaChain-SDK/<version>`, `false` omits it), `parts.defaults`,\n * `wire.headers`, `Content-Type` (JSON bodies only), `parts.fixed`. A later entry replaces an\n * earlier one of the same name regardless of case, so a header is never sent twice.\n */\nexport function buildRequestHeaders(\n wire: WireOptions | undefined,\n parts: RequestHeaderParts = {},\n): Record<string, string> {\n const entries = new Map<string, [name: string, value: string]>();\n const put = (headers: Record<string, string> | undefined, last = false): void => {\n for (const [name, value] of Object.entries(headers ?? {})) {\n // A fixed header leaves any earlier same-named entry behind, so it also keeps its place at the end.\n if (last) entries.delete(name.toLowerCase());\n entries.set(name.toLowerCase(), [name, value]);\n }\n };\n if (wire?.userAgent !== false) {\n put({ 'User-Agent': wire?.userAgent ?? `GalaChain-SDK/${SDK_VERSION}` });\n }\n put(parts.defaults);\n put(wire?.headers);\n if (parts.json === true && !entries.has('content-type')) {\n put({ 'Content-Type': 'application/json' });\n }\n put(parts.fixed, true);\n return Object.fromEntries(entries.values());\n}\n\n/**\n * The default requestor: the global `fetch`, with a failure before any answer (offline, DNS,\n * CORS) coded as `TRANSPORT_ERROR` and the original error kept as `cause`. An aborted request is\n * left to {@link requestWithTimeout}, which knows whether the timeout or the caller aborted it.\n * A requestor the app supplies is not wrapped: its rejection reaches the caller unchanged.\n */\nexport const fetchRequestor: HttpRequestor = async (url, init) => {\n try {\n return await fetch(url, init);\n } catch (error: unknown) {\n if (init?.signal?.aborted === true) throw error;\n throw new GSwapSDKError('TRANSPORT_ERROR', { url }, { url, cause: error });\n }\n};\n\nexport async function requestWithTimeout(\n requestor: HttpRequestor,\n url: string,\n options: RequestInit,\n timeoutMs: number,\n): Promise<HTTPResponse> {\n const controller = new AbortController();\n const disarm = armTimeout(controller, timeoutMs);\n const externalSignal = options.signal;\n const abortFromCaller = (): void => controller.abort();\n externalSignal?.addEventListener('abort', abortFromCaller, { once: true });\n try {\n return await requestor(url, { ...options, signal: controller.signal });\n } catch (error: unknown) {\n // The caller's own abort is theirs: it passes through as the abort it is, never as a timeout.\n if (externalSignal?.aborted === true) throw error;\n if (controller.signal.aborted) {\n throw new GSwapSDKError('REQUEST_TIMEOUT', { url, timeoutMs }, { url, cause: error });\n }\n // Anything else is the requestor's own rejection (an app's axios interceptor error, say):\n // rethrown as it is, because the app's error handling produced it.\n throw error;\n } finally {\n disarm();\n externalSignal?.removeEventListener('abort', abortFromCaller);\n }\n}\n\nexport async function readResponseBody(response: HTTPResponse): Promise<unknown> {\n const text = await response.text();\n return parseJson(text) ?? text;\n}\n\n/** Read a case-insensitive response header from either supported header shape. */\nexport function readHeader(response: HTTPResponse, name: string): string | undefined {\n const headers = response.headers;\n if (headers === undefined) return undefined;\n if (hasHeaderGetter(headers)) {\n const value = headers.get(name);\n return value === null || value === '' ? undefined : value;\n }\n const value = Object.entries(headers).find(\n ([key]) => key.toLowerCase() === name.toLowerCase(),\n )?.[1];\n return value === undefined || value === '' ? undefined : value;\n}\n\n/** Read a Retry-After header (delta-seconds or an HTTP date) as non-negative milliseconds. */\nexport function readRetryAfter(response: HTTPResponse): number | undefined {\n const raw = readHeader(response, 'retry-after');\n if (raw === undefined) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000;\n const timestamp = Date.parse(raw);\n return Number.isNaN(timestamp) ? undefined : Math.max(0, timestamp - Date.now());\n}\n\n/** Read a non-negative integer block number header. */\nexport function readBlockNumberHeader(\n response: HTTPResponse,\n headerName = 'x-block-number',\n): number | undefined {\n const raw = readHeader(response, headerName);\n if (raw === undefined) return undefined;\n const blockNumber = Number(raw);\n return Number.isInteger(blockNumber) && blockNumber >= 0 ? blockNumber : undefined;\n}\n\nfunction hasHeaderGetter(\n headers: NonNullable<HTTPResponse['headers']>,\n): headers is { get(name: string): string | null } {\n return 'get' in headers && typeof headers.get === 'function';\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{GSwapSDKError as e}from"../classes/gswap_sdk_error.js";import{signHash as t}from"./signing.js";import{withPrivateKey as n}from"./chain_dto_signing.js";import{keccak_256 as r}from"@noble/hashes/sha3";const i=new TextEncoder,a=/^[A-Za-z_$][A-Za-z0-9_$]*$/u,o=/^([A-Za-z_$][A-Za-z0-9_$]*)((?:\[(?:0|[1-9][0-9]*)?\])*)$/u,s=/^-?[0-9]+$/u,c=/^-?0x[0-9a-fA-F]+$/u,l=[{name:`name`,type:`string`},{name:`version`,type:`string`},{name:`chainId`,type:`uint256`},{name:`verifyingContract`,type:`address`},{name:`salt`,type:`bytes32`}];function u(e){let t=new Uint8Array(e.reduce((e,t)=>e+t.length,0)),n=0;for(let r of e)t.set(r,n),n+=r.length;return t}function d(e){let t=/* @__PURE__ */ new Uint8Array(32),n=e<0n?e+(1n<<256n):e;for(let e=31;e>=0;--e)t[e]=Number(n&255n),n>>=8n;return t}function f(e){let t=e.slice(2),n=new Uint8Array(t.length/2);for(let e=0;e<n.length;e+=1)n[e]=parseInt(t.slice(e*2,e*2+2),16);return n}function p(t,n){if(t instanceof Uint8Array)return t;if(typeof t==`string`&&/^0x(?:[0-9a-fA-F]{2})*$/u.test(t))return f(t);throw new e(`TYPED_DATA_NOT_HEX_BYTES`,{what:n})}function m(t,n){if(typeof t==`bigint`)return t;if(typeof t==`number`){if(!Number.isSafeInteger(t))throw new e(`TYPED_DATA_NOT_SAFE_INTEGER`,{what:n});return BigInt(t)}if(typeof t==`string`){if(s.test(t))return BigInt(t);if(c.test(t))return t.startsWith(`-`)?-BigInt(t.slice(1)):BigInt(t)}throw new e(`TYPED_DATA_NOT_INTEGER`,{what:n})}function h(t,n){if(typeof t!=`string`)throw new e(`TYPED_DATA_NOT_STRING`,{what:n});for(let r=0;r<t.length;r+=1){let i=t.charCodeAt(r);if(i>=55296&&i<=56319){let i=t.charCodeAt(r+1);if(!(i>=56320&&i<=57343))throw new e(`TYPED_DATA_UNPAIRED_SURROGATE`,{what:n});r+=1}else if(i>=56320&&i<=57343)throw new e(`TYPED_DATA_UNPAIRED_SURROGATE`,{what:n})}return i.encode(t)}function g(t){if(typeof t!=`string`||!/^0x[0-9a-fA-F]{40}$/u.test(t))throw new e(`TYPED_DATA_BAD_ADDRESS`,{});let n=t.slice(2);if(/[A-F]/u.test(n)&&/[a-f]/u.test(n)){let t=r(i.encode(n.toLowerCase()));for(let r=0;r<40;r+=1){let i=t[r>>1]>>(r%2==0?4:0)&15,a=n.charAt(r);if(a!==(i>=8?a.toUpperCase():a.toLowerCase()))throw new e(`TYPED_DATA_BAD_CHECKSUM`,{})}}return f(t)}function _(t){if(t===`string`)return e=>r(h(e,`string`));if(t===`bytes`)return e=>r(p(e,`bytes`));if(t===`bool`)return t=>{if(typeof t!=`boolean`)throw new e(`TYPED_DATA_NOT_BOOLEAN`,{});return d(t?1n:0n)};if(t===`address`)return e=>u([/* @__PURE__ */ new Uint8Array(12),g(e)]);let n=/^bytes([1-9][0-9]?)$/u.exec(t);if(n!==null){let r=Number(n[1]);return r>32||String(r)!==n[1]?void 0:n=>{let i=p(n,t);if(i.length!==r)throw new e(`TYPED_DATA_BYTES_LENGTH`,{type:t,width:r});return u([i,new Uint8Array(32-r)])}}let i=/^(u?)int([1-9][0-9]*)$/u.exec(t);if(i!==null){let n=Number(i[2]);if(n%8!=0||n>256||String(n)!==i[2])return;let r=i[1]===``,a=r?-(1n<<BigInt(n-1)):0n,o=r?(1n<<BigInt(n-1))-1n:(1n<<BigInt(n))-1n;return n=>{let r=m(n,t);if(r<a||r>o)throw new e(`TYPED_DATA_OUT_OF_BOUNDS`,{type:t});return d(r)}}}function v(t){let n=o.exec(t);if(n===null)throw new e(`TYPED_DATA_UNSUPPORTED_TYPE`,{type:t});let r=[...(n[2]??``).matchAll(/\[([0-9]*)\]/gu)].map(e=>e[1]===``?-1:Number(e[1]));return{base:n[1],dimensions:r}}function y(t,n){if(!Array.isArray(n))throw new e(`TYPED_DATA_FIELDS_NOT_LIST`,{typeName:t});let r=/* @__PURE__ */ new Set;return n.map(n=>{let i=n;if(typeof i?.name!=`string`||typeof i.type!=`string`)throw new e(`TYPED_DATA_FIELD_MALFORMED`,{typeName:t});if(!a.test(i.name))throw new e(`TYPED_DATA_INVALID_FIELD_NAME`,{name:i.name});if(r.has(i.name))throw new e(`TYPED_DATA_DUPLICATE_FIELD`,{name:i.name,typeName:t});r.add(i.name);let o=v(i.type),s=o.base===`uint`||o.base===`int`?`${o.base}256`:o.base;return{name:i.name,type:s+i.type.slice(o.base.length)}})}function b(t){let n=Object.keys(t),o=/* @__PURE__ */ new Map;for(let r of n){if(!a.test(r))throw new e(`TYPED_DATA_INVALID_TYPE_NAME`,{name:r});o.set(r,y(r,t[r]))}let s=/* @__PURE__ */ new Map,c=/* @__PURE__ */ new Map;for(let e of n)s.set(e,/* @__PURE__ */ new Set),c.set(e,/* @__PURE__ */ new Set);for(let[t,n]of o)for(let r of n){let{base:n}=v(r.type);if(n===t)throw new e(`TYPED_DATA_CIRCULAR_TYPE`,{typeName:t});if(_(n)===void 0){if(!o.has(n))throw new e(`TYPED_DATA_UNKNOWN_FIELD_TYPE`,{type:n,typeName:t});s.get(t)?.add(n),c.get(n)?.add(t)}}let l=n.filter(e=>c.get(e)?.size===0);if(l.length===0)throw new e(`TYPED_DATA_NO_PRIMARY_TYPE`,{});if(l.length>1)throw new e(`TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE`,{roots:l.join(`, `)});let d=l[0],f=/* @__PURE__ */ new Set,p=/* @__PURE__ */ new Set,m=t=>{if(f.has(t))throw new e(`TYPED_DATA_CIRCULAR_TYPE`,{typeName:t});if(!p.has(t)){f.add(t);for(let e of s.get(t)??[])m(e);f.delete(t),p.add(t)}};m(d);let h=(e,t)=>{for(let n of s.get(e)??[])t.has(n)||(t.add(n),h(n,t));return t},g=e=>`${e}(${(o.get(e)??[]).map(e=>`${e.type} ${e.name}`).join(`,`)})`,b=/* @__PURE__ */ new Map;for(let e of n){let t=[...h(e,/* @__PURE__ */ new Set)].filter(t=>t!==e).sort();b.set(e,r(i.encode([e,...t].map(g).join(``))))}let x=(t,n,i)=>{let a=t.dimensions[t.dimensions.length-1-i];if(a!==void 0){if(!Array.isArray(n))throw new e(`TYPED_DATA_ARRAY_EXPECTED`,{type:t.base});if(a!==-1&&a!==n.length)throw new e(`TYPED_DATA_ARRAY_LENGTH_MISMATCH`,{});return r(u(n.map(e=>x(t,e,i+1))))}let o=_(t.base);return o===void 0?S(t.base,n):o(n)};function S(t,n){let i=o.get(t),a=b.get(t);if(i===void 0||a===void 0)throw Error(`Internal error: no encoder for struct ${t}`);if(typeof n!=`object`||!n||Array.isArray(n))throw new e(`TYPED_DATA_STRUCT_NOT_OBJECT`,{typeName:t});let s=n,c=i.map(n=>{if(!Object.prototype.hasOwnProperty.call(s,n.name))throw new e(`TYPED_DATA_MISSING_FIELD`,{typeName:t,field:n.name});return x(v(n.type),s[n.name],0)});return r(u([a,...c]))}return{primaryType:d,hashStruct:S}}function x(t){if(typeof t!=`object`||!t||Array.isArray(t))throw new e(`TYPED_DATA_DOMAIN_NOT_OBJECT`,{});for(let n of Object.keys(t))if(!l.some(e=>e.name===n))throw new e(`TYPED_DATA_INVALID_DOMAIN_KEY`,{key:JSON.stringify(n)});return b({EIP712Domain:l.filter(e=>Object.prototype.hasOwnProperty.call(t,e.name))}).hashStruct(`EIP712Domain`,t)}function S(e){let t=x(e.domain),n=b(e.types),i=n.hashStruct(n.primaryType,e.message);return r(u([Uint8Array.of(25,1),t,i]))}async function C(e,r){let i=S(r);return n(e,e=>`0x${t(e,i)}`)}export{S as hashTypedData,C as signTypedDataPayload};
|
|
2
|
-
//# sourceMappingURL=typed_data.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"typed_data.js","names":[],"sources":["../../../src/utils/typed_data.ts"],"sourcesContent":["/**\n * EIP-712 (`eth_signTypedData_v4`) hashing and signing for ARBITRARY dApp typed data, built on the\n * SDK's own primitives (`@noble/curves`, `@noble/hashes`) so a wallet can sign a dApp's typed-data\n * approval without ethers. It replaces the wallet's `new ethers.Wallet(key).signTypedData(...)`\n * and is pinned to it: the golden suite reproduces every fixture signature exactly and a seeded\n * differential fuzz compares the digest and signature with ethers for every supported type.\n *\n * Compared with ethers this encoder is deliberately STRICTER (it fails closed rather than coerce):\n * `bool` accepts only a boolean, numbers accept only safe integers / decimal or `0x` strings,\n * strings must be well-formed UTF-16, struct values must be objects whose fields are their own\n * properties, and every struct, field and type name must be a plain identifier. Anything ethers\n * accepts that is NOT in that set is refused here instead of being signed in a different shape\n * from what a user reviewed.\n */\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { signHash } from './signing.js';\nimport { withPrivateKey, type PrivateKeyInput } from './chain_dto_signing.js';\n\n/** A typed-data payload as `eth_signTypedData_v4` carries it, minus `primaryType` (it is inferred). */\nexport interface TypedDataPayload {\n domain: Record<string, unknown>;\n /** Struct definitions WITHOUT `EIP712Domain` (see `stripEip712DomainType`). */\n types: Record<string, readonly unknown[]>;\n message: Record<string, unknown>;\n}\n\ninterface TypedField {\n name: string;\n type: string;\n}\n\nconst textEncoder = new TextEncoder();\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/u;\nconst TYPE_SYNTAX = /^([A-Za-z_$][A-Za-z0-9_$]*)((?:\\[(?:0|[1-9][0-9]*)?\\])*)$/u;\nconst BIGINT_DECIMAL = /^-?[0-9]+$/u;\nconst BIGINT_HEX = /^-?0x[0-9a-fA-F]+$/u;\n\n/** The EIP-712 domain members and their types, in the order ethers (and the spec) hash them. */\nconst DOMAIN_FIELDS: readonly TypedField[] = [\n { name: 'name', type: 'string' },\n { name: 'version', type: 'string' },\n { name: 'chainId', type: 'uint256' },\n { name: 'verifyingContract', type: 'address' },\n { name: 'salt', type: 'bytes32' },\n];\n\nfunction concat(parts: readonly Uint8Array[]): Uint8Array {\n const out = new Uint8Array(parts.reduce((total, part) => total + part.length, 0));\n let offset = 0;\n for (const part of parts) {\n out.set(part, offset);\n offset += part.length;\n }\n return out;\n}\n\nfunction bigintToWord(value: bigint): Uint8Array {\n const word = new Uint8Array(32);\n // Every caller has bounds-checked `value` against its Solidity type, so it fits in 256 bits.\n let rest = value < 0n ? value + (1n << 256n) : value;\n for (let index = 31; index >= 0; index -= 1) {\n word[index] = Number(rest & 0xffn);\n rest >>= 8n;\n }\n return word;\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const body = hex.slice(2);\n const out = new Uint8Array(body.length / 2);\n for (let index = 0; index < out.length; index += 1) {\n out[index] = parseInt(body.slice(index * 2, index * 2 + 2), 16);\n }\n return out;\n}\n\nfunction toBytes(value: unknown, what: string): Uint8Array {\n if (value instanceof Uint8Array) return value;\n if (typeof value === 'string' && /^0x(?:[0-9a-fA-F]{2})*$/u.test(value)) return hexToBytes(value);\n throw new GSwapSDKError('TYPED_DATA_NOT_HEX_BYTES', { what });\n}\n\nfunction toBigInt(value: unknown, what: string): bigint {\n if (typeof value === 'bigint') return value;\n if (typeof value === 'number') {\n if (!Number.isSafeInteger(value))\n throw new GSwapSDKError('TYPED_DATA_NOT_SAFE_INTEGER', { what });\n return BigInt(value);\n }\n if (typeof value === 'string') {\n if (BIGINT_DECIMAL.test(value)) return BigInt(value);\n if (BIGINT_HEX.test(value)) {\n return value.startsWith('-') ? -BigInt(value.slice(1)) : BigInt(value);\n }\n }\n throw new GSwapSDKError('TYPED_DATA_NOT_INTEGER', { what });\n}\n\nfunction utf8(value: unknown, what: string): Uint8Array {\n if (typeof value !== 'string') throw new GSwapSDKError('TYPED_DATA_NOT_STRING', { what });\n for (let index = 0; index < value.length; index += 1) {\n const unit = value.charCodeAt(index);\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (!(next >= 0xdc00 && next <= 0xdfff)) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n index += 1;\n } else if (unit >= 0xdc00 && unit <= 0xdfff) {\n throw new GSwapSDKError('TYPED_DATA_UNPAIRED_SURROGATE', { what });\n }\n }\n return textEncoder.encode(value);\n}\n\n/** EIP-55: a mixed-case address must carry the right checksum; all-lower / all-upper is accepted. */\nfunction addressBytes(value: unknown): Uint8Array {\n if (typeof value !== 'string' || !/^0x[0-9a-fA-F]{40}$/u.test(value)) {\n throw new GSwapSDKError('TYPED_DATA_BAD_ADDRESS', {});\n }\n const digits = value.slice(2);\n if (/[A-F]/u.test(digits) && /[a-f]/u.test(digits)) {\n const hash = keccak_256(textEncoder.encode(digits.toLowerCase()));\n for (let index = 0; index < 40; index += 1) {\n const nibble = ((hash[index >> 1] as number) >> (index % 2 === 0 ? 4 : 0)) & 0xf;\n const char = digits.charAt(index);\n const expected = nibble >= 8 ? char.toUpperCase() : char.toLowerCase();\n if (char !== expected) throw new GSwapSDKError('TYPED_DATA_BAD_CHECKSUM', {});\n }\n }\n return hexToBytes(value);\n}\n\ntype LeafEncoder = (value: unknown) => Uint8Array;\n\n/** The encoder for a non-struct, non-array type, or undefined when `base` is not one. */\nfunction leafEncoder(base: string): LeafEncoder | undefined {\n if (base === 'string') return (value) => keccak_256(utf8(value, 'string'));\n if (base === 'bytes') return (value) => keccak_256(toBytes(value, 'bytes'));\n if (base === 'bool') {\n return (value) => {\n if (typeof value !== 'boolean') throw new GSwapSDKError('TYPED_DATA_NOT_BOOLEAN', {});\n return bigintToWord(value ? 1n : 0n);\n };\n }\n if (base === 'address') {\n return (value) => concat([new Uint8Array(12), addressBytes(value)]);\n }\n const fixed = /^bytes([1-9][0-9]?)$/u.exec(base);\n if (fixed !== null) {\n const width = Number(fixed[1]);\n if (width > 32 || String(width) !== fixed[1]) return undefined;\n return (value) => {\n const bytes = toBytes(value, base);\n if (bytes.length !== width) {\n throw new GSwapSDKError('TYPED_DATA_BYTES_LENGTH', { type: base, width });\n }\n return concat([bytes, new Uint8Array(32 - width)]);\n };\n }\n const integer = /^(u?)int([1-9][0-9]*)$/u.exec(base);\n if (integer !== null) {\n const width = Number(integer[2]);\n if (width % 8 !== 0 || width > 256 || String(width) !== integer[2]) return undefined;\n const signed = integer[1] === '';\n const lower = signed ? -(1n << BigInt(width - 1)) : 0n;\n const upper = signed ? (1n << BigInt(width - 1)) - 1n : (1n << BigInt(width)) - 1n;\n return (value) => {\n const number = toBigInt(value, base);\n if (number < lower || number > upper) {\n throw new GSwapSDKError('TYPED_DATA_OUT_OF_BOUNDS', { type: base });\n }\n return bigintToWord(number);\n };\n }\n return undefined;\n}\n\ninterface ParsedType {\n base: string;\n /** Array suffixes outermost-last, e.g. `uint256[2][]` is `[2, -1]` (-1 = dynamic). */\n dimensions: number[];\n}\n\nfunction parseType(type: string): ParsedType {\n const match = TYPE_SYNTAX.exec(type);\n if (match === null) throw new GSwapSDKError('TYPED_DATA_UNSUPPORTED_TYPE', { type });\n const dimensions = [...(match[2] ?? '').matchAll(/\\[([0-9]*)\\]/gu)].map((dimension) =>\n dimension[1] === '' ? -1 : Number(dimension[1]),\n );\n return { base: match[1] as string, dimensions };\n}\n\nfunction parseFields(typeName: string, rawFields: readonly unknown[]): TypedField[] {\n if (!Array.isArray(rawFields))\n throw new GSwapSDKError('TYPED_DATA_FIELDS_NOT_LIST', { typeName });\n const seen = new Set<string>();\n return rawFields.map((raw: unknown) => {\n const field = raw as { name?: unknown; type?: unknown } | null;\n if (typeof field?.name !== 'string' || typeof field.type !== 'string') {\n throw new GSwapSDKError('TYPED_DATA_FIELD_MALFORMED', { typeName });\n }\n if (!IDENTIFIER.test(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_FIELD_NAME', { name: field.name });\n }\n if (seen.has(field.name)) {\n throw new GSwapSDKError('TYPED_DATA_DUPLICATE_FIELD', { name: field.name, typeName });\n }\n seen.add(field.name);\n // A bare `int` / `uint` is the 256-bit type and is hashed as `int256` / `uint256`, like ethers.\n const parsed = parseType(field.type);\n const base =\n parsed.base === 'uint' || parsed.base === 'int' ? `${parsed.base}256` : parsed.base;\n return { name: field.name, type: base + field.type.slice(parsed.base.length) };\n });\n}\n\ninterface StructEncoder {\n primaryType: string;\n hashStruct: (typeName: string, value: unknown) => Uint8Array;\n}\n\n/**\n * Builds the struct encoder for a set of type definitions: validates the type graph (unknown or\n * circular references, duplicate fields) and infers the primary type as the single type no other\n * type references, exactly like ethers' `TypedDataEncoder`.\n */\nfunction createStructEncoder(rawTypes: Record<string, readonly unknown[]>): StructEncoder {\n const names = Object.keys(rawTypes);\n const fields = new Map<string, TypedField[]>();\n for (const name of names) {\n if (!IDENTIFIER.test(name)) throw new GSwapSDKError('TYPED_DATA_INVALID_TYPE_NAME', { name });\n fields.set(name, parseFields(name, rawTypes[name] as readonly unknown[]));\n }\n\n const children = new Map<string, Set<string>>();\n const parents = new Map<string, Set<string>>();\n for (const name of names) {\n children.set(name, new Set());\n parents.set(name, new Set());\n }\n for (const [name, list] of fields) {\n for (const field of list) {\n const { base } = parseType(field.type);\n if (base === name) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (leafEncoder(base) !== undefined) continue;\n if (!fields.has(base)) {\n throw new GSwapSDKError('TYPED_DATA_UNKNOWN_FIELD_TYPE', { type: base, typeName: name });\n }\n children.get(name)?.add(base);\n parents.get(base)?.add(name);\n }\n }\n\n const roots = names.filter((name) => parents.get(name)?.size === 0);\n if (roots.length === 0) throw new GSwapSDKError('TYPED_DATA_NO_PRIMARY_TYPE', {});\n if (roots.length > 1) {\n throw new GSwapSDKError('TYPED_DATA_AMBIGUOUS_PRIMARY_TYPE', { roots: roots.join(', ') });\n }\n const primaryType = roots[0] as string;\n\n const visiting = new Set<string>();\n const checked = new Set<string>();\n const checkCircular = (name: string): void => {\n if (visiting.has(name)) throw new GSwapSDKError('TYPED_DATA_CIRCULAR_TYPE', { typeName: name });\n if (checked.has(name)) return;\n visiting.add(name);\n for (const child of children.get(name) ?? []) checkCircular(child);\n visiting.delete(name);\n checked.add(name);\n };\n checkCircular(primaryType);\n\n const dependencies = (name: string, found: Set<string>): Set<string> => {\n for (const child of children.get(name) ?? []) {\n if (!found.has(child)) {\n found.add(child);\n dependencies(child, found);\n }\n }\n return found;\n };\n const encodeOne = (name: string): string =>\n `${name}(${(fields.get(name) ?? []).map((field) => `${field.type} ${field.name}`).join(',')})`;\n const typeHashes = new Map<string, Uint8Array>();\n for (const name of names) {\n const sorted = [...dependencies(name, new Set())].filter((dep) => dep !== name).sort();\n typeHashes.set(name, keccak_256(textEncoder.encode([name, ...sorted].map(encodeOne).join(''))));\n }\n\n const encodeValue = (parsed: ParsedType, value: unknown, depth: number): Uint8Array => {\n // The LAST bracket written is the outermost array: `uint8[][2]` is two `uint8[]`.\n const dimension = parsed.dimensions[parsed.dimensions.length - 1 - depth];\n if (dimension !== undefined) {\n if (!Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_EXPECTED', { type: parsed.base });\n }\n if (dimension !== -1 && dimension !== value.length) {\n throw new GSwapSDKError('TYPED_DATA_ARRAY_LENGTH_MISMATCH', {});\n }\n return keccak_256(concat(value.map((item) => encodeValue(parsed, item, depth + 1))));\n }\n const leaf = leafEncoder(parsed.base);\n if (leaf !== undefined) return leaf(value);\n return hashStruct(parsed.base, value);\n };\n\n function hashStruct(typeName: string, value: unknown): Uint8Array {\n const list = fields.get(typeName);\n const typeHash = typeHashes.get(typeName);\n if (list === undefined || typeHash === undefined) {\n // createStructEncoder has already validated every struct name this is called with.\n throw new Error(`Internal error: no encoder for struct ${typeName}`);\n }\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new GSwapSDKError('TYPED_DATA_STRUCT_NOT_OBJECT', { typeName });\n }\n const record = value as Record<string, unknown>;\n const words = list.map((field) => {\n if (!Object.prototype.hasOwnProperty.call(record, field.name)) {\n throw new GSwapSDKError('TYPED_DATA_MISSING_FIELD', { typeName, field: field.name });\n }\n // Struct-valued fields are encoded to their 32-byte struct hash by encodeValue.\n return encodeValue(parseType(field.type), record[field.name], 0);\n });\n return keccak_256(concat([typeHash, ...words]));\n }\n\n return { primaryType, hashStruct };\n}\n\nfunction hashDomain(domain: Record<string, unknown>): Uint8Array {\n if (domain === null || typeof domain !== 'object' || Array.isArray(domain)) {\n throw new GSwapSDKError('TYPED_DATA_DOMAIN_NOT_OBJECT', {});\n }\n for (const key of Object.keys(domain)) {\n if (!DOMAIN_FIELDS.some((field) => field.name === key)) {\n throw new GSwapSDKError('TYPED_DATA_INVALID_DOMAIN_KEY', { key: JSON.stringify(key) });\n }\n }\n const present = DOMAIN_FIELDS.filter((field) =>\n Object.prototype.hasOwnProperty.call(domain, field.name),\n );\n const encoder = createStructEncoder({ EIP712Domain: present });\n return encoder.hashStruct('EIP712Domain', domain);\n}\n\n/**\n * The EIP-712 digest `keccak256(0x1901 || domainSeparator || hashStruct(primaryType, message))`\n * that a wallet signs for `eth_signTypedData_v4`. The primary type is inferred, as ethers does.\n *\n * @throws GSwapSDKError (`TYPED_DATA_*`) for any type graph or value it cannot encode\n * exactly (see the module note on strictness).\n */\nexport function hashTypedData(payload: TypedDataPayload): Uint8Array {\n const domainHash = hashDomain(payload.domain);\n const encoder = createStructEncoder(payload.types);\n const structHash = encoder.hashStruct(encoder.primaryType, payload.message);\n return keccak_256(concat([Uint8Array.of(0x19, 0x01), domainHash, structHash]));\n}\n\n/**\n * Signs a dApp's EIP-712 typed-data approval (the wallet's `signTypedMessage` path), replacing\n * `new ethers.Wallet(key).signTypedData(domain, types, message)`. `types` must already have\n * `EIP712Domain` removed (`stripEip712DomainType`).\n *\n * @returns `0x` + r + s + v with `v` = `0x1b`/`0x1c` (27/28): ethers' serialized signature form,\n * recoverable with `verifyTypedData` / `eth_signTypedData_v4` verifiers. Rejects (never throws\n * synchronously) on invalid input.\n */\nexport async function signTypedDataPayload(\n privateKey: PrivateKeyInput,\n payload: TypedDataPayload,\n): Promise<string> {\n const digest = hashTypedData(payload);\n return withPrivateKey(privateKey, (key) => `0x${signHash(key, digest)}`);\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{isValidUniqueKey as e}from"./unique_key_syntax.js";import{GSwapSDKError as t}from"../classes/gswap_sdk_error.js";const n=`galaswap-operation-`,r=/^[A-Za-z0-9._:-]*$/u;function i(e){if(e===void 0)return n;if(!r.test(e)||e.length>92)throw new t(`INVALID_UNIQUE_KEY_PREFIX`,{uniqueKeyPrefix:e,maxLength:92});return e}function a(n){if(!e(n))throw new t(`INVALID_UNIQUE_KEY`,{uniqueKey:String(n)})}function o(e){return`${e}${globalThis.crypto.randomUUID()}`}export{n as DEFAULT_UNIQUE_KEY_PREFIX,a as assertUniqueKey,o as createUniqueKey,i as resolveUniqueKeyPrefix};
|
|
2
|
-
//# sourceMappingURL=unique_key.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unique_key.js","names":[],"sources":["../../../src/utils/unique_key.ts"],"sourcesContent":["import { GSwapSDKError } from '../classes/gswap_sdk_error.js';\nimport { isValidUniqueKey } from './unique_key_syntax.js';\n\n/**\n * The `uniqueKey` prefix frontend_v2 and wallet_extension have always sent\n * (`galaswap-operation-<uuid>`). defi-backend does not depend on it: the chain-write verifier\n * only requires a non-empty key of at most 256 characters, and apply-results accepts\n * `[A-Za-z0-9._:-]{1,128}`; the only code that mints a prefixed key itself is the server-side v1\n * trade builder, which nothing reads back by prefix.\n */\nexport const DEFAULT_UNIQUE_KEY_PREFIX = 'galaswap-operation-';\n\n/** Options shared by the services that mint `uniqueKey`s for writes. */\nexport interface UniqueKeyOptions {\n /**\n * Prefix of every minted `uniqueKey` (`<prefix><uuid>`). Defaults to\n * `DEFAULT_UNIQUE_KEY_PREFIX` (`galaswap-operation-`).\n */\n uniqueKeyPrefix?: string | undefined;\n}\n\n/** A canonical UUID is 36 characters; the apply-results key limit is 128. */\nconst MAX_UNIQUE_KEY_PREFIX_LENGTH = 128 - 36;\nconst UNIQUE_KEY_PREFIX_PATTERN = /^[A-Za-z0-9._:-]*$/u;\n\n/**\n * Validates a caller-supplied `uniqueKey` prefix. The whole key (`<prefix><uuid>`) must stay a\n * valid apply-results key, otherwise `confirm()` could never read the outcome of the write.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY_PREFIX` when the prefix has characters outside\n * `A-Za-z0-9._:-` or is longer than 92 characters.\n */\nexport function resolveUniqueKeyPrefix(prefix: string | undefined): string {\n if (prefix === undefined) return DEFAULT_UNIQUE_KEY_PREFIX;\n if (!UNIQUE_KEY_PREFIX_PATTERN.test(prefix) || prefix.length > MAX_UNIQUE_KEY_PREFIX_LENGTH) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY_PREFIX', {\n uniqueKeyPrefix: prefix,\n maxLength: MAX_UNIQUE_KEY_PREFIX_LENGTH,\n });\n }\n return prefix;\n}\n\n/**\n * Validates a caller-supplied write `uniqueKey`: 1 to 128 characters of `A-Za-z0-9._:-`, the\n * shape the apply-results route accepts, so the write's outcome can always be read back with\n * `confirm()`. A key is one attempt's identity: reuse it only to retry that same attempt.\n *\n * @throws GSwapSDKError `INVALID_UNIQUE_KEY` otherwise.\n */\nexport function assertUniqueKey(uniqueKey: string): void {\n if (!isValidUniqueKey(uniqueKey)) {\n throw new GSwapSDKError('INVALID_UNIQUE_KEY', { uniqueKey: String(uniqueKey) });\n }\n}\n\n/** A fresh per-attempt key: `<prefix><random UUID>`. */\nexport function createUniqueKey(prefix: string): string {\n return `${prefix}${globalThis.crypto.randomUUID()}`;\n}\n"],"mappings":"wHAUA,MAAa,EAA4B,sBAanC,EAA4B,sBASlC,SAAgB,EAAuB,EAAoC,CACzE,GAAI,IAAW,IAAA,GAAW,OAAO,EACjC,GAAI,CAAC,EAA0B,KAAK,CAAM,GAAK,EAAO,OAAS,GAC7D,MAAM,IAAI,EAAc,4BAA6B,CACnD,gBAAiB,EACjB,UAAW,EACb,CAAC,EAEH,OAAO,CACT,CASA,SAAgB,EAAgB,EAAyB,CACvD,GAAI,CAAC,EAAiB,CAAS,EAC7B,MAAM,IAAI,EAAc,qBAAsB,CAAE,UAAW,OAAO,CAAS,CAAE,CAAC,CAElF,CAGA,SAAgB,EAAgB,EAAwB,CACtD,MAAO,GAAG,IAAS,WAAW,OAAO,WAAW,GAClD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"unique_key_syntax.js","names":[],"sources":["../../../src/utils/unique_key_syntax.ts"],"sourcesContent":["/**\n * The shape of a write `uniqueKey`, with NO imports: the pending-swap store and the failure guards\n * need only this check, and importing it from `unique_key.ts` would drag in `GSwapSDKError` and the\n * whole error catalog for it.\n */\n\n/** The swap backend's apply-results key constraint (`apply-results.dto.ts`). */\nconst UNIQUE_KEY_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/u;\n\n/**\n * True when `uniqueKey` is a usable write key: 1 to 128 characters of `A-Za-z0-9._:-`, the shape\n * the apply-results route accepts. The one definition behind `assertUniqueKey`, `confirm()` and\n * the pending-swap store, so they can never disagree about what a valid key is.\n */\nexport function isValidUniqueKey(uniqueKey: unknown): uniqueKey is string {\n return typeof uniqueKey === 'string' && UNIQUE_KEY_PATTERN.test(uniqueKey);\n}\n"],"mappings":"AAOA,MAAM,EAAqB,4BAO3B,SAAgB,EAAiB,EAAyC,CACxE,OAAO,OAAO,GAAc,UAAY,EAAmB,KAAK,CAAS,CAC3E"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{hasGSwapErrorBrand as e,isGSwapErrorLike as t}from"./error_brand.js";const n=[4001,`ACTION_REJECTED`,`USER_REJECTED`],r=[`user rejected`,`user denied`,`user cancel`,`rejected the request`,`request rejected`,`rejected by user`,`action_rejected`,`cancelled`,`canceled`],i=[`message`,`Message`,`shortMessage`,`details`,`errorDetails`,`reason`];function a(e){return typeof e==`object`&&!!e}function o(e,t=0){return typeof e==`string`?[e]:!a(e)||t>=3?[]:i.flatMap(n=>o(e[n],t+1))}function s(e){let t=e.toLowerCase();return r.some(e=>t.includes(e))||t.includes(`signature`)&&t.includes(`cancel`)}function c(r){return t(r)?r.code===`SIGNING_FAILED`?r.params.reason===`user_rejected`:!e(r)&&n.includes(r.code):a(r)&&(n.includes(r.code)||r.name===`UserRejectedRequestError`)?!0:o(r).some(s)}function l(e){if(typeof e!=`object`||!e)return;let{code:t}=e;if(typeof t==`number`)return Number.isFinite(t)?t:void 0;if(typeof t==`string`&&t.length>0&&t.length<=64)return t}export{c as isWalletUserRejection,l as walletDeclineCode};
|
|
2
|
-
//# sourceMappingURL=wallet_rejection.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wallet_rejection.js","names":[],"sources":["../../../src/utils/wallet_rejection.ts"],"sourcesContent":["/**\n * What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet\n * code of the app's own): the code the wallet put on it, and whether it means the person declined.\n * Both read only the wallet's own error value; neither shows or forwards its text.\n */\n\nimport { hasGSwapErrorBrand, isGSwapErrorLike } from './error_brand.js';\n\n// This module is the whole of the light `@gala-chain/gswap-sdk/wallet` entry (and the main entry\n// re-exports it, so there is one implementation). It must stay dependency-free: it may import\n// only `./error_brand.js`, never the error catalog, `GSwapSDKError` or the main index.\n\n/** Codes the EIP-1193 / ethers / viem families use for \"the person declined in the wallet\". */\nconst REJECTION_CODES: readonly unknown[] = [4001, 'ACTION_REJECTED', 'USER_REJECTED'];\n\n/** The `name` viem / wagmi give the error of a declined request. */\nconst REJECTION_NAME = 'UserRejectedRequestError';\n\n/**\n * Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for\n * wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on\n * purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle\n * match an unrelated message that uses these words.\n */\nconst REJECTION_PHRASES: readonly string[] = [\n 'user rejected',\n 'user denied',\n 'user cancel',\n 'rejected the request',\n 'request rejected',\n 'rejected by user',\n 'action_rejected',\n 'cancelled',\n 'canceled',\n];\n\n/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */\nconst TEXT_KEYS: readonly string[] = [\n 'message',\n 'Message',\n 'shortMessage',\n 'details',\n 'errorDetails',\n 'reason',\n];\n\n/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */\nconst MAX_TEXT_DEPTH = 3;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction textsOf(value: unknown, depth = 0): string[] {\n if (typeof value === 'string') return [value];\n if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];\n return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));\n}\n\nfunction wordsADecline(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) ||\n (lower.includes('signature') && lower.includes('cancel'))\n );\n}\n\n/**\n * True when a wallet's error (or just its message text) says the person DECLINED the request in\n * their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===\n * 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a\n * v1 write path) so an app keeps no matcher of its own.\n *\n * It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`\n * (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are\n * absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,\n * `reason`, up to three levels deep, or a bare string): \"user rejected\", \"user denied\", \"user\n * cancelled\", \"request rejected\", \"rejected by user\", \"rejected the request\", \"cancelled\" /\n * \"canceled\", or a \"signature ... cancel\" sentence. The wording fallback is a last resort for\n * wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.\n *\n * An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its\n * `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a\n * plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape\n * of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with\n * the wallet code list above still honoured for a view that is not branded, and its English is\n * never read. This works without `instanceof`, so it is safe across two copies of the SDK.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (isWalletUserRejection(error)) return; // the person said no: not an error to report\n * report(error);\n * }\n * ```\n */\nexport function isWalletUserRejection(value: unknown): boolean {\n if (isGSwapErrorLike(value)) {\n if (value.code === 'SIGNING_FAILED') return value.params['reason'] === 'user_rejected';\n return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);\n }\n if (isRecord(value)) {\n if (REJECTION_CODES.includes(value['code']) || value['name'] === REJECTION_NAME) return true;\n }\n return textsOf(value).some(wordsADecline);\n}\n\n/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */\nconst MAX_WALLET_CODE_LENGTH = 64;\n\n/**\n * The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an\n * ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything\n * else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so\n * the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.\n *\n * @example\n * ```ts\n * walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001\n * walletDeclineCode(new Error('locked')); // undefined\n * ```\n */\nexport function walletDeclineCode(value: unknown): number | string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const { code } = value as { code?: unknown };\n if (typeof code === 'number') return Number.isFinite(code) ? code : undefined;\n if (typeof code === 'string' && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) {\n return code;\n }\n return undefined;\n}\n"],"mappings":"4EAaA,MAAM,EAAsC,CAAC,KAAM,kBAAmB,eAAe,EAW/E,EAAuC,CAC3C,gBACA,cACA,cACA,uBACA,mBACA,mBACA,kBACA,YACA,UACF,EAGM,EAA+B,CACnC,UACA,UACA,eACA,UACA,eACA,QACF,EAKA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,CACtC,CAEA,SAAS,EAAQ,EAAgB,EAAQ,EAAa,CAGpD,OAFI,OAAO,GAAU,SAAiB,CAAC,CAAK,EACxC,CAAC,EAAS,CAAK,GAAK,GAAS,EAAuB,CAAC,EAClD,EAAU,QAAS,GAAQ,EAAQ,EAAM,GAAM,EAAQ,CAAC,CAAC,CAClE,CAEA,SAAS,EAAc,EAAuB,CAC5C,IAAM,EAAQ,EAAK,YAAY,EAC/B,OACE,EAAkB,KAAM,GAAW,EAAM,SAAS,CAAM,CAAC,GACxD,EAAM,SAAS,WAAW,GAAK,EAAM,SAAS,QAAQ,CAE3D,CAiCA,SAAgB,EAAsB,EAAyB,CAQ7D,OAPI,EAAiB,CAAK,EACpB,EAAM,OAAS,iBAAyB,EAAM,OAAO,SAAc,gBAChE,CAAC,EAAmB,CAAK,GAAK,EAAgB,SAAS,EAAM,IAAI,EAEtE,EAAS,CAAK,IACZ,EAAgB,SAAS,EAAM,IAAO,GAAK,EAAM,OAAY,4BAAuB,GAEnF,EAAQ,CAAK,CAAC,CAAC,KAAK,CAAa,CAC1C,CAiBA,SAAgB,EAAkB,EAA6C,CAC7E,GAAI,OAAO,GAAU,WAAY,EAAgB,OACjD,GAAM,CAAE,QAAS,EACjB,GAAI,OAAO,GAAS,SAAU,OAAO,OAAO,SAAS,CAAI,EAAI,EAAO,IAAA,GACpE,GAAI,OAAO,GAAS,UAAY,EAAK,OAAS,GAAK,EAAK,QAAU,GAChE,OAAO,CAGX"}
|
package/dist/browser/version.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","names":[],"sources":["../../src/version.ts"],"sourcesContent":["declare const __GSWAP_SDK_VERSION__: string | undefined;\n\n/** Package version embedded by the bundler, with a source-test fallback. */\nexport const SDK_VERSION =\n typeof __GSWAP_SDK_VERSION__ === 'string' ? __GSWAP_SDK_VERSION__ : '1.2.0';\n"],"mappings":"AAGA,MAAa,EAAA"}
|
package/dist/browser/wallet.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=Symbol.for(`@gala-chain/gswap-sdk/error`);function t(e){return typeof e==`object`&&!!e}function n(n){return t(n)&&n[e]===!0}function r(e){return n(e)?!0:t(e)&&typeof e.code==`string`&&t(e.params)&&!Array.isArray(e.params)}const i=[4001,`ACTION_REJECTED`,`USER_REJECTED`],a=[`user rejected`,`user denied`,`user cancel`,`rejected the request`,`request rejected`,`rejected by user`,`action_rejected`,`cancelled`,`canceled`],o=[`message`,`Message`,`shortMessage`,`details`,`errorDetails`,`reason`];function s(e){return typeof e==`object`&&!!e}function c(e,t=0){return typeof e==`string`?[e]:!s(e)||t>=3?[]:o.flatMap(n=>c(e[n],t+1))}function l(e){let t=e.toLowerCase();return a.some(e=>t.includes(e))||t.includes(`signature`)&&t.includes(`cancel`)}function u(e){return r(e)?e.code===`SIGNING_FAILED`?e.params.reason===`user_rejected`:!n(e)&&i.includes(e.code):s(e)&&(i.includes(e.code)||e.name===`UserRejectedRequestError`)?!0:c(e).some(l)}function d(e){if(typeof e!=`object`||!e)return;let{code:t}=e;if(typeof t==`number`)return Number.isFinite(t)?t:void 0;if(typeof t==`string`&&t.length>0&&t.length<=64)return t}export{r as isGSwapErrorLike,u as isWalletUserRejection,d as walletDeclineCode};
|
|
2
|
-
//# sourceMappingURL=wallet.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.js","names":["isRecord"],"sources":["../../src/utils/error_brand.ts","../../src/utils/wallet_rejection.ts"],"sourcesContent":["/**\n * The brand every `GSwapSDKError` carries, and the duck-type check for the \"failure shape\". This\n * module has NO imports on purpose: it is part of the light `@gala-chain/gswap-sdk/wallet` entry,\n * which must never pull the error catalog or the main bundle in.\n */\n\n/**\n * The brand of an SDK error: `error[GSWAP_ERROR_BRAND] === true`. It is a registered symbol\n * (`Symbol.for`), so two copies of the SDK in one page (a wallet bundle and an app bundle) still\n * recognise each other's errors, which `instanceof` cannot do.\n */\nexport const GSWAP_ERROR_BRAND: unique symbol = Symbol.for('@gala-chain/gswap-sdk/error');\n\n/** The least an object must have to be read as an SDK error or its plain-object view. */\nexport interface GSwapErrorShape {\n readonly code: string;\n readonly params: Readonly<Record<string, unknown>>;\n}\n\nfunction isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** True when `value` carries the SDK error brand (a real `GSwapSDKError`, from any copy of the SDK). */\nexport function hasGSwapErrorBrand(value: unknown): boolean {\n return isRecord(value) && value[GSWAP_ERROR_BRAND] === true;\n}\n\n/**\n * True when `value` is an SDK error (it carries the brand) or a plain-object VIEW of one: a string\n * `code` and an object `params`, which is the shape of `GSwapSDKError` and of the wrapper objects\n * an app builds from one (`{ code, params, status?, phase?, ... }`). A wallet's own error (an\n * EIP-1193 numeric `code`, an ethers error with a string `code` and no `params`) is neither. It\n * says the value has the SDK's shape, not that `code` is a code the SDK knows.\n *\n * @example\n * ```ts\n * if (isGSwapErrorLike(error)) report(error.code, error.params); // no `instanceof`, no SDK import\n * ```\n */\nexport function isGSwapErrorLike(value: unknown): value is GSwapErrorShape {\n if (hasGSwapErrorBrand(value)) return true;\n return (\n isRecord(value) &&\n typeof value['code'] === 'string' &&\n isRecord(value['params']) &&\n !Array.isArray(value['params'])\n );\n}\n","/**\n * What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet\n * code of the app's own): the code the wallet put on it, and whether it means the person declined.\n * Both read only the wallet's own error value; neither shows or forwards its text.\n */\n\nimport { hasGSwapErrorBrand, isGSwapErrorLike } from './error_brand.js';\n\n// This module is the whole of the light `@gala-chain/gswap-sdk/wallet` entry (and the main entry\n// re-exports it, so there is one implementation). It must stay dependency-free: it may import\n// only `./error_brand.js`, never the error catalog, `GSwapSDKError` or the main index.\n\n/** Codes the EIP-1193 / ethers / viem families use for \"the person declined in the wallet\". */\nconst REJECTION_CODES: readonly unknown[] = [4001, 'ACTION_REJECTED', 'USER_REJECTED'];\n\n/** The `name` viem / wagmi give the error of a declined request. */\nconst REJECTION_NAME = 'UserRejectedRequestError';\n\n/**\n * Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for\n * wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on\n * purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle\n * match an unrelated message that uses these words.\n */\nconst REJECTION_PHRASES: readonly string[] = [\n 'user rejected',\n 'user denied',\n 'user cancel',\n 'rejected the request',\n 'request rejected',\n 'rejected by user',\n 'action_rejected',\n 'cancelled',\n 'canceled',\n];\n\n/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */\nconst TEXT_KEYS: readonly string[] = [\n 'message',\n 'Message',\n 'shortMessage',\n 'details',\n 'errorDetails',\n 'reason',\n];\n\n/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */\nconst MAX_TEXT_DEPTH = 3;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction textsOf(value: unknown, depth = 0): string[] {\n if (typeof value === 'string') return [value];\n if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];\n return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));\n}\n\nfunction wordsADecline(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) ||\n (lower.includes('signature') && lower.includes('cancel'))\n );\n}\n\n/**\n * True when a wallet's error (or just its message text) says the person DECLINED the request in\n * their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===\n * 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a\n * v1 write path) so an app keeps no matcher of its own.\n *\n * It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`\n * (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are\n * absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,\n * `reason`, up to three levels deep, or a bare string): \"user rejected\", \"user denied\", \"user\n * cancelled\", \"request rejected\", \"rejected by user\", \"rejected the request\", \"cancelled\" /\n * \"canceled\", or a \"signature ... cancel\" sentence. The wording fallback is a last resort for\n * wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.\n *\n * An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its\n * `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a\n * plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape\n * of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with\n * the wallet code list above still honoured for a view that is not branded, and its English is\n * never read. This works without `instanceof`, so it is safe across two copies of the SDK.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (isWalletUserRejection(error)) return; // the person said no: not an error to report\n * report(error);\n * }\n * ```\n */\nexport function isWalletUserRejection(value: unknown): boolean {\n if (isGSwapErrorLike(value)) {\n if (value.code === 'SIGNING_FAILED') return value.params['reason'] === 'user_rejected';\n return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);\n }\n if (isRecord(value)) {\n if (REJECTION_CODES.includes(value['code']) || value['name'] === REJECTION_NAME) return true;\n }\n return textsOf(value).some(wordsADecline);\n}\n\n/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */\nconst MAX_WALLET_CODE_LENGTH = 64;\n\n/**\n * The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an\n * ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything\n * else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so\n * the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.\n *\n * @example\n * ```ts\n * walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001\n * walletDeclineCode(new Error('locked')); // undefined\n * ```\n */\nexport function walletDeclineCode(value: unknown): number | string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const { code } = value as { code?: unknown };\n if (typeof code === 'number') return Number.isFinite(code) ? code : undefined;\n if (typeof code === 'string' && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) {\n return code;\n }\n return undefined;\n}\n"],"mappings":"AAWA,MAAa,EAAmC,OAAO,IAAI,6BAA6B,EAQxF,SAASA,EAAS,EAAuD,CACvE,OAAO,OAAO,GAAU,YAAY,CACtC,CAGA,SAAgB,EAAmB,EAAyB,CAC1D,OAAOA,EAAS,CAAK,GAAK,EAAM,KAAuB,EACzD,CAcA,SAAgB,EAAiB,EAA0C,CAEzE,OADI,EAAmB,CAAK,EAAU,GAEpCA,EAAS,CAAK,GACd,OAAO,EAAM,MAAY,UACzBA,EAAS,EAAM,MAAS,GACxB,CAAC,MAAM,QAAQ,EAAM,MAAS,CAElC,CCnCA,MAAM,EAAsC,CAAC,KAAM,kBAAmB,eAAe,EAW/E,EAAuC,CAC3C,gBACA,cACA,cACA,uBACA,mBACA,mBACA,kBACA,YACA,UACF,EAGM,EAA+B,CACnC,UACA,UACA,eACA,UACA,eACA,QACF,EAKA,SAAS,EAAS,EAAkD,CAClE,OAAO,OAAO,GAAU,YAAY,CACtC,CAEA,SAAS,EAAQ,EAAgB,EAAQ,EAAa,CAGpD,OAFI,OAAO,GAAU,SAAiB,CAAC,CAAK,EACxC,CAAC,EAAS,CAAK,GAAK,GAAS,EAAuB,CAAC,EAClD,EAAU,QAAS,GAAQ,EAAQ,EAAM,GAAM,EAAQ,CAAC,CAAC,CAClE,CAEA,SAAS,EAAc,EAAuB,CAC5C,IAAM,EAAQ,EAAK,YAAY,EAC/B,OACE,EAAkB,KAAM,GAAW,EAAM,SAAS,CAAM,CAAC,GACxD,EAAM,SAAS,WAAW,GAAK,EAAM,SAAS,QAAQ,CAE3D,CAiCA,SAAgB,EAAsB,EAAyB,CAQ7D,OAPI,EAAiB,CAAK,EACpB,EAAM,OAAS,iBAAyB,EAAM,OAAO,SAAc,gBAChE,CAAC,EAAmB,CAAK,GAAK,EAAgB,SAAS,EAAM,IAAI,EAEtE,EAAS,CAAK,IACZ,EAAgB,SAAS,EAAM,IAAO,GAAK,EAAM,OAAY,4BAAuB,GAEnF,EAAQ,CAAK,CAAC,CAAC,KAAK,CAAa,CAC1C,CAiBA,SAAgB,EAAkB,EAA6C,CAC7E,GAAI,OAAO,GAAU,WAAY,EAAgB,OACjD,GAAM,CAAE,QAAS,EACjB,GAAI,OAAO,GAAS,SAAU,OAAO,OAAO,SAAS,CAAI,EAAI,EAAO,IAAA,GACpE,GAAI,OAAO,GAAS,UAAY,EAAK,OAAS,GAAK,EAAK,QAAU,GAChE,OAAO,CAGX"}
|
package/dist/wallet.cjs
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
//#region src/utils/error_brand.ts
|
|
3
|
-
/**
|
|
4
|
-
* The brand every `GSwapSDKError` carries, and the duck-type check for the "failure shape". This
|
|
5
|
-
* module has NO imports on purpose: it is part of the light `@gala-chain/gswap-sdk/wallet` entry,
|
|
6
|
-
* which must never pull the error catalog or the main bundle in.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* The brand of an SDK error: `error[GSWAP_ERROR_BRAND] === true`. It is a registered symbol
|
|
10
|
-
* (`Symbol.for`), so two copies of the SDK in one page (a wallet bundle and an app bundle) still
|
|
11
|
-
* recognise each other's errors, which `instanceof` cannot do.
|
|
12
|
-
*/
|
|
13
|
-
const GSWAP_ERROR_BRAND = Symbol.for("@gala-chain/gswap-sdk/error");
|
|
14
|
-
function isRecord$1(value) {
|
|
15
|
-
return typeof value === "object" && value !== null;
|
|
16
|
-
}
|
|
17
|
-
/** True when `value` carries the SDK error brand (a real `GSwapSDKError`, from any copy of the SDK). */
|
|
18
|
-
function hasGSwapErrorBrand(value) {
|
|
19
|
-
return isRecord$1(value) && value[GSWAP_ERROR_BRAND] === true;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* True when `value` is an SDK error (it carries the brand) or a plain-object VIEW of one: a string
|
|
23
|
-
* `code` and an object `params`, which is the shape of `GSwapSDKError` and of the wrapper objects
|
|
24
|
-
* an app builds from one (`{ code, params, status?, phase?, ... }`). A wallet's own error (an
|
|
25
|
-
* EIP-1193 numeric `code`, an ethers error with a string `code` and no `params`) is neither. It
|
|
26
|
-
* says the value has the SDK's shape, not that `code` is a code the SDK knows.
|
|
27
|
-
*
|
|
28
|
-
* @example
|
|
29
|
-
* ```ts
|
|
30
|
-
* if (isGSwapErrorLike(error)) report(error.code, error.params); // no `instanceof`, no SDK import
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
function isGSwapErrorLike(value) {
|
|
34
|
-
if (hasGSwapErrorBrand(value)) return true;
|
|
35
|
-
return isRecord$1(value) && typeof value["code"] === "string" && isRecord$1(value["params"]) && !Array.isArray(value["params"]);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
//#endregion
|
|
39
|
-
//#region src/utils/wallet_rejection.ts
|
|
40
|
-
/**
|
|
41
|
-
* What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet
|
|
42
|
-
* code of the app's own): the code the wallet put on it, and whether it means the person declined.
|
|
43
|
-
* Both read only the wallet's own error value; neither shows or forwards its text.
|
|
44
|
-
*/
|
|
45
|
-
/** Codes the EIP-1193 / ethers / viem families use for "the person declined in the wallet". */
|
|
46
|
-
const REJECTION_CODES = [
|
|
47
|
-
4001,
|
|
48
|
-
"ACTION_REJECTED",
|
|
49
|
-
"USER_REJECTED"
|
|
50
|
-
];
|
|
51
|
-
/** The `name` viem / wagmi give the error of a declined request. */
|
|
52
|
-
const REJECTION_NAME = "UserRejectedRequestError";
|
|
53
|
-
/**
|
|
54
|
-
* Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for
|
|
55
|
-
* wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on
|
|
56
|
-
* purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle
|
|
57
|
-
* match an unrelated message that uses these words.
|
|
58
|
-
*/
|
|
59
|
-
const REJECTION_PHRASES = [
|
|
60
|
-
"user rejected",
|
|
61
|
-
"user denied",
|
|
62
|
-
"user cancel",
|
|
63
|
-
"rejected the request",
|
|
64
|
-
"request rejected",
|
|
65
|
-
"rejected by user",
|
|
66
|
-
"action_rejected",
|
|
67
|
-
"cancelled",
|
|
68
|
-
"canceled"
|
|
69
|
-
];
|
|
70
|
-
/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */
|
|
71
|
-
const TEXT_KEYS = [
|
|
72
|
-
"message",
|
|
73
|
-
"Message",
|
|
74
|
-
"shortMessage",
|
|
75
|
-
"details",
|
|
76
|
-
"errorDetails",
|
|
77
|
-
"reason"
|
|
78
|
-
];
|
|
79
|
-
/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */
|
|
80
|
-
const MAX_TEXT_DEPTH = 3;
|
|
81
|
-
function isRecord(value) {
|
|
82
|
-
return typeof value === "object" && value !== null;
|
|
83
|
-
}
|
|
84
|
-
function textsOf(value, depth = 0) {
|
|
85
|
-
if (typeof value === "string") return [value];
|
|
86
|
-
if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];
|
|
87
|
-
return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));
|
|
88
|
-
}
|
|
89
|
-
function wordsADecline(text) {
|
|
90
|
-
const lower = text.toLowerCase();
|
|
91
|
-
return REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) || lower.includes("signature") && lower.includes("cancel");
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* True when a wallet's error (or just its message text) says the person DECLINED the request in
|
|
95
|
-
* their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===
|
|
96
|
-
* 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a
|
|
97
|
-
* v1 write path) so an app keeps no matcher of its own.
|
|
98
|
-
*
|
|
99
|
-
* It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`
|
|
100
|
-
* (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are
|
|
101
|
-
* absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,
|
|
102
|
-
* `reason`, up to three levels deep, or a bare string): "user rejected", "user denied", "user
|
|
103
|
-
* cancelled", "request rejected", "rejected by user", "rejected the request", "cancelled" /
|
|
104
|
-
* "canceled", or a "signature ... cancel" sentence. The wording fallback is a last resort for
|
|
105
|
-
* wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.
|
|
106
|
-
*
|
|
107
|
-
* An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its
|
|
108
|
-
* `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a
|
|
109
|
-
* plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape
|
|
110
|
-
* of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with
|
|
111
|
-
* the wallet code list above still honoured for a view that is not branded, and its English is
|
|
112
|
-
* never read. This works without `instanceof`, so it is safe across two copies of the SDK.
|
|
113
|
-
*
|
|
114
|
-
* @example
|
|
115
|
-
* ```ts
|
|
116
|
-
* try {
|
|
117
|
-
* await wallet.connect();
|
|
118
|
-
* } catch (error) {
|
|
119
|
-
* if (isWalletUserRejection(error)) return; // the person said no: not an error to report
|
|
120
|
-
* report(error);
|
|
121
|
-
* }
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
function isWalletUserRejection(value) {
|
|
125
|
-
if (isGSwapErrorLike(value)) {
|
|
126
|
-
if (value.code === "SIGNING_FAILED") return value.params["reason"] === "user_rejected";
|
|
127
|
-
return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);
|
|
128
|
-
}
|
|
129
|
-
if (isRecord(value)) {
|
|
130
|
-
if (REJECTION_CODES.includes(value["code"]) || value["name"] === REJECTION_NAME) return true;
|
|
131
|
-
}
|
|
132
|
-
return textsOf(value).some(wordsADecline);
|
|
133
|
-
}
|
|
134
|
-
/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */
|
|
135
|
-
const MAX_WALLET_CODE_LENGTH = 64;
|
|
136
|
-
/**
|
|
137
|
-
* The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an
|
|
138
|
-
* ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything
|
|
139
|
-
* else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so
|
|
140
|
-
* the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.
|
|
141
|
-
*
|
|
142
|
-
* @example
|
|
143
|
-
* ```ts
|
|
144
|
-
* walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001
|
|
145
|
-
* walletDeclineCode(new Error('locked')); // undefined
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
function walletDeclineCode(value) {
|
|
149
|
-
if (typeof value !== "object" || value === null) return void 0;
|
|
150
|
-
const { code } = value;
|
|
151
|
-
if (typeof code === "number") return Number.isFinite(code) ? code : void 0;
|
|
152
|
-
if (typeof code === "string" && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) return code;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
//#endregion
|
|
156
|
-
exports.isGSwapErrorLike = isGSwapErrorLike;
|
|
157
|
-
exports.isWalletUserRejection = isWalletUserRejection;
|
|
158
|
-
exports.walletDeclineCode = walletDeclineCode;
|
|
159
|
-
//# sourceMappingURL=wallet.cjs.map
|
package/dist/wallet.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"wallet.cjs","names":["isRecord"],"sources":["../src/utils/error_brand.ts","../src/utils/wallet_rejection.ts"],"sourcesContent":["/**\n * The brand every `GSwapSDKError` carries, and the duck-type check for the \"failure shape\". This\n * module has NO imports on purpose: it is part of the light `@gala-chain/gswap-sdk/wallet` entry,\n * which must never pull the error catalog or the main bundle in.\n */\n\n/**\n * The brand of an SDK error: `error[GSWAP_ERROR_BRAND] === true`. It is a registered symbol\n * (`Symbol.for`), so two copies of the SDK in one page (a wallet bundle and an app bundle) still\n * recognise each other's errors, which `instanceof` cannot do.\n */\nexport const GSWAP_ERROR_BRAND: unique symbol = Symbol.for('@gala-chain/gswap-sdk/error');\n\n/** The least an object must have to be read as an SDK error or its plain-object view. */\nexport interface GSwapErrorShape {\n readonly code: string;\n readonly params: Readonly<Record<string, unknown>>;\n}\n\nfunction isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n/** True when `value` carries the SDK error brand (a real `GSwapSDKError`, from any copy of the SDK). */\nexport function hasGSwapErrorBrand(value: unknown): boolean {\n return isRecord(value) && value[GSWAP_ERROR_BRAND] === true;\n}\n\n/**\n * True when `value` is an SDK error (it carries the brand) or a plain-object VIEW of one: a string\n * `code` and an object `params`, which is the shape of `GSwapSDKError` and of the wrapper objects\n * an app builds from one (`{ code, params, status?, phase?, ... }`). A wallet's own error (an\n * EIP-1193 numeric `code`, an ethers error with a string `code` and no `params`) is neither. It\n * says the value has the SDK's shape, not that `code` is a code the SDK knows.\n *\n * @example\n * ```ts\n * if (isGSwapErrorLike(error)) report(error.code, error.params); // no `instanceof`, no SDK import\n * ```\n */\nexport function isGSwapErrorLike(value: unknown): value is GSwapErrorShape {\n if (hasGSwapErrorBrand(value)) return true;\n return (\n isRecord(value) &&\n typeof value['code'] === 'string' &&\n isRecord(value['params']) &&\n !Array.isArray(value['params'])\n );\n}\n","/**\n * What the SDK knows about a failure thrown by a WALLET (the signer an app supplies, or wallet\n * code of the app's own): the code the wallet put on it, and whether it means the person declined.\n * Both read only the wallet's own error value; neither shows or forwards its text.\n */\n\nimport { hasGSwapErrorBrand, isGSwapErrorLike } from './error_brand.js';\n\n// This module is the whole of the light `@gala-chain/gswap-sdk/wallet` entry (and the main entry\n// re-exports it, so there is one implementation). It must stay dependency-free: it may import\n// only `./error_brand.js`, never the error catalog, `GSwapSDKError` or the main index.\n\n/** Codes the EIP-1193 / ethers / viem families use for \"the person declined in the wallet\". */\nconst REJECTION_CODES: readonly unknown[] = [4001, 'ACTION_REJECTED', 'USER_REJECTED'];\n\n/** The `name` viem / wagmi give the error of a declined request. */\nconst REJECTION_NAME = 'UserRejectedRequestError';\n\n/**\n * Wordings of a decline, matched case-insensitively as substrings. This is a LAST RESORT for\n * wallets that set neither a `code` nor a `name`: it reads a third party's text, so it is broad on\n * purpose (a superset of the matchers the Gala wallet and frontend_v2 used) and can in principle\n * match an unrelated message that uses these words.\n */\nconst REJECTION_PHRASES: readonly string[] = [\n 'user rejected',\n 'user denied',\n 'user cancel',\n 'rejected the request',\n 'request rejected',\n 'rejected by user',\n 'action_rejected',\n 'cancelled',\n 'canceled',\n];\n\n/** Properties wallets nest their text under (EIP-1193, ethers, viem, Gala wallet). */\nconst TEXT_KEYS: readonly string[] = [\n 'message',\n 'Message',\n 'shortMessage',\n 'details',\n 'errorDetails',\n 'reason',\n];\n\n/** Wallet errors nest their text at most a level or two deep; the bound also stops a cyclic object. */\nconst MAX_TEXT_DEPTH = 3;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction textsOf(value: unknown, depth = 0): string[] {\n if (typeof value === 'string') return [value];\n if (!isRecord(value) || depth >= MAX_TEXT_DEPTH) return [];\n return TEXT_KEYS.flatMap((key) => textsOf(value[key], depth + 1));\n}\n\nfunction wordsADecline(text: string): boolean {\n const lower = text.toLowerCase();\n return (\n REJECTION_PHRASES.some((phrase) => lower.includes(phrase)) ||\n (lower.includes('signature') && lower.includes('cancel'))\n );\n}\n\n/**\n * True when a wallet's error (or just its message text) says the person DECLINED the request in\n * their wallet. This is exactly the test behind `SIGNING_FAILED` with `params.reason ===\n * 'user_rejected'`, exported for wallet code outside the SDK (connect and registration flows, a\n * v1 write path) so an app keeps no matcher of its own.\n *\n * It is decided from the wallet's own fields first: a `code` of `4001` (EIP-1193), `'ACTION_REJECTED'`\n * (ethers) or `'USER_REJECTED'`, or `name === 'UserRejectedRequestError'` (viem). Only when those are\n * absent is the wallet's TEXT read (`message`, `Message`, `shortMessage`, `details`, `errorDetails`,\n * `reason`, up to three levels deep, or a bare string): \"user rejected\", \"user denied\", \"user\n * cancelled\", \"request rejected\", \"rejected by user\", \"rejected the request\", \"cancelled\" /\n * \"canceled\", or a \"signature ... cancel\" sentence. The wording fallback is a last resort for\n * wallets that do not set codes; prefer `code` and `name` wherever you control the wallet.\n *\n * An SDK error is never read by its text: a `SIGNING_FAILED` is a decline exactly when its\n * `params.reason` is `user_rejected`, and every other SDK error is not one. The same holds for a\n * plain-object VIEW of an SDK error (`{ code: 'SIGNING_FAILED', params: { reason } }`, the shape\n * of an app's wrapper): a string `code` plus an object `params` is decided by the code alone, with\n * the wallet code list above still honoured for a view that is not branded, and its English is\n * never read. This works without `instanceof`, so it is safe across two copies of the SDK.\n *\n * @example\n * ```ts\n * try {\n * await wallet.connect();\n * } catch (error) {\n * if (isWalletUserRejection(error)) return; // the person said no: not an error to report\n * report(error);\n * }\n * ```\n */\nexport function isWalletUserRejection(value: unknown): boolean {\n if (isGSwapErrorLike(value)) {\n if (value.code === 'SIGNING_FAILED') return value.params['reason'] === 'user_rejected';\n return !hasGSwapErrorBrand(value) && REJECTION_CODES.includes(value.code);\n }\n if (isRecord(value)) {\n if (REJECTION_CODES.includes(value['code']) || value['name'] === REJECTION_NAME) return true;\n }\n return textsOf(value).some(wordsADecline);\n}\n\n/** The longest wallet code kept: real ones (`4001`, `ACTION_REJECTED`) are short. */\nconst MAX_WALLET_CODE_LENGTH = 64;\n\n/**\n * The code a wallet put on its error: an EIP-1193 / JSON-RPC number (`4001`, `-32603`) or an\n * ethers / viem string (`'ACTION_REJECTED'`), read from the error's own top-level `code`. Anything\n * else (no code, a non-finite number, an empty or very long string, an object) is `undefined`, so\n * the value is always a safe primitive. Used for `GSwapSDKError.walletCode`.\n *\n * @example\n * ```ts\n * walletDeclineCode({ code: 4001, message: 'User rejected the request.' }); // 4001\n * walletDeclineCode(new Error('locked')); // undefined\n * ```\n */\nexport function walletDeclineCode(value: unknown): number | string | undefined {\n if (typeof value !== 'object' || value === null) return undefined;\n const { code } = value as { code?: unknown };\n if (typeof code === 'number') return Number.isFinite(code) ? code : undefined;\n if (typeof code === 'string' && code.length > 0 && code.length <= MAX_WALLET_CODE_LENGTH) {\n return code;\n }\n return undefined;\n}\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,oBAAmC,OAAO,IAAI,6BAA6B;AAQxF,SAASA,WAAS,OAAuD;CACvE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;;AAGA,SAAgB,mBAAmB,OAAyB;CAC1D,OAAOA,WAAS,KAAK,KAAK,MAAM,uBAAuB;AACzD;;;;;;;;;;;;;AAcA,SAAgB,iBAAiB,OAA0C;CACzE,IAAI,mBAAmB,KAAK,GAAG,OAAO;CACtC,OACEA,WAAS,KAAK,KACd,OAAO,MAAM,YAAY,YACzBA,WAAS,MAAM,SAAS,KACxB,CAAC,MAAM,QAAQ,MAAM,SAAS;AAElC;;;;;;;;;;ACnCA,MAAM,kBAAsC;CAAC;CAAM;CAAmB;AAAe;;AAGrF,MAAM,iBAAiB;;;;;;;AAQvB,MAAM,oBAAuC;CAC3C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,YAA+B;CACnC;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,iBAAiB;AAEvB,SAAS,SAAS,OAAkD;CAClE,OAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,QAAQ,OAAgB,QAAQ,GAAa;CACpD,IAAI,OAAO,UAAU,UAAU,OAAO,CAAC,KAAK;CAC5C,IAAI,CAAC,SAAS,KAAK,KAAK,SAAS,gBAAgB,OAAO,CAAC;CACzD,OAAO,UAAU,SAAS,QAAQ,QAAQ,MAAM,MAAM,QAAQ,CAAC,CAAC;AAClE;AAEA,SAAS,cAAc,MAAuB;CAC5C,MAAM,QAAQ,KAAK,YAAY;CAC/B,OACE,kBAAkB,MAAM,WAAW,MAAM,SAAS,MAAM,CAAC,KACxD,MAAM,SAAS,WAAW,KAAK,MAAM,SAAS,QAAQ;AAE3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,sBAAsB,OAAyB;CAC7D,IAAI,iBAAiB,KAAK,GAAG;EAC3B,IAAI,MAAM,SAAS,kBAAkB,OAAO,MAAM,OAAO,cAAc;EACvE,OAAO,CAAC,mBAAmB,KAAK,KAAK,gBAAgB,SAAS,MAAM,IAAI;CAC1E;CACA,IAAI,SAAS,KAAK,GAChB;MAAI,gBAAgB,SAAS,MAAM,OAAO,KAAK,MAAM,YAAY,gBAAgB,OAAO;CAAI;CAE9F,OAAO,QAAQ,KAAK,CAAC,CAAC,KAAK,aAAa;AAC1C;;AAGA,MAAM,yBAAyB;;;;;;;;;;;;;AAc/B,SAAgB,kBAAkB,OAA6C;CAC7E,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO;CACxD,MAAM,EAAE,SAAS;CACjB,IAAI,OAAO,SAAS,UAAU,OAAO,OAAO,SAAS,IAAI,IAAI,OAAO;CACpE,IAAI,OAAO,SAAS,YAAY,KAAK,SAAS,KAAK,KAAK,UAAU,wBAChE,OAAO;AAGX"}
|