@gala-chain/gswap-sdk 1.1.1 → 1.2.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,37 @@
1
1
  import BigNumber from "bignumber.js";
2
+ //#region src/types/confirm_options.d.ts
3
+ /**
4
+ * Controls timeout, polling and cancellation of confirmation.
5
+ *
6
+ * - `timeoutMs` (default 60 000): overall deadline, counted from the `confirm()` call and
7
+ * including `initialDelayMs`. At least one read is always made.
8
+ * - `pollIntervalMs` (default 2 000, minimum 500): base interval, doubled with jitter up to 8 s.
9
+ * - `initialDelayMs`: wait before the first read. Defaults to 3 000 for a queued RequestTrade
10
+ * (the AutoApplier needs a few seconds) and 0 for liquidity writes (already executed).
11
+ * - `signal`: aborts the wait or an in-flight read. Confirmation then throws an error with code
12
+ * `CONFIRMATION_ABORTED`; nothing is learned about the outcome, so confirm the same
13
+ * `uniqueKey` again later.
14
+ */
15
+ export interface ConfirmOptions {
16
+ timeoutMs?: number | undefined;
17
+ pollIntervalMs?: number | undefined;
18
+ initialDelayMs?: number | undefined;
19
+ signal?: AbortSignal | undefined;
20
+ }
21
+ //#endregion
22
+ //#region src/types/http_requestor.d.ts
23
+ type FetchReturnValue = Awaited<ReturnType<typeof fetch>>;
24
+ interface HTTPResponse {
25
+ ok: FetchReturnValue['ok'];
26
+ status: FetchReturnValue['status'];
27
+ json: FetchReturnValue['json'];
28
+ text: FetchReturnValue['text'];
29
+ headers?: {
30
+ get(name: string): string | null;
31
+ } | Record<string, string | undefined>;
32
+ }
33
+ type HttpRequestor = (uri: string, options?: Parameters<typeof fetch>[1]) => Promise<HTTPResponse>;
34
+ //#endregion
2
35
  //#region src/types/v2_results.d.ts
3
36
  /** Pool metadata returned by GalaChainDex. */
4
37
  export interface PoolInfo {
@@ -15,19 +48,26 @@ export interface PoolInfo {
15
48
  isPrivate?: boolean;
16
49
  flippedFromRequest?: boolean;
17
50
  }
18
- /** Pool summary returned by the backend pool-list route. */
51
+ /**
52
+ * Pool summary returned by the backend pool-list route. Only the identity (`token0`, `token1`,
53
+ * `poolRef`) and `fee` are guaranteed; a row that lacks any other field is still a usable row, as
54
+ * the apps that list pools treat it.
55
+ */
19
56
  export interface PoolListInfo {
20
- contractVersion: 'v2';
57
+ contractVersion?: 'v2' | undefined;
21
58
  token0: string;
22
59
  token1: string;
23
60
  token0CompositeKey?: string | undefined;
24
61
  token1CompositeKey?: string | undefined;
62
+ /** Registry image URL of token0 resolved by the backend; empty when the token is unregistered. */
63
+ token0Image?: string | undefined;
64
+ token1Image?: string | undefined;
25
65
  fee: number;
26
- poolName: string;
66
+ poolName?: string | undefined;
27
67
  poolRef: string;
28
- tickSpacing: number;
29
- protocolFees: number;
30
- tradingFees: number;
68
+ tickSpacing?: number | undefined;
69
+ protocolFees?: number | undefined;
70
+ tradingFees?: number | undefined;
31
71
  creator?: string | undefined;
32
72
  price?: string | undefined;
33
73
  sqrtPrice?: string | undefined;
@@ -103,6 +143,9 @@ export interface Position {
103
143
  token1Symbol: string;
104
144
  token0CompositeKey?: string;
105
145
  token1CompositeKey?: string;
146
+ /** Registry image URL of token0 resolved by the backend; empty when the token is unregistered. */
147
+ token0Image?: string;
148
+ token1Image?: string;
106
149
  fee: number;
107
150
  tickLower: number;
108
151
  tickUpper: number;
@@ -209,25 +252,189 @@ export interface ChainSubmissionResult {
209
252
  uniqueKey?: string;
210
253
  }
211
254
  //#endregion
212
- //#region src/types/http_requestor.d.ts
213
- type FetchReturnValue = Awaited<ReturnType<typeof fetch>>;
214
- interface HTTPResponse {
215
- ok: FetchReturnValue['ok'];
216
- status: FetchReturnValue['status'];
217
- json: FetchReturnValue['json'];
218
- text: FetchReturnValue['text'];
219
- headers?: {
220
- get(name: string): string | null;
221
- } | Record<string, string | undefined>;
255
+ //#region src/types/wire.d.ts
256
+ /**
257
+ * How the SDK writes a read request on the wire. The defaults suit a server-side caller; an app
258
+ * that already issues the same requests from its own HTTP stack (frontend_v2, the Gala Wallet)
259
+ * sets these so the SDK's requests are indistinguishable from the ones it replaces.
260
+ *
261
+ * One object, carried by {@link ChainGateway}, so every service built on a gateway (symbols,
262
+ * pools, positions, quoting) shares it without per-service plumbing.
263
+ */
264
+ export interface WireOptions {
265
+ /**
266
+ * Query-string encoding of GET parameters.
267
+ *
268
+ * - `'standard'` (default): `URLSearchParams` (`application/x-www-form-urlencoded`), where `$`
269
+ * and `|` become `%24` and `%7C`.
270
+ * - `'readable'`: keeps `$ | : ,` and the RFC 3986 sub-delimiters `! ' ( ) *` unescaped, so a
271
+ * composite key such as `GALA$Unit$none$none` or `client|abc` reads as written. Everything
272
+ * that would change a query's meaning (`& = # % +`, space, non-ASCII, controls) is still
273
+ * percent-encoded (a space is `+`), so the server decodes exactly the value that was passed.
274
+ * This is the text frontend_v2's `formatUrl` produces for every value it can represent.
275
+ */
276
+ queryEncoding?: 'standard' | 'readable' | undefined;
277
+ /**
278
+ * The `User-Agent` request header. Defaults to `GalaChain-SDK/<version>`; `false` omits it
279
+ * (browsers forbid setting it, and an app whose own requests carry none can match them).
280
+ * `Content-Type` is only ever sent with a request body, never on a GET.
281
+ */
282
+ userAgent?: string | false | undefined;
283
+ /**
284
+ * Extra request headers for every read, sent after (and so able to replace) the defaults above;
285
+ * for example axios' `Accept: application/json, text/plain, *\/*`, so a request is the same as
286
+ * the one an app's own HTTP stack used to send.
287
+ */
288
+ headers?: Record<string, string> | undefined;
222
289
  }
223
- type HttpRequestor = (uri: string, options?: Parameters<typeof fetch>[1]) => Promise<HTTPResponse>;
290
+ //#endregion
291
+ //#region src/types/token.d.ts
292
+ export interface GalaChainTokenClassKey {
293
+ collection: string;
294
+ category: string;
295
+ type: string;
296
+ additionalKey: string;
297
+ }
298
+ //#endregion
299
+ //#region src/classes/gswap_sdk_error.d.ts
300
+ /** Error raised by the SDK for validation, gateway, chain, or transaction failures. */
301
+ export declare class GSwapSDKError extends Error {
302
+ readonly code: string;
303
+ readonly details?: Record<string, unknown> | undefined;
304
+ readonly chainMessage: string | undefined;
305
+ readonly retryAfterMs: number | undefined;
306
+ /** The HTTP status of the response that caused this error, when there was one. */
307
+ readonly status: number | undefined;
308
+ /**
309
+ * The response body parsed as JSON, when the failing response had one; `undefined` for a body
310
+ * that was not JSON (see {@link bodyText}). Never part of {@link message}.
311
+ */
312
+ readonly body: unknown;
313
+ /**
314
+ * The raw text of a failing response whose body was NOT JSON (a proxy's HTML 502, a WAF page,
315
+ * an empty body). It is kept here for diagnostics and is never copied into {@link message} or
316
+ * {@link userMessage}, so it cannot reach a user interface by accident.
317
+ */
318
+ readonly bodyText: string | undefined;
319
+ constructor(message: string, code: string, details?: Record<string, unknown> | undefined, chainMessage?: string, retryAfterMs?: number);
320
+ /**
321
+ * A message that is safe to show a user as is: the server's own message when it sent one
322
+ * (a gateway or chain rejection), a neutral line naming the status for an HTTP failure with no
323
+ * readable answer, and otherwise {@link message}. Apps that word these differently (a
324
+ * "network busy" line for a 502, say) branch on {@link code} and {@link status} instead.
325
+ */
326
+ get userMessage(): string;
327
+ /**
328
+ * True when the failure means "that market, pool or position does not exist" rather than
329
+ * "something went wrong": an HTTP 404, a pair with no pool at any fee tier
330
+ * (`NO_POOL_AVAILABLE`), or a token the DEX contract has no trading symbol for
331
+ * (`UNKNOWN_TOKEN`). A pool that exists but is too thin (`INSUFFICIENT_LIQUIDITY`) is NOT
332
+ * not-found.
333
+ */
334
+ get notFound(): boolean;
335
+ /** Create the standard missing-signer error. */
336
+ static noSignerError(): GSwapSDKError;
337
+ /** Create the error used when confirming a position write without a configured wallet address. */
338
+ static noWalletAddressError(): GSwapSDKError;
339
+ /**
340
+ * Create the error used when no pool can quote the requested pair. `source` is the backend
341
+ * answer that said so; its status, body and message are kept (the message as `chainMessage`,
342
+ * so {@link userMessage} is the server's own wording).
343
+ */
344
+ static noPoolAvailableError(tokenIn: GalaChainTokenClassKey | string, tokenOut: GalaChainTokenClassKey | string, fee?: number, source?: GSwapSDKError): GSwapSDKError;
345
+ /** Create the error used when a pool lacks liquidity for a quote. `source` as for {@link noPoolAvailableError}. */
346
+ static insufficientLiquidityError(tokenIn: GalaChainTokenClassKey | string, tokenOut: GalaChainTokenClassKey | string, fee?: number, source?: GSwapSDKError): GSwapSDKError;
347
+ /**
348
+ * The message the server put in a JSON answer (`message`, or `error.Message`), when this error
349
+ * came from an HTTP response that had one.
350
+ */
351
+ get serverMessage(): string | undefined;
352
+ /** Convert a chain-gateway bounce into a typed SDK error. */
353
+ static fromGatewayBounce(code: string, message: string, status: number, retryAfterMs?: number): GSwapSDKError;
354
+ /** Convert a GalaChain `Status: 0` response into a typed SDK error. */
355
+ static fromChainError(errorKey: string, message: string, details?: Record<string, unknown>): GSwapSDKError;
356
+ /** Create the error used when a token is not registered by the current DEX contract. */
357
+ static unknownTokenError(token: GalaChainTokenClassKey | string): GSwapSDKError;
358
+ /** Create the error used when apply-results confirmation does not arrive in time. */
359
+ static confirmationTimeoutError(uniqueKey: string, cause?: unknown): GSwapSDKError;
360
+ /** Convert an unexpected HTTP response into an SDK error. */
361
+ static fromErrorResponse(url: string, response: HTTPResponse): Promise<GSwapSDKError>;
362
+ }
363
+ /** Narrow an object property without trusting a cast at a network boundary. */
364
+ export declare function getObjectProperty(value: unknown, property: string): Record<string, unknown> | undefined;
365
+ /** Read a string property from an unknown object. */
366
+ export declare function getStringProperty(value: unknown, property: string): string | undefined;
367
+ /** Parse a response body, preserving non-JSON text for error reporting. */
368
+ export declare function parseJson(text: string): unknown;
369
+ //#endregion
370
+ //#region src/classes/apply_results.d.ts
371
+ /**
372
+ * The outcome of a queued RequestTrade that could not be delivered as an {@link AppliedTrade}.
373
+ * `code` says why:
374
+ *
375
+ * - `CONFIRMATION_TIMEOUT`: no terminal result before the deadline. The trade may still apply;
376
+ * confirm the same `uniqueKey` again later and never resubmit.
377
+ * - `CONFIRMATION_ABORTED`: the caller's `signal` aborted. Nothing is known about the outcome.
378
+ * - `CONFIRMATION_FAILED`: the apply-results read itself failed (malformed key or body, a
379
+ * non-retryable HTTP status). The outcome is unknown.
380
+ * - anything else: the chain REJECTED the trade; `code` is the chain `ErrorKey` (or
381
+ * `CHAIN_ERROR`) and `chainMessage` is its message, which is also `message`.
382
+ *
383
+ * `details` always carries `uniqueKey` and, where known, `requestTransactionId`,
384
+ * `applyTransactionId`, `blockNumber`, `status`, `body`, `url` and the last transport `cause`.
385
+ */
386
+ export declare class AppliedTradeError extends GSwapSDKError {
387
+ constructor(message: string, code: string, details?: Record<string, unknown>, chainMessage?: string);
388
+ }
389
+ /** The transport and backend a confirmation reads from. */
390
+ export interface ApplyResultsClient {
391
+ /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com` (no trailing path). */
392
+ dexBackendBaseUrl: string;
393
+ /** Defaults to the global `fetch`. */
394
+ httpRequestor?: HttpRequestor | undefined;
395
+ /** Per-read timeout in milliseconds (default 30 000). */
396
+ requestTimeoutMs?: number | undefined;
397
+ /** Request headers of the poll (`userAgent`, `headers`); see {@link WireOptions}. */
398
+ wire?: WireOptions | undefined;
399
+ }
400
+ /** What identifies the queued trade to confirm. */
401
+ export interface AppliedTradeInput {
402
+ uniqueKey: string;
403
+ /** The transaction id of the queued request, carried through to the result; `null` if unknown. */
404
+ requestTransactionId: string | null;
405
+ }
406
+ /**
407
+ * Polls `GET /v1/chain/apply-results/{uniqueKey}?channel=asset&contract=dex-contract` until the
408
+ * queued RequestTrade reaches a terminal state.
409
+ *
410
+ * Pacing: wait `initialDelayMs` (default 3 s), then read; on 404, 429, 500, 502, 503, 504 or a
411
+ * transport error wait with jittered exponential backoff (`pollIntervalMs` doubling to 8 s,
412
+ * `Retry-After` honored as seconds or an HTTP date) until `timeoutMs`. Any other status is
413
+ * terminal. At least one read is always made.
414
+ *
415
+ * @returns The applied trade.
416
+ * @throws AppliedTradeError - see its documentation for every `code`.
417
+ * @example
418
+ * ```ts
419
+ * const applied = await confirmAppliedTrade(
420
+ * { dexBackendBaseUrl: 'https://dex-backend-prod1.defi.gala.com' },
421
+ * { uniqueKey, requestTransactionId: null },
422
+ * { initialDelayMs: 0, timeoutMs: 60_000, signal: controller.signal },
423
+ * );
424
+ * ```
425
+ */
426
+ export declare function confirmAppliedTrade(client: ApplyResultsClient, input: AppliedTradeInput, options?: ConfirmOptions): Promise<AppliedTrade>;
224
427
  //#endregion
225
428
  //#region src/classes/http_client.d.ts
226
429
  declare class HttpClient {
227
430
  private readonly httpRequestor;
228
431
  private readonly timeoutMs;
229
- /** Create an HTTP client around fetch or an injected requestor. */
230
- constructor(httpRequestor?: HttpRequestor, timeoutMs?: number);
432
+ private readonly wire;
433
+ /**
434
+ * Create an HTTP client around fetch or an injected requestor. `wire` selects the query
435
+ * encoding and the `User-Agent` (see {@link WireOptions}).
436
+ */
437
+ constructor(httpRequestor?: HttpRequestor, timeoutMs?: number, wire?: WireOptions);
231
438
  private sendRequest;
232
439
  /** Send a JSON POST request and decode its response. */
233
440
  sendPostRequest<TReturnType>(baseUrl: string, basePath: string, endpoint: string, body: unknown): Promise<TReturnType>;
@@ -262,96 +469,552 @@ export declare class Assets {
262
469
  getUserAssets(ownerAddress: string, page?: number, limit?: number): Promise<UserAssetsResult>;
263
470
  }
264
471
  //#endregion
265
- //#region src/classes/submitted_transaction.d.ts
266
- /** Result of one position-confirmation poll. */
267
- export type PositionConfirmationResult = {
268
- confirmed: true;
269
- position: Position | null;
270
- } | {
271
- confirmed: false;
272
- position?: Position | null;
472
+ //#region src/classes/signers.d.ts
473
+ /** The signing schemes supported by the Gala Wallet signer. */
474
+ export type GalaWalletScheme = 'native' | 'personal-sign';
475
+ /** The request surface used by an EIP-1193 browser wallet. */
476
+ export interface BrowserWalletProvider {
477
+ request(args: {
478
+ method: string;
479
+ params?: unknown[];
480
+ }): Promise<unknown>;
481
+ }
482
+ type SignedDto<T extends Record<string, unknown>> = T & {
483
+ signature: string;
273
484
  };
274
- /** A submitted v2 transaction whose confirmation mode is explicit in the gateway response. */
275
- export declare class SubmittedTransaction<TConfirmation = AppliedTrade | Position | null> {
276
- readonly method: string;
277
- readonly uniqueKey: string;
278
- readonly transactionId: string | null;
279
- readonly blockNumber: number | null;
280
- readonly mode: 'sync' | 'queued';
281
- /** The synchronous gateway result, or `undefined` when `mode === 'queued'`. */
282
- readonly result: unknown;
283
- private readonly backendBaseUrl;
284
- private readonly requestor;
285
- private readonly requestTimeoutMs;
286
- private readonly positionConfirmation;
287
- /** Construct a submitted transaction from a successful gateway response.
485
+ /**
486
+ * A signer for complete GalaChain write bodies.
487
+ *
488
+ * Implementations return the DTO fields together with the signature that belongs in the
489
+ * gateway request body. Signer identity is recovered from that signature; implementations do
490
+ * not add signer hints, typed-data metadata, or a domain.
491
+ */
492
+ export interface GalaChainSigner {
493
+ /**
494
+ * Signs a DTO for a named GalaChain contract method.
288
495
  *
289
496
  * @example
290
- * ```ts
291
- * const transaction = new SubmittedTransaction({
292
- * method: 'RequestTrade', mode: 'queued', uniqueKey: 'swap-1',
293
- * transactionId: 'request-tx', result: undefined,
294
- * dexBackendBaseUrl: 'https://dex.example', httpRequestor,
295
- * });
497
+ * ```typescript
498
+ * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
296
499
  * ```
297
500
  */
298
- constructor(options: {
299
- method: string;
300
- uniqueKey: string;
301
- transactionId: string | null;
302
- mode: 'sync' | 'queued';
303
- result: unknown;
304
- dexBackendBaseUrl: string;
305
- httpRequestor: HttpRequestor;
306
- blockNumber?: number | null | undefined;
307
- requestTimeoutMs?: number | undefined;
308
- positionConfirmation?: ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;
309
- });
310
- /** Confirm a queued RequestTrade or prove the affected position for a liquidity write.
311
- *
312
- * For RequestTrade, calling this method is required to learn the outcome: the queued
313
- * acknowledgement proves acceptance, not execution.
501
+ signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
502
+ }
503
+ /**
504
+ * The `0x`-prefixed Ethereum address a Gala account is signed by, or `undefined` when the account
505
+ * names no key (a `client|` alias or a bare GalaChain id is not derivable from a key). Accepts
506
+ * `0x` plus 40 hex digits and `eth|` plus 40 hex digits, with or without `0x`; the caller's casing
507
+ * is kept. For {@link LazyPrivateKeySignerOptions.expectedAddress}, which should only be set for
508
+ * an account whose key can be checked.
509
+ *
510
+ * @example
511
+ * ```ts
512
+ * createLazyPrivateKeySigner(getKey, { expectedAddress: ethereumAddressOfAccount(account) });
513
+ * ```
514
+ */
515
+ export declare function ethereumAddressOfAccount(account: string): string | undefined;
516
+ /**
517
+ * A GalaChain native signer backed by a secp256k1 private key.
518
+ *
519
+ * Native signing produces the bare GalaChain signature format, without a personal-sign prefix
520
+ * or EIP-712 metadata. The private-key identity is recovered by the chain.
521
+ */
522
+ export declare class PrivateKeySigner implements GalaChainSigner {
523
+ private readonly privateKey;
524
+ /**
525
+ * Creates a native signer from a hex or base64 secp256k1 private key.
314
526
  *
315
527
  * @example
316
- * ```ts
317
- * const applied = await submitted.confirm({ initialDelayMs: 3_000 });
528
+ * ```typescript
529
+ * const signer = new PrivateKeySigner('1'.padStart(64, '0'));
530
+ * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
318
531
  * ```
319
532
  */
320
- confirm(options?: ConfirmOptions): Promise<TConfirmation>;
321
- private confirmApplied;
322
- private readAppliedResult;
323
- /** Confirm a liquidity write against the position's observable effect.
533
+ constructor(privateKey: string);
534
+ /**
535
+ * Signs the DTO with GalaChain native signing.
324
536
  *
325
- * @returns The position after the write, or `null` for a confirmed full close.
326
537
  * @example
327
- * ```ts
328
- * const position = await submitted.confirm({ timeoutMs: 60_000 });
538
+ * ```typescript
539
+ * const signed = await signer.signObject('RequestTrade', {
540
+ * token0: 'GALA',
541
+ * token1: 'GUSDC',
542
+ * fee: 3000,
543
+ * });
329
544
  * ```
330
545
  */
331
- private confirmPosition;
546
+ signObject<T extends Record<string, unknown>>(_methodName: string, dto: T): Promise<SignedDto<T>>;
547
+ }
548
+ /** Supplies a private key at sign time: a hex/base64 string, possibly fetched asynchronously. */
549
+ export type PrivateKeyProvider = () => Promise<string> | string;
550
+ /** Options for {@link createLazyPrivateKeySigner}. */
551
+ export interface LazyPrivateKeySignerOptions {
552
+ /**
553
+ * When set, every signature first checks that the fetched key belongs to this account (`0x...`
554
+ * or the Gala `eth|0x...` / `eth|<40 hex>` form, case-insensitive) and refuses to sign otherwise
555
+ * (`SIGNER_ADDRESS_MISMATCH`). Use it when the key lives in a slot another surface can switch
556
+ * between the moment a request was approved and the moment it is signed.
557
+ */
558
+ expectedAddress?: string | undefined;
332
559
  }
333
560
  /**
334
- * Controls timeout and polling behavior for confirmation.
561
+ * Creates the native-signing equivalent of {@link PrivateKeySigner} for apps that must not hold a
562
+ * key in a long-lived object (an extension that reads its session key at sign time).
335
563
  *
336
- * - `timeoutMs` (default 60 000): overall deadline, counted from the `confirm()` call and
337
- * including `initialDelayMs`. At least one read is always made.
338
- * - `pollIntervalMs` (default 2 000, minimum 500): base interval, doubled with jitter up to 8 s.
339
- * - `initialDelayMs`: wait before the first read. Defaults to 3 000 for a queued RequestTrade
340
- * (the AutoApplier needs a few seconds) and 0 for liquidity writes (already executed).
564
+ * `getPrivateKey` is called once per `signObject` call, never cached, never shared between calls
565
+ * (concurrent signatures each fetch their own key), and the normalized key bytes are zeroed
566
+ * before `signObject` settles, also on failure. A rejection or exception from `getPrivateKey` is
567
+ * passed through unchanged, so the app's own "wallet is locked" error reaches its caller; a key
568
+ * that is not a valid secp256k1 key string is a `VALIDATION_ERROR` (`INVALID_PRIVATE_KEY`).
569
+ * Signatures are byte-identical to `new PrivateKeySigner(key).signObject(...)`.
570
+ *
571
+ * A JavaScript string cannot be wiped; the provider owns the lifetime of the string it returns.
572
+ *
573
+ * @example
574
+ * ```typescript
575
+ * const signer = createLazyPrivateKeySigner(
576
+ * () => SecurityHelper.getSessionSecret(SecurityHelper.SESSION_PRIVATE_KEY_KEY),
577
+ * { expectedAddress: account.address },
578
+ * );
579
+ * const gswap = new GSwap({ signer });
580
+ * ```
341
581
  */
342
- export interface ConfirmOptions {
343
- timeoutMs?: number | undefined;
344
- pollIntervalMs?: number | undefined;
345
- initialDelayMs?: number | undefined;
346
- }
347
- //#endregion
348
- //#region src/classes/gateway.d.ts
349
- /** Options for a chain-gateway client. */
350
- export interface ChainGatewayOptions {
351
- dexBackendBaseUrl: string;
582
+ export declare function createLazyPrivateKeySigner(getPrivateKey: PrivateKeyProvider, options?: LazyPrivateKeySignerOptions): GalaChainSigner;
583
+ /**
584
+ * A Gala Wallet signer using native GalaChain signing, with an opt-in personal-sign mode.
585
+ *
586
+ * The selected Ethereum account is passed to Gala Wallet. There is NO automatic fallback: a
587
+ * wallet that rejects `native` surfaces its error to the caller, because the only alternative,
588
+ * `personal-sign`, silently recovers a phantom signer on every released Gala Wallet.
589
+ *
590
+ * `scheme: 'personal-sign'` calls
591
+ * `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])` and REQUIRES
592
+ * a wallet build that contains wallet_extension commit 3ad7ae6 (strips the embedded `prefix`
593
+ * field and hashes `prefix` + the prefix-less canonical body, the chain's scheme). Wallets
594
+ * released before that fix hash the string with the `prefix` field still inside it and the
595
+ * signature recovers to an address nobody holds, so only opt in once the fixed wallet is
596
+ * released. See SIGNING-PARITY.md.
597
+ */
598
+ export declare class GalaWalletSigner implements GalaChainSigner {
599
+ /** The wallet address supplied to Gala Wallet for each signing request. */
600
+ readonly walletAddress: string;
601
+ /** The signing scheme used for every request; it never changes after construction. */
602
+ readonly scheme: GalaWalletScheme;
603
+ /**
604
+ * Creates a Gala Wallet signer.
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * const signer = new GalaWalletSigner('0x0123456789012345678901234567890123456789');
609
+ * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
610
+ * ```
611
+ *
612
+ * @param walletAddress - The account passed to Gala Wallet as the signer address. An Ethereum
613
+ * account is `0x` plus 40 hex digits (Gala Wallet's `eth|...` form is normalized to it and held
614
+ * to the same check); a GalaChain id is `client|` plus 24 hex digits, or the bare 24 hex digits
615
+ * frontend_v2 keeps for a direct `client|` login, and is passed through unchanged.
616
+ * @param options - Select native signing (default) or personal-sign explicitly.
617
+ * `'personal-sign'` requires a Gala Wallet build with wallet_extension commit 3ad7ae6.
618
+ * `selectAddress` is the identity (`client|...` / `eth|...`) Gala Wallet is switched to with
619
+ * `window.gala.setAddress` before every signature, when the wallet offers it.
620
+ */
621
+ constructor(walletAddress: string, options?: {
622
+ scheme?: GalaWalletScheme | undefined;
623
+ selectAddress?: string | undefined;
624
+ });
625
+ /** The identity Gala Wallet is switched to before each signature, if one was given. */
626
+ readonly selectAddress: string | undefined;
627
+ /**
628
+ * Signs a DTO through `gala_signChainDto`.
629
+ *
630
+ * @example
631
+ * ```typescript
632
+ * const signed = await signer.signObject('AddLiquidity', {
633
+ * token0: 'GALA',
634
+ * token1: 'GUSDC',
635
+ * tickLower: -60,
636
+ * tickUpper: 60,
637
+ * });
638
+ * ```
639
+ */
640
+ signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
641
+ }
642
+ /**
643
+ * A personal-sign signer for MetaMask and other EIP-1193 browser wallets.
644
+ *
645
+ * The chain recovers this signature using the EIP-191 wrap applied by the wallet to
646
+ * `personal_sign`. This is the browser-wallet path used by the v2 frontend and resolves the
647
+ * bare `eth|` identity.
648
+ */
649
+ export declare class BrowserWalletSigner implements GalaChainSigner {
650
+ private readonly provider;
651
+ /**
652
+ * Creates a browser-wallet signer.
653
+ *
654
+ * Defaults to `personal_sign` — unchanged from every existing integration, since it only ever
655
+ * resolves the bare `eth|` identity and changing that silently would be a real behavior
656
+ * break for anyone already depending on it. Pass `{ scheme: 'eip712' }` to correctly resolve
657
+ * a registered `client|` alias instead, for `RequestTrade`/`AddLiquidity`/`RemoveLiquidity`/
658
+ * `CollectPositionFees` (`EIP712_CAPABLE_METHODS`) — `CreatePool` and any other method still
659
+ * falls back to `personal_sign` even in `'eip712'` mode, since its EIP-712 signing is a
660
+ * separate, unsolved chain-side problem.
661
+ *
662
+ * @example
663
+ * ```typescript
664
+ * const signer = new BrowserWalletSigner(window.ethereum, '0x0123456789012345678901234567890123456789');
665
+ * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
666
+ * ```
667
+ * @example
668
+ * ```typescript
669
+ * // Correctly resolves a registered client| alias instead of the bare eth| address.
670
+ * const signer = new BrowserWalletSigner(window.ethereum, walletAddress, { scheme: 'eip712' });
671
+ * ```
672
+ */
673
+ constructor(provider: BrowserWalletProvider, walletAddress: string, options?: {
674
+ scheme?: 'personal-sign' | 'eip712';
675
+ });
676
+ readonly walletAddress: string;
677
+ private readonly scheme;
678
+ /**
679
+ * Signs the DTO with `eth_signTypedData_v4` (when constructed with `{ scheme: 'eip712' }` and
680
+ * `methodName` is in `EIP712_CAPABLE_METHODS`) or the EIP-1193 `personal_sign` method
681
+ * (otherwise — the default).
682
+ *
683
+ * @example
684
+ * ```typescript
685
+ * const signed = await signer.signObject('RequestTrade', {
686
+ * token0: 'GALA',
687
+ * token1: 'GUSDC',
688
+ * fee: 3000,
689
+ * });
690
+ * ```
691
+ */
692
+ signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
693
+ }
694
+ //#endregion
695
+ //#region src/classes/dex_fees.d.ts
696
+ /** DEX methods the backend accepts a fee quote for (its allow-list enumerates the same six). */
697
+ export declare const DEX_FEE_METHODS: readonly ['Swap', 'RequestTrade', 'AddLiquidity', 'RemoveLiquidity', 'CollectPositionFees', 'CreatePool'];
698
+ export type DexFeeMethod = (typeof DEX_FEE_METHODS)[number];
699
+ /** Which pool contract the DTO being quoted targets: legacy (V3) or current (GalaChainDex). */
700
+ export type DexFeeContract = 'dexv3-contract' | 'dex-contract';
701
+ /** The chain method name the signed DryRun wrapper is signed under. */
702
+ export declare const DRY_RUN_METHOD = "DryRun";
703
+ /** `uniqueKey` prefix of the DryRun WRAPPER (distinct from the inner DTO's key). */
704
+ export declare const DRY_RUN_UNIQUE_KEY_PREFIX = "galaconnect-operation-";
705
+ /** True when `method` is a DEX method a fee can be quoted for. */
706
+ export declare function isDexFeeMethod(method: unknown): method is DexFeeMethod;
707
+ /** Current-contract typed DEX messages use trading symbols instead of TokenClassKey objects. */
708
+ export declare function isCurrentContractDexMessage(message: Record<string, unknown> | null | undefined, method: unknown): boolean;
709
+ /**
710
+ * The backend's response. It ALWAYS carries a usable `fees[0].feeInGala`: the backend decides what
711
+ * to serve when the chain cannot price the operation, so the client never invents a fee.
712
+ *
713
+ * `source` is informational: `'dry-run'` is simulated on chain and authoritative (possibly a
714
+ * legitimate `'0'`), `'default'` means the chain could not price it and the platform default was
715
+ * served.
716
+ */
717
+ export interface DexFeeQuote {
718
+ fees: Array<{
719
+ feeInGala: string;
720
+ }>;
721
+ source: 'dry-run' | 'default';
722
+ }
723
+ /**
724
+ * Reduces an EIP-712 approval `message` to the DTO the chain actually receives: drops the signing
725
+ * envelope (`signature`, `prefix`, `types`, `domain`) and transport metadata (`trace`).
726
+ */
727
+ export declare function toChainDto(message: Record<string, unknown>): Record<string, unknown>;
728
+ /**
729
+ * Signs the DryRun WRAPPER the gateway accepts for every contract:
730
+ * `{ callerPublicKey, method, dto: <inner DTO object>, uniqueKey, signature }`. The inner DTO
731
+ * travels unsigned and as an object; no `signerPublicKey` is sent because the signature already
732
+ * recovers it (the gateway rejects it as REDUNDANT_SIGNER_PUBLIC_KEY). The wrapper carries its own
733
+ * `uniqueKey`, distinct from the DTO's.
734
+ */
735
+ export declare function buildDryRunWrapper(signer: GalaChainSigner, callerPublicKey: string, method: string, dto: Record<string, unknown>, uniqueKeyPrefix?: string): Promise<Record<string, unknown>>;
736
+ /** The transport and backend a fee quote reads from. */
737
+ export interface DexFeesClient {
738
+ /** Swap backend origin, e.g. `https://dex-backend-prod1.defi.gala.com`. */
739
+ dexBackendBaseUrl: string;
740
+ /** Defaults to the global `fetch`. */
741
+ httpRequestor?: HttpRequestor | undefined;
742
+ /** Per-request timeout in milliseconds (default 30 000). */
743
+ requestTimeoutMs?: number | undefined;
744
+ /**
745
+ * Request headers of the fee POST (`userAgent`, `headers`); see {@link WireOptions}. The SDK's
746
+ * `Accept: application/json` is a default that `wire.headers` may replace.
747
+ */
748
+ wire?: WireOptions | undefined;
749
+ }
750
+ /** Options for a single quote. */
751
+ export interface DexFeeQuoteOptions {
752
+ /** GalaChain channel. Default `asset`. */
753
+ channel?: string | undefined;
754
+ /**
755
+ * Contract the DTO targets. Default `dexv3-contract` (what every legacy caller quotes against);
756
+ * a current-contract operation must pass `dex-contract` explicitly.
757
+ */
758
+ contract?: DexFeeContract | undefined;
759
+ }
760
+ /**
761
+ * Network-fee quote for GalaChain DEX methods, derived from a server-side DryRun.
762
+ *
763
+ * The client only SIGNS the DryRun wrapper (with whatever {@link GalaChainSigner} it is given) and
764
+ * the backend forwards it to the gateway, where the simulated writes carry the fee; the backend
765
+ * never holds a key. Intended for wallets: the DTO quoted is the typed message a dApp handed over.
766
+ *
767
+ * @example
768
+ * ```ts
769
+ * const fees = new DexFees({ dexBackendBaseUrl }, new PrivateKeySigner(sessionKey));
770
+ * const quote = await fees.quote(publicKey, 'RequestTrade', toChainDto(message), {
771
+ * contract: 'dex-contract',
772
+ * });
773
+ * const feeInGala = quote?.fees[0]?.feeInGala;
774
+ * ```
775
+ */
776
+ export declare class DexFees {
777
+ private readonly signer;
778
+ private readonly requestor;
779
+ private readonly baseUrl;
780
+ private readonly requestTimeoutMs;
781
+ private readonly wire;
782
+ constructor(client: DexFeesClient, signer: GalaChainSigner | undefined);
783
+ /**
784
+ * Quotes the network fee for `method` applied to `message`. The message is reduced with
785
+ * {@link toChainDto} first, so an EIP-712 approval message can be passed as is.
786
+ *
787
+ * Resolves `null` when the BACKEND could not be reached or answered unusably (offline, 4xx/5xx,
788
+ * malformed body): a transport outcome, not a fee. Deciding what to charge when the chain is
789
+ * silent is the backend's job (it serves `source: 'default'`), so the client never substitutes
790
+ * a fee of its own, with ONE exception that mirrors the wallet: a `dex-contract` quote answered
791
+ * 403 or 404 means the contract has no fee route yet and resolves `{ source: 'default', '0' }`.
792
+ * Never throws on transport, so a fee lookup cannot block or break a signing screen.
793
+ *
794
+ * @throws GSwapSDKError NO_SIGNER when constructed without a signer; any error the signer
795
+ * throws (for example a locked wallet) propagates unchanged.
796
+ */
797
+ quote(callerPublicKey: string, method: DexFeeMethod, message: Record<string, unknown>, options?: DexFeeQuoteOptions): Promise<DexFeeQuote | null>;
798
+ }
799
+ //#endregion
800
+ //#region src/classes/shadow_submit.d.ts
801
+ /** The raw answer to a shadow (dark) write: every HTTP status resolves. */
802
+ export interface ShadowSubmitResult {
803
+ httpStatus: number;
804
+ /** Parsed JSON body, or the raw text when the body was not JSON. */
805
+ body: unknown;
806
+ }
807
+ /**
808
+ * Machine-readable codes defi-backend returns in a shadow failure body (`{ code, message }`, with
809
+ * no `statusCode`; the HTTP status carries the number).
810
+ *
811
+ * - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back
812
+ * silently to a public swap.
813
+ * - `SHADOW_DISABLED` (400): the feature is off for this environment.
814
+ * - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.
815
+ * - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;
816
+ * `message` is the gateway's verbatim string.
817
+ */
818
+ export type ShadowSubmitCode = 'SHADOW_UNAVAILABLE' | 'SHADOW_DISABLED' | 'SHADOW_UNSUPPORTED_TYPE' | 'SHADOW_RELAY_REJECTED';
819
+ /** The normalized outcome of a shadow write. */
820
+ export type ShadowSubmitOutcome = {
821
+ ok: true;
822
+ /** The request transaction id (`''` when the gateway gave none). */
823
+ bundleId: string;
824
+ /** Present for a queued RequestTrade: confirm with `confirmAppliedTrade`. */
825
+ queued?: {
826
+ uniqueKey: string;
827
+ requestTransactionId: string | null;
828
+ };
829
+ } | {
830
+ ok: false;
831
+ kind: 'unavailable';
832
+ retryable: true;
833
+ } | {
834
+ ok: false;
835
+ kind: 'disabled';
836
+ retryable: false;
837
+ } | {
838
+ ok: false;
839
+ kind: 'rejected';
840
+ retryable: false;
841
+ message: string;
842
+ } | {
843
+ ok: false;
844
+ kind: 'unknown';
845
+ retryable: false;
846
+ };
847
+ type ShadowFailureKind = Exclude<ShadowSubmitOutcome, {
848
+ ok: true;
849
+ }>['kind'];
850
+ /** Maps an HTTP status to a failure kind: 503 retryable, 400 disabled, anything else unknown. */
851
+ export declare function classifyShadowSubmitStatus(status: number): ShadowFailureKind;
852
+ /**
853
+ * Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.
854
+ * `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway
855
+ * rejection; the two other 400 codes and any unknown 400 map to "disabled".
856
+ */
857
+ export declare function classifyShadowSubmitError(status: number, code?: string): ShadowFailureKind;
858
+ /**
859
+ * Normalizes a shadow write's raw answer.
860
+ *
861
+ * A 2xx envelope with `error === false` is a success when it is a queued RequestTrade that
862
+ * acknowledges the EXACT signed `uniqueKey`, or a synchronous (`mode: 'sync'`) liquidity write.
863
+ * Everything else is classified as a failure from the status and the body's `code`.
864
+ *
865
+ * @throws GSwapSDKError INVALID_GATEWAY_RESPONSE when a RequestTrade success does not queue the
866
+ * signed `uniqueKey` (a synchronous or mismatched answer must never be accepted as a swap).
867
+ */
868
+ export declare function readShadowSubmitOutcome(method: string, signedBody: Record<string, unknown>, result: ShadowSubmitResult): ShadowSubmitOutcome;
869
+ //#endregion
870
+ //#region src/utils/submit_state.d.ts
871
+ /**
872
+ * What a write's gateway answer says about the write, as one vocabulary for every app.
873
+ *
874
+ * The gateway answers `{ status, message, error, data }`. `data.mode` is `'sync'` for a liquidity
875
+ * write (its executed chain result is in `data.result`) and `'queued'` for a RequestTrade
876
+ * acknowledgement (accepted, NOT executed: the outcome is read from apply-results with
877
+ * `confirm()`). `error: true` is the gateway refusing the write.
878
+ *
879
+ * A {@link SubmittedTransaction} only exists for an answer the SDK accepted, so its
880
+ * {@link SubmitStatus} is `'executed'` or `'queued'`; a refused answer is a thrown
881
+ * {@link GSwapSDKError}. The predicates below classify a RAW envelope instead, for an app that
882
+ * holds one (`SubmittedTransaction.envelope`, `GSwapSDKError.body`, a stored answer) and for the
883
+ * answers that never became a transaction. They reproduce frontend_v2's `isV2SubmitSuccess` /
884
+ * `isV2SubmitQueued` / `isV2SubmitRejected` exactly, so the app can delete its own copies.
885
+ */
886
+ /** The state of an accepted write: executed on chain (`mode: 'sync'`) or queued (`mode: 'queued'`). */
887
+ export type SubmitStatus = 'executed' | 'queued';
888
+ /**
889
+ * How a raw gateway envelope classifies:
890
+ *
891
+ * - `'executed'`: `error === false` and `data.mode === 'sync'` (the executed result came back).
892
+ * - `'queued'`: `error === false`, `data.mode === 'queued'` and `data.uniqueKey` is a string.
893
+ * - `'rejected'`: no envelope at all, or `error === true`: a DEFINITE failure.
894
+ * - `'unconfirmed'`: anything else (`error: false` with another or no `mode`, a queued answer
895
+ * with no `uniqueKey`, an envelope with no boolean `error`): accepted, outcome not known. It is
896
+ * NOT a rejection and must not be shown as one.
897
+ *
898
+ * The four are mutually exclusive and exhaustive.
899
+ */
900
+ export type SubmitClassification = SubmitStatus | 'rejected' | 'unconfirmed';
901
+ /** True when the envelope is a definite failure: absent, or `error === true`. */
902
+ export declare function isSubmitRejected(envelope: unknown): boolean;
903
+ /**
904
+ * True when the envelope carries an executed result: `error === false` and `data.mode === 'sync'`.
905
+ * A queued RequestTrade acknowledgement is deliberately NOT executed: its outcome is not known
906
+ * until apply-results resolves.
907
+ */
908
+ export declare function isSubmitExecuted(envelope: unknown): boolean;
909
+ /** True when the envelope acknowledges a `uniqueKey` as queued (`data.mode === 'queued'`). */
910
+ export declare function isSubmitQueued(envelope: unknown): boolean;
911
+ /** Classifies a raw gateway envelope; see {@link SubmitClassification}. */
912
+ export declare function classifySubmitEnvelope(envelope: unknown): SubmitClassification;
913
+ //#endregion
914
+ //#region src/classes/submitted_transaction.d.ts
915
+ /** Result of one position-confirmation poll. */
916
+ export type PositionConfirmationResult = {
917
+ confirmed: true;
918
+ position: Position | null;
919
+ } | {
920
+ confirmed: false;
921
+ position?: Position | null;
922
+ };
923
+ /** A submitted v2 transaction whose confirmation mode is explicit in the gateway response. */
924
+ export declare class SubmittedTransaction<TConfirmation = AppliedTrade | Position | null> {
925
+ readonly method: string;
926
+ readonly uniqueKey: string;
927
+ readonly transactionId: string | null;
928
+ readonly blockNumber: number | null;
929
+ /** The gateway's `data.mode`: `'sync'` (executed, `result` is the chain result) or `'queued'`. */
930
+ readonly mode: 'sync' | 'queued';
931
+ /**
932
+ * What the gateway's answer established: `'executed'` for `mode: 'sync'`, `'queued'` for
933
+ * `mode: 'queued'` (accepted, NOT executed: `await confirm()` for the outcome). A refused answer
934
+ * never becomes a transaction, so there is no `'rejected'` here; see {@link classifySubmitEnvelope}
935
+ * for classifying a raw envelope.
936
+ */
937
+ readonly status: SubmitStatus;
938
+ /** The synchronous gateway result, or `undefined` when `mode === 'queued'`. */
939
+ readonly result: unknown;
940
+ /**
941
+ * The gateway's whole JSON answer as it came (`{ status, message, error, data }`), for an app
942
+ * that hands the backend's own envelope to its callers; `undefined` for a transaction built from
943
+ * a uniqueKey alone.
944
+ */
945
+ readonly envelope: unknown;
946
+ private readonly backendBaseUrl;
947
+ private readonly requestor;
948
+ private readonly requestTimeoutMs;
949
+ private readonly wire;
950
+ private readonly positionConfirmation;
951
+ /** Construct a submitted transaction from a successful gateway response.
952
+ *
953
+ * @example
954
+ * ```ts
955
+ * const transaction = new SubmittedTransaction({
956
+ * method: 'RequestTrade', mode: 'queued', uniqueKey: 'swap-1',
957
+ * transactionId: 'request-tx', result: undefined,
958
+ * dexBackendBaseUrl: 'https://dex.example', httpRequestor,
959
+ * });
960
+ * ```
961
+ */
962
+ constructor(options: {
963
+ method: string;
964
+ uniqueKey: string;
965
+ transactionId: string | null;
966
+ mode: 'sync' | 'queued';
967
+ result: unknown;
968
+ dexBackendBaseUrl: string;
969
+ httpRequestor: HttpRequestor;
970
+ blockNumber?: number | null | undefined;
971
+ envelope?: unknown;
972
+ requestTimeoutMs?: number | undefined;
973
+ /** Wire options of the apply-results polls `confirm()` makes. */
974
+ wire?: WireOptions | undefined;
975
+ positionConfirmation?: ((signal: AbortSignal) => Promise<PositionConfirmationResult>) | undefined;
976
+ });
977
+ /** Confirm a queued RequestTrade or prove the affected position for a liquidity write.
978
+ *
979
+ * For RequestTrade, calling this method is required to learn the outcome: the queued
980
+ * acknowledgement proves acceptance, not execution.
981
+ *
982
+ * @example
983
+ * ```ts
984
+ * const applied = await submitted.confirm({ initialDelayMs: 3_000 });
985
+ * ```
986
+ */
987
+ confirm(options?: ConfirmOptions): Promise<TConfirmation>;
988
+ private confirmApplied;
989
+ /** Confirm a liquidity write against the position's observable effect.
990
+ *
991
+ * @returns The position after the write, or `null` for a confirmed full close.
992
+ * @example
993
+ * ```ts
994
+ * const position = await submitted.confirm({ timeoutMs: 60_000 });
995
+ * ```
996
+ */
997
+ private confirmPosition;
998
+ }
999
+ //#endregion
1000
+ //#region src/classes/gateway.d.ts
1001
+ /** Options for a chain-gateway client. */
1002
+ export interface ChainGatewayOptions {
1003
+ dexBackendBaseUrl: string;
352
1004
  httpRequestor?: HttpRequestor | undefined;
353
1005
  walletAddress?: string | undefined;
1006
+ /**
1007
+ * Timeout of every gateway request in milliseconds (default 30 000); also the per-read timeout
1008
+ * of the services built on this gateway and of `confirm()`. `Infinity` arms no timer, for an
1009
+ * app whose HTTP stack owns request lifetimes.
1010
+ */
354
1011
  chainCallTimeoutMs?: number | undefined;
1012
+ /**
1013
+ * Wire format of every request of this gateway and of the services built on it: the headers
1014
+ * (`userAgent`, `headers`) of reads AND of the POSTs that submit writes, and the query encoding
1015
+ * of reads. `X-Wallet-Address` and `X-Shadow` always win over a same-named `wire.headers` entry.
1016
+ */
1017
+ wire?: WireOptions | undefined;
355
1018
  }
356
1019
  /** Optional attribution and operation-specific confirmation hooks for a write. */
357
1020
  export interface ChainSubmitOptions {
@@ -365,11 +1028,35 @@ export declare class ChainGateway {
365
1028
  private readonly chainCallTimeoutMs;
366
1029
  readonly requestTimeoutMs: number;
367
1030
  readonly dexBackendBaseUrl: string;
1031
+ /** Wire format shared by the read services built on this gateway. */
1032
+ readonly wire: WireOptions;
368
1033
  /** Create a chain gateway client. */
369
1034
  constructor(options: ChainGatewayOptions);
370
1035
  /** Submit a signed v2 DTO through the chain gateway. */
371
1036
  submit(method: 'RequestTrade', signedBody: Record<string, unknown>, options?: ChainSubmitOptions): Promise<SubmittedTransaction<AppliedTrade>>;
372
1037
  submit(method: string, signedBody: Record<string, unknown>, options?: ChainSubmitOptions): Promise<SubmittedTransaction<Position | null>>;
1038
+ /**
1039
+ * Submit a signed v2 DTO as a SHADOW (dark) write: the same route and body as {@link submit},
1040
+ * plus `X-Wallet-Address` and `X-Shadow: true`, so defi-backend marks the transaction private
1041
+ * before it reaches the contract. The wallet address is required (the backend resolves the
1042
+ * owner from it).
1043
+ *
1044
+ * Unlike `submit`, EVERY HTTP status resolves: the result is the raw `{ httpStatus, body }`,
1045
+ * because shadow failures are classified from the status together with the body's `code`
1046
+ * (`SHADOW_UNAVAILABLE`, `SHADOW_DISABLED`, `SHADOW_UNSUPPORTED_TYPE`, `SHADOW_RELAY_REJECTED`);
1047
+ * see `readShadowSubmitOutcome`. Only a transport failure rejects, and a timeout rejects
1048
+ * with `SUBMISSION_OUTCOME_UNKNOWN`.
1049
+ *
1050
+ * @example
1051
+ * ```ts
1052
+ * const result = await gateway.submitShadow('RequestTrade', signedDto, { walletAddress });
1053
+ * const outcome = readShadowSubmitOutcome('RequestTrade', signedDto, result);
1054
+ * ```
1055
+ */
1056
+ submitShadow(method: string, signedBody: Record<string, unknown>, options?: ChainSubmitOptions): Promise<ShadowSubmitResult>;
1057
+ private writeUrl;
1058
+ /** POSTs a signed body; a timeout means the outcome is unknown, never "not submitted". */
1059
+ private post;
373
1060
  /** Expose the requestor for sibling read services that share this gateway transport. */
374
1061
  get httpRequestor(): HttpRequestor;
375
1062
  }
@@ -390,6 +1077,20 @@ export interface GdexStreamConfig {
390
1077
  * global `WebSocket` (pass the one from the `ws` package).
391
1078
  */
392
1079
  webSocketImpl?: unknown;
1080
+ /**
1081
+ * Presents `x-api-key` on the WebSocket upgrade request, which defi-backend uses to serve the
1082
+ * PRIVILEGED view (shadow swaps with the wallet unredacted). Without it, or with a wrong key, the
1083
+ * connection is simply public: the server never says whether a privileged mode exists.
1084
+ *
1085
+ * It must travel as an HTTP header, because the server reads no other credential, and a browser
1086
+ * `WebSocket` cannot set headers. So this option needs a constructor that accepts them as its
1087
+ * third argument (`{ headers }`): the `ws` package on Node.js, or React Native's built-in
1088
+ * `WebSocket`. It therefore REQUIRES `webSocketImpl` (the platform default is never assumed to
1089
+ * honor headers, and a key that is silently dropped would look like a working privileged
1090
+ * connection); the constructor throws otherwise. Use it from server-side code only: a key
1091
+ * shipped inside a browser or app bundle is not a secret. Browser clients stay public.
1092
+ */
1093
+ apiKey?: string | undefined;
393
1094
  }
394
1095
  /** The channels of the realtime stream. */
395
1096
  export type GdexChannel = 'pool' | 'balance' | 'poolCreated' | 'swap' | 'liquidity' | 'blocks';
@@ -482,6 +1183,7 @@ export declare class GdexStreamError extends Error {
482
1183
  export declare class GdexStreamService {
483
1184
  private readonly url;
484
1185
  private readonly requestTimeoutMs;
1186
+ private readonly apiKey;
485
1187
  private readonly webSocketConstructor;
486
1188
  private readonly backoff;
487
1189
  private socket;
@@ -502,6 +1204,7 @@ export declare class GdexStreamService {
502
1204
  isConnected(): boolean;
503
1205
  /** Raw JSON-RPC escape hatch. */
504
1206
  request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
1207
+ private send;
505
1208
  serverInfo(): Promise<Record<string, unknown>>;
506
1209
  ping(): Promise<{
507
1210
  pong: boolean;
@@ -595,13 +1298,31 @@ export declare const TICK_SPACING_BY_FEE: Readonly<Record<FEE_TIER, number>>;
595
1298
  /** All fee tiers supported by the current GalaChainDex contract. */
596
1299
  export declare const ALL_FEE_TIERS: readonly FEE_TIER[];
597
1300
  //#endregion
598
- //#region src/types/token.d.ts
599
- export interface GalaChainTokenClassKey {
600
- collection: string;
601
- category: string;
602
- type: string;
603
- additionalKey: string;
1301
+ //#region src/utils/lenient.d.ts
1302
+ /** One row of a list answer that the SDK skipped because it was not usable. */
1303
+ interface InvalidEntry {
1304
+ /** Which read the row came from. */
1305
+ source: 'pools' | 'symbols' | 'positions';
1306
+ /** Position of the row in the answer's array. */
1307
+ index: number;
1308
+ /** The row exactly as the backend sent it. */
1309
+ entry: unknown;
1310
+ /** Why it was skipped, in words. */
1311
+ reason: string;
604
1312
  }
1313
+ /**
1314
+ * Called once per skipped row, in order, before the read resolves. It is a diagnostics hook: what it
1315
+ * does, or throws, never changes the result of the read.
1316
+ */
1317
+ type InvalidEntryHandler = (invalid: InvalidEntry) => void;
1318
+ /** The outcome of reading one row. */
1319
+ type EntryParse<T> = {
1320
+ ok: true;
1321
+ value: T;
1322
+ } | {
1323
+ ok: false;
1324
+ reason: string;
1325
+ };
605
1326
  //#endregion
606
1327
  //#region src/utils/ordering.d.ts
607
1328
  /** A symbol or a GalaChain token class key accepted by v2 operations. */
@@ -642,15 +1363,26 @@ export declare function parseTokenClassKey(tokenClassKey: TokenRef): GalaChainTo
642
1363
  /** Symbol registry client for the current GalaChainDex contract. */
643
1364
  export declare class Symbols {
644
1365
  private readonly gateway;
1366
+ private readonly options;
645
1367
  private cachedSymbols;
646
1368
  private cachedAt;
647
1369
  private refreshInFlight;
648
1370
  private readonly http;
649
- /** Create a symbol service backed by the swap backend. */
1371
+ /**
1372
+ * Create a symbol service backed by the swap backend. `onInvalidEntry` is told about every
1373
+ * registry row that was skipped as unusable (see {@link InvalidEntryHandler}).
1374
+ */
650
1375
  constructor(gateway: Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {
651
1376
  requestTimeoutMs?: number | undefined;
1377
+ wire?: WireOptions | undefined;
1378
+ }, options?: {
1379
+ onInvalidEntry?: InvalidEntryHandler | undefined;
652
1380
  });
653
- /** List all registered GalaChainDex trading symbols, cached for 60 seconds. */
1381
+ /**
1382
+ * List all registered GalaChainDex trading symbols, cached for 60 seconds. A registry row that
1383
+ * is not a usable symbol is skipped (and reported to `onInvalidEntry`) instead of failing the
1384
+ * whole list.
1385
+ */
654
1386
  list(): Promise<TradingSymbol[]>;
655
1387
  /** Invalidate the cached symbol registry after a write changes registration state.
656
1388
  *
@@ -670,7 +1402,32 @@ export declare class Symbols {
670
1402
  refresh(): Promise<TradingSymbol[]>;
671
1403
  /** Resolve a symbol or token class key to its registered symbol metadata. */
672
1404
  resolve(ref: TokenRef): Promise<TradingSymbol>;
673
- /** Resolve and put two token references in canonical trading-symbol order. */
1405
+ /**
1406
+ * The trading symbol to put in a token's first CreatePool.
1407
+ *
1408
+ * 1. The symbol ALREADY registered for exactly this class key, if any: proposing another one
1409
+ * fails the gateway's registry-conflict check.
1410
+ * 2. Otherwise `displaySymbol` (the token's curated symbol), when it is proposable
1411
+ * ({@link isProposableTradingSymbol}).
1412
+ * 3. Otherwise a `VALIDATION_ERROR`: a symbol is never derived from the key (BNB's collection is
1413
+ * `GBNB`, a launchpad token's is the reserved word `Token`).
1414
+ *
1415
+ * `registryFailure: 'ignore'` treats an unreachable registry as an empty one and falls through
1416
+ * to step 2 (the gateway still rejects a conflicting symbol); the default `'throw'` propagates
1417
+ * the failure.
1418
+ *
1419
+ * @example
1420
+ * ```ts
1421
+ * const symbol = await gSwap.symbols.proposeSymbol(
1422
+ * { collection: 'GALA_TEST1', category: 'Unit', type: 'none', additionalKey: 'none' },
1423
+ * 'GALATEST',
1424
+ * );
1425
+ * ```
1426
+ */
1427
+ proposeSymbol(classKey: GalaChainTokenClassKey, displaySymbol: string, options?: {
1428
+ registryFailure?: 'throw' | 'ignore' | undefined;
1429
+ }): Promise<string>;
1430
+ /** Resolve and put two token references in canonical trading-symbol order. */
674
1431
  orderPair(a: TokenRef, b: TokenRef): Promise<{
675
1432
  token0: TradingSymbol;
676
1433
  token1: TradingSymbol;
@@ -679,38 +1436,109 @@ export declare class Symbols {
679
1436
  }
680
1437
  /** Alias exported for callers that use the contract's shorter type name. */
681
1438
  export type TokenClassKey = GalaChainTokenClassKey;
1439
+ /**
1440
+ * What the services need from a token resolver: how a token reference becomes a trading symbol,
1441
+ * and whether requests carry the caller's references untouched. {@link Symbols} is the registry
1442
+ * resolver (one `GET /v2/trade/symbols`, cached); {@link CanonicalSymbols} is the offline one.
1443
+ */
1444
+ export interface TokenResolver {
1445
+ resolve(ref: TokenRef): Promise<TradingSymbol>;
1446
+ /**
1447
+ * True when reads send the caller's token references verbatim (a symbol, or a composite key as
1448
+ * the caller wrote it) and let the backend resolve and orient the pair — no registry request
1449
+ * and no client-side ordering or tick flip.
1450
+ */
1451
+ readonly passthrough?: boolean | undefined;
1452
+ }
1453
+ /** A token reference as the caller wrote it: a string verbatim, a class key as its `$` composite. */
1454
+ export declare function rawTokenOf(ref: TokenRef): string;
1455
+ /** The trading symbol of a reference, or `SYMBOL_NOT_FOUND` when the resolver has none. */
1456
+ export declare function tradingSymbolOf(resolver: TokenResolver, ref: TokenRef): Promise<string>;
1457
+ /** What a read request names a token by: the reference itself in pass-through mode, else its symbol. */
1458
+ export declare function queryTokenOf(resolver: TokenResolver, ref: TokenRef): Promise<string>;
1459
+ /**
1460
+ * The offline resolver for apps that already hold the backend's canonical trading symbols (from
1461
+ * `/quote`, `/add-liq-estimate`, a position row) and must not make a registry request of their own.
1462
+ *
1463
+ * - `resolve` accepts a bare trading symbol and returns it as is; a class key (object, `$` or `|`
1464
+ * form) is not a symbol and is refused as `UNKNOWN_TOKEN`. `createPool` relies on that refusal to
1465
+ * fall back to the symbols its caller supplies.
1466
+ * - `orderPair` orders two symbols by plain string comparison, as the contract does.
1467
+ * - Reads are pass-through (see {@link TokenResolver.passthrough}): the caller's references go on
1468
+ * the wire verbatim, composite keys included, and the backend orients the pair.
1469
+ *
1470
+ * @example
1471
+ * ```ts
1472
+ * const swaps = new Swaps(gateway, new CanonicalSymbols(), signer, walletAddress);
1473
+ * await swaps.swap('GALA', 'GUSDC', 3000, { exactIn: '10' });
1474
+ * ```
1475
+ */
1476
+ export declare class CanonicalSymbols implements TokenResolver {
1477
+ readonly passthrough = true;
1478
+ /** Resolve a bare trading symbol to itself. */
1479
+ resolve(ref: TokenRef): Promise<TradingSymbol>;
1480
+ /** Put two symbols in canonical (string) order. */
1481
+ orderPair(a: TokenRef, b: TokenRef): Promise<{
1482
+ token0: TradingSymbol;
1483
+ token1: TradingSymbol;
1484
+ flipped: boolean;
1485
+ }>;
1486
+ /** There is no registry state to drop. */
1487
+ invalidate(): void;
1488
+ }
682
1489
  //#endregion
683
1490
  //#region src/classes/pools.d.ts
684
1491
  type PoolGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {
685
1492
  requestTimeoutMs?: number | undefined;
1493
+ wire?: WireOptions | undefined;
686
1494
  };
687
- type PoolSymbols = Pick<Symbols, 'resolve'>;
1495
+ /** The sort keys of `GET /v2/trade/pools`. */
1496
+ export type PoolSortBy = 'tvl' | 'volume1d' | 'volume30d';
1497
+ /** Options of {@link Pools.getPools}. Omit all of `search`, `sortBy`, `sortOrder`, `page`, `limit` for the full, unsorted list. */
1498
+ export interface PoolListOptions {
1499
+ signal?: AbortSignal | undefined;
1500
+ /** Case-insensitive match on the pair's symbols; `A/B` or `A B` matches either order. At most 64 characters. */
1501
+ search?: string | undefined;
1502
+ sortBy?: PoolSortBy | undefined;
1503
+ sortOrder?: 'asc' | 'desc' | undefined;
1504
+ /** 1-based page number; only meaningful together with `limit`. */
1505
+ page?: number | undefined;
1506
+ /** Rows per page, 1-1000; omitted returns every row. */
1507
+ limit?: number | undefined;
1508
+ /** Overrides the service-level handler for this call. */
1509
+ onInvalidEntry?: InvalidEntryHandler | undefined;
1510
+ }
688
1511
  /** Read-only pool and current-price access for the current GalaChainDex contract. */
689
1512
  export declare class Pools {
690
1513
  private readonly gateway;
691
1514
  private readonly symbols;
1515
+ private readonly options;
692
1516
  /**
693
- * Creates a pool service.
1517
+ * Creates a pool service. `options.onInvalidEntry` is told about every pool row that was
1518
+ * skipped as unusable (see {@link InvalidEntryHandler}).
694
1519
  *
695
1520
  * @example
696
1521
  * ```ts
697
1522
  * const pools = new Pools(gateway, symbols);
698
1523
  * ```
699
1524
  */
700
- constructor(gateway: PoolGateway, symbols: PoolSymbols);
1525
+ constructor(gateway: PoolGateway, symbols: TokenResolver, options?: {
1526
+ onInvalidEntry?: InvalidEntryHandler | undefined;
1527
+ });
701
1528
  private readonly http;
702
1529
  /**
703
- * Fetches every current-contract pool from the swap backend.
1530
+ * Fetches current-contract pools from the swap backend, optionally searched, sorted and paged
1531
+ * by the backend. A row that is not a usable pool is skipped and reported to `onInvalidEntry`
1532
+ * instead of failing the whole list; an answer that is not a list at all is
1533
+ * `INVALID_CHAIN_RESPONSE`.
704
1534
  *
705
1535
  * @example
706
1536
  * ```ts
707
- * const pools = await service.getPools();
708
- * console.log(pools.length);
1537
+ * const top = await service.getPools({ sortBy: 'tvl', sortOrder: 'desc', page: 1, limit: 8 });
1538
+ * console.log(top.length);
709
1539
  * ```
710
1540
  */
711
- getPools(options?: {
712
- signal?: AbortSignal | undefined;
713
- }): Promise<PoolListInfo[]>;
1541
+ getPools(options?: PoolListOptions): Promise<PoolListInfo[]>;
714
1542
  /**
715
1543
  * Fetches one pool from the backend, preserving whether the request order was flipped.
716
1544
  *
@@ -745,237 +1573,342 @@ export declare class Pools {
745
1573
  private getBackend;
746
1574
  }
747
1575
  //#endregion
748
- //#region src/classes/signers.d.ts
749
- /** The signing schemes supported by the Gala Wallet signer. */
750
- export type GalaWalletScheme = 'native' | 'personal-sign';
751
- /** The request surface used by an EIP-1193 browser wallet. */
752
- export interface BrowserWalletProvider {
753
- request(args: {
754
- method: string;
755
- params?: unknown[];
756
- }): Promise<unknown>;
1576
+ //#region src/types/branding.d.ts
1577
+ interface Branding<BrandT> {
1578
+ _type: BrandT;
757
1579
  }
758
- type SignedDto<T extends Record<string, unknown>> = T & {
759
- signature: string;
1580
+ type Brand<T, BrandT> = T & Branding<BrandT>;
1581
+ //#endregion
1582
+ //#region src/types/amounts.d.ts
1583
+ export type NumericAmount = string | BigNumber;
1584
+ export type SqrtPrice = Brand<BigNumber, 'SqrtPrice'>;
1585
+ export type SqrtPriceIn = Brand<NumericAmount, 'SqrtPriceIn'> | SqrtPrice;
1586
+ export type Price = Brand<BigNumber, 'Price'>;
1587
+ export type PriceIn = Brand<NumericAmount, 'PriceIn'> | Price;
1588
+ /**
1589
+ * What a swap trades: exactly one of `exactIn` (sell this much of the input token) or `exactOut`
1590
+ * (receive this much of the output token), with that side's slippage bound and an optional
1591
+ * sqrt-price limit.
1592
+ */
1593
+ export type SwapAmount = {
1594
+ exactIn: NumericAmount;
1595
+ exactOut?: undefined;
1596
+ amountOutMinimum?: NumericAmount | undefined;
1597
+ amountInMaximum?: undefined;
1598
+ /** Sqrt-price limit passed through to the chain as `priceLimit`; omitted when undefined. */
1599
+ priceLimit?: NumericAmount | undefined;
1600
+ } | {
1601
+ exactIn?: undefined;
1602
+ exactOut: NumericAmount;
1603
+ amountOutMinimum?: undefined;
1604
+ amountInMaximum?: NumericAmount | undefined;
1605
+ /** Sqrt-price limit passed through to the chain as `priceLimit`; omitted when undefined. */
1606
+ priceLimit?: NumericAmount | undefined;
1607
+ };
1608
+ //#endregion
1609
+ //#region src/types/v2_dtos.d.ts
1610
+ /** Common identity fields for v2 pool writes. */
1611
+ export type V2PoolWriteBase = Record<'token0' | 'token1' | 'uniqueKey', string> & {
1612
+ fee: FEE_TIER;
1613
+ };
1614
+ /** A v2 RequestTrade with exactly one selected trade-side quantity. */
1615
+ export type RequestTradeDTO = V2PoolWriteBase & ({
1616
+ sell0Qty: string;
1617
+ sell1Qty?: never;
1618
+ buy0Qty?: never;
1619
+ buy1Qty?: never;
1620
+ } | {
1621
+ sell0Qty?: never;
1622
+ sell1Qty: string;
1623
+ buy0Qty?: never;
1624
+ buy1Qty?: never;
1625
+ } | {
1626
+ sell0Qty?: never;
1627
+ sell1Qty?: never;
1628
+ buy0Qty: string;
1629
+ buy1Qty?: never;
1630
+ } | {
1631
+ sell0Qty?: never;
1632
+ sell1Qty?: never;
1633
+ buy0Qty?: never;
1634
+ buy1Qty: string;
1635
+ }) & {
1636
+ amountOutMinimum?: string | undefined;
1637
+ amountInMaximum?: string | undefined;
1638
+ priceLimit?: string | undefined;
1639
+ };
1640
+ /** A v2 liquidity deposit with exactly one selected deposit quantity. */
1641
+ export type AddLiquidityDTO = V2PoolWriteBase & {
1642
+ tickLower: number;
1643
+ tickUpper: number;
1644
+ } & ({
1645
+ depositQuantityToken0: string;
1646
+ depositQuantityToken1?: never;
1647
+ } | {
1648
+ depositQuantityToken0?: never;
1649
+ depositQuantityToken1: string;
1650
+ });
1651
+ /** A v2 liquidity withdrawal; omitting both quantities closes the position. */
1652
+ export type RemoveLiquidityDTO = V2PoolWriteBase & {
1653
+ tickLower: number;
1654
+ tickUpper: number;
1655
+ } & ({
1656
+ withdrawalQuantityToken0: string;
1657
+ withdrawalQuantityToken1?: never;
1658
+ } | {
1659
+ withdrawalQuantityToken0?: never;
1660
+ withdrawalQuantityToken1: string;
1661
+ } | {
1662
+ withdrawalQuantityToken0?: never;
1663
+ withdrawalQuantityToken1?: never;
1664
+ });
1665
+ /** A v2 request to sweep all fees from one position. */
1666
+ export type CollectPositionFeesDTO = V2PoolWriteBase & {
1667
+ tickLower: number;
1668
+ tickUpper: number;
760
1669
  };
1670
+ /** A v2 pool creation request with exactly one initial-price representation. */
1671
+ export type CreatePoolDTO = {
1672
+ token0Key: GalaChainTokenClassKey;
1673
+ token1Key: GalaChainTokenClassKey;
1674
+ token0Symbol: string;
1675
+ token1Symbol: string;
1676
+ fee: FEE_TIER;
1677
+ name?: string | undefined;
1678
+ isPrivate?: boolean | undefined;
1679
+ privateAccess?: string[] | undefined;
1680
+ uniqueKey: string;
1681
+ } & ({
1682
+ startingPrice: string;
1683
+ startingSqrtPrice?: never;
1684
+ } | {
1685
+ startingPrice?: never;
1686
+ startingSqrtPrice: string;
1687
+ });
1688
+ /** Optional page cursor accepted by chain read methods. */
1689
+ export interface PageDTO {
1690
+ limit?: number | undefined;
1691
+ bookmark?: string | undefined;
1692
+ }
1693
+ /** Fetch all registered trading symbols. */
1694
+ export type FetchTokenTradingSymbolsDTO = PageDTO;
1695
+ /** Fetch a composite pool snapshot. */
1696
+ export interface FetchCompositePoolDataDTO {
1697
+ token0: string;
1698
+ token1: string;
1699
+ fee: FEE_TIER;
1700
+ }
1701
+ /** Fetch one current trading price, or all prices when no pair is supplied. */
1702
+ export type FetchCurrentTradingPricesDTO = Partial<FetchCompositePoolDataDTO> & PageDTO;
1703
+ /** Fetch pools, optionally narrowed to one pair and paged. */
1704
+ export type FetchPoolsDTO = Partial<FetchCompositePoolDataDTO> & PageDTO;
1705
+ /** Fetch all liquidity positions, optionally narrowed to a pool reference. */
1706
+ export interface FetchLiquidityPositionsDTO extends PageDTO {
1707
+ pool?: string | undefined;
1708
+ }
1709
+ //#endregion
1710
+ //#region src/utils/unique_key.d.ts
761
1711
  /**
762
- * A signer for complete GalaChain write bodies.
1712
+ * The `uniqueKey` prefix frontend_v2 and wallet_extension have always sent
1713
+ * (`galaswap-operation-<uuid>`). defi-backend does not depend on it: the chain-write verifier
1714
+ * only requires a non-empty key of at most 256 characters, and apply-results accepts
1715
+ * `[A-Za-z0-9._:-]{1,128}`; the only code that mints a prefixed key itself is the server-side v1
1716
+ * trade builder, which nothing reads back by prefix.
1717
+ */
1718
+ export declare const DEFAULT_UNIQUE_KEY_PREFIX = "galaswap-operation-";
1719
+ /** Options shared by the services that mint `uniqueKey`s for writes. */
1720
+ export interface UniqueKeyOptions {
1721
+ /**
1722
+ * Prefix of every minted `uniqueKey` (`<prefix><uuid>`). Defaults to
1723
+ * `DEFAULT_UNIQUE_KEY_PREFIX` (`galaswap-operation-`).
1724
+ */
1725
+ uniqueKeyPrefix?: string | undefined;
1726
+ }
1727
+ /**
1728
+ * Validates a caller-supplied `uniqueKey` prefix. The whole key (`<prefix><uuid>`) must stay a
1729
+ * valid apply-results key, otherwise `confirm()` could never read the outcome of the write.
763
1730
  *
764
- * Implementations return the DTO fields together with the signature that belongs in the
765
- * gateway request body. Signer identity is recovered from that signature; implementations do
766
- * not add signer hints, typed-data metadata, or a domain.
1731
+ * @throws GSwapSDKError VALIDATION_ERROR when the prefix has characters outside `A-Za-z0-9._:-` or
1732
+ * is longer than 92 characters.
767
1733
  */
768
- export interface GalaChainSigner {
1734
+ export declare function resolveUniqueKeyPrefix(prefix: string | undefined): string;
1735
+ /**
1736
+ * Validates a caller-supplied write `uniqueKey`: 1 to 128 characters of `A-Za-z0-9._:-`, the
1737
+ * shape the apply-results route accepts, so the write's outcome can always be read back with
1738
+ * `confirm()`. A key is one attempt's identity: reuse it only to retry that same attempt.
1739
+ *
1740
+ * @throws GSwapSDKError VALIDATION_ERROR otherwise.
1741
+ */
1742
+ export declare function assertUniqueKey(uniqueKey: string): void;
1743
+ /** A fresh per-attempt key: `<prefix><random UUID>`. */
1744
+ export declare function createUniqueKey(prefix: string): string;
1745
+ //#endregion
1746
+ //#region src/classes/positions.d.ts
1747
+ type PositionGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {
1748
+ submit: (method: string, signedBody: Record<string, unknown>, options?: ChainSubmitOptions) => Promise<SubmittedTransaction<Position | null>>;
1749
+ requestTimeoutMs?: number | undefined;
1750
+ wire?: WireOptions | undefined;
1751
+ };
1752
+ type PositionSymbols = TokenResolver & Pick<Symbols, 'orderPair'> & {
1753
+ invalidate?: () => void;
1754
+ };
1755
+ /** Options of {@link Positions}: the `uniqueKey` prefix and a handler for skipped list rows. */
1756
+ export interface PositionsOptions extends UniqueKeyOptions {
1757
+ /** Told about every position row of a list that was skipped as unusable. */
1758
+ onInvalidEntry?: InvalidEntryHandler | undefined;
1759
+ }
1760
+ /** A write's optional attempt identity. */
1761
+ interface UniqueKeyArg {
769
1762
  /**
770
- * Signs a DTO for a named GalaChain contract method.
771
- *
772
- * @example
773
- * ```typescript
774
- * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
775
- * ```
1763
+ * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh
1764
+ * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing, or to retry the SAME
1765
+ * attempt after a lost response; never reuse it for another write.
776
1766
  */
777
- signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
1767
+ uniqueKey?: string | undefined;
1768
+ }
1769
+ /** Arguments of {@link Positions.addLiquidityByTicks} and {@link Positions.buildAddLiquidity}. */
1770
+ export interface AddLiquidityArgs extends UniqueKeyArg {
1771
+ token0: TokenRef;
1772
+ token1: TokenRef;
1773
+ fee: FEE_TIER;
1774
+ tickLower: number;
1775
+ tickUpper: number;
1776
+ amount: NumericAmount;
1777
+ /** Whether `amount` is of `token0` as the caller passed it (not of the canonical token0). */
1778
+ amountIsToken0: boolean;
1779
+ }
1780
+ /** Arguments of {@link Positions.removeLiquidity} and {@link Positions.buildRemoveLiquidity}. */
1781
+ export interface RemoveLiquidityArgs extends UniqueKeyArg {
1782
+ token0: TokenRef;
1783
+ token1: TokenRef;
1784
+ fee: FEE_TIER;
1785
+ tickLower: number;
1786
+ tickUpper: number;
1787
+ /** Withdraw this much of the caller's `token0`; give at most one of `amount0` / `amount1`. */
1788
+ amount0?: NumericAmount | undefined;
1789
+ amount1?: NumericAmount | undefined;
1790
+ }
1791
+ /** Arguments of {@link Positions.collectPositionFees} and {@link Positions.buildCollectPositionFees}. */
1792
+ export interface CollectPositionFeesArgs extends UniqueKeyArg {
1793
+ token0: TokenRef;
1794
+ token1: TokenRef;
1795
+ fee: FEE_TIER;
1796
+ tickLower: number;
1797
+ tickUpper: number;
1798
+ }
1799
+ /** Arguments of {@link Positions.createPool} and {@link Positions.buildCreatePool}. */
1800
+ export interface CreatePoolArgs extends UniqueKeyArg {
1801
+ token0: TokenRef;
1802
+ token1: TokenRef;
1803
+ token0Symbol?: string | undefined;
1804
+ token1Symbol?: string | undefined;
1805
+ fee: FEE_TIER;
1806
+ startingPrice?: NumericAmount | undefined;
1807
+ startingSqrtPrice?: NumericAmount | undefined;
1808
+ /** Optional pool display name, sent as the DTO's `name`; omitted when undefined or empty. */
1809
+ name?: string | undefined;
1810
+ isPrivate?: boolean | undefined;
1811
+ privateAccess?: string[] | undefined;
778
1812
  }
779
1813
  /**
780
- * A GalaChain native signer backed by a secp256k1 private key.
1814
+ * The outcome of {@link Positions.readPosition}. Only `not_found` is chain-confirmed absence (the
1815
+ * backend answers HTTP 404 only when the chain itself found no such position); `unknown` is "no
1816
+ * evidence either way" — a transport failure, a gateway timeout, any other error status or an
1817
+ * answer that is not a position — and must never be read as a removal.
1818
+ */
1819
+ export type PositionRead = {
1820
+ kind: 'found';
1821
+ data: Position;
1822
+ } | {
1823
+ kind: 'not_found';
1824
+ } | {
1825
+ kind: 'unknown';
1826
+ error: GSwapSDKError;
1827
+ };
1828
+ /**
1829
+ * Manages current-contract concentrated-liquidity positions.
781
1830
  *
782
- * Native signing produces the bare GalaChain signature format, without a personal-sign prefix
783
- * or EIP-712 metadata. The private-key identity is recovered by the chain.
1831
+ * @example
1832
+ * ```typescript
1833
+ * const positions = gSwap.positions;
1834
+ * const mine = await positions.getUserPositions('client|012345678901234567890123');
1835
+ * console.log(mine.length);
1836
+ * ```
784
1837
  */
785
- export declare class PrivateKeySigner implements GalaChainSigner {
786
- private readonly keyBuffer;
1838
+ export declare class Positions {
1839
+ private readonly gateway;
1840
+ private readonly symbols;
1841
+ private readonly signer?;
1842
+ private readonly walletAddress?;
1843
+ constructor(gateway: PositionGateway, symbols: PositionSymbols, signer?: GalaChainSigner | undefined, walletAddress?: string | undefined, options?: PositionsOptions);
1844
+ private readonly http;
1845
+ private readonly uniqueKeyPrefix;
1846
+ private readonly onInvalidEntry;
787
1847
  /**
788
- * Creates a native signer from a hex or base64 secp256k1 private key.
1848
+ * Gets all current-contract positions owned by an address.
789
1849
  *
1850
+ * @param owner - GalaChain owner identity.
1851
+ * @returns Enriched positions from the v2 trade backend, token images included. A row that is
1852
+ * not a usable position is skipped and reported to `onInvalidEntry`.
790
1853
  * @example
791
1854
  * ```typescript
792
- * const signer = new PrivateKeySigner('1'.padStart(64, '0'));
793
- * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
1855
+ * const positions = await gSwap.positions.getUserPositions('client|012345678901234567890123');
794
1856
  * ```
795
1857
  */
796
- constructor(privateKey: string);
1858
+ getUserPositions(owner: string): Promise<Position[]>;
797
1859
  /**
798
- * Signs the DTO with GalaChain native signing.
1860
+ * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.
1861
+ * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.
799
1862
  *
1863
+ * @param args - Pair, owner, fee, and position tick range.
1864
+ * @returns The position, or `null` when the backend returns 404.
800
1865
  * @example
801
1866
  * ```typescript
802
- * const signed = await signer.signObject('RequestTrade', {
803
- * token0: 'GALA',
804
- * token1: 'GUSDC',
805
- * fee: 3000,
1867
+ * const position = await gSwap.positions.getPosition({
1868
+ * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',
1869
+ * fee: 3000, tickLower: -19200, tickUpper: 12000,
806
1870
  * });
807
1871
  * ```
808
1872
  */
809
- signObject<T extends Record<string, unknown>>(_methodName: string, dto: T): Promise<SignedDto<T>>;
810
- }
811
- /**
812
- * A Gala Wallet signer using native GalaChain signing, with an opt-in personal-sign mode and
813
- * automatic fallback for older wallets.
814
- *
815
- * The selected Ethereum account is passed to Gala Wallet. Personal-sign resolves the bare
816
- * `eth|` identity; the legacy EIP-712 `eth_signTypedData` path is not used. The fallback calls
817
- * `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])`.
818
- */
819
- export declare class GalaWalletSigner implements GalaChainSigner {
820
- /** The wallet address supplied to Gala Wallet for each signing request. */
821
- readonly walletAddress: string;
822
- /** The scheme currently used, including any automatic native-to-personal fallback. */
823
- effectiveScheme: GalaWalletScheme;
824
- /**
825
- * Creates a Gala Wallet signer.
826
- *
827
- * @example
828
- * ```typescript
829
- * const signer = new GalaWalletSigner('0x0123456789012345678901234567890123456789');
830
- * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
831
- * ```
832
- *
833
- * @param walletAddress - The selected Ethereum account (`0x` plus 40 hex digits); Gala Wallet's
834
- * `eth|0x...` form is also accepted and normalized.
835
- * @param options - Select native signing or personal-sign explicitly.
836
- */
837
- constructor(walletAddress: string, options?: {
838
- scheme?: GalaWalletScheme | undefined;
839
- });
840
- /**
841
- * Signs a DTO through `gala_signChainDto`.
842
- *
843
- * @example
844
- * ```typescript
845
- * const signed = await signer.signObject('AddLiquidity', {
846
- * token0: 'GALA',
847
- * token1: 'GUSDC',
848
- * tickLower: -60,
849
- * tickUpper: 60,
850
- * });
851
- * ```
852
- */
853
- signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
854
- }
855
- /**
856
- * A personal-sign signer for MetaMask and other EIP-1193 browser wallets.
857
- *
858
- * The chain recovers this signature using the EIP-191 wrap applied by the wallet to
859
- * `personal_sign`. This is the browser-wallet path used by the v2 frontend and resolves the
860
- * bare `eth|` identity.
861
- */
862
- export declare class BrowserWalletSigner implements GalaChainSigner {
863
- private readonly provider;
864
- /**
865
- * Creates a browser-wallet signer.
866
- *
867
- * Defaults to `personal_sign` — unchanged from every existing integration, since it only ever
868
- * resolves the bare `eth|` identity and changing that silently would be a real behavior
869
- * break for anyone already depending on it. Pass `{ scheme: 'eip712' }` to correctly resolve
870
- * a registered `client|` alias instead, for `RequestTrade`/`AddLiquidity`/`RemoveLiquidity`/
871
- * `CollectPositionFees` (`EIP712_CAPABLE_METHODS`) — `CreatePool` and any other method still
872
- * falls back to `personal_sign` even in `'eip712'` mode, since its EIP-712 signing is a
873
- * separate, unsolved chain-side problem.
874
- *
875
- * @example
876
- * ```typescript
877
- * const signer = new BrowserWalletSigner(window.ethereum, '0x0123456789012345678901234567890123456789');
878
- * const signed = await signer.signObject('RequestTrade', { token0: 'GALA', token1: 'GUSDC' });
879
- * ```
880
- * @example
881
- * ```typescript
882
- * // Correctly resolves a registered client| alias instead of the bare eth| address.
883
- * const signer = new BrowserWalletSigner(window.ethereum, walletAddress, { scheme: 'eip712' });
884
- * ```
885
- */
886
- constructor(provider: BrowserWalletProvider, walletAddress: string, options?: {
887
- scheme?: 'personal-sign' | 'eip712';
888
- });
889
- readonly walletAddress: string;
890
- private readonly scheme;
891
- /**
892
- * Signs the DTO with `eth_signTypedData_v4` (when constructed with `{ scheme: 'eip712' }` and
893
- * `methodName` is in `EIP712_CAPABLE_METHODS`) or the EIP-1193 `personal_sign` method
894
- * (otherwise — the default).
895
- *
896
- * @example
897
- * ```typescript
898
- * const signed = await signer.signObject('RequestTrade', {
899
- * token0: 'GALA',
900
- * token1: 'GUSDC',
901
- * fee: 3000,
902
- * });
903
- * ```
904
- */
905
- signObject<T extends Record<string, unknown>>(methodName: string, dto: T): Promise<SignedDto<T>>;
906
- }
907
- //#endregion
908
- //#region src/types/branding.d.ts
909
- interface Branding<BrandT> {
910
- _type: BrandT;
911
- }
912
- type Brand<T, BrandT> = T & Branding<BrandT>;
913
- //#endregion
914
- //#region src/types/amounts.d.ts
915
- export type NumericAmount = string | BigNumber;
916
- export type SqrtPrice = Brand<BigNumber, 'SqrtPrice'>;
917
- export type SqrtPriceIn = Brand<NumericAmount, 'SqrtPriceIn'> | SqrtPrice;
918
- export type Price = Brand<BigNumber, 'Price'>;
919
- export type PriceIn = Brand<NumericAmount, 'PriceIn'> | Price;
920
- //#endregion
921
- //#region src/classes/positions.d.ts
922
- type PositionGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {
923
- submit: (method: string, signedBody: Record<string, unknown>, options?: ChainSubmitOptions) => Promise<SubmittedTransaction<Position | null>>;
924
- requestTimeoutMs?: number | undefined;
925
- };
926
- type PositionSymbols = Pick<Symbols, 'resolve' | 'orderPair'> & {
927
- invalidate?: () => void;
928
- };
929
- /**
930
- * Manages current-contract concentrated-liquidity positions.
931
- *
932
- * @example
933
- * ```typescript
934
- * const positions = gSwap.positions;
935
- * const mine = await positions.getUserPositions('client|012345678901234567890123');
936
- * console.log(mine.length);
937
- * ```
938
- */
939
- export declare class Positions {
940
- private readonly gateway;
941
- private readonly symbols;
942
- private readonly signer?;
943
- private readonly walletAddress?;
944
- constructor(gateway: PositionGateway, symbols: PositionSymbols, signer?: GalaChainSigner | undefined, walletAddress?: string | undefined);
945
- private readonly http;
1873
+ getPosition(args: {
1874
+ token0: TokenRef;
1875
+ token1: TokenRef;
1876
+ fee: FEE_TIER;
1877
+ owner: string;
1878
+ tickLower: number;
1879
+ tickUpper: number;
1880
+ }, signal?: AbortSignal): Promise<Position | null>;
946
1881
  /**
947
- * Gets all current-contract positions owned by an address.
1882
+ * Reads one position and classifies the outcome instead of throwing: `found` with the position
1883
+ * (fees included), `not_found` (the backend's HTTP 404, which it sends only when the chain
1884
+ * itself has no such position) or `unknown` (any other failure, carried as `error`). Use it
1885
+ * to confirm a write: `unknown` is "no evidence either way", never a confirmed absence.
948
1886
  *
949
- * @param owner - GalaChain owner identity.
950
- * @returns Enriched positions from the v2 trade backend.
951
- * @example
952
- * ```typescript
953
- * const positions = await gSwap.positions.getUserPositions('client|012345678901234567890123');
954
- * ```
955
- */
956
- getUserPositions(owner: string): Promise<Position[]>;
957
- /**
958
- * Gets one position, normalizing a caller-supplied reversed pair to canonical symbol order.
959
- * Reversed pairs also invert the price axis, so `[lower, upper]` becomes `[-upper, -lower]`.
1887
+ * Only the caller's own abort rethrows. With a pass-through resolver ({@link CanonicalSymbols})
1888
+ * the pair and ticks go to the backend exactly as given and the backend orients them.
960
1889
  *
961
- * @param args - Pair, owner, fee, and position tick range.
962
- * @returns The position, or `null` when the backend returns 404.
963
1890
  * @example
964
1891
  * ```typescript
965
- * const position = await gSwap.positions.getPosition({
1892
+ * const read = await gSwap.positions.readPosition({
966
1893
  * token0: 'GALA', token1: 'GUSDC', owner: 'client|012345678901234567890123',
967
1894
  * fee: 3000, tickLower: -19200, tickUpper: 12000,
968
1895
  * });
1896
+ * if (read.kind === 'found') console.log(read.data.fees0);
969
1897
  * ```
970
1898
  */
971
- getPosition(args: {
1899
+ readPosition(args: {
972
1900
  token0: TokenRef;
973
1901
  token1: TokenRef;
974
1902
  fee: FEE_TIER;
975
1903
  owner: string;
976
1904
  tickLower: number;
977
1905
  tickUpper: number;
978
- }, signal?: AbortSignal): Promise<Position | null>;
1906
+ }, signal?: AbortSignal): Promise<PositionRead>;
1907
+ /**
1908
+ * The `/position` query: canonical symbols and canonical ticks after a client-side flip, or,
1909
+ * for a pass-through resolver, the caller's references and ticks untouched.
1910
+ */
1911
+ private positionParams;
979
1912
  /**
980
1913
  * Estimates the other token amount and resulting liquidity for a deposit.
981
1914
  *
@@ -1033,15 +1966,28 @@ export declare class Positions {
1033
1966
  * await tx.confirm();
1034
1967
  * ```
1035
1968
  */
1036
- addLiquidityByTicks(args: {
1037
- token0: TokenRef;
1038
- token1: TokenRef;
1039
- fee: FEE_TIER;
1040
- tickLower: number;
1041
- tickUpper: number;
1042
- amount: NumericAmount;
1043
- amountIsToken0: boolean;
1044
- }): Promise<SubmittedTransaction<Position | null>>;
1969
+ addLiquidityByTicks(args: AddLiquidityArgs): Promise<SubmittedTransaction<Position | null>>;
1970
+ /**
1971
+ * Builds the AddLiquidity DTO that {@link addLiquidityByTicks} would sign, without signing or
1972
+ * sending it: to show in an approval popup, or to sign elsewhere. Submit exactly this DTO with
1973
+ * {@link submitAddLiquidity}. The pure counterpart, with canonical inputs and no resolution,
1974
+ * is `buildAddLiquidityDto`.
1975
+ *
1976
+ * @example
1977
+ * ```typescript
1978
+ * const dto = await gSwap.positions.buildAddLiquidity({
1979
+ * token0: 'GALA', token1: 'GUSDC', fee: 3000,
1980
+ * tickLower: -19200, tickUpper: 12000, amount: '100', amountIsToken0: true,
1981
+ * });
1982
+ * ```
1983
+ */
1984
+ buildAddLiquidity(args: AddLiquidityArgs): Promise<AddLiquidityDTO>;
1985
+ /**
1986
+ * Signs and submits a DTO built by {@link buildAddLiquidity} or `buildAddLiquidityDto`; it must
1987
+ * be exactly what the builder produces. The returned transaction confirms by proving the
1988
+ * position's liquidity grew.
1989
+ */
1990
+ submitAddLiquidity(dto: AddLiquidityDTO): Promise<SubmittedTransaction<Position | null>>;
1045
1991
  /**
1046
1992
  * Adds liquidity from prices, flooring the lower tick and ceiling the upper tick to fee spacing.
1047
1993
  * The resulting range is therefore no narrower than the requested price interval.
@@ -1064,6 +2010,8 @@ export declare class Positions {
1064
2010
  maxPrice: PriceIn;
1065
2011
  amount: NumericAmount;
1066
2012
  amountIsToken0: boolean;
2013
+ /** The attempt's `uniqueKey`; default a fresh one (see {@link AddLiquidityArgs.uniqueKey}). */
2014
+ uniqueKey?: string | undefined;
1067
2015
  }): Promise<SubmittedTransaction<Position | null>>;
1068
2016
  /**
1069
2017
  * Removes liquidity by withdrawing at most one canonical token quantity.
@@ -1079,15 +2027,19 @@ export declare class Positions {
1079
2027
  * });
1080
2028
  * ```
1081
2029
  */
1082
- removeLiquidity(args: {
1083
- token0: TokenRef;
1084
- token1: TokenRef;
1085
- fee: FEE_TIER;
1086
- tickLower: number;
1087
- tickUpper: number;
1088
- amount0?: NumericAmount | undefined;
1089
- amount1?: NumericAmount | undefined;
1090
- }): Promise<SubmittedTransaction<Position | null>>;
2030
+ removeLiquidity(args: RemoveLiquidityArgs): Promise<SubmittedTransaction<Position | null>>;
2031
+ /**
2032
+ * Builds the RemoveLiquidity DTO that {@link removeLiquidity} would sign, without signing or
2033
+ * sending it. Submit exactly this DTO with {@link submitRemoveLiquidity}. The pure counterpart
2034
+ * is `buildRemoveLiquidityDto`.
2035
+ */
2036
+ buildRemoveLiquidity(args: RemoveLiquidityArgs): Promise<RemoveLiquidityDTO>;
2037
+ /**
2038
+ * Signs and submits a DTO built by {@link buildRemoveLiquidity} or `buildRemoveLiquidityDto`;
2039
+ * it must be exactly what the builder produces. A DTO with no withdrawal quantity closes the
2040
+ * position, and the returned transaction then confirms by proving the position is gone.
2041
+ */
2042
+ submitRemoveLiquidity(dto: RemoveLiquidityDTO): Promise<SubmittedTransaction<Position | null>>;
1091
2043
  /**
1092
2044
  * Collects all accrued fees for a position; the contract does not support partial collection.
1093
2045
  *
@@ -1101,13 +2053,18 @@ export declare class Positions {
1101
2053
  * });
1102
2054
  * ```
1103
2055
  */
1104
- collectPositionFees(args: {
1105
- token0: TokenRef;
1106
- token1: TokenRef;
1107
- fee: FEE_TIER;
1108
- tickLower: number;
1109
- tickUpper: number;
1110
- }): Promise<SubmittedTransaction<Position | null>>;
2056
+ collectPositionFees(args: CollectPositionFeesArgs): Promise<SubmittedTransaction<Position | null>>;
2057
+ /**
2058
+ * Builds the CollectPositionFees DTO that {@link collectPositionFees} would sign, without
2059
+ * signing or sending it. Submit exactly this DTO with {@link submitCollectPositionFees}. The
2060
+ * pure counterpart is `buildCollectPositionFeesDto`.
2061
+ */
2062
+ buildCollectPositionFees(args: CollectPositionFeesArgs): Promise<CollectPositionFeesDTO>;
2063
+ /**
2064
+ * Signs and submits a DTO built by {@link buildCollectPositionFees} or
2065
+ * `buildCollectPositionFeesDto`; it must be exactly what the builder produces.
2066
+ */
2067
+ submitCollectPositionFees(dto: CollectPositionFeesDTO): Promise<SubmittedTransaction<Position | null>>;
1111
2068
  /**
1112
2069
  * Creates a pool, resolving registered trading symbols.
1113
2070
  * Reversed symbol order inverts the supplied starting price or square-root price.
@@ -1129,17 +2086,20 @@ export declare class Positions {
1129
2086
  * });
1130
2087
  * ```
1131
2088
  */
1132
- createPool(args: {
1133
- token0: TokenRef;
1134
- token1: TokenRef;
1135
- token0Symbol?: string | undefined;
1136
- token1Symbol?: string | undefined;
1137
- fee: FEE_TIER;
1138
- startingPrice?: NumericAmount | undefined;
1139
- startingSqrtPrice?: NumericAmount | undefined;
1140
- isPrivate?: boolean | undefined;
1141
- privateAccess?: string[] | undefined;
1142
- }): Promise<SubmittedTransaction<Position | null>>;
2089
+ createPool(args: CreatePoolArgs): Promise<SubmittedTransaction<Position | null>>;
2090
+ /**
2091
+ * Builds the CreatePool DTO that {@link createPool} would sign, without signing or sending it:
2092
+ * symbols resolved or proposed, the pair put in canonical order and the price inverted when it
2093
+ * was reversed. Submit exactly this DTO with {@link submitCreatePool}. The pure counterpart,
2094
+ * with canonical inputs, is `buildCreatePoolDto`.
2095
+ */
2096
+ buildCreatePool(args: CreatePoolArgs): Promise<CreatePoolDTO>;
2097
+ /**
2098
+ * Signs and submits a DTO built by {@link buildCreatePool} or `buildCreatePoolDto`; it must be
2099
+ * exactly what the builder produces. The returned transaction confirms by the pool existing, and
2100
+ * the cached symbol registry is dropped, since the pool may have registered new symbols.
2101
+ */
2102
+ submitCreatePool(dto: CreatePoolDTO): Promise<SubmittedTransaction<Position | null>>;
1143
2103
  private submit;
1144
2104
  /**
1145
2105
  * Builds a confirmation closure that proves the write's own effect, not just that a
@@ -1157,32 +2117,35 @@ export declare class Positions {
1157
2117
  private get;
1158
2118
  private getNullable;
1159
2119
  private isNotFound;
1160
- private mapPosition;
1161
- private requestToken;
1162
2120
  private canonicalTicks;
1163
2121
  private tickSpacing;
1164
2122
  private rejectNumber;
1165
- private uniqueKey;
2123
+ /** The caller's `uniqueKey` (validated), else a fresh one. */
2124
+ private uniqueKeyFor;
1166
2125
  private resolveCreateToken;
1167
2126
  private tryParseClassKey;
1168
2127
  }
1169
2128
  //#endregion
1170
2129
  //#region src/classes/quoting.d.ts
1171
- type QuoteSymbols = Pick<Symbols, 'resolve'>;
2130
+ /** The transport a quote service reads through: the same shape `Pools` and `Symbols` take. */
2131
+ type QuoteGateway = Pick<ChainGateway, 'httpRequestor' | 'dexBackendBaseUrl'> & {
2132
+ requestTimeoutMs?: number | undefined;
2133
+ wire?: WireOptions | undefined;
2134
+ };
1172
2135
  /** Read-only quote service backed by the v2 offline quote engine. */
1173
2136
  export declare class Quoting {
1174
- private readonly dexBackendBaseUrl;
1175
- private readonly http;
2137
+ private readonly gateway;
1176
2138
  private readonly symbols;
1177
2139
  /**
1178
2140
  * Creates a quote service.
1179
2141
  *
1180
2142
  * @example
1181
2143
  * ```ts
1182
- * const quoting = new Quoting('https://swap-backend.stage.defi.ovh.gala.com', http, symbols);
2144
+ * const quoting = new Quoting(gateway, symbols); // a ChainGateway, or any { dexBackendBaseUrl, httpRequestor }
1183
2145
  * ```
1184
2146
  */
1185
- constructor(dexBackendBaseUrl: string, http: HttpClient, symbols: QuoteSymbols);
2147
+ constructor(gateway: QuoteGateway, symbols: TokenResolver);
2148
+ private readonly http;
1186
2149
  /**
1187
2150
  * Quotes the output for a positive exact-input amount.
1188
2151
  *
@@ -1207,24 +2170,52 @@ export declare class Quoting {
1207
2170
  }
1208
2171
  //#endregion
1209
2172
  //#region src/classes/swaps.d.ts
1210
- export type SwapAmount = {
1211
- exactIn: NumericAmount;
1212
- exactOut?: undefined;
1213
- amountOutMinimum?: NumericAmount | undefined;
1214
- amountInMaximum?: undefined;
1215
- } | {
1216
- exactIn?: undefined;
1217
- exactOut: NumericAmount;
1218
- amountOutMinimum?: undefined;
1219
- amountInMaximum?: NumericAmount | undefined;
1220
- };
1221
2173
  interface SwapGateway {
1222
2174
  submit: (method: 'RequestTrade', signedBody: Record<string, unknown>, options?: ChainSubmitOptions) => Promise<SubmittedTransaction<AppliedTrade>>;
2175
+ submitShadow: (method: 'RequestTrade', signedBody: Record<string, unknown>, options?: ChainSubmitOptions) => Promise<ShadowSubmitResult>;
1223
2176
  readonly dexBackendBaseUrl: string;
1224
2177
  readonly httpRequestor: HttpRequestor;
1225
2178
  readonly requestTimeoutMs: number;
2179
+ readonly wire?: WireOptions | undefined;
2180
+ }
2181
+ /** The canonical pool a swap trades in, as a quote names it. */
2182
+ export interface SwapPool {
2183
+ token0: string;
2184
+ token1: string;
2185
+ }
2186
+ /** Options of a swap. */
2187
+ export interface SwapOptions {
2188
+ /**
2189
+ * The attempt's `uniqueKey` (1-128 characters of `A-Za-z0-9._:-`). Default: a fresh
2190
+ * `<uniqueKeyPrefix><uuid>`. Supply one to know the key before signing (to remember it, to
2191
+ * show it), or to retry the SAME attempt after a lost response; never reuse it for another trade.
2192
+ */
2193
+ uniqueKey?: string | undefined;
2194
+ /**
2195
+ * Pin the pool: take `token0` / `token1` verbatim from the quote the user saw, instead of
2196
+ * ordering `tokenIn` / `tokenOut` by string comparison. `tokenIn` and `tokenOut` must be exactly
2197
+ * these two symbols, and `token0` must sort before `token1`. See {@link swapRouteFromQuote}.
2198
+ */
2199
+ pool?: SwapPool | undefined;
2200
+ }
2201
+ /** Everything {@link Swaps.swap} needs to trade in the pool a quote priced. */
2202
+ export interface SwapRoute {
2203
+ tokenIn: string;
2204
+ tokenOut: string;
2205
+ fee: FEE_TIER;
2206
+ pool: SwapPool;
1226
2207
  }
1227
- type SwapSymbols = Pick<Symbols, 'resolve'>;
2208
+ /**
2209
+ * The route of a quote: its fee tier and pool, with `tokenIn` / `tokenOut` taken from
2210
+ * `tokenInIsToken0`, nothing re-derived. Use it to swap in exactly the pool a quote priced:
2211
+ *
2212
+ * @example
2213
+ * ```ts
2214
+ * const route = swapRouteFromQuote(quote);
2215
+ * await swaps.swap(route.tokenIn, route.tokenOut, route.fee, { exactIn: '100' }, { pool: route.pool });
2216
+ * ```
2217
+ */
2218
+ export declare function swapRouteFromQuote(quote: Pick<QuoteResult, 'token0Symbol' | 'token1Symbol' | 'tokenInIsToken0' | 'fee'>): SwapRoute;
1228
2219
  /** Executes queued current-contract RequestTrade operations through the Chain Gateway. */
1229
2220
  export declare class Swaps {
1230
2221
  private readonly gateway;
@@ -1239,7 +2230,8 @@ export declare class Swaps {
1239
2230
  * const swaps = new Swaps(gateway, symbols, signer, 'client|alice');
1240
2231
  * ```
1241
2232
  */
1242
- constructor(gateway: SwapGateway, symbols: SwapSymbols, signer?: GalaChainSigner | undefined, walletAddress?: string | undefined);
2233
+ constructor(gateway: SwapGateway, symbols: TokenResolver, signer?: GalaChainSigner | undefined, walletAddress?: string | undefined, options?: UniqueKeyOptions);
2234
+ private readonly uniqueKeyPrefix;
1243
2235
  /**
1244
2236
  * Signs and submits an exact-input or exact-output RequestTrade DTO. The returned transaction
1245
2237
  * is QUEUED; call `await tx.confirm()` to obtain the executed trade or chain rejection.
@@ -1252,7 +2244,54 @@ export declare class Swaps {
1252
2244
  * });
1253
2245
  * ```
1254
2246
  */
1255
- swap(tokenIn: TokenRef, tokenOut: TokenRef, fee: FEE_TIER, amount: SwapAmount): Promise<SubmittedTransaction<AppliedTrade>>;
2247
+ swap(tokenIn: TokenRef, tokenOut: TokenRef, fee: FEE_TIER, amount: SwapAmount, options?: SwapOptions): Promise<SubmittedTransaction<AppliedTrade>>;
2248
+ /**
2249
+ * Signs and submits a SHADOW (dark) swap: the same RequestTrade as {@link swap}, relayed with
2250
+ * `X-Shadow: true` so defi-backend marks it private before it reaches the contract. Requires a
2251
+ * `walletAddress`. Resolves the normalized outcome instead of throwing on a gateway refusal:
2252
+ * `ok: false` carries `unavailable` (retryable), `disabled`, `rejected` (with the gateway's
2253
+ * message) or `unknown`. A success carries `queued`, to be confirmed with
2254
+ * `confirmSwap(queued.uniqueKey)`; never fall back to a public swap on failure.
2255
+ *
2256
+ * @example
2257
+ * ```ts
2258
+ * const outcome = await swaps.swapShadow('GALA', 'GUSDC', 3000, { exactIn: '100' });
2259
+ * if (outcome.ok && outcome.queued) await swaps.confirmSwap(outcome.queued.uniqueKey);
2260
+ * ```
2261
+ */
2262
+ swapShadow(tokenIn: TokenRef, tokenOut: TokenRef, fee: FEE_TIER, amount: SwapAmount, options?: SwapOptions): Promise<ShadowSubmitOutcome>;
2263
+ /**
2264
+ * Builds the RequestTrade DTO that {@link swap} would sign, without signing or sending it: to
2265
+ * show in an approval popup, to remember its `uniqueKey`, or to sign elsewhere. Submit exactly
2266
+ * this DTO with {@link submitSwap}. The pure counterpart, with canonical inputs and no
2267
+ * resolution, is `buildRequestTradeDto`.
2268
+ *
2269
+ * @example
2270
+ * ```ts
2271
+ * const dto = await swaps.buildSwap('GALA', 'GUSDC', 3000, { exactIn: '100' });
2272
+ * showApproval(dto);
2273
+ * const submitted = await swaps.submitSwap(dto);
2274
+ * ```
2275
+ */
2276
+ buildSwap(tokenIn: TokenRef, tokenOut: TokenRef, fee: FEE_TIER, amount: SwapAmount, options?: SwapOptions): Promise<RequestTradeDTO>;
2277
+ /**
2278
+ * Signs and submits a DTO built by {@link buildSwap} or `buildRequestTradeDto`. The DTO must be
2279
+ * exactly what the builder produces (no signature, canonical decimals, builder key order), so
2280
+ * what an app showed is what gets signed.
2281
+ *
2282
+ * @example
2283
+ * ```ts
2284
+ * const submitted = await swaps.submitSwap(dto);
2285
+ * const applied = await submitted.confirm();
2286
+ * ```
2287
+ */
2288
+ submitSwap(dto: RequestTradeDTO): Promise<SubmittedTransaction<AppliedTrade>>;
2289
+ /** Signs and shadow-submits a DTO built by {@link buildSwap}; see {@link swapShadow}. */
2290
+ submitSwapShadow(dto: RequestTradeDTO): Promise<ShadowSubmitOutcome>;
2291
+ private submitOptions;
2292
+ private signRequestTrade;
2293
+ /** The pool's two symbols in contract order: the quote's own when pinned, else string order. */
2294
+ private orientPool;
1256
2295
  /**
1257
2296
  * Confirm a swap by its durable `uniqueKey` without resubmitting it. This is the recovery
1258
2297
  * path after a `CONFIRMATION_TIMEOUT`, a `SUBMISSION_OUTCOME_UNKNOWN`, a `409` replay
@@ -1263,11 +2302,10 @@ export declare class Swaps {
1263
2302
  *
1264
2303
  * @example
1265
2304
  * ```ts
1266
- * const applied = await swaps.confirmSwap('gswap-sdk-2f1c…');
2305
+ * const applied = await swaps.confirmSwap('galaswap-operation-2f1c…');
1267
2306
  * ```
1268
2307
  */
1269
2308
  confirmSwap(uniqueKey: string, options?: ConfirmOptions): Promise<AppliedTrade>;
1270
- private buildRequestTradeDto;
1271
2309
  }
1272
2310
  //#endregion
1273
2311
  //#region src/types/env.d.ts
@@ -1290,11 +2328,37 @@ export interface GSwapOptions {
1290
2328
  env?: GSwapEnv | undefined;
1291
2329
  dexBackendBaseUrl?: string | undefined;
1292
2330
  httpRequestor?: HttpRequestor | undefined;
2331
+ /** Request timeout in milliseconds (default 30 000); `Infinity` arms no timer. */
1293
2332
  chainCallTimeoutMs?: number | undefined;
2333
+ /** Query encoding and `User-Agent` of the read requests (see {@link WireOptions}). */
2334
+ wire?: WireOptions | undefined;
2335
+ /**
2336
+ * How tokens are turned into trading symbols. `'registry'` (default) reads the symbol registry
2337
+ * once (`GET /v2/trade/symbols`, cached) and accepts symbols or class keys. `'canonical'` makes
2338
+ * no registry request: the caller passes the backend's canonical trading symbols (from a quote,
2339
+ * an estimate or a position), reads send tokens and ticks exactly as given (composite keys
2340
+ * included) and the backend orients the pair; see {@link CanonicalSymbols}.
2341
+ */
2342
+ symbolResolution?: 'registry' | 'canonical' | undefined;
2343
+ /**
2344
+ * Told about every row of a pool, symbol or position list that was skipped as unusable (see
2345
+ * {@link InvalidEntryHandler}); without it such rows are skipped silently.
2346
+ */
2347
+ onInvalidEntry?: InvalidEntryHandler | undefined;
1294
2348
  /** Realtime stream endpoint. Defaults to the environment's, or is derived from `dexBackendBaseUrl`. */
1295
2349
  dexBackendWsUrl?: string | undefined;
1296
2350
  /** WebSocket constructor for the realtime stream; required on Node.js older than 22. */
1297
2351
  webSocketImpl?: unknown;
2352
+ /**
2353
+ * `x-api-key` for the privileged stream view; server-side only, and it requires `webSocketImpl`
2354
+ * (see `GdexStreamConfig.apiKey`).
2355
+ */
2356
+ streamApiKey?: string | undefined;
2357
+ /**
2358
+ * Prefix of every write's `uniqueKey` (`<prefix><uuid>`). Defaults to `galaswap-operation-`,
2359
+ * what frontend_v2 and wallet_extension send; defi-backend does not depend on it.
2360
+ */
2361
+ uniqueKeyPrefix?: string | undefined;
1298
2362
  }
1299
2363
  /** Main entry point for the current GalaChainDex SDK. */
1300
2364
  export declare class GSwap {
@@ -1309,8 +2373,11 @@ export declare class GSwap {
1309
2373
  readonly positions: Positions;
1310
2374
  readonly swaps: Swaps;
1311
2375
  readonly assets: Assets;
2376
+ /** Network-fee quotes (DryRun) signed with this client's signer. */
2377
+ readonly fees: DexFees;
1312
2378
  readonly dexBackendWsUrl: string;
1313
2379
  private readonly webSocketImpl;
2380
+ private readonly streamApiKey;
1314
2381
  private streamClient;
1315
2382
  /**
1316
2383
  * Create an SDK client for prod or stage.
@@ -1336,141 +2403,583 @@ export declare class GSwap {
1336
2403
  get stream(): GdexStreamService;
1337
2404
  }
1338
2405
  //#endregion
1339
- //#region src/classes/gswap_sdk_error.d.ts
1340
- /** Error raised by the SDK for validation, gateway, chain, or transaction failures. */
1341
- export declare class GSwapSDKError extends Error {
1342
- readonly code: string;
1343
- readonly details?: Record<string, unknown> | undefined;
1344
- readonly chainMessage: string | undefined;
1345
- readonly retryAfterMs: number | undefined;
1346
- constructor(message: string, code: string, details?: Record<string, unknown> | undefined, chainMessage?: string, retryAfterMs?: number);
1347
- /** Create the standard missing-signer error. */
1348
- static noSignerError(): GSwapSDKError;
1349
- /** Create the error used when confirming a position write without a configured wallet address. */
1350
- static noWalletAddressError(): GSwapSDKError;
1351
- /** Create the error used when no pool can quote the requested pair. */
1352
- static noPoolAvailableError(tokenIn: GalaChainTokenClassKey | string, tokenOut: GalaChainTokenClassKey | string, fee?: number): GSwapSDKError;
1353
- /** Create the error used when a pool lacks liquidity for a quote. */
1354
- static insufficientLiquidityError(tokenIn: GalaChainTokenClassKey | string, tokenOut: GalaChainTokenClassKey | string, fee?: number): GSwapSDKError;
1355
- /** Convert a chain-gateway bounce into a typed SDK error. */
1356
- static fromGatewayBounce(code: string, message: string, status: number, retryAfterMs?: number): GSwapSDKError;
1357
- /** Convert a GalaChain `Status: 0` response into a typed SDK error. */
1358
- static fromChainError(errorKey: string, message: string, details?: Record<string, unknown>): GSwapSDKError;
1359
- /** Create the error used when a token is not registered by the current DEX contract. */
1360
- static unknownTokenError(token: GalaChainTokenClassKey | string): GSwapSDKError;
1361
- /** Create the error used when apply-results confirmation does not arrive in time. */
1362
- static confirmationTimeoutError(uniqueKey: string, cause?: unknown): GSwapSDKError;
1363
- /** Convert an unexpected HTTP response into an SDK error. */
1364
- static fromErrorResponse(url: string, response: HTTPResponse): Promise<GSwapSDKError>;
2406
+ //#region src/classes/pending_swaps.d.ts
2407
+ /** Key the wallet_extension has always used; its storage value is a plain array of entries. */
2408
+ export declare const PENDING_SWAPS_STORAGE_KEY = "pendingSwaps.v1";
2409
+ /** Entries older than this are dropped the next time a wallet's swaps are listed. */
2410
+ export declare const PENDING_SWAP_EXPIRY_MS: number;
2411
+ /**
2412
+ * Async key/value storage the pending-swap store persists through. It stores STRUCTURED VALUES
2413
+ * (the store never serializes), so each platform decides how a value lands on disk:
2414
+ *
2415
+ * - `chrome.storage.local`: `get: async (k) => (await chrome.storage.local.get(k))[k]`,
2416
+ * `set: (k, v) => chrome.storage.local.set({ [k]: v })`. This is the wallet's stored shape.
2417
+ * - `localStorage` (frontend_v2): `get: async (k) => { const raw = localStorage.getItem(k);
2418
+ * if (raw === null) return undefined; try { return JSON.parse(raw); } catch { return raw; } }`,
2419
+ * `set: async (k, v) => localStorage.setItem(k, JSON.stringify(v))`. Corrupt JSON MUST come back
2420
+ * as a value (here the raw string), not as a rejection: a value that is not an array reads as
2421
+ * "no entries" and the next write repairs it, whereas a `get` that rejects forever makes every
2422
+ * `remember` a no-op.
2423
+ * - React Native: AsyncStorage with the same JSON wrapping and the same corrupt-JSON rule.
2424
+ *
2425
+ * `get` resolves `undefined` for a missing key. Either method may reject; the store treats that
2426
+ * as "storage unavailable" and never lets it surface (see {@link PendingSwapStore}).
2427
+ */
2428
+ export interface StorageAdapter {
2429
+ get(key: string): Promise<unknown>;
2430
+ set(key: string, value: unknown): Promise<void>;
2431
+ }
2432
+ /** A RequestTrade that was accepted by the gateway but whose outcome has not been read yet. */
2433
+ export interface PendingSwap {
2434
+ uniqueKey: string;
2435
+ requestTransactionId: string | null;
2436
+ /** The wallet (account) that submitted the swap; `list` filters by it. */
2437
+ wallet: string;
2438
+ token0Symbol: string;
2439
+ token1Symbol: string;
2440
+ /** Whether the swap was a shadow ("dark") swap. */
2441
+ isDarkSwap: boolean;
2442
+ /** Epoch milliseconds when the swap was queued. */
2443
+ createdAt: number;
2444
+ }
2445
+ /** Options for {@link PendingSwapStore}. */
2446
+ export interface PendingSwapStoreOptions {
2447
+ /** Storage key. Default {@link PENDING_SWAPS_STORAGE_KEY}. */
2448
+ storageKey?: string | undefined;
2449
+ /**
2450
+ * The stored name of the dark-swap flag. `isDarkSwap` (default) is wallet_extension's shape;
2451
+ * `shadow` is frontend_v2's. Entries are always exposed to callers as `isDarkSwap`.
2452
+ */
2453
+ darkFlagField?: 'isDarkSwap' | 'shadow' | undefined;
2454
+ /**
2455
+ * Where `remember` puts a new entry in the stored array: `end` (default, wallet_extension) or
2456
+ * `start` (frontend_v2).
2457
+ */
2458
+ insertAt?: 'end' | 'start' | undefined;
2459
+ /**
2460
+ * The order of `list`: `stored` (default, wallet_extension: oldest first for `insertAt: 'end'`)
2461
+ * or `newest-first` (frontend_v2).
2462
+ */
2463
+ listOrder?: 'stored' | 'newest-first' | undefined;
2464
+ /** Clock, in epoch milliseconds. Defaults to `Date.now`. */
2465
+ now?: (() => number) | undefined;
2466
+ }
2467
+ /**
2468
+ * Remembers queued swaps so their outcome can be confirmed after the UI, popup or service worker
2469
+ * that submitted them is gone (`confirmAppliedTrade` with the stored `uniqueKey`).
2470
+ *
2471
+ * Guarantees:
2472
+ * - Persistence is best effort and NEVER throws: a failing or missing storage must not turn an
2473
+ * accepted request into a client-side resubmission. `list` resolves `[]` when storage fails.
2474
+ * - Operations of one store instance are serialized, so concurrent `remember` / `forget` calls
2475
+ * cannot lose each other's write (read-modify-write over an async adapter). Two store instances
2476
+ * over the same storage (for example popup and service worker) are not coordinated.
2477
+ * - Entries that do not match the expected shape are ignored and dropped on the next write.
2478
+ * - Entries expire after seven days (an entry exactly seven days old is expired; frontend_v2
2479
+ * kept it for that one millisecond); `list` removes them from storage, which frontend_v2 never
2480
+ * did on read.
2481
+ * - New entries go to the end (or `insertAt: 'start'`); `list` returns the wallet's entries in
2482
+ * stored order (or `listOrder: 'newest-first'`).
2483
+ * - The stored shape is wallet_extension's by default; `storageKey`, `darkFlagField`, `insertAt`
2484
+ * and `listOrder` reproduce frontend_v2's. JSON key order inside an entry is not preserved.
2485
+ *
2486
+ * Passing no `storage` yields a store that remembers nothing.
2487
+ *
2488
+ * @example
2489
+ * ```ts
2490
+ * const store = new PendingSwapStore({
2491
+ * get: async (key) => (await chrome.storage.local.get(key))[key],
2492
+ * set: (key, value) => chrome.storage.local.set({ [key]: value }),
2493
+ * });
2494
+ * await store.remember({ uniqueKey, requestTransactionId, wallet, token0Symbol: 'GALA',
2495
+ * token1Symbol: 'GUSDC', isDarkSwap: false, createdAt: Date.now() });
2496
+ * for (const swap of await store.list(wallet)) await confirmAppliedTrade(client, swap);
2497
+ * ```
2498
+ */
2499
+ export declare class PendingSwapStore {
2500
+ private readonly storage;
2501
+ private readonly storageKey;
2502
+ private readonly darkFlagField;
2503
+ private readonly insertAt;
2504
+ private readonly listOrder;
2505
+ private readonly now;
2506
+ private queue;
2507
+ constructor(storage: StorageAdapter | undefined, options?: PendingSwapStoreOptions);
2508
+ /** Saves (or replaces, by `uniqueKey`) a pending swap. */
2509
+ remember(swap: PendingSwap): Promise<void>;
2510
+ /** Removes a pending swap once its outcome is known. */
2511
+ forget(uniqueKey: string): Promise<void>;
2512
+ /** The wallet's unexpired pending swaps (see `listOrder`). Expired entries are pruned. */
2513
+ list(wallet: string): Promise<PendingSwap[]>;
2514
+ private enqueue;
2515
+ private read;
2516
+ private readonly toStored;
2517
+ private fromStored;
1365
2518
  }
1366
- /** Narrow an object property without trusting a cast at a network boundary. */
1367
- export declare function getObjectProperty(value: unknown, property: string): Record<string, unknown> | undefined;
1368
- /** Read a string property from an unknown object. */
1369
- export declare function getStringProperty(value: unknown, property: string): string | undefined;
1370
- /** Parse a response body, preserving non-JSON text for error reporting. */
1371
- export declare function parseJson(text: string): unknown;
1372
2519
  //#endregion
1373
- //#region src/types/v2_dtos.d.ts
1374
- /** Common identity fields for v2 pool writes. */
1375
- export interface V2PoolWriteBase {
2520
+ //#region src/utils/signing.d.ts
2521
+ /**
2522
+ * GalaChain's deterministic JSON: object keys sorted (UTF-16 code-unit order) at every depth, no
2523
+ * whitespace, `undefined`/function members dropped, `toJSON()` honored. Byte-identical to
2524
+ * `serialize` from `@gala-chain/api` / `json-stringify-deterministic` for every JSON-shaped
2525
+ * value, which is all a DTO ever is.
2526
+ *
2527
+ * @throws TypeError for circular structures and BigInt values (as `JSON.stringify` does) and
2528
+ * when the value itself has no JSON representation (`undefined`, a function, a symbol).
2529
+ */
2530
+ export declare function serialize(value: unknown): string;
2531
+ /**
2532
+ * The exact string GalaChain hashes for a DTO: the (optional, string) `prefix` field PREPENDED to
2533
+ * the deterministic serialization of the DTO WITHOUT `signature`, `multisig`, `trace` and `prefix`.
2534
+ * Equivalent to `@gala-chain/api` 3.x `getPayloadToSign` for every non-EIP-712 DTO.
2535
+ */
2536
+ export declare function getPayloadToSign(dto: Record<string, unknown>): string;
2537
+ /**
2538
+ * The EIP-191 header for `message`: `"\x19Ethereum Signed Message:\n"` + the message's UTF-8 BYTE
2539
+ * length. This is what a wallet's `personal_sign` prepends, and what the chain recomputes when it
2540
+ * recovers a personal-signed DTO.
2541
+ */
2542
+ export declare function calculatePersonalSignPrefix(message: string): string;
2543
+ /**
2544
+ * The EIP-191 header for `serialize(dto)` (any `prefix` already on the DTO is ignored). This is
2545
+ * deliberately the same string the signers hand a wallet to sign, so the header's length can never
2546
+ * disagree with the signed message. Wallet-neutral: it is the value both a browser wallet's
2547
+ * `personal_sign` and Gala Wallet's `gala_signChainDto` (personal-sign scheme) prepend.
2548
+ */
2549
+ export declare function personalSignPrefixFor(dto: Record<string, unknown>): string;
2550
+ /**
2551
+ * The `@gala-chain/connect`-style prefix frontend_v2 puts in the body of an EIP-712 write: the
2552
+ * EIP-191 header whose number counts the prefix string ITSELF plus the body (the UTF-8 length of
2553
+ * `getPayloadToSign({ ...dto, prefix })`), found by fixpoint because adding the prefix changes the
2554
+ * length (a body of 99 bytes settles on 101).
2555
+ *
2556
+ * It is NOT a personal-sign prefix (a personal-sign write with this value recovers a phantom
2557
+ * signer; use `personalSignPrefixFor`). Under EIP-712 the field is an untyped extra that the
2558
+ * typed-data hash ignores and defi-backend recomputes, so it only exists to keep the submitted
2559
+ * body byte-identical to what frontend_v2 has always sent.
2560
+ */
2561
+ export declare function fixpointPrefixFor(dto: Record<string, unknown>): string;
2562
+ /**
2563
+ * Normalizes a secp256k1 private key to a fresh 32-byte array (the caller may zero it). Also
2564
+ * accepts 32 raw bytes, which are validated and copied. For strings it accepts what `@gala-chain/api`'s
2565
+ * `normalizePrivateKey` accepted for a usable key: 64 hex characters (optionally `0x`-prefixed;
2566
+ * a 63-character hex key is left-padded with a zero) or a 44-character base64 string.
2567
+ *
2568
+ * @throws GSwapSDKError (`VALIDATION_ERROR`) for any other shape or an out-of-range scalar.
2569
+ */
2570
+ export declare function normalizePrivateKey(input: string | Uint8Array): Uint8Array;
2571
+ /**
2572
+ * The lowercase `0x` Ethereum address (last 20 bytes of keccak256 of the uncompressed public key)
2573
+ * of a normalized private key. The Gala `eth|` identity of a key is this address.
2574
+ */
2575
+ export declare function ethAddressOfPrivateKey(privateKey: Uint8Array): string;
2576
+ /**
2577
+ * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes, with no
2578
+ * prefix and no signature envelope. The caller owns serialization, so the bytes shown to a user
2579
+ * and the bytes signed can never diverge.
2580
+ */
2581
+ export declare function signSerializedNative(privateKey: Uint8Array, serializedDto: string): string;
2582
+ /**
2583
+ * GalaChain NATIVE signature for a DTO: keccak256 of `getPayloadToSign(dto)`, signed with
2584
+ * secp256k1. Byte-identical to `signatures.getSignature` from `@gala-chain/api`.
2585
+ */
2586
+ export declare function signNative(privateKey: Uint8Array, dto: Record<string, unknown>): string;
2587
+ /**
2588
+ * Personal-sign hash and signature: keccak256(`prefix` + `message`), both hashed VERBATIM with no
2589
+ * further EIP-191 wrapping. Passing `prefix = calculatePersonalSignPrefix(message)` reproduces a
2590
+ * wallet's `personal_sign` of `message`. Gala Wallet's `gala_signChainDto` (personal-sign
2591
+ * scheme) hashes `prefix` + the exact string it is handed, which can differ from the bare message
2592
+ * (see the `signatureOverPrefixlessBody` vectors); that quirk is why the two inputs stay separate.
2593
+ */
2594
+ export declare function signPersonalMessage(privateKey: Uint8Array, prefix: string, message: string): string;
2595
+ //#endregion
2596
+ //#region src/utils/chain_dto_signing.d.ts
2597
+ /** A secp256k1 private key as a hex/base64 string or as raw 32 bytes. */
2598
+ type PrivateKeyInput = string | Uint8Array;
2599
+ /**
2600
+ * Runs `action` with a private normalized copy of the key, zeroed afterwards (also when `action`
2601
+ * throws). Bytes given by the caller are copied, never modified: the caller owns them.
2602
+ */
2603
+ export declare function withPrivateKey<T>(privateKey: PrivateKeyInput, action: (key: Uint8Array) => T): T;
2604
+ /**
2605
+ * GalaChain NATIVE signature over an already-serialized DTO: keccak256 of the exact bytes with no
2606
+ * prefix and no envelope (wallet `signChainDtoNative`). The caller owns serialization, so the
2607
+ * bytes a user reviewed and the bytes signed cannot diverge.
2608
+ *
2609
+ * @returns 130 lowercase hex characters, `r || s || v` with `v` = `1b`/`1c`, no `0x`.
2610
+ */
2611
+ export declare function signChainDtoNative(privateKey: PrivateKeyInput, serializedDto: string): string;
2612
+ /**
2613
+ * The personal-sign hash primitive (wallet `signChainDtoHash`): keccak256(`prefix` + `message`),
2614
+ * both verbatim, with no further EIP-191 wrap. `message` must be the DTO's serialization WITHOUT
2615
+ * its `prefix` field; callers holding a dApp-supplied string go through `signChainDtoPersonalSign`,
2616
+ * which derives both inputs from it.
2617
+ */
2618
+ export declare function signChainDtoHash(privateKey: PrivateKeyInput, prefix: string, message: string): string;
2619
+ /** What a `gala_signChainDto` personal-sign request hashes. */
2620
+ interface PersonalSignChainDtoPayload {
2621
+ /** The `prefix` the chain prepends: the DTO's own `prefix` field, or `''` when it has none. */
2622
+ prefix: string;
2623
+ /** The exact message hashed after `prefix`. */
2624
+ message: string;
2625
+ }
2626
+ /**
2627
+ * Derives what to hash for a `gala_signChainDto` personal-sign request from the exact string the
2628
+ * dApp sent (and the approval card displayed): wallet `resolvePersonalSignChainDtoPayload`.
2629
+ *
2630
+ * The dApp submits `{ ...dto, prefix, signature }`, which the chain recovers from
2631
+ * `keccak256(prefix + serialize(dto WITHOUT prefix))`. So when the string embeds a `prefix`
2632
+ * field, that field is removed and the remainder re-serialized; the prefix used is the dApp's own
2633
+ * value byte for byte. A string with no `prefix` field is hashed verbatim with an empty prefix
2634
+ * (chain-equivalent to a native signature of that exact string).
2635
+ *
2636
+ * Fails closed (throws `GSwapSDKError` `INVALID_PERSONAL_SIGN_DTO`, message text identical to the
2637
+ * wallet's) on: malformed JSON; JSON that is not a plain object; a `prefix` that is not an EIP-191
2638
+ * "Ethereum Signed Message" header; any signing-envelope field (`signature`, `multisig`, `trace`,
2639
+ * `types`, `domain`, `stringsInstructions`); and a string that is not already the canonical
2640
+ * serialization of what it parses to (duplicate keys, lossy numbers, key-order tricks the card
2641
+ * would render differently). Stripping `prefix` is therefore the ONLY byte change between the
2642
+ * reviewed string and the signed message.
2643
+ */
2644
+ export declare function resolvePersonalSignChainDtoPayload(data: string): PersonalSignChainDtoPayload;
2645
+ /**
2646
+ * Signs a GalaChain personal-sign scheme DTO from the exact string a dApp sent through
2647
+ * `gala_signChainDto` (wallet `signChainDtoPersonalSign`). See
2648
+ * `resolvePersonalSignChainDtoPayload` for what is signed and what is refused; the signature
2649
+ * recovers, under the chain's `getPayloadToSign`, to this key for the DTO the dApp submits with
2650
+ * its `prefix`, and equals a `personal_sign` of the bare body when that prefix is the EIP-191
2651
+ * header of the bare body's byte length.
2652
+ *
2653
+ * @throws GSwapSDKError (`INVALID_PERSONAL_SIGN_DTO`) before any signing when the input is refused.
2654
+ */
2655
+ export declare function signChainDtoPersonalSign(privateKey: PrivateKeyInput, data: string): string;
2656
+ /**
2657
+ * Raw object signing (wallet `signObject`), used for transfers, bridge and fee-dry-run DTOs the
2658
+ * wallet signs itself. Removes ONLY `signature`, signs `keccak256(serialize(rest))` natively
2659
+ * (no `prefix` handling, and `trace` / `multisig` stay in the signed bytes, unlike
2660
+ * `signNative`), and returns `{ signature, ...rest }` with the signature as the FIRST key, exactly
2661
+ * like the wallet. Callers that must not sign extra fields strip them first.
2662
+ */
2663
+ export declare function signRawObject(privateKey: PrivateKeyInput, obj: Record<string, unknown>): {
2664
+ signature: string;
2665
+ } & Record<string, unknown>;
2666
+ /**
2667
+ * Drops the `EIP712Domain` entry from a dApp-supplied types map (a typed-data encoder derives the
2668
+ * domain type itself and rejects an explicit one). The order of the remaining types is preserved.
2669
+ */
2670
+ export declare function stripEip712DomainType<T>(types: Record<string, T>): Record<string, T>;
2671
+ /**
2672
+ * `collection$category$type$additionalKey` for a token-class object (wallet `decodeTokenData`).
2673
+ * Lenient on purpose: any missing or non-string part becomes `''`, so a display layer never
2674
+ * throws on odd input.
2675
+ */
2676
+ export declare function tokenClassDollarKey(token: Record<string, unknown> | null | undefined): string;
2677
+ /**
2678
+ * A quantity in the form GalaChain's `IsBigNumber` validator accepts: FIXED notation, no leading
2679
+ * zeros, no trailing decimal zeros (`BigNumber#toFixed()`; never `toString()`, which turns
2680
+ * `0.00000001` into `1e-8`, and never a JS number in between).
2681
+ *
2682
+ * @throws GSwapSDKError (`VALIDATION_ERROR`) for a value that is not a finite number. The wallet's
2683
+ * `cleanNumber` returned the string `'NaN'` there; signing that text can only fail on chain.
2684
+ */
2685
+ export declare function canonicalDecimalString(value: string | number): string;
2686
+ //#endregion
2687
+ //#region src/utils/eip712.d.ts
2688
+ type EIP712Types = Record<string, Array<{
2689
+ name: string;
2690
+ type: string;
2691
+ }>>;
2692
+ /**
2693
+ * Derives the EIP-712 `types` for a DTO from its runtime shape.
2694
+ *
2695
+ * The generated `types` travel with the signed payload and are what BOTH sides hash, so they
2696
+ * must enumerate EVERY field the chain-side DTO will carry. GalaChain refuses any signature
2697
+ * whose `types` leave a DTO field uncovered (`assertNoUnsignedFields`, the fix for the
2698
+ * 2026-08-18 unsigned-field-injection drain); when that happens signature recovery fails
2699
+ * outright and the chain reports "Missing signerPublicKey or signerAddress field in dto".
2700
+ */
2701
+ export declare function generateEIP712Types(typeName: string, params: Record<string, unknown>): EIP712Types;
2702
+ /** The EIP-712 domain carried by a signed payload: GalaChain only uses `name` and `chainId`. */
2703
+ interface EIP712DomainValue {
2704
+ name: string;
2705
+ chainId: number;
2706
+ }
2707
+ /**
2708
+ * Builds the EIP-712 domain from the wallet's LIVE `eth_chainId` result, exactly like frontend_v2
2709
+ * (DEFI-1895): a wallet hashes whatever domain it is handed, and MetaMask refuses a `chainId` that
2710
+ * differs from its active network, so a hardcoded `1` breaks every wallet that is not on Mainnet.
2711
+ * defi-backend recovers the signer from the `domain` the payload carries (live-proven for chain
2712
+ * ids 1, 56 and 11155111), so following the wallet is correct on every network.
2713
+ *
2714
+ * @param chainId - The raw `eth_chainId` result: a `0x` hex string (the JSON-RPC form) or an integer.
2715
+ * @throws GSwapSDKError (`INVALID_CHAIN_ID`) when the wallet answers with anything else.
2716
+ */
2717
+ export declare function eip712DomainFor(chainId: unknown): EIP712DomainValue;
2718
+ /**
2719
+ * The four v2 operations proven to recover the signer correctly via genuine EIP-712: `RequestTrade`
2720
+ * never had the problem (one numeric field). `AddLiquidity`/`RemoveLiquidity`/
2721
+ * `CollectPositionFees` each need their `types` completed with a handful of fields their real
2722
+ * server-side DTO always carries — see the `complete*Fields` functions below. `CreatePool` is a
2723
+ * genuinely different, unsolved problem (nested `TokenClassKey` structs, not a flat
2724
+ * missing-field gap) and is NOT in this set — callers must keep using `personal-sign` for it.
2725
+ */
2726
+ export declare const EIP712_CAPABLE_METHODS: ReadonlySet<string>;
2727
+ /**
2728
+ * Completes a DTO's fields for EIP-712 signing (a no-op for methods with no known gap, e.g.
2729
+ * `RequestTrade`) and derives its `types`. Exported separately from the signing call itself so tests
2730
+ * can assert on the exact payload without needing a live provider.
2731
+ */
2732
+ export declare function buildEIP712Payload(methodName: string, dto: Record<string, unknown>): {
2733
+ completedDto: Record<string, unknown>;
2734
+ types: EIP712Types;
2735
+ };
2736
+ //#endregion
2737
+ //#region src/utils/typed_data.d.ts
2738
+ /** A typed-data payload as `eth_signTypedData_v4` carries it, minus `primaryType` (it is inferred). */
2739
+ interface TypedDataPayload {
2740
+ domain: Record<string, unknown>;
2741
+ /** Struct definitions WITHOUT `EIP712Domain` (see `stripEip712DomainType`). */
2742
+ types: Record<string, readonly unknown[]>;
2743
+ message: Record<string, unknown>;
2744
+ }
2745
+ /**
2746
+ * The EIP-712 digest `keccak256(0x1901 || domainSeparator || hashStruct(primaryType, message))`
2747
+ * that a wallet signs for `eth_signTypedData_v4`. The primary type is inferred, as ethers does.
2748
+ *
2749
+ * @throws GSwapSDKError (`INVALID_TYPED_DATA`) for any type graph or value it cannot encode
2750
+ * exactly (see the module note on strictness).
2751
+ */
2752
+ export declare function hashTypedData(payload: TypedDataPayload): Uint8Array;
2753
+ /**
2754
+ * Signs a dApp's EIP-712 typed-data approval (the wallet's `signTypedMessage` path), replacing
2755
+ * `new ethers.Wallet(key).signTypedData(domain, types, message)`. `types` must already have
2756
+ * `EIP712Domain` removed (`stripEip712DomainType`).
2757
+ *
2758
+ * @returns `0x` + r + s + v with `v` = `0x1b`/`0x1c` (27/28): ethers' serialized signature form,
2759
+ * recoverable with `verifyTypedData` / `eth_signTypedData_v4` verifiers. Rejects (never throws
2760
+ * synchronously) on invalid input.
2761
+ */
2762
+ export declare function signTypedDataPayload(privateKey: PrivateKeyInput, payload: TypedDataPayload): Promise<string>;
2763
+ //#endregion
2764
+ //#region src/utils/dto_builders.d.ts
2765
+ /** The pool a RequestTrade trades in, its fee tier, the `uniqueKey` and what is traded. */
2766
+ type RequestTradeInput = {
2767
+ /** Canonical pool symbols: `token0 < token1`. Take them from a quote verbatim. */
1376
2768
  token0: string;
1377
2769
  token1: string;
1378
- fee: FEE_TIER;
2770
+ fee: number;
2771
+ /** Which side of the pool is sold: `true` when the input token is `token0`. */
2772
+ tokenInIsToken0: boolean;
1379
2773
  uniqueKey: string;
1380
- }
1381
- /** A v2 RequestTrade with exactly one selected trade-side quantity. */
1382
- export type RequestTradeDTO = V2PoolWriteBase & ({
1383
- sell0Qty: string;
1384
- sell1Qty?: never;
1385
- buy0Qty?: never;
1386
- buy1Qty?: never;
1387
- } | {
1388
- sell0Qty?: never;
1389
- sell1Qty: string;
1390
- buy0Qty?: never;
1391
- buy1Qty?: never;
1392
- } | {
1393
- sell0Qty?: never;
1394
- sell1Qty?: never;
1395
- buy0Qty: string;
1396
- buy1Qty?: never;
1397
- } | {
1398
- sell0Qty?: never;
1399
- sell1Qty?: never;
1400
- buy0Qty?: never;
1401
- buy1Qty: string;
1402
- }) & {
1403
- amountOutMinimum?: string | undefined;
1404
- amountInMaximum?: string | undefined;
1405
- };
1406
- /** A v2 liquidity deposit with exactly one selected deposit quantity. */
1407
- export type AddLiquidityDTO = V2PoolWriteBase & {
1408
- tickLower: number;
1409
- tickUpper: number;
1410
- } & ({
1411
- depositQuantityToken0: string;
1412
- depositQuantityToken1?: never;
1413
- } | {
1414
- depositQuantityToken0?: never;
1415
- depositQuantityToken1: string;
1416
- });
1417
- /** A v2 liquidity withdrawal; omitting both quantities closes the position. */
1418
- export type RemoveLiquidityDTO = V2PoolWriteBase & {
2774
+ } & SwapAmount;
2775
+ /**
2776
+ * Builds the RequestTrade DTO: `exactIn` sells that much of the input token (`sell0Qty` or
2777
+ * `sell1Qty`), `exactOut` buys that much of the output token (`buy1Qty` or `buy0Qty`), plus the
2778
+ * side's slippage bound and an optional `priceLimit`. Key order: `token0, token1, fee, uniqueKey,
2779
+ * <quantity>, amountOutMinimum | amountInMaximum, priceLimit`.
2780
+ *
2781
+ * @example
2782
+ * ```ts
2783
+ * const dto = buildRequestTradeDto({
2784
+ * token0: quote.token0Symbol, token1: quote.token1Symbol,
2785
+ * tokenInIsToken0: quote.tokenInIsToken0, fee: quote.fee,
2786
+ * uniqueKey: createUniqueKey('galaswap-operation-'),
2787
+ * exactIn: '100', amountOutMinimum: '14',
2788
+ * });
2789
+ * ```
2790
+ */
2791
+ export declare function buildRequestTradeDto(input: RequestTradeInput): RequestTradeDTO;
2792
+ /** A canonical pool position: the pair, fee tier, tick range and the attempt's `uniqueKey`. */
2793
+ interface PoolPositionInput {
2794
+ token0: string;
2795
+ token1: string;
2796
+ fee: number;
1419
2797
  tickLower: number;
1420
2798
  tickUpper: number;
1421
- } & ({
1422
- withdrawalQuantityToken0: string;
1423
- withdrawalQuantityToken1?: never;
1424
- } | {
1425
- withdrawalQuantityToken0?: never;
1426
- withdrawalQuantityToken1: string;
2799
+ uniqueKey: string;
2800
+ }
2801
+ /** Exactly one canonical deposit side. */
2802
+ type AddLiquidityInput = PoolPositionInput & ({
2803
+ depositQuantityToken0: NumericAmount;
2804
+ depositQuantityToken1?: undefined;
1427
2805
  } | {
1428
- withdrawalQuantityToken0?: never;
1429
- withdrawalQuantityToken1?: never;
2806
+ depositQuantityToken0?: undefined;
2807
+ depositQuantityToken1: NumericAmount;
1430
2808
  });
1431
- /** A v2 request to sweep all fees from one position. */
1432
- export interface CollectPositionFeesDTO extends V2PoolWriteBase {
1433
- tickLower: number;
1434
- tickUpper: number;
1435
- }
1436
- /** A v2 pool creation request with exactly one initial-price representation. */
1437
- export type CreatePoolDTO = {
2809
+ /**
2810
+ * Builds the AddLiquidity DTO: exactly one of `depositQuantityToken0` / `depositQuantityToken1`
2811
+ * (the other side is derived on chain). Key order: `token0, token1, fee, tickLower, tickUpper,
2812
+ * uniqueKey, <deposit>`.
2813
+ */
2814
+ export declare function buildAddLiquidityDto(input: AddLiquidityInput): AddLiquidityDTO;
2815
+ /** At most one canonical withdrawal side; neither closes the position. */
2816
+ type RemoveLiquidityInput = PoolPositionInput & {
2817
+ withdrawalQuantityToken0?: NumericAmount | undefined;
2818
+ withdrawalQuantityToken1?: NumericAmount | undefined;
2819
+ };
2820
+ /**
2821
+ * Builds the RemoveLiquidity DTO: at most one of `withdrawalQuantityToken0` /
2822
+ * `withdrawalQuantityToken1`; omitting both closes the position and sweeps its fees.
2823
+ */
2824
+ export declare function buildRemoveLiquidityDto(input: RemoveLiquidityInput): RemoveLiquidityDTO;
2825
+ /** Builds the CollectPositionFees DTO (the contract sweeps all of a position's fees). */
2826
+ export declare function buildCollectPositionFeesDto(input: PoolPositionInput): CollectPositionFeesDTO;
2827
+ /** A CreatePool in canonical orientation, with exactly one starting price. */
2828
+ type CreatePoolInput = {
1438
2829
  token0Key: GalaChainTokenClassKey;
1439
2830
  token1Key: GalaChainTokenClassKey;
2831
+ /** The symbols to register; `token0Symbol < token1Symbol` and both proposable. */
1440
2832
  token0Symbol: string;
1441
2833
  token1Symbol: string;
1442
- fee: FEE_TIER;
2834
+ fee: number;
2835
+ /** Optional display name; omitted when undefined or empty. */
2836
+ name?: string | undefined;
1443
2837
  isPrivate?: boolean | undefined;
1444
2838
  privateAccess?: string[] | undefined;
1445
2839
  uniqueKey: string;
1446
2840
  } & ({
1447
- startingPrice: string;
1448
- startingSqrtPrice?: never;
2841
+ startingPrice: NumericAmount;
2842
+ startingSqrtPrice?: undefined;
1449
2843
  } | {
1450
- startingPrice?: never;
1451
- startingSqrtPrice: string;
2844
+ startingPrice?: undefined;
2845
+ startingSqrtPrice: NumericAmount;
1452
2846
  });
1453
- /** Optional page cursor accepted by chain read methods. */
1454
- export interface PageDTO {
1455
- limit?: number | undefined;
1456
- bookmark?: string | undefined;
2847
+ /**
2848
+ * Builds the CreatePool DTO. Key order: `token0Key, token1Key, fee, startingPrice |
2849
+ * startingSqrtPrice, token0Symbol, token1Symbol, uniqueKey, name, isPrivate, privateAccess`.
2850
+ * Prices are those of the canonical pair (token1 per token0); a price quoted the other way round
2851
+ * is inverted by the caller before it gets here.
2852
+ */
2853
+ export declare function buildCreatePoolDto(input: CreatePoolInput): CreatePoolDTO;
2854
+ /** The methods whose DTOs the builders produce. */
2855
+ type V2WriteMethod = 'RequestTrade' | 'AddLiquidity' | 'RemoveLiquidity' | 'CollectPositionFees' | 'CreatePool';
2856
+ /**
2857
+ * Asserts that `dto` is EXACTLY what the builder of `method` produces for its own fields — the
2858
+ * same fields, canonical decimal text, builder key order, nothing extra (no `signature`). The
2859
+ * `submit*` methods use it so that what an app showed a user (a DTO it built) is byte for byte
2860
+ * what gets signed; a DTO edited by hand, or built elsewhere, is refused rather than signed.
2861
+ *
2862
+ * @throws GSwapSDKError VALIDATION_ERROR (`details.type` = `INVALID_DTO` or `DTO_NOT_CANONICAL`).
2863
+ */
2864
+ export declare function assertCanonicalV2Dto(method: V2WriteMethod, dto: Record<string, unknown>): void;
2865
+ //#endregion
2866
+ //#region src/utils/axios_requestor.d.ts
2867
+ /** What the adapter reads of an axios response. */
2868
+ export interface AxiosLikeResponse {
2869
+ status: number;
2870
+ data?: unknown;
2871
+ /** axios' `AxiosHeaders` (has `get`) or a plain header record. */
2872
+ headers?: unknown;
1457
2873
  }
1458
- /** Fetch all registered trading symbols. */
1459
- export type FetchTokenTradingSymbolsDTO = PageDTO;
1460
- /** Fetch a composite pool snapshot. */
1461
- export interface FetchCompositePoolDataDTO {
1462
- token0: string;
1463
- token1: string;
1464
- fee: FEE_TIER;
2874
+ /** The request config the adapter hands to axios. */
2875
+ export interface AxiosLikeConfig {
2876
+ headers: Record<string, string>;
2877
+ signal?: AbortSignal;
2878
+ validateStatus?: () => boolean;
1465
2879
  }
1466
- /** Fetch one current trading price, or all prices when no pair is supplied. */
1467
- export type FetchCurrentTradingPricesDTO = Partial<FetchCompositePoolDataDTO> & PageDTO;
1468
- /** Fetch pools, optionally narrowed to one pair and paged. */
1469
- export type FetchPoolsDTO = Partial<FetchCompositePoolDataDTO> & PageDTO;
1470
- /** Fetch all liquidity positions, optionally narrowed to a pool reference. */
1471
- export interface FetchLiquidityPositionsDTO extends PageDTO {
1472
- pool?: string | undefined;
2880
+ /**
2881
+ * The part of an axios instance the adapter calls. Declared structurally, so the SDK takes no
2882
+ * dependency on axios and any axios instance (with its interceptors) satisfies it.
2883
+ */
2884
+ export interface AxiosLikeInstance {
2885
+ get(url: string, config?: AxiosLikeConfig): Promise<unknown>;
2886
+ post(url: string, data?: unknown, config?: AxiosLikeConfig): Promise<unknown>;
2887
+ }
2888
+ /** Options of {@link httpRequestorFromAxios}. */
2889
+ export interface AxiosRequestorOptions {
2890
+ /**
2891
+ * `true`: leave axios' default status validation alone, so a 4xx/5xx REJECTS through the
2892
+ * instance's own interceptors and the SDK rethrows what the app's error handling produced.
2893
+ * `false`: every HTTP status resolves, so the SDK classifies it itself (shadow submits,
2894
+ * apply-results reads); transport failures still reject.
2895
+ */
2896
+ rejectOnHttpError: boolean;
2897
+ /**
2898
+ * Request headers NOT to hand to axios, matched case-insensitively. Default `['content-type']`:
2899
+ * axios derives `Content-Type: application/json` from the object body it is given, and an
2900
+ * interceptor may set its own, so the SDK's copy would only be a second opinion.
2901
+ */
2902
+ omitHeaders?: readonly string[] | undefined;
2903
+ }
2904
+ /**
2905
+ * An SDK {@link HttpRequestor} over an axios instance, so the SDK's requests travel through the
2906
+ * app's own base URL, interceptors and error handling.
2907
+ *
2908
+ * A POST's string body is parsed back to the object the SDK serialized it from (axios serializes
2909
+ * again, and an interceptor may read the object); a GET goes through `instance.get`. The answer
2910
+ * is an HTTP response whose `json()`/`text()` read `response.data`. An answer that is not an
2911
+ * axios response is a `TRANSPORT_ERROR` rejection.
2912
+ *
2913
+ * Pair it with `ChainGateway`'s `dexBackendBaseUrl: ''` when the instance owns the base URL.
2914
+ *
2915
+ * @example
2916
+ * ```ts
2917
+ * const submitGateway = new ChainGateway({
2918
+ * dexBackendBaseUrl: '',
2919
+ * httpRequestor: httpRequestorFromAxios(chainGatewayInstance, { rejectOnHttpError: true }),
2920
+ * });
2921
+ * ```
2922
+ */
2923
+ export declare function httpRequestorFromAxios(instance: AxiosLikeInstance, options: AxiosRequestorOptions): HttpRequestor;
2924
+ //#endregion
2925
+ //#region src/utils/ethers_provider.d.ts
2926
+ /**
2927
+ * The part of an ethers v6 signer (`JsonRpcSigner`, `Wallet`) the adapter calls. Declared
2928
+ * structurally, so the SDK takes no dependency on ethers and an ethers object satisfies it as is.
2929
+ */
2930
+ export interface EthersLikeSigner {
2931
+ signTypedData(domain: Record<string, unknown>, types: Record<string, Array<{
2932
+ name: string;
2933
+ type: string;
2934
+ }>>, value: Record<string, unknown>): Promise<string>;
2935
+ signMessage(message: string): Promise<string>;
2936
+ }
2937
+ /** The part of an ethers v6 provider (`BrowserProvider`) the adapter calls. */
2938
+ export interface EthersLikeProvider {
2939
+ getSigner(): Promise<EthersLikeSigner>;
2940
+ /** The raw JSON-RPC passthrough (`BrowserProvider.send`). */
2941
+ send(method: string, params: unknown[]): Promise<unknown>;
2942
+ }
2943
+ /** Options of {@link eip1193ProviderFromEthers}. */
2944
+ export interface EthersEip1193Options {
2945
+ /**
2946
+ * Signs a `personal_sign` message when the provider cannot or should not: a wallet SDK that
2947
+ * signs through its own object (TrustWallet's `web3Wallet.signMessage`). When set it answers
2948
+ * every `personal_sign`, and the provider is not touched for it.
2949
+ */
2950
+ personalSign?: ((message: string) => Promise<string>) | undefined;
2951
+ /**
2952
+ * The message of the `WALLET_UNAVAILABLE` error raised when a request needs the provider and
2953
+ * there is none (no wallet connected). Default: "No wallet is connected."
2954
+ */
2955
+ unavailableMessage?: string | undefined;
1473
2956
  }
2957
+ /**
2958
+ * An EIP-1193 provider over an ethers v6 provider, for {@link BrowserWalletSigner}: apps whose
2959
+ * wallet connection is an ethers `BrowserProvider` sign through the very ethers calls they always
2960
+ * made, with no hand-written shim.
2961
+ *
2962
+ * - `eth_chainId` is `provider.send('eth_chainId', [])`: the wallet's LIVE chain. Never
2963
+ * `provider.getNetwork()`, which ethers caches and does not invalidate on `chainChanged`, so a
2964
+ * user who switches networks after connecting would sign against a stale chainId.
2965
+ * - `eth_signTypedData_v4` parses the `[account, JSON]` params and calls
2966
+ * `signer.signTypedData(domain, types, message)` with `EIP712Domain` removed from `types`.
2967
+ * - `personal_sign` is `options.personalSign(message)` when given, else `signer.signMessage`.
2968
+ * - Anything else is `UNSUPPORTED_WALLET_METHOD`; a malformed request is
2969
+ * `MALFORMED_WALLET_REQUEST`; a missing provider is `WALLET_UNAVAILABLE`.
2970
+ *
2971
+ * `provider` may be `null`/`undefined` (nothing connected): a request that needs it then fails
2972
+ * with `WALLET_UNAVAILABLE` rather than at construction, so a signer can be built before the
2973
+ * connection state is known.
2974
+ *
2975
+ * @example
2976
+ * ```ts
2977
+ * const signer = new BrowserWalletSigner(eip1193ProviderFromEthers(browserProvider), account, {
2978
+ * scheme: 'eip712',
2979
+ * });
2980
+ * ```
2981
+ */
2982
+ export declare function eip1193ProviderFromEthers(provider: EthersLikeProvider | null | undefined, options?: EthersEip1193Options): BrowserWalletProvider;
1474
2983
  //#endregion
1475
2984
  //#region src/utils/ticks.d.ts
1476
2985
  /** Minimum tick supported by GalaChainDex. */
@@ -1489,6 +2998,32 @@ export declare function alignTickDown(tick: number, spacing: number): number;
1489
2998
  export declare function alignTickUp(tick: number, spacing: number): number;
1490
2999
  /** Validate a position range against the global tick bounds and fee-tier spacing. */
1491
3000
  export declare function assertTickRange(lower: number, upper: number, fee: FEE_TIER): void;
3001
+ /** A pool's current price in the frame of the request that asked for it. */
3002
+ export interface FramedSlot0 {
3003
+ /** The square-root price, token1 per token0 in the REQUESTED order. */
3004
+ sqrtPrice: string;
3005
+ /** The greatest tick whose square-root price is no greater than `sqrtPrice`. */
3006
+ tick: number;
3007
+ }
3008
+ /**
3009
+ * Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's
3010
+ * canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse
3011
+ * order the price is inverted here (at 60 significant digits, so a very large or very small
3012
+ * reciprocal keeps its precision) and the tick is re-derived from the inverted price with the
3013
+ * contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks
3014
+ * (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).
3015
+ *
3016
+ * @example
3017
+ * ```ts
3018
+ * const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);
3019
+ * const { sqrtPrice, tick } = frameSlot0(slot0);
3020
+ * ```
3021
+ */
3022
+ export declare function frameSlot0(slot0: {
3023
+ sqrtPrice: string;
3024
+ tick: number;
3025
+ flippedFromRequest?: boolean | undefined;
3026
+ }): FramedSlot0;
1492
3027
  //#endregion
1493
3028
  //#region src/utils/validation.d.ts
1494
3029
  export declare function validateNumericAmount(amount: NumericAmount, parameterName: string, allowZero?: boolean): void;
@@ -1498,5 +3033,20 @@ export declare function validateTickRange(tickLower: number, tickUpper: number):
1498
3033
  export declare function validateFee(fee: number): asserts fee is FEE_TIER;
1499
3034
  export declare function validateTickSpacing(tickSpacing: number): void;
1500
3035
  export declare function validateWalletAddress(address?: string): asserts address is string;
3036
+ /**
3037
+ * True when `symbol` is acceptable to propose into the trading-symbol registry: ASCII letters and
3038
+ * digits only, 1 to 32 characters, and not a reserved word (`Token`, `Unit`, `none`) — the rules
3039
+ * the chain gateway enforces on a CreatePool symbol.
3040
+ */
3041
+ export declare function isProposableTradingSymbol(symbol: string): boolean;
3042
+ /**
3043
+ * Asserts that a pair is in the contract's canonical order (`token0 < token1` by plain string
3044
+ * comparison), which every write DTO requires. A pair a caller took from a stale quote or
3045
+ * position can be reversed; signing it would sign something other than what was priced.
3046
+ *
3047
+ * @throws GSwapSDKError VALIDATION_ERROR (`details.type` = `NON_CANONICAL_PAIR`) otherwise.
3048
+ */
3049
+ export declare function assertCanonicalPair(token0: string, token1: string): void;
1501
3050
  //#endregion
3051
+ export type { AddLiquidityInput, CreatePoolInput, EIP712DomainValue, EIP712Types, EntryParse, InvalidEntry, InvalidEntryHandler, PersonalSignChainDtoPayload, PoolPositionInput, PrivateKeyInput, RemoveLiquidityInput, RequestTradeInput, TypedDataPayload, V2WriteMethod };
1502
3052
  //# sourceMappingURL=index.d.cts.map