@gala-chain/gswap-sdk 1.2.0-rc.8 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -10
- package/dist/browser/classes/dex_fees.js.map +1 -1
- package/dist/browser/classes/gateway.js.map +1 -1
- package/dist/browser/classes/gdex_stream.js.map +1 -1
- package/dist/browser/classes/gswap.js.map +1 -1
- package/dist/browser/classes/gswap_sdk_error.js.map +1 -1
- package/dist/browser/classes/pending_swap_fate.js +2 -0
- package/dist/browser/classes/pending_swap_fate.js.map +1 -0
- package/dist/browser/classes/pending_swaps.js +1 -1
- package/dist/browser/classes/pending_swaps.js.map +1 -1
- package/dist/browser/classes/positions.js +1 -1
- package/dist/browser/classes/positions.js.map +1 -1
- package/dist/browser/classes/shadow_submit.js +1 -1
- package/dist/browser/classes/shadow_submit.js.map +1 -1
- package/dist/browser/classes/signers.js.map +1 -1
- package/dist/browser/classes/storage_adapters.js +2 -0
- package/dist/browser/classes/storage_adapters.js.map +1 -0
- package/dist/browser/classes/submitted_transaction.js.map +1 -1
- package/dist/browser/classes/symbols.js +1 -1
- package/dist/browser/classes/symbols.js.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/utils/chain_dto_signing.js.map +1 -1
- package/dist/browser/utils/class_key.js +2 -0
- package/dist/browser/utils/class_key.js.map +1 -0
- package/dist/browser/utils/classification.js +2 -0
- package/dist/browser/utils/classification.js.map +1 -0
- package/dist/browser/utils/dto_builders.js +1 -1
- package/dist/browser/utils/dto_builders.js.map +1 -1
- package/dist/browser/utils/eip712.js.map +1 -1
- package/dist/browser/utils/failure_classification.js +1 -1
- package/dist/browser/utils/failure_classification.js.map +1 -1
- package/dist/browser/utils/failure_guards.js +2 -0
- package/dist/browser/utils/failure_guards.js.map +1 -0
- package/dist/browser/utils/ordering.js +1 -1
- package/dist/browser/utils/ordering.js.map +1 -1
- package/dist/browser/utils/tick_align.js +2 -0
- package/dist/browser/utils/tick_align.js.map +1 -0
- package/dist/browser/utils/tick_math.js +2 -0
- package/dist/browser/utils/tick_math.js.map +1 -0
- package/dist/browser/utils/tick_range.js +2 -0
- package/dist/browser/utils/tick_range.js.map +1 -0
- package/dist/browser/utils/ticks.js +1 -1
- package/dist/browser/utils/ticks.js.map +1 -1
- package/dist/browser/utils/transport.js +1 -1
- package/dist/browser/utils/transport.js.map +1 -1
- package/dist/browser/utils/validation.js +1 -1
- package/dist/browser/utils/validation.js.map +1 -1
- package/dist/browser/version.js +1 -1
- package/dist/browser/version.js.map +1 -1
- package/dist/index.cjs +641 -336
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +470 -186
- package/dist/index.d.ts +470 -186
- package/dist/index.mjs +636 -337
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1315,6 +1315,7 @@ var GSwapSDKError = class GSwapSDKError extends Error {
|
|
|
1315
1315
|
code;
|
|
1316
1316
|
/** The named placeholders of the error: a flat object of primitives, safe to localize with. */
|
|
1317
1317
|
params;
|
|
1318
|
+
/** The server's `Retry-After` in milliseconds (a `RATE_LIMITED` answer), when it sent one. */
|
|
1318
1319
|
retryAfterMs;
|
|
1319
1320
|
/** The HTTP status of the response that caused this error, when there was one. */
|
|
1320
1321
|
status;
|
|
@@ -1640,7 +1641,7 @@ function parseJson(text) {
|
|
|
1640
1641
|
//#endregion
|
|
1641
1642
|
//#region src/version.ts
|
|
1642
1643
|
/** Package version embedded by the bundler, with a source-test fallback. */
|
|
1643
|
-
const SDK_VERSION = "1.2.0
|
|
1644
|
+
const SDK_VERSION = "1.2.0";
|
|
1644
1645
|
|
|
1645
1646
|
//#endregion
|
|
1646
1647
|
//#region src/utils/transport.ts
|
|
@@ -1701,7 +1702,7 @@ function buildRequestHeaders(wire, parts = {}) {
|
|
|
1701
1702
|
entries.set(name.toLowerCase(), [name, value]);
|
|
1702
1703
|
}
|
|
1703
1704
|
};
|
|
1704
|
-
if ((wire === null || wire === void 0 ? void 0 : wire.userAgent) !== false) put({ "User-Agent": (wire === null || wire === void 0 ? void 0 : wire.userAgent) ?? `GalaChain-SDK/${"1.2.0
|
|
1705
|
+
if ((wire === null || wire === void 0 ? void 0 : wire.userAgent) !== false) put({ "User-Agent": (wire === null || wire === void 0 ? void 0 : wire.userAgent) ?? `GalaChain-SDK/${"1.2.0"}` });
|
|
1705
1706
|
put(parts.defaults);
|
|
1706
1707
|
put(wire === null || wire === void 0 ? void 0 : wire.headers);
|
|
1707
1708
|
if (parts.json === true && !entries.has("content-type")) put({ "Content-Type": "application/json" });
|
|
@@ -2005,7 +2006,54 @@ const ALL_FEE_TIERS = [
|
|
|
2005
2006
|
];
|
|
2006
2007
|
|
|
2007
2008
|
//#endregion
|
|
2008
|
-
//#region src/utils/
|
|
2009
|
+
//#region src/utils/tick_range.ts
|
|
2010
|
+
function integerTickOf(tick) {
|
|
2011
|
+
if (typeof tick === "string") return tick.trim() === "" ? NaN : Number(tick);
|
|
2012
|
+
return tick;
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* True when a position over `[tickLower, tickUpper)` is IN RANGE at `currentTick`: the lower tick
|
|
2016
|
+
* is INCLUSIVE and the upper tick is EXCLUSIVE. That is the GalaChainDex contract's rule
|
|
2017
|
+
* (`DexV3Pool`: `tickCurrent >= tickLower && tickCurrent < tickUpper` is the case in which a
|
|
2018
|
+
* position holds both tokens and earns fees). A pool whose tick equals `tickUpper` is already out
|
|
2019
|
+
* of range: the position is entirely token1 there, and a swap through the tick has crossed it.
|
|
2020
|
+
*
|
|
2021
|
+
* `currentTick` is the pool's tick (`slot0.tick`, the greatest tick whose price is no greater than
|
|
2022
|
+
* the pool's price), not a rounded display value. A tick may be a number or the decimal string a
|
|
2023
|
+
* backend returns. Anything that is not an integer (`NaN`, `undefined`-like, an empty string, a
|
|
2024
|
+
* fraction) makes the answer `false`: an app that must tell "not loaded yet" from "out of range"
|
|
2025
|
+
* checks for the missing value itself first.
|
|
2026
|
+
*
|
|
2027
|
+
* Do NOT decide range by comparing a price with a tick's price (`tickToPrice`) using `<=` on both
|
|
2028
|
+
* ends, or by mixing a square-root price with a price. A price exactly on a tick's boundary is
|
|
2029
|
+
* then in range at the upper edge (the contract says it is not), and two representations of the
|
|
2030
|
+
* same boundary can round to opposite sides. For a pool price use {@link isSqrtPriceInRange}, which
|
|
2031
|
+
* derives the tick the way the contract does and then applies this rule.
|
|
2032
|
+
*
|
|
2033
|
+
* @example
|
|
2034
|
+
* ```ts
|
|
2035
|
+
* isTickInRange(-60, -60, 60); // true: the lower tick is inclusive
|
|
2036
|
+
* isTickInRange(60, -60, 60); // false: the upper tick is exclusive
|
|
2037
|
+
* ```
|
|
2038
|
+
*/
|
|
2039
|
+
function isTickInRange(currentTick, tickLower, tickUpper) {
|
|
2040
|
+
const current = integerTickOf(currentTick);
|
|
2041
|
+
const lower = integerTickOf(tickLower);
|
|
2042
|
+
const upper = integerTickOf(tickUpper);
|
|
2043
|
+
if (!Number.isInteger(current) || !Number.isInteger(lower) || !Number.isInteger(upper)) return false;
|
|
2044
|
+
return current >= lower && current < upper;
|
|
2045
|
+
}
|
|
2046
|
+
|
|
2047
|
+
//#endregion
|
|
2048
|
+
//#region src/utils/tick_math.ts
|
|
2049
|
+
/**
|
|
2050
|
+
* Tick and price arithmetic that never throws an SDK error: the contract's tick bounds, the
|
|
2051
|
+
* conversions between ticks and prices, and nothing that validates a range. It imports only the
|
|
2052
|
+
* two number libraries it computes with, never the `GSwapSDKError` class or the error catalog
|
|
2053
|
+
* (functions that must throw, `alignTickDown` and `assertTickRange`, are in `ticks.ts`), so an
|
|
2054
|
+
* app shell that prices a tick pays for the libraries and these few functions, not for ~25 kB of
|
|
2055
|
+
* error templates. A value that cannot be computed is `NaN`, never an exception.
|
|
2056
|
+
*/
|
|
2009
2057
|
/** Minimum tick supported by GalaChainDex. */
|
|
2010
2058
|
const GC_MIN_TICK = -887272;
|
|
2011
2059
|
/** Maximum tick supported by GalaChainDex. */
|
|
@@ -2014,6 +2062,7 @@ const DexMath = BigNumber.clone({
|
|
|
2014
2062
|
DECIMAL_PLACES: 60,
|
|
2015
2063
|
ROUNDING_MODE: BigNumber.ROUND_DOWN
|
|
2016
2064
|
});
|
|
2065
|
+
/** `decimal.js` at the 60 significant digits the contract's price math is exact to. */
|
|
2017
2066
|
const DexDecimal = Decimal.clone({ precision: 60 });
|
|
2018
2067
|
/** Convert a tick to the corresponding square-root price. */
|
|
2019
2068
|
function tickToSqrtPrice(tick) {
|
|
@@ -2048,6 +2097,26 @@ function tickToPrice(tick) {
|
|
|
2048
2097
|
return new BigNumber(new DexDecimal(1.0001).pow(tick).toString());
|
|
2049
2098
|
}
|
|
2050
2099
|
/**
|
|
2100
|
+
* {@link isTickInRange} for a pool's square-root price instead of its tick (a position row that
|
|
2101
|
+
* carries `sqrtPrice`, `tickLower` and `tickUpper`). The tick is derived from the price exactly as
|
|
2102
|
+
* the contract does (`sqrtPriceToTick`: the greatest tick whose square-root price is no greater
|
|
2103
|
+
* than the price, exact to 60 digits), then the contract's rule applies: lower tick inclusive,
|
|
2104
|
+
* upper tick exclusive. So a pool sitting exactly on `tickLower`'s price is in range, and exactly
|
|
2105
|
+
* on `tickUpper`'s price is not, and no float rounding can flip either.
|
|
2106
|
+
*
|
|
2107
|
+
* `false` for a price that is not positive and finite (not loaded, zero, `NaN`): it says nothing
|
|
2108
|
+
* about the position, so an app that must show a neutral state checks for the missing price
|
|
2109
|
+
* itself first. `tickLower` and `tickUpper` follow {@link isTickInRange}.
|
|
2110
|
+
*
|
|
2111
|
+
* @example
|
|
2112
|
+
* ```ts
|
|
2113
|
+
* const inRange = isSqrtPriceInRange(position.sqrtPrice, position.tickLower, position.tickUpper);
|
|
2114
|
+
* ```
|
|
2115
|
+
*/
|
|
2116
|
+
function isSqrtPriceInRange(sqrtPrice, tickLower, tickUpper) {
|
|
2117
|
+
return isTickInRange(sqrtPriceToTick(sqrtPrice), tickLower, tickUpper);
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2051
2120
|
* Return the integer tick for a token1/token0 `price`: by default the greatest tick whose price
|
|
2052
2121
|
* is no greater than `price`; `{ rounding: 'nearest' }` the closest tick. `NaN` for a price that
|
|
2053
2122
|
* is not positive and finite.
|
|
@@ -2061,77 +2130,18 @@ function tickFromPrice(price, options = {}) {
|
|
|
2061
2130
|
const tick = (options.rounding === "nearest" ? exact.round() : exact.floor()).toNumber();
|
|
2062
2131
|
return Number.isFinite(tick) ? tick : NaN;
|
|
2063
2132
|
}
|
|
2064
|
-
/** Align a tick down to the nearest multiple of a positive spacing. */
|
|
2065
|
-
function alignTickDown(tick, spacing) {
|
|
2066
|
-
assertSpacing(spacing);
|
|
2067
|
-
return Math.floor(tick / spacing) * spacing;
|
|
2068
|
-
}
|
|
2069
|
-
/** Align a tick up to the nearest multiple of a positive spacing. */
|
|
2070
|
-
function alignTickUp(tick, spacing) {
|
|
2071
|
-
assertSpacing(spacing);
|
|
2072
|
-
return Math.ceil(tick / spacing) * spacing;
|
|
2073
|
-
}
|
|
2074
|
-
/** Validate a position range against the global tick bounds and fee-tier spacing. */
|
|
2075
|
-
function assertTickRange(lower, upper, fee) {
|
|
2076
|
-
const spacing = TICK_SPACING_BY_FEE[fee];
|
|
2077
|
-
if (spacing === void 0) throw new GSwapSDKError("INVALID_FEE", {
|
|
2078
|
-
field: "fee",
|
|
2079
|
-
value: fee,
|
|
2080
|
-
allowed: ALLOWED_FEE_TIERS_TEXT
|
|
2081
|
-
});
|
|
2082
|
-
if (!Number.isInteger(lower) || !Number.isInteger(upper)) throw new GSwapSDKError("TICKS_NOT_INTEGERS", {
|
|
2083
|
-
tickLower: lower,
|
|
2084
|
-
tickUpper: upper
|
|
2085
|
-
});
|
|
2086
|
-
if (lower >= upper) throw new GSwapSDKError("INVALID_TICK_RANGE", {
|
|
2087
|
-
tickLower: lower,
|
|
2088
|
-
tickUpper: upper
|
|
2089
|
-
});
|
|
2090
|
-
if (lower < -887272 || upper > 887272) throw new GSwapSDKError("TICKS_OUT_OF_BOUNDS", {
|
|
2091
|
-
tickLower: lower,
|
|
2092
|
-
tickUpper: upper,
|
|
2093
|
-
minTick: GC_MIN_TICK,
|
|
2094
|
-
maxTick: GC_MAX_TICK
|
|
2095
|
-
});
|
|
2096
|
-
if (lower % spacing !== 0 || upper % spacing !== 0) throw new GSwapSDKError("TICKS_NOT_ALIGNED", {
|
|
2097
|
-
tickLower: lower,
|
|
2098
|
-
tickUpper: upper,
|
|
2099
|
-
spacing
|
|
2100
|
-
});
|
|
2101
|
-
}
|
|
2102
|
-
function assertSpacing(spacing) {
|
|
2103
|
-
if (!Number.isInteger(spacing) || spacing <= 0) throw new GSwapSDKError("INVALID_TICK_SPACING", { value: spacing });
|
|
2104
|
-
}
|
|
2105
|
-
/**
|
|
2106
|
-
* Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's
|
|
2107
|
-
* canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse
|
|
2108
|
-
* order the price is inverted here (at 60 significant digits, so a very large or very small
|
|
2109
|
-
* reciprocal keeps its precision) and the tick is re-derived from the inverted price with the
|
|
2110
|
-
* contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks
|
|
2111
|
-
* (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).
|
|
2112
|
-
*
|
|
2113
|
-
* @example
|
|
2114
|
-
* ```ts
|
|
2115
|
-
* const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);
|
|
2116
|
-
* const { sqrtPrice, tick } = frameSlot0(slot0);
|
|
2117
|
-
* ```
|
|
2118
|
-
*/
|
|
2119
|
-
function frameSlot0(slot0) {
|
|
2120
|
-
if (slot0.flippedFromRequest !== true) return {
|
|
2121
|
-
sqrtPrice: slot0.sqrtPrice,
|
|
2122
|
-
tick: slot0.tick
|
|
2123
|
-
};
|
|
2124
|
-
const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));
|
|
2125
|
-
if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) throw new GSwapSDKError("INVALID_SQRT_PRICE", { sqrtPrice: slot0.sqrtPrice });
|
|
2126
|
-
const sqrtPrice = inverted.toString();
|
|
2127
|
-
return {
|
|
2128
|
-
sqrtPrice,
|
|
2129
|
-
tick: sqrtPriceToTick(sqrtPrice)
|
|
2130
|
-
};
|
|
2131
|
-
}
|
|
2132
2133
|
|
|
2133
2134
|
//#endregion
|
|
2134
2135
|
//#region src/utils/validation.ts
|
|
2136
|
+
/**
|
|
2137
|
+
* Validates a decimal amount: a string or `BigNumber`, never a JavaScript number.
|
|
2138
|
+
*
|
|
2139
|
+
* @param amount - The amount to check.
|
|
2140
|
+
* @param parameterName - The field name reported in the error's `params.field`.
|
|
2141
|
+
* @param allowZero - Accept zero (default `false`).
|
|
2142
|
+
* @throws GSwapSDKError `AMOUNT_IS_JS_NUMBER`, `AMOUNT_NOT_FINITE`, `AMOUNT_NOT_POSITIVE` (zero
|
|
2143
|
+
* when `allowZero` is false) or `AMOUNT_NEGATIVE`.
|
|
2144
|
+
*/
|
|
2135
2145
|
function validateNumericAmount(amount, parameterName, allowZero = false) {
|
|
2136
2146
|
if (typeof amount === "number") throw new GSwapSDKError("AMOUNT_IS_JS_NUMBER", { field: parameterName });
|
|
2137
2147
|
let bnAmount;
|
|
@@ -2153,6 +2163,12 @@ function validateNumericAmount(amount, parameterName, allowZero = false) {
|
|
|
2153
2163
|
value: String(amount)
|
|
2154
2164
|
});
|
|
2155
2165
|
}
|
|
2166
|
+
/**
|
|
2167
|
+
* Validates a spot price and a lower/upper price range: none a JavaScript number, all positive and
|
|
2168
|
+
* finite (a non-finite upper bound counts as an unbounded `1e18`), and `lowerPrice <= upperPrice`.
|
|
2169
|
+
*
|
|
2170
|
+
* @throws GSwapSDKError `PRICE_VALUES_IS_JS_NUMBER`, `INVALID_PRICE_VALUES` or `INVALID_PRICE_RANGE`.
|
|
2171
|
+
*/
|
|
2156
2172
|
function validatePriceValues(spotPrice, lowerPrice, upperPrice) {
|
|
2157
2173
|
if ([
|
|
2158
2174
|
spotPrice,
|
|
@@ -2180,12 +2196,24 @@ function validatePriceValues(spotPrice, lowerPrice, upperPrice) {
|
|
|
2180
2196
|
upperPrice: String(upperPrice)
|
|
2181
2197
|
});
|
|
2182
2198
|
}
|
|
2199
|
+
/**
|
|
2200
|
+
* Validates a token's decimals: a non-negative integer.
|
|
2201
|
+
*
|
|
2202
|
+
* @throws GSwapSDKError `INVALID_TOKEN_DECIMALS` (`params.field` is `parameterName`).
|
|
2203
|
+
*/
|
|
2183
2204
|
function validateTokenDecimals(decimals, parameterName) {
|
|
2184
2205
|
if (decimals < 0 || !Number.isInteger(decimals)) throw new GSwapSDKError("INVALID_TOKEN_DECIMALS", {
|
|
2185
2206
|
field: parameterName,
|
|
2186
2207
|
value: decimals
|
|
2187
2208
|
});
|
|
2188
2209
|
}
|
|
2210
|
+
/**
|
|
2211
|
+
* Validates a position's tick range: two integers with `tickLower < tickUpper`, both within
|
|
2212
|
+
* `GC_MIN_TICK`..`GC_MAX_TICK`. It does not check alignment to a fee tier's spacing (see
|
|
2213
|
+
* `assertTickRange`).
|
|
2214
|
+
*
|
|
2215
|
+
* @throws GSwapSDKError `TICKS_NOT_INTEGERS`, `INVALID_TICK_RANGE` or `TICKS_OUT_OF_BOUNDS`.
|
|
2216
|
+
*/
|
|
2189
2217
|
function validateTickRange(tickLower, tickUpper) {
|
|
2190
2218
|
if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper)) throw new GSwapSDKError("TICKS_NOT_INTEGERS", {
|
|
2191
2219
|
tickLower,
|
|
@@ -2202,6 +2230,11 @@ function validateTickRange(tickLower, tickUpper) {
|
|
|
2202
2230
|
maxTick: GC_MAX_TICK
|
|
2203
2231
|
});
|
|
2204
2232
|
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Asserts that `fee` is one of the fee tiers in `ALL_FEE_TIERS` (`0`, `500`, `3000`, `10000`).
|
|
2235
|
+
*
|
|
2236
|
+
* @throws GSwapSDKError `INVALID_FEE` (`params.field` `'fee'`, `params.allowed` the tiers).
|
|
2237
|
+
*/
|
|
2205
2238
|
function validateFee(fee) {
|
|
2206
2239
|
if (!ALL_FEE_TIERS.some((tier) => Number(tier) === fee)) throw new GSwapSDKError("INVALID_FEE", {
|
|
2207
2240
|
field: "fee",
|
|
@@ -2209,9 +2242,20 @@ function validateFee(fee) {
|
|
|
2209
2242
|
allowed: ALLOWED_FEE_TIERS_TEXT
|
|
2210
2243
|
});
|
|
2211
2244
|
}
|
|
2245
|
+
/**
|
|
2246
|
+
* Validates a tick spacing: a positive integer.
|
|
2247
|
+
*
|
|
2248
|
+
* @throws GSwapSDKError `INVALID_TICK_SPACING`.
|
|
2249
|
+
*/
|
|
2212
2250
|
function validateTickSpacing(tickSpacing) {
|
|
2213
2251
|
if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) throw new GSwapSDKError("INVALID_TICK_SPACING", { value: tickSpacing });
|
|
2214
2252
|
}
|
|
2253
|
+
/**
|
|
2254
|
+
* Asserts that a wallet address was given and is a non-blank string. It does not check the address
|
|
2255
|
+
* format.
|
|
2256
|
+
*
|
|
2257
|
+
* @throws GSwapSDKError `MISSING_WALLET_ADDRESS` (undefined) or `INVALID_WALLET_ADDRESS` (blank).
|
|
2258
|
+
*/
|
|
2215
2259
|
function validateWalletAddress(address) {
|
|
2216
2260
|
if (address === void 0) throw new GSwapSDKError("MISSING_WALLET_ADDRESS", {});
|
|
2217
2261
|
if (!address || typeof address !== "string" || address.trim().length === 0) throw new GSwapSDKError("INVALID_WALLET_ADDRESS", {
|
|
@@ -2694,9 +2738,13 @@ async function shadowFailures(run) {
|
|
|
2694
2738
|
//#region src/classes/submitted_transaction.ts
|
|
2695
2739
|
/** A submitted v2 transaction whose confirmation mode is explicit in the gateway response. */
|
|
2696
2740
|
var SubmittedTransaction = class {
|
|
2741
|
+
/** The chain method that was submitted (`RequestTrade`, `AddLiquidity`, ...). */
|
|
2697
2742
|
method;
|
|
2743
|
+
/** The write's durable correlation key: persist it, and confirm from it alone later. */
|
|
2698
2744
|
uniqueKey;
|
|
2745
|
+
/** The request transaction id the gateway reported, or `null` when it gave none. */
|
|
2699
2746
|
transactionId;
|
|
2747
|
+
/** The block of the transaction, when the answer carried one; otherwise `null`. */
|
|
2700
2748
|
blockNumber;
|
|
2701
2749
|
/** The gateway's `data.mode`: `'sync'` (executed, `result` is the chain result) or `'queued'`. */
|
|
2702
2750
|
mode;
|
|
@@ -2818,7 +2866,9 @@ var ChainGateway = class {
|
|
|
2818
2866
|
chainCallTimeoutMs;
|
|
2819
2867
|
isTransportFailure;
|
|
2820
2868
|
answerOfRejectionHook;
|
|
2869
|
+
/** The request timeout in milliseconds (`Infinity` when no timer is armed). */
|
|
2821
2870
|
requestTimeoutMs;
|
|
2871
|
+
/** The swap backend base URL every request is sent to, without a trailing slash. */
|
|
2822
2872
|
dexBackendBaseUrl;
|
|
2823
2873
|
/** Wire format shared by the read services built on this gateway. */
|
|
2824
2874
|
wire;
|
|
@@ -2892,7 +2942,7 @@ var ChainGateway = class {
|
|
|
2892
2942
|
*
|
|
2893
2943
|
* Unlike `submit`, EVERY HTTP status resolves: the result is the raw `{ httpStatus, body }`,
|
|
2894
2944
|
* because shadow failures are classified from the status together with the body's `code`
|
|
2895
|
-
* (`SHADOW_UNAVAILABLE`, `
|
|
2945
|
+
* (`SHADOW_UNAVAILABLE`, `SHADOW_UNSUPPORTED_TYPE`, `SHADOW_RELAY_REJECTED`);
|
|
2896
2946
|
* see `readShadowSubmitOutcome`. Only a failure to get an answer rejects, and it rejects with
|
|
2897
2947
|
* `SUBMISSION_OUTCOME_UNKNOWN` (`params.reason` `'timeout'` or `'transport'`): the request may
|
|
2898
2948
|
* have been accepted. Every error it throws has `error.shadow === true`, and a non-SDK object
|
|
@@ -3140,7 +3190,9 @@ function isGdexLiquidityEvent(value) {
|
|
|
3140
3190
|
}
|
|
3141
3191
|
/** A JSON-RPC error answered by the stream. */
|
|
3142
3192
|
var GdexStreamError = class extends Error {
|
|
3193
|
+
/** The JSON-RPC error code. */
|
|
3143
3194
|
code;
|
|
3195
|
+
/** The error's optional `data` member, as the server sent it. */
|
|
3144
3196
|
data;
|
|
3145
3197
|
constructor(code, message, data) {
|
|
3146
3198
|
super(message);
|
|
@@ -3218,6 +3270,7 @@ var GdexStreamService = class {
|
|
|
3218
3270
|
this.connectPromise = void 0;
|
|
3219
3271
|
socket === null || socket === void 0 || socket.close(1e3, "client disconnect");
|
|
3220
3272
|
}
|
|
3273
|
+
/** `true` while the socket is open (false while connecting, reconnecting or after `disconnect()`). */
|
|
3221
3274
|
isConnected() {
|
|
3222
3275
|
var _this$socket;
|
|
3223
3276
|
return ((_this$socket = this.socket) === null || _this$socket === void 0 ? void 0 : _this$socket.readyState) === WEBSOCKET_OPEN;
|
|
@@ -3259,30 +3312,41 @@ var GdexStreamService = class {
|
|
|
3259
3312
|
}
|
|
3260
3313
|
});
|
|
3261
3314
|
}
|
|
3315
|
+
/** `gdex_serverInfo`: the server's own description of itself, as it sends it. */
|
|
3262
3316
|
serverInfo() {
|
|
3263
3317
|
return this.request("gdex_serverInfo");
|
|
3264
3318
|
}
|
|
3319
|
+
/** `gdex_ping`: a round trip that answers `{ pong, serverTime }`. */
|
|
3265
3320
|
ping() {
|
|
3266
3321
|
return this.request("gdex_ping");
|
|
3267
3322
|
}
|
|
3323
|
+
/** `gdex_getPool`: the current state of one pool, selected by its key or hash. */
|
|
3268
3324
|
getPool(selector) {
|
|
3269
3325
|
return this.request("gdex_getPool", selector);
|
|
3270
3326
|
}
|
|
3327
|
+
/** `gdex_getBalance`: an owner's balances, or only the one of `tokenClassKey` when given. */
|
|
3271
3328
|
getBalance(owner, tokenClassKey) {
|
|
3272
3329
|
return this.request("gdex_getBalance", tokenClassKey === void 0 ? { owner } : {
|
|
3273
3330
|
owner,
|
|
3274
3331
|
tokenClassKey
|
|
3275
3332
|
});
|
|
3276
3333
|
}
|
|
3334
|
+
/**
|
|
3335
|
+
* `gdex_getPositions`: an owner's positions, optionally in one pool, a page at a time. Pass the
|
|
3336
|
+
* returned `bookmark` back in as `bookmark` for the next page.
|
|
3337
|
+
*/
|
|
3277
3338
|
getPositions(opts) {
|
|
3278
3339
|
return this.request("gdex_getPositions", opts);
|
|
3279
3340
|
}
|
|
3341
|
+
/** `gdex_getBlockHeight`: the block number the server reports, with its timestamp. */
|
|
3280
3342
|
getBlockHeight() {
|
|
3281
3343
|
return this.request("gdex_getBlockHeight");
|
|
3282
3344
|
}
|
|
3345
|
+
/** `gdex_quote`: a quote over the stream; give exactly one of `amountIn` or `amountOut`. */
|
|
3283
3346
|
quote(params) {
|
|
3284
3347
|
return this.request("gdex_quote", params);
|
|
3285
3348
|
}
|
|
3349
|
+
/** `gdex_getToken`: the server's record of one token class, as it sends it. */
|
|
3286
3350
|
getToken(tokenClassKey) {
|
|
3287
3351
|
return this.request("gdex_getToken", { tokenClassKey });
|
|
3288
3352
|
}
|
|
@@ -3615,39 +3679,13 @@ function finiteNumberOf(value) {
|
|
|
3615
3679
|
}
|
|
3616
3680
|
|
|
3617
3681
|
//#endregion
|
|
3618
|
-
//#region src/utils/
|
|
3619
|
-
/**
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
*
|
|
3625
|
-
* @example
|
|
3626
|
-
* ```ts
|
|
3627
|
-
* const pair = readOrderedSymbols(['GALA', 'GUSDC']);
|
|
3628
|
-
* console.log(pair.token0);
|
|
3629
|
-
* ```
|
|
3682
|
+
//#region src/utils/class_key.ts
|
|
3683
|
+
/**
|
|
3684
|
+
* Token class keys that never throw: the `$`-joined composite key and the non-throwing parsers.
|
|
3685
|
+
* This module imports nothing at run time (the key type is erased), so an app shell that reads a
|
|
3686
|
+
* stored key pays for a few hundred bytes, never for the error class or the catalog. The parser
|
|
3687
|
+
* that THROWS an SDK error on a bad key (`parseTokenClassKey`) lives in `ordering.ts`.
|
|
3630
3688
|
*/
|
|
3631
|
-
function readOrderedSymbols(value) {
|
|
3632
|
-
if (Array.isArray(value) && value.length >= 2) {
|
|
3633
|
-
const token0 = value[0];
|
|
3634
|
-
const token1 = value[1];
|
|
3635
|
-
if (typeof token0 === "string" && typeof token1 === "string") return {
|
|
3636
|
-
token0,
|
|
3637
|
-
token1
|
|
3638
|
-
};
|
|
3639
|
-
}
|
|
3640
|
-
if (typeof value === "object" && value !== null) {
|
|
3641
|
-
const record = value;
|
|
3642
|
-
const token0 = record["token0"];
|
|
3643
|
-
const token1 = record["token1"];
|
|
3644
|
-
if (typeof token0 === "string" && typeof token1 === "string") return {
|
|
3645
|
-
token0,
|
|
3646
|
-
token1
|
|
3647
|
-
};
|
|
3648
|
-
}
|
|
3649
|
-
throw new GSwapSDKError("UNORDERABLE_SYMBOLS", { received: Array.isArray(value) ? "array" : value === null ? "null" : typeof value });
|
|
3650
|
-
}
|
|
3651
3689
|
/** Return the `$`-joined composite key used by GalaChain object identities. */
|
|
3652
3690
|
function compositeKeyOf(token) {
|
|
3653
3691
|
return [
|
|
@@ -3658,33 +3696,14 @@ function compositeKeyOf(token) {
|
|
|
3658
3696
|
].join("$");
|
|
3659
3697
|
}
|
|
3660
3698
|
/**
|
|
3661
|
-
*
|
|
3699
|
+
* Splits `collection<d>category<d>type<d>additionalKey` from the right, or `undefined` when there
|
|
3700
|
+
* are fewer than four segments or any of the four is empty. The one place the split is written;
|
|
3701
|
+
* the strict `parseTokenClassKey` calls it too.
|
|
3662
3702
|
*
|
|
3663
3703
|
* The LAST three segments are always `category`, `type` and `additionalKey`; everything before
|
|
3664
3704
|
* them is the `collection`. Parsing from the right is required because real collections contain
|
|
3665
3705
|
* the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`
|
|
3666
|
-
* shifts every field.
|
|
3667
|
-
* no symbol, which must come from the token class or trading-symbol registry.
|
|
3668
|
-
*
|
|
3669
|
-
* @example
|
|
3670
|
-
* ```ts
|
|
3671
|
-
* parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'
|
|
3672
|
-
* ```
|
|
3673
|
-
*/
|
|
3674
|
-
function parseTokenClassKey(tokenClassKey) {
|
|
3675
|
-
if (typeof tokenClassKey === "object") return {
|
|
3676
|
-
collection: tokenClassKey.collection,
|
|
3677
|
-
category: tokenClassKey.category,
|
|
3678
|
-
type: tokenClassKey.type,
|
|
3679
|
-
additionalKey: tokenClassKey.additionalKey
|
|
3680
|
-
};
|
|
3681
|
-
const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes("|") ? "|" : "$");
|
|
3682
|
-
if (parsed === void 0) throw new GSwapSDKError("INVALID_TOKEN_CLASS_KEY", { tokenClassKey });
|
|
3683
|
-
return parsed;
|
|
3684
|
-
}
|
|
3685
|
-
/**
|
|
3686
|
-
* Splits `collection<d>category<d>type<d>additionalKey` from the right, or `undefined` when there
|
|
3687
|
-
* are fewer than four segments or any of the four is empty. The one place the split is written.
|
|
3706
|
+
* shifts every field.
|
|
3688
3707
|
*/
|
|
3689
3708
|
function splitClassKey(key, delimiter) {
|
|
3690
3709
|
const segments = key.split(delimiter);
|
|
@@ -3700,7 +3719,7 @@ function splitClassKey(key, delimiter) {
|
|
|
3700
3719
|
};
|
|
3701
3720
|
}
|
|
3702
3721
|
/**
|
|
3703
|
-
* The non-throwing
|
|
3722
|
+
* The non-throwing `parseTokenClassKey`: the class key, or `undefined` when `value` is not
|
|
3704
3723
|
* one. A string is split exactly as `parseTokenClassKey` splits it (`|` form when it contains a
|
|
3705
3724
|
* `|`, else `$`, from the right, all four parts non-empty). Unlike `parseTokenClassKey`, an
|
|
3706
3725
|
* object is VALIDATED, not just copied: all four fields must be non-empty strings. Anything else
|
|
@@ -3753,6 +3772,66 @@ function tryParseCompositeKey(value) {
|
|
|
3753
3772
|
return typeof value === "string" ? splitClassKey(value, "$") : void 0;
|
|
3754
3773
|
}
|
|
3755
3774
|
|
|
3775
|
+
//#endregion
|
|
3776
|
+
//#region src/utils/ordering.ts
|
|
3777
|
+
/** Return two trading symbols in the contract's plain-string order. */
|
|
3778
|
+
function orderSymbols(a, b) {
|
|
3779
|
+
return a < b ? [a, b] : [b, a];
|
|
3780
|
+
}
|
|
3781
|
+
/** Read an ordered symbol pair from a tuple or object returned by a boundary helper.
|
|
3782
|
+
*
|
|
3783
|
+
* @example
|
|
3784
|
+
* ```ts
|
|
3785
|
+
* const pair = readOrderedSymbols(['GALA', 'GUSDC']);
|
|
3786
|
+
* console.log(pair.token0);
|
|
3787
|
+
* ```
|
|
3788
|
+
*/
|
|
3789
|
+
function readOrderedSymbols(value) {
|
|
3790
|
+
if (Array.isArray(value) && value.length >= 2) {
|
|
3791
|
+
const token0 = value[0];
|
|
3792
|
+
const token1 = value[1];
|
|
3793
|
+
if (typeof token0 === "string" && typeof token1 === "string") return {
|
|
3794
|
+
token0,
|
|
3795
|
+
token1
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3798
|
+
if (typeof value === "object" && value !== null) {
|
|
3799
|
+
const record = value;
|
|
3800
|
+
const token0 = record["token0"];
|
|
3801
|
+
const token1 = record["token1"];
|
|
3802
|
+
if (typeof token0 === "string" && typeof token1 === "string") return {
|
|
3803
|
+
token0,
|
|
3804
|
+
token1
|
|
3805
|
+
};
|
|
3806
|
+
}
|
|
3807
|
+
throw new GSwapSDKError("UNORDERABLE_SYMBOLS", { received: Array.isArray(value) ? "array" : value === null ? "null" : typeof value });
|
|
3808
|
+
}
|
|
3809
|
+
/**
|
|
3810
|
+
* Parse a pipe- or dollar-separated token class key.
|
|
3811
|
+
*
|
|
3812
|
+
* The LAST three segments are always `category`, `type` and `additionalKey`; everything before
|
|
3813
|
+
* them is the `collection`. Parsing from the right is required because real collections contain
|
|
3814
|
+
* the `$` delimiter themselves (for example `$GMUSIC`), so a plain left-to-right `split('$')`
|
|
3815
|
+
* shifts every field. Nothing here says anything about the token's symbol: a class key carries
|
|
3816
|
+
* no symbol, which must come from the token class or trading-symbol registry.
|
|
3817
|
+
*
|
|
3818
|
+
* @example
|
|
3819
|
+
* ```ts
|
|
3820
|
+
* parseTokenClassKey('$GMUSIC$Unit$none$none').collection; // '$GMUSIC'
|
|
3821
|
+
* ```
|
|
3822
|
+
*/
|
|
3823
|
+
function parseTokenClassKey(tokenClassKey) {
|
|
3824
|
+
if (typeof tokenClassKey === "object") return {
|
|
3825
|
+
collection: tokenClassKey.collection,
|
|
3826
|
+
category: tokenClassKey.category,
|
|
3827
|
+
type: tokenClassKey.type,
|
|
3828
|
+
additionalKey: tokenClassKey.additionalKey
|
|
3829
|
+
};
|
|
3830
|
+
const parsed = splitClassKey(tokenClassKey, tokenClassKey.includes("|") ? "|" : "$");
|
|
3831
|
+
if (parsed === void 0) throw new GSwapSDKError("INVALID_TOKEN_CLASS_KEY", { tokenClassKey });
|
|
3832
|
+
return parsed;
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3756
3835
|
//#endregion
|
|
3757
3836
|
//#region src/classes/symbols.ts
|
|
3758
3837
|
const SYMBOL_CACHE_TTL_MS = 6e4;
|
|
@@ -4171,37 +4250,151 @@ function parsePoolListInfo(entry) {
|
|
|
4171
4250
|
}
|
|
4172
4251
|
|
|
4173
4252
|
//#endregion
|
|
4174
|
-
//#region src/utils/
|
|
4253
|
+
//#region src/utils/tick_align.ts
|
|
4175
4254
|
/**
|
|
4176
|
-
*
|
|
4177
|
-
* (
|
|
4178
|
-
*
|
|
4179
|
-
* `
|
|
4180
|
-
* trade builder, which nothing reads back by prefix.
|
|
4255
|
+
* Aligning a tick to a pool's tick spacing without throwing. This module imports nothing, so an
|
|
4256
|
+
* app shell (a price input that snaps to a tick) pays for a few dozen bytes, not for the error
|
|
4257
|
+
* class and catalog that `alignTickDown` and `alignTickUp` (in `ticks.ts`) carry because they
|
|
4258
|
+
* throw `INVALID_TICK_SPACING` for a spacing that is not a positive integer.
|
|
4181
4259
|
*/
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4260
|
+
/** True for a tick spacing the contract can use: a positive integer. The one definition. */
|
|
4261
|
+
function hasValidSpacing(spacing) {
|
|
4262
|
+
return Number.isInteger(spacing) && spacing > 0;
|
|
4263
|
+
}
|
|
4186
4264
|
/**
|
|
4187
|
-
*
|
|
4188
|
-
*
|
|
4265
|
+
* {@link alignTickDown} that answers `NaN` instead of throwing: the greatest multiple of `spacing`
|
|
4266
|
+
* that is no greater than `tick`, or `NaN` when `spacing` is not a positive integer (a pool whose
|
|
4267
|
+
* spacing has not loaded yet) or `tick` is not a number. For an app shell and for a drag handler,
|
|
4268
|
+
* which must not throw while the spacing is missing. `alignTickDown` (the SDK's own call sites use
|
|
4269
|
+
* it) gives the same value and throws for the bad spacing.
|
|
4189
4270
|
*
|
|
4190
|
-
* @
|
|
4191
|
-
*
|
|
4271
|
+
* @example
|
|
4272
|
+
* ```ts
|
|
4273
|
+
* alignTickDownOrNaN(-61, 60); // -120: it floors, it does not truncate toward zero
|
|
4274
|
+
* alignTickDownOrNaN(100, 0); // NaN
|
|
4275
|
+
* ```
|
|
4192
4276
|
*/
|
|
4193
|
-
function
|
|
4194
|
-
|
|
4195
|
-
if (!UNIQUE_KEY_PREFIX_PATTERN.test(prefix) || prefix.length > MAX_UNIQUE_KEY_PREFIX_LENGTH) throw new GSwapSDKError("INVALID_UNIQUE_KEY_PREFIX", {
|
|
4196
|
-
uniqueKeyPrefix: prefix,
|
|
4197
|
-
maxLength: MAX_UNIQUE_KEY_PREFIX_LENGTH
|
|
4198
|
-
});
|
|
4199
|
-
return prefix;
|
|
4277
|
+
function alignTickDownOrNaN(tick, spacing) {
|
|
4278
|
+
return hasValidSpacing(spacing) ? Math.floor(tick / spacing) * spacing : NaN;
|
|
4200
4279
|
}
|
|
4201
4280
|
/**
|
|
4202
|
-
*
|
|
4203
|
-
*
|
|
4204
|
-
*
|
|
4281
|
+
* {@link alignTickUp} that answers `NaN` instead of throwing: the least multiple of `spacing` that
|
|
4282
|
+
* is no less than `tick`, or `NaN` for a spacing that is not a positive integer. See
|
|
4283
|
+
* {@link alignTickDownOrNaN}.
|
|
4284
|
+
*/
|
|
4285
|
+
function alignTickUpOrNaN(tick, spacing) {
|
|
4286
|
+
return hasValidSpacing(spacing) ? Math.ceil(tick / spacing) * spacing : NaN;
|
|
4287
|
+
}
|
|
4288
|
+
|
|
4289
|
+
//#endregion
|
|
4290
|
+
//#region src/utils/ticks.ts
|
|
4291
|
+
/**
|
|
4292
|
+
* The tick functions that THROW an SDK error on a bad input (`alignTickDown`, `alignTickUp`,
|
|
4293
|
+
* `assertTickRange`, `frameSlot0`). The arithmetic that never throws (`tickToPrice`,
|
|
4294
|
+
* `tickFromPrice`, `tickToSqrtPrice`, `sqrtPriceToTick`, the bounds) is in `tick_math.ts`, which
|
|
4295
|
+
* does not import the error class or the catalog; import it from the package entry as usual.
|
|
4296
|
+
*/
|
|
4297
|
+
/** Align a tick down to the nearest multiple of a positive spacing. */
|
|
4298
|
+
function alignTickDown(tick, spacing) {
|
|
4299
|
+
assertSpacing(spacing);
|
|
4300
|
+
return alignTickDownOrNaN(tick, spacing);
|
|
4301
|
+
}
|
|
4302
|
+
/** Align a tick up to the nearest multiple of a positive spacing. */
|
|
4303
|
+
function alignTickUp(tick, spacing) {
|
|
4304
|
+
assertSpacing(spacing);
|
|
4305
|
+
return alignTickUpOrNaN(tick, spacing);
|
|
4306
|
+
}
|
|
4307
|
+
/** Validate a position range against the global tick bounds and fee-tier spacing. */
|
|
4308
|
+
function assertTickRange(lower, upper, fee) {
|
|
4309
|
+
const spacing = TICK_SPACING_BY_FEE[fee];
|
|
4310
|
+
if (spacing === void 0) throw new GSwapSDKError("INVALID_FEE", {
|
|
4311
|
+
field: "fee",
|
|
4312
|
+
value: fee,
|
|
4313
|
+
allowed: ALLOWED_FEE_TIERS_TEXT
|
|
4314
|
+
});
|
|
4315
|
+
if (!Number.isInteger(lower) || !Number.isInteger(upper)) throw new GSwapSDKError("TICKS_NOT_INTEGERS", {
|
|
4316
|
+
tickLower: lower,
|
|
4317
|
+
tickUpper: upper
|
|
4318
|
+
});
|
|
4319
|
+
if (lower >= upper) throw new GSwapSDKError("INVALID_TICK_RANGE", {
|
|
4320
|
+
tickLower: lower,
|
|
4321
|
+
tickUpper: upper
|
|
4322
|
+
});
|
|
4323
|
+
if (lower < -887272 || upper > 887272) throw new GSwapSDKError("TICKS_OUT_OF_BOUNDS", {
|
|
4324
|
+
tickLower: lower,
|
|
4325
|
+
tickUpper: upper,
|
|
4326
|
+
minTick: GC_MIN_TICK,
|
|
4327
|
+
maxTick: GC_MAX_TICK
|
|
4328
|
+
});
|
|
4329
|
+
if (lower % spacing !== 0 || upper % spacing !== 0) throw new GSwapSDKError("TICKS_NOT_ALIGNED", {
|
|
4330
|
+
tickLower: lower,
|
|
4331
|
+
tickUpper: upper,
|
|
4332
|
+
spacing
|
|
4333
|
+
});
|
|
4334
|
+
}
|
|
4335
|
+
function assertSpacing(spacing) {
|
|
4336
|
+
if (!hasValidSpacing(spacing)) throw new GSwapSDKError("INVALID_TICK_SPACING", { value: spacing });
|
|
4337
|
+
}
|
|
4338
|
+
/**
|
|
4339
|
+
* Puts a `slot0` answer into the frame of the request. The backend always answers in the pool's
|
|
4340
|
+
* canonical order and says so with `flippedFromRequest`; when the caller asked for the reverse
|
|
4341
|
+
* order the price is inverted here (at 60 significant digits, so a very large or very small
|
|
4342
|
+
* reciprocal keeps its precision) and the tick is re-derived from the inverted price with the
|
|
4343
|
+
* contract's greatest-tick rule. Negating the tick instead is wrong for a price between ticks
|
|
4344
|
+
* (and `-t - 1` is wrong for a price exactly on a tick: sqrtPrice 1 / tick 0 stays 1 / 0).
|
|
4345
|
+
*
|
|
4346
|
+
* @example
|
|
4347
|
+
* ```ts
|
|
4348
|
+
* const slot0 = await gSwap.pools.getSlot0('A', 'B', 500);
|
|
4349
|
+
* const { sqrtPrice, tick } = frameSlot0(slot0);
|
|
4350
|
+
* ```
|
|
4351
|
+
*/
|
|
4352
|
+
function frameSlot0(slot0) {
|
|
4353
|
+
if (slot0.flippedFromRequest !== true) return {
|
|
4354
|
+
sqrtPrice: slot0.sqrtPrice,
|
|
4355
|
+
tick: slot0.tick
|
|
4356
|
+
};
|
|
4357
|
+
const inverted = new DexDecimal(1).dividedBy(new DexDecimal(slot0.sqrtPrice));
|
|
4358
|
+
if (!inverted.isFinite() || inverted.lessThanOrEqualTo(0)) throw new GSwapSDKError("INVALID_SQRT_PRICE", { sqrtPrice: slot0.sqrtPrice });
|
|
4359
|
+
const sqrtPrice = inverted.toString();
|
|
4360
|
+
return {
|
|
4361
|
+
sqrtPrice,
|
|
4362
|
+
tick: sqrtPriceToTick(sqrtPrice)
|
|
4363
|
+
};
|
|
4364
|
+
}
|
|
4365
|
+
|
|
4366
|
+
//#endregion
|
|
4367
|
+
//#region src/utils/unique_key.ts
|
|
4368
|
+
/**
|
|
4369
|
+
* The `uniqueKey` prefix frontend_v2 and wallet_extension have always sent
|
|
4370
|
+
* (`galaswap-operation-<uuid>`). defi-backend does not depend on it: the chain-write verifier
|
|
4371
|
+
* only requires a non-empty key of at most 256 characters, and apply-results accepts
|
|
4372
|
+
* `[A-Za-z0-9._:-]{1,128}`; the only code that mints a prefixed key itself is the server-side v1
|
|
4373
|
+
* trade builder, which nothing reads back by prefix.
|
|
4374
|
+
*/
|
|
4375
|
+
const DEFAULT_UNIQUE_KEY_PREFIX = "galaswap-operation-";
|
|
4376
|
+
/** A canonical UUID is 36 characters; the apply-results key limit is 128. */
|
|
4377
|
+
const MAX_UNIQUE_KEY_PREFIX_LENGTH = 92;
|
|
4378
|
+
const UNIQUE_KEY_PREFIX_PATTERN = /^[A-Za-z0-9._:-]*$/u;
|
|
4379
|
+
/**
|
|
4380
|
+
* Validates a caller-supplied `uniqueKey` prefix. The whole key (`<prefix><uuid>`) must stay a
|
|
4381
|
+
* valid apply-results key, otherwise `confirm()` could never read the outcome of the write.
|
|
4382
|
+
*
|
|
4383
|
+
* @throws GSwapSDKError `INVALID_UNIQUE_KEY_PREFIX` when the prefix has characters outside
|
|
4384
|
+
* `A-Za-z0-9._:-` or is longer than 92 characters.
|
|
4385
|
+
*/
|
|
4386
|
+
function resolveUniqueKeyPrefix(prefix) {
|
|
4387
|
+
if (prefix === void 0) return DEFAULT_UNIQUE_KEY_PREFIX;
|
|
4388
|
+
if (!UNIQUE_KEY_PREFIX_PATTERN.test(prefix) || prefix.length > MAX_UNIQUE_KEY_PREFIX_LENGTH) throw new GSwapSDKError("INVALID_UNIQUE_KEY_PREFIX", {
|
|
4389
|
+
uniqueKeyPrefix: prefix,
|
|
4390
|
+
maxLength: MAX_UNIQUE_KEY_PREFIX_LENGTH
|
|
4391
|
+
});
|
|
4392
|
+
return prefix;
|
|
4393
|
+
}
|
|
4394
|
+
/**
|
|
4395
|
+
* Validates a caller-supplied write `uniqueKey`: 1 to 128 characters of `A-Za-z0-9._:-`, the
|
|
4396
|
+
* shape the apply-results route accepts, so the write's outcome can always be read back with
|
|
4397
|
+
* `confirm()`. A key is one attempt's identity: reuse it only to retry that same attempt.
|
|
4205
4398
|
*
|
|
4206
4399
|
* @throws GSwapSDKError `INVALID_UNIQUE_KEY` otherwise.
|
|
4207
4400
|
*/
|
|
@@ -4219,8 +4412,9 @@ const decimalString = (amount) => new BigNumber(amount).toFixed();
|
|
|
4219
4412
|
/**
|
|
4220
4413
|
* Builds the RequestTrade DTO: `exactIn` sells that much of the input token (`sell0Qty` or
|
|
4221
4414
|
* `sell1Qty`), `exactOut` buys that much of the output token (`buy1Qty` or `buy0Qty`), plus the
|
|
4222
|
-
* side's slippage bound and an optional `priceLimit`. Key order
|
|
4223
|
-
*
|
|
4415
|
+
* side's slippage bound and an optional `priceLimit`. Key order is
|
|
4416
|
+
* `token0, token1, fee, uniqueKey`, then the one quantity, then the slippage bound, then
|
|
4417
|
+
* `priceLimit`.
|
|
4224
4418
|
*
|
|
4225
4419
|
* @example
|
|
4226
4420
|
* ```ts
|
|
@@ -5408,21 +5602,21 @@ function toDecimalString(amount) {
|
|
|
5408
5602
|
*
|
|
5409
5603
|
* - `SHADOW_UNAVAILABLE` (503): marking failed or infra not configured; retryable. Never fall back
|
|
5410
5604
|
* silently to a public swap.
|
|
5411
|
-
* - `SHADOW_DISABLED` (400): the feature is off for this environment.
|
|
5412
5605
|
* - `SHADOW_UNSUPPORTED_TYPE` (400): shadow requested on a non-swap method.
|
|
5413
5606
|
* - `SHADOW_RELAY_REJECTED`: terminal business rejection (slippage, balance, ...), not retryable;
|
|
5414
5607
|
* `message` is the gateway's verbatim string.
|
|
5415
5608
|
*/
|
|
5416
5609
|
const SHADOW_SUBMIT_CODES = [
|
|
5417
5610
|
"SHADOW_UNAVAILABLE",
|
|
5418
|
-
"SHADOW_DISABLED",
|
|
5419
5611
|
"SHADOW_UNSUPPORTED_TYPE",
|
|
5420
5612
|
"SHADOW_RELAY_REJECTED"
|
|
5421
5613
|
];
|
|
5422
5614
|
/**
|
|
5423
5615
|
* Every `kind` of a failed {@link ShadowSubmitOutcome}, for an app that maps each to its own text
|
|
5424
|
-
* (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled
|
|
5425
|
-
* the
|
|
5616
|
+
* (`Record<ShadowFailureKind, string>`): `unavailable` (retryable), `disabled` (the shadow route
|
|
5617
|
+
* answered 400: the request is not a dark-swappable one, e.g. `SHADOW_UNSUPPORTED_TYPE`; Shadow
|
|
5618
|
+
* Swaps themselves are enabled in every environment), `rejected` (carries the gateway's `message`)
|
|
5619
|
+
* and `unknown`.
|
|
5426
5620
|
*/
|
|
5427
5621
|
const SHADOW_FAILURE_KINDS = [
|
|
5428
5622
|
"unavailable",
|
|
@@ -5439,12 +5633,12 @@ function classifyShadowSubmitStatus(status) {
|
|
|
5439
5633
|
/**
|
|
5440
5634
|
* Prefers the body `code` (stable across status remaps) and falls back to the HTTP status.
|
|
5441
5635
|
* `SHADOW_UNAVAILABLE` is the only retryable case; `SHADOW_RELAY_REJECTED` is a terminal gateway
|
|
5442
|
-
* rejection;
|
|
5636
|
+
* rejection; `SHADOW_UNSUPPORTED_TYPE` and any other 400 map to "disabled".
|
|
5443
5637
|
*/
|
|
5444
5638
|
function classifyShadowSubmitError(status, code) {
|
|
5445
5639
|
if (code === "SHADOW_UNAVAILABLE") return "unavailable";
|
|
5446
5640
|
if (code === "SHADOW_RELAY_REJECTED") return "rejected";
|
|
5447
|
-
if (code === "
|
|
5641
|
+
if (code === "SHADOW_UNSUPPORTED_TYPE") return "disabled";
|
|
5448
5642
|
return classifyShadowSubmitStatus(status);
|
|
5449
5643
|
}
|
|
5450
5644
|
function readShadowSubmitOutcome(method, signedBody, result) {
|
|
@@ -5686,27 +5880,43 @@ var Swaps = class {
|
|
|
5686
5880
|
|
|
5687
5881
|
//#endregion
|
|
5688
5882
|
//#region src/classes/gswap.ts
|
|
5689
|
-
/**
|
|
5883
|
+
/**
|
|
5884
|
+
* Main entry point for the current GalaChainDex SDK: one client bundling the services that read
|
|
5885
|
+
* and write through the swap backend (`quoting`, `swaps`, `pools`, `positions`, `assets`,
|
|
5886
|
+
* `symbols`, `fees`, `stream`). See {@link GSwapOptions} for configuration.
|
|
5887
|
+
*/
|
|
5690
5888
|
var GSwap = class {
|
|
5889
|
+
/** The swap backend base URL every request goes to, without a trailing slash. */
|
|
5691
5890
|
dexBackendBaseUrl;
|
|
5891
|
+
/** The request timeout in milliseconds (default 30 000; `Infinity` arms no timer). */
|
|
5692
5892
|
chainCallTimeoutMs;
|
|
5893
|
+
/** The signer given at construction, if any. */
|
|
5693
5894
|
signer;
|
|
5895
|
+
/** The account given at construction, if any. */
|
|
5694
5896
|
walletAddress;
|
|
5897
|
+
/** The chain-gateway client every other service reads and writes through. */
|
|
5695
5898
|
gateway;
|
|
5899
|
+
/** The trading-symbol registry. */
|
|
5696
5900
|
symbols;
|
|
5901
|
+
/** Read-only exact-input and exact-output quotes. */
|
|
5697
5902
|
quoting;
|
|
5903
|
+
/** Pool, slot0 and composite-pool reads. */
|
|
5698
5904
|
pools;
|
|
5905
|
+
/** Position reads, liquidity estimates and liquidity / pool-creation writes. */
|
|
5699
5906
|
positions;
|
|
5907
|
+
/** Queued swaps (`RequestTrade`), dark swaps and swap confirmation. */
|
|
5700
5908
|
swaps;
|
|
5909
|
+
/** User token balances. */
|
|
5701
5910
|
assets;
|
|
5702
5911
|
/** Network-fee quotes (DryRun) signed with this client's signer. */
|
|
5703
5912
|
fees;
|
|
5913
|
+
/** The realtime stream endpoint {@link GSwap.stream} connects to. */
|
|
5704
5914
|
dexBackendWsUrl;
|
|
5705
5915
|
webSocketImpl;
|
|
5706
5916
|
streamApiKey;
|
|
5707
5917
|
streamClient;
|
|
5708
5918
|
/**
|
|
5709
|
-
* Create an SDK client for prod or stage.
|
|
5919
|
+
* Create an SDK client for prod (the default) or stage, or for a `dexBackendBaseUrl` of your own.
|
|
5710
5920
|
*
|
|
5711
5921
|
* @example
|
|
5712
5922
|
* ```typescript
|
|
@@ -5770,10 +5980,10 @@ function trimTrailingSlash(value) {
|
|
|
5770
5980
|
}
|
|
5771
5981
|
|
|
5772
5982
|
//#endregion
|
|
5773
|
-
//#region src/utils/
|
|
5983
|
+
//#region src/utils/classification.ts
|
|
5774
5984
|
/**
|
|
5775
5985
|
* The SDK's default Retry answer for each outcome. A decision that departs from it (a refusal the
|
|
5776
|
-
* gateway will repeat, `SHADOW_NOT_QUEUED`) is written out in the table
|
|
5986
|
+
* gateway will repeat, `SHADOW_NOT_QUEUED`) is written out in the table of `classifyFailure`.
|
|
5777
5987
|
*/
|
|
5778
5988
|
const DEFAULT_RETRYABLE = {
|
|
5779
5989
|
rejected: true,
|
|
@@ -5791,10 +6001,10 @@ const DEFAULT_RETRYABLE = {
|
|
|
5791
6001
|
* object, safe to mutate or freeze.
|
|
5792
6002
|
*
|
|
5793
6003
|
* `options.retryable: false` WITHHOLDS Retry from an outcome that would otherwise allow it: the
|
|
5794
|
-
* SDK's own `not_queued` for a refusal the gateway will repeat is
|
|
5795
|
-
* { retryable: false })` (also exported, frozen, as
|
|
5796
|
-
* Retry away from an outcome but never grant it to one
|
|
5797
|
-
* accepted.
|
|
6004
|
+
* SDK's own `not_queued` for a refusal the gateway will repeat is
|
|
6005
|
+
* `classification('not_queued', { retryable: false })` (also exported, frozen, as
|
|
6006
|
+
* {@link NOT_QUEUED_FINAL}). An app may take Retry away from an outcome but never grant it to one
|
|
6007
|
+
* that cannot have it, so only `false` is accepted.
|
|
5798
6008
|
*
|
|
5799
6009
|
* @example
|
|
5800
6010
|
* ```ts
|
|
@@ -5825,6 +6035,15 @@ const NOT_QUEUED_FINAL = Object.freeze(classification("not_queued", { retryable:
|
|
|
5825
6035
|
function notSentClassification() {
|
|
5826
6036
|
return classification("not_sent");
|
|
5827
6037
|
}
|
|
6038
|
+
|
|
6039
|
+
//#endregion
|
|
6040
|
+
//#region src/utils/failure_classification.ts
|
|
6041
|
+
/**
|
|
6042
|
+
* `classifyFailure` and `mayHaveBeenQueued`: the one module that holds the decision for every
|
|
6043
|
+
* catalog code (~135 names, a floor no minifier can remove). It needs the code table and nothing
|
|
6044
|
+
* else: the classification values live in `classification.ts`, the yes/no guards in
|
|
6045
|
+
* `failure_guards.ts`, and the error class and catalog are only named as types.
|
|
6046
|
+
*/
|
|
5828
6047
|
const REJECTED = classification("rejected");
|
|
5829
6048
|
const UNKNOWN = classification("unknown");
|
|
5830
6049
|
const NOT_QUEUED = classification("not_queued");
|
|
@@ -5924,90 +6143,6 @@ function classifyChainDispatchFailed(view) {
|
|
|
5924
6143
|
return status === 422 ? REJECTED : NOT_QUEUED;
|
|
5925
6144
|
}
|
|
5926
6145
|
/**
|
|
5927
|
-
* True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a
|
|
5928
|
-
* `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied
|
|
5929
|
-
* (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting
|
|
5930
|
-
* again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&
|
|
5931
|
-
* error.status === 409` and the regex on "already saved". Accepts an SDK error or a plain-object
|
|
5932
|
-
* view ({@link FailureView}: `code` and `status`); every other value is `false`.
|
|
5933
|
-
*
|
|
5934
|
-
* @example
|
|
5935
|
-
* ```ts
|
|
5936
|
-
* if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);
|
|
5937
|
-
* ```
|
|
5938
|
-
*/
|
|
5939
|
-
function isUniqueKeyConsumed(error) {
|
|
5940
|
-
const view = toFailureView(error);
|
|
5941
|
-
return (view === null || view === void 0 ? void 0 : view.code) === "CHAIN_DISPATCH_FAILED" && view.status === 409;
|
|
5942
|
-
}
|
|
5943
|
-
const UNPROVEN_ACKNOWLEDGEMENT_CODES = [
|
|
5944
|
-
"GATEWAY_DATA_MISSING",
|
|
5945
|
-
"GATEWAY_MODE_INVALID",
|
|
5946
|
-
"GATEWAY_SYNC_REQUEST_TRADE",
|
|
5947
|
-
"MISSING_UNIQUE_KEY",
|
|
5948
|
-
"UNIQUE_KEY_MISMATCH"
|
|
5949
|
-
];
|
|
5950
|
-
/**
|
|
5951
|
-
* True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no
|
|
5952
|
-
* `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.
|
|
5953
|
-
* The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an
|
|
5954
|
-
* app shows is one line for all five ("the backend did not confirm it queued the request"), so
|
|
5955
|
-
* the app asks this instead of keeping its own list of the codes. A gateway that says
|
|
5956
|
-
* `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.
|
|
5957
|
-
*
|
|
5958
|
-
* @example
|
|
5959
|
-
* ```ts
|
|
5960
|
-
* if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);
|
|
5961
|
-
* ```
|
|
5962
|
-
*/
|
|
5963
|
-
function isUnprovenAcknowledgement(error) {
|
|
5964
|
-
return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);
|
|
5965
|
-
}
|
|
5966
|
-
/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */
|
|
5967
|
-
function isCodeIn(code, codes) {
|
|
5968
|
-
return codes.some((known) => known === code);
|
|
5969
|
-
}
|
|
5970
|
-
/**
|
|
5971
|
-
* True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose
|
|
5972
|
-
* `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet
|
|
5973
|
-
* error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.
|
|
5974
|
-
*/
|
|
5975
|
-
function hasCodeIn(error, codes) {
|
|
5976
|
-
const view = toFailureView(error);
|
|
5977
|
-
return view !== void 0 && isCodeIn(view.code, codes);
|
|
5978
|
-
}
|
|
5979
|
-
/**
|
|
5980
|
-
* The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app
|
|
5981
|
-
* may show as it is (and falls back to its own line when it is empty): a refusal the gateway made
|
|
5982
|
-
* (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the
|
|
5983
|
-
* SDK knows, and `GATEWAY_REJECTED` for one it does not).
|
|
5984
|
-
*/
|
|
5985
|
-
const RELAYABLE_REFUSAL_CODES = [
|
|
5986
|
-
"GATEWAY_REPORTED_ERROR",
|
|
5987
|
-
"METHOD_NOT_ALLOWED",
|
|
5988
|
-
"SIGNATURE_INVALID",
|
|
5989
|
-
"SIGNER_MISMATCH",
|
|
5990
|
-
"DTO_INVALID",
|
|
5991
|
-
"BOUNDS_VIOLATION",
|
|
5992
|
-
"SYMBOL_CONFLICT",
|
|
5993
|
-
"RATE_LIMITED",
|
|
5994
|
-
"CHAIN_DISPATCH_FAILED",
|
|
5995
|
-
"GATEWAY_REJECTED"
|
|
5996
|
-
];
|
|
5997
|
-
function isRelayableRefusal(error) {
|
|
5998
|
-
return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);
|
|
5999
|
-
}
|
|
6000
|
-
/**
|
|
6001
|
-
* True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in
|
|
6002
|
-
* `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements
|
|
6003
|
-
* (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).
|
|
6004
|
-
* The outcome is `unknown` for all six. It replaces the app's own
|
|
6005
|
-
* `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.
|
|
6006
|
-
*/
|
|
6007
|
-
function isUninterpretedAnswer(error) {
|
|
6008
|
-
return isUnprovenAcknowledgement(error) || hasCodeIn(error, ["GATEWAY_REPORTED_ERROR"]);
|
|
6009
|
-
}
|
|
6010
|
-
/**
|
|
6011
6146
|
* Classifies any thrown value from its code (and, for two codes, its HTTP status), never from
|
|
6012
6147
|
* message text, so an app does not have to re-derive "may I offer Retry?" and "is the outcome
|
|
6013
6148
|
* unknown?" for every code. The decision for each code is in this module's table; a new catalog
|
|
@@ -6084,34 +6219,6 @@ function classifyView(view) {
|
|
|
6084
6219
|
if (code === "INVALID_PRIVATE_KEY") return { ...classifyInvalidPrivateKey(view) };
|
|
6085
6220
|
return { ...BY_CODE[code] ?? INVALID_INPUT };
|
|
6086
6221
|
}
|
|
6087
|
-
/** Codes that mean "there is no market for this" however the app reached them. */
|
|
6088
|
-
const NO_MARKET_CODES = [
|
|
6089
|
-
"NO_POOL_AVAILABLE",
|
|
6090
|
-
"INSUFFICIENT_LIQUIDITY",
|
|
6091
|
-
"UNKNOWN_TOKEN"
|
|
6092
|
-
];
|
|
6093
|
-
/**
|
|
6094
|
-
* True when a failure means "there is no market to trade this pair": `NO_POOL_AVAILABLE` (no pool
|
|
6095
|
-
* at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX
|
|
6096
|
-
* has no trading symbol for the token), or a READ that was answered 404 (a quote the backend
|
|
6097
|
-
* cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||
|
|
6098
|
-
* notFound` list, so the empty-state ("No market for this pair") has one definition.
|
|
6099
|
-
*
|
|
6100
|
-
* A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing
|
|
6101
|
-
* market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every
|
|
6102
|
-
* other value is `false`.
|
|
6103
|
-
*
|
|
6104
|
-
* @example
|
|
6105
|
-
* ```ts
|
|
6106
|
-
* if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);
|
|
6107
|
-
* ```
|
|
6108
|
-
*/
|
|
6109
|
-
function isNoMarket(error) {
|
|
6110
|
-
const view = toFailureView(error);
|
|
6111
|
-
if (view === void 0) return false;
|
|
6112
|
-
if (isCodeIn(view.code, NO_MARKET_CODES)) return true;
|
|
6113
|
-
return !isWriteView(view) && (view.notFound === true || view.status === 404);
|
|
6114
|
-
}
|
|
6115
6222
|
/**
|
|
6116
6223
|
* True when the failed call was a WRITE that may nevertheless have been queued: its outcome is
|
|
6117
6224
|
* `unknown` (`classifyFailure(error).outcome === 'unknown'`: a timeout or broken connection after
|
|
@@ -6138,59 +6245,7 @@ function mayHaveBeenQueued(error) {
|
|
|
6138
6245
|
}
|
|
6139
6246
|
|
|
6140
6247
|
//#endregion
|
|
6141
|
-
//#region src/classes/
|
|
6142
|
-
/** Key the wallet_extension has always used; its storage value is a plain array of entries. */
|
|
6143
|
-
const PENDING_SWAPS_STORAGE_KEY = "pendingSwaps.v1";
|
|
6144
|
-
/** Entries older than this are dropped the next time a wallet's swaps are listed. */
|
|
6145
|
-
const PENDING_SWAP_EXPIRY_MS = 6048e5;
|
|
6146
|
-
/**
|
|
6147
|
-
* A {@link StorageAdapter} over a `chrome.storage` area, the shape the wallet stores pending swaps
|
|
6148
|
-
* in: the value lands under the key as the structured value it is (the browser clones it; nothing
|
|
6149
|
-
* is serialized here). A missing key resolves `undefined`; a rejection of the area reaches the
|
|
6150
|
-
* store, which treats it as "storage unavailable".
|
|
6151
|
-
*
|
|
6152
|
-
* Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is
|
|
6153
|
-
* built: a module that is imported where `chrome` does not exist yet (a test, a closing extension
|
|
6154
|
-
* context) then fails only when the store touches storage, and that failure (a throw inside the
|
|
6155
|
-
* function) is the same "storage unavailable" rejection.
|
|
6156
|
-
*
|
|
6157
|
-
* @example
|
|
6158
|
-
* ```ts
|
|
6159
|
-
* const store = new PendingSwapStore(storageAdapterFromChromeStorage(chrome.storage.local));
|
|
6160
|
-
* const lazy = new PendingSwapStore(storageAdapterFromChromeStorage(() => chrome.storage.local));
|
|
6161
|
-
* ```
|
|
6162
|
-
*/
|
|
6163
|
-
function storageAdapterFromChromeStorage(area) {
|
|
6164
|
-
const areaNow = () => typeof area === "function" ? area() : area;
|
|
6165
|
-
return {
|
|
6166
|
-
async get(key) {
|
|
6167
|
-
const items = await areaNow().get(key);
|
|
6168
|
-
return Object.hasOwn(items, key) ? items[key] : void 0;
|
|
6169
|
-
},
|
|
6170
|
-
async set(key, value) {
|
|
6171
|
-
await areaNow().set({ [key]: value });
|
|
6172
|
-
}
|
|
6173
|
-
};
|
|
6174
|
-
}
|
|
6175
|
-
/**
|
|
6176
|
-
* Why the store dropped a pending swap (the `reason` of {@link PrunedPendingSwap}).
|
|
6177
|
-
*
|
|
6178
|
-
* - `expired`: older than {@link PENDING_SWAP_EXPIRY_MS}.
|
|
6179
|
-
* - `invalid_unique_key`: its `uniqueKey` is not a valid apply-results key (1 to 128 characters
|
|
6180
|
-
* of `A-Za-z0-9._:-`). `confirmAppliedTrade` refuses such a key with `INVALID_UNIQUE_KEY`
|
|
6181
|
-
* before reading anything and always will, so keeping the entry would retry it forever. The
|
|
6182
|
-
* SDK never signs such a key; an entry like this is corrupt or foreign.
|
|
6183
|
-
* - `chain_rejected`: {@link PendingSwapStore.settle} dropped it because a confirmation proved the
|
|
6184
|
-
* chain REFUSED the trade (`pendingSwapFateFor` is `forget`): it did not happen.
|
|
6185
|
-
* - `unconfirmable`: {@link PendingSwapStore.settle} dropped it because a confirmation failed in a
|
|
6186
|
-
* way that never changes (`forget_quietly`: the key itself is refused): nothing can be learned.
|
|
6187
|
-
*/
|
|
6188
|
-
const PENDING_SWAP_PRUNE_REASONS = [
|
|
6189
|
-
"expired",
|
|
6190
|
-
"invalid_unique_key",
|
|
6191
|
-
"chain_rejected",
|
|
6192
|
-
"unconfirmable"
|
|
6193
|
-
];
|
|
6248
|
+
//#region src/classes/pending_swap_fate.ts
|
|
6194
6249
|
/**
|
|
6195
6250
|
* What to do with a pending swap after confirming it failed (the answer of
|
|
6196
6251
|
* {@link pendingSwapFateFor}).
|
|
@@ -6200,6 +6255,9 @@ const PENDING_SWAP_PRUNE_REASONS = [
|
|
|
6200
6255
|
* Drop it without claiming anything about the trade.
|
|
6201
6256
|
* - `keep`: the trade may still have been applied (a timeout, a broken connection, a gateway
|
|
6202
6257
|
* hiccup, anything not proven). Leave it pending and look again later.
|
|
6258
|
+
*
|
|
6259
|
+
* This module holds the decision and nothing of the store, so an app shell that only needs the
|
|
6260
|
+
* fate pays for `classifyFailure` and this table, not for `PendingSwapStore`.
|
|
6203
6261
|
*/
|
|
6204
6262
|
const PENDING_SWAP_FATES = [
|
|
6205
6263
|
"forget",
|
|
@@ -6248,6 +6306,32 @@ function pendingSwapFateOfOutcome(outcome) {
|
|
|
6248
6306
|
function pendingSwapFateFor(error) {
|
|
6249
6307
|
return pendingSwapFateOfOutcome(classifyFailure(error, { afterQueued: true }).outcome);
|
|
6250
6308
|
}
|
|
6309
|
+
|
|
6310
|
+
//#endregion
|
|
6311
|
+
//#region src/classes/pending_swaps.ts
|
|
6312
|
+
/** Key the wallet_extension has always used; its storage value is a plain array of entries. */
|
|
6313
|
+
const PENDING_SWAPS_STORAGE_KEY = "pendingSwaps.v1";
|
|
6314
|
+
/** Entries older than this are dropped the next time a wallet's swaps are listed. */
|
|
6315
|
+
const PENDING_SWAP_EXPIRY_MS = 6048e5;
|
|
6316
|
+
/**
|
|
6317
|
+
* Why the store dropped a pending swap (the `reason` of {@link PrunedPendingSwap}).
|
|
6318
|
+
*
|
|
6319
|
+
* - `expired`: older than {@link PENDING_SWAP_EXPIRY_MS}.
|
|
6320
|
+
* - `invalid_unique_key`: its `uniqueKey` is not a valid apply-results key (1 to 128 characters
|
|
6321
|
+
* of `A-Za-z0-9._:-`). `confirmAppliedTrade` refuses such a key with `INVALID_UNIQUE_KEY`
|
|
6322
|
+
* before reading anything and always will, so keeping the entry would retry it forever. The
|
|
6323
|
+
* SDK never signs such a key; an entry like this is corrupt or foreign.
|
|
6324
|
+
* - `chain_rejected`: {@link PendingSwapStore.settle} dropped it because a confirmation proved the
|
|
6325
|
+
* chain REFUSED the trade (`pendingSwapFateFor` is `forget`): it did not happen.
|
|
6326
|
+
* - `unconfirmable`: {@link PendingSwapStore.settle} dropped it because a confirmation failed in a
|
|
6327
|
+
* way that never changes (`forget_quietly`: the key itself is refused): nothing can be learned.
|
|
6328
|
+
*/
|
|
6329
|
+
const PENDING_SWAP_PRUNE_REASONS = [
|
|
6330
|
+
"expired",
|
|
6331
|
+
"invalid_unique_key",
|
|
6332
|
+
"chain_rejected",
|
|
6333
|
+
"unconfirmable"
|
|
6334
|
+
];
|
|
6251
6335
|
/**
|
|
6252
6336
|
* Remembers queued swaps so their outcome can be confirmed after the UI, popup or service worker
|
|
6253
6337
|
* that submitted them is gone (`confirmAppliedTrade` with the stored `uniqueKey`).
|
|
@@ -7101,7 +7185,7 @@ function createLazyPrivateKeySigner(getPrivateKey, options = {}) {
|
|
|
7101
7185
|
*
|
|
7102
7186
|
* `scheme: 'personal-sign'` calls
|
|
7103
7187
|
* `gala_signChainDto([serialize({ ...dto, prefix }), walletAddress, methodName])` and REQUIRES
|
|
7104
|
-
* a wallet build that contains wallet_extension commit
|
|
7188
|
+
* a wallet build that contains wallet_extension commit 34ca4e4 (strips the embedded `prefix`
|
|
7105
7189
|
* field and hashes `prefix` + the prefix-less canonical body, the chain's scheme). Wallets
|
|
7106
7190
|
* released before that fix hash the string with the `prefix` field still inside it and the
|
|
7107
7191
|
* signature recovers to an address nobody holds, so only opt in once the fixed wallet is
|
|
@@ -7126,7 +7210,7 @@ var GalaWalletSigner = class {
|
|
|
7126
7210
|
* to the same check); a GalaChain id is `client|` plus 24 hex digits, or the bare 24 hex digits
|
|
7127
7211
|
* frontend_v2 keeps for a direct `client|` login, and is passed through unchanged.
|
|
7128
7212
|
* @param options - Select native signing (default) or personal-sign explicitly.
|
|
7129
|
-
* `'personal-sign'` requires a Gala Wallet build with wallet_extension commit
|
|
7213
|
+
* `'personal-sign'` requires a Gala Wallet build with wallet_extension commit 34ca4e4.
|
|
7130
7214
|
* `selectAddress` is the identity (`client|...` / `eth|...`) Gala Wallet is switched to with
|
|
7131
7215
|
* `window.gala.setAddress` before every signature, when the wallet offers it.
|
|
7132
7216
|
*/
|
|
@@ -7207,6 +7291,7 @@ var BrowserWalletSigner = class {
|
|
|
7207
7291
|
this.walletAddress = normalizeEthereumAccount(walletAddress, false);
|
|
7208
7292
|
this.scheme = options.scheme ?? "personal-sign";
|
|
7209
7293
|
}
|
|
7294
|
+
/** The selected `0x` Ethereum account every signature is requested for. */
|
|
7210
7295
|
walletAddress;
|
|
7211
7296
|
scheme;
|
|
7212
7297
|
/**
|
|
@@ -7229,6 +7314,74 @@ var BrowserWalletSigner = class {
|
|
|
7229
7314
|
}
|
|
7230
7315
|
};
|
|
7231
7316
|
|
|
7317
|
+
//#endregion
|
|
7318
|
+
//#region src/classes/storage_adapters.ts
|
|
7319
|
+
/**
|
|
7320
|
+
* A {@link StorageAdapter} over a `chrome.storage` area, the shape the wallet stores pending swaps
|
|
7321
|
+
* in: the value lands under the key as the structured value it is (the browser clones it; nothing
|
|
7322
|
+
* is serialized here). A missing key resolves `undefined`; a rejection of the area reaches the
|
|
7323
|
+
* store, which treats it as "storage unavailable".
|
|
7324
|
+
*
|
|
7325
|
+
* Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is
|
|
7326
|
+
* built: a module that is imported where `chrome` does not exist yet (a test, a closing extension
|
|
7327
|
+
* context) then fails only when the store touches storage, and that failure (a throw inside the
|
|
7328
|
+
* function) is the same "storage unavailable" rejection.
|
|
7329
|
+
*
|
|
7330
|
+
* @example
|
|
7331
|
+
* ```ts
|
|
7332
|
+
* const store = new PendingSwapStore(storageAdapterFromChromeStorage(chrome.storage.local));
|
|
7333
|
+
* const lazy = new PendingSwapStore(storageAdapterFromChromeStorage(() => chrome.storage.local));
|
|
7334
|
+
* ```
|
|
7335
|
+
*/
|
|
7336
|
+
function storageAdapterFromChromeStorage(area) {
|
|
7337
|
+
const areaNow = () => typeof area === "function" ? area() : area;
|
|
7338
|
+
return {
|
|
7339
|
+
async get(key) {
|
|
7340
|
+
const items = await areaNow().get(key);
|
|
7341
|
+
return Object.hasOwn(items, key) ? items[key] : void 0;
|
|
7342
|
+
},
|
|
7343
|
+
async set(key, value) {
|
|
7344
|
+
await areaNow().set({ [key]: value });
|
|
7345
|
+
}
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
/**
|
|
7349
|
+
* A {@link StorageAdapter} over a Web Storage area (`localStorage`, `sessionStorage`), the shape
|
|
7350
|
+
* frontend_v2 stores pending swaps in: the value lands under the key as JSON text. A missing key
|
|
7351
|
+
* resolves `undefined`. CORRUPT JSON resolves as the raw string, never a rejection (the store
|
|
7352
|
+
* reads a value that is not an array as "no entries" and the next write repairs it, whereas a
|
|
7353
|
+
* `get` that rejects forever would make every `remember` a no-op). A throwing area (storage blocked
|
|
7354
|
+
* by the browser, quota exceeded on `setItem`) rejects, which the store treats as "storage
|
|
7355
|
+
* unavailable".
|
|
7356
|
+
*
|
|
7357
|
+
* Pass a FUNCTION that returns the area to look it up at each call instead of when the adapter is
|
|
7358
|
+
* built: where `localStorage` does not exist (server rendering, a test, a blocked context)
|
|
7359
|
+
* the access throws inside the function, which is the same "storage unavailable" rejection, and
|
|
7360
|
+
* the module that builds the adapter still loads.
|
|
7361
|
+
*
|
|
7362
|
+
* @example
|
|
7363
|
+
* ```ts
|
|
7364
|
+
* const store = new PendingSwapStore(webStorageAdapter(() => localStorage));
|
|
7365
|
+
* ```
|
|
7366
|
+
*/
|
|
7367
|
+
function webStorageAdapter(area) {
|
|
7368
|
+
const areaNow = () => typeof area === "function" ? area() : area;
|
|
7369
|
+
return {
|
|
7370
|
+
async get(key) {
|
|
7371
|
+
const raw = areaNow().getItem(key);
|
|
7372
|
+
if (raw === null) return void 0;
|
|
7373
|
+
try {
|
|
7374
|
+
return JSON.parse(raw);
|
|
7375
|
+
} catch {
|
|
7376
|
+
return raw;
|
|
7377
|
+
}
|
|
7378
|
+
},
|
|
7379
|
+
async set(key, value) {
|
|
7380
|
+
areaNow().setItem(key, JSON.stringify(value));
|
|
7381
|
+
}
|
|
7382
|
+
};
|
|
7383
|
+
}
|
|
7384
|
+
|
|
7232
7385
|
//#endregion
|
|
7233
7386
|
//#region src/utils/chain_dto_signing.ts
|
|
7234
7387
|
/**
|
|
@@ -7237,7 +7390,7 @@ var BrowserWalletSigner = class {
|
|
|
7237
7390
|
*
|
|
7238
7391
|
* These are thin, byte-exact ports of the functions the wallet shipped in
|
|
7239
7392
|
* `wallet_extension/src/helpers/wallet/signing.ts` (including the fail-closed personal-sign
|
|
7240
|
-
* payload resolver from its commit
|
|
7393
|
+
* payload resolver from its commit 34ca4e4), re-expressed over the SDK's own primitives. Every
|
|
7241
7394
|
* function takes the key as a string (`0x`-optional hex, or base64) or as bytes, normalizes it per
|
|
7242
7395
|
* call, and zeroes the normalized copy before returning, so nothing in this module retains a key.
|
|
7243
7396
|
* A JavaScript string cannot be wiped; the caller owns the lifetime of the string it passes in.
|
|
@@ -7958,6 +8111,152 @@ function isFetchTransportFailure(error) {
|
|
|
7958
8111
|
}
|
|
7959
8112
|
}
|
|
7960
8113
|
|
|
8114
|
+
//#endregion
|
|
8115
|
+
//#region src/utils/failure_guards.ts
|
|
8116
|
+
/**
|
|
8117
|
+
* The yes/no questions an app asks about a failure from its CODE alone. They read only the failure
|
|
8118
|
+
* view and a short list of codes: no table of every code (that is `classifyFailure`'s, in
|
|
8119
|
+
* `failure_classification.ts`), no error class and no catalog (the imports above are types, erased
|
|
8120
|
+
* at build time). An app shell that imports one of them pays for this module and nothing else.
|
|
8121
|
+
*/
|
|
8122
|
+
/**
|
|
8123
|
+
* True when the gateway answered that the write's `uniqueKey` was ALREADY CONSUMED: a
|
|
8124
|
+
* `CHAIN_DISPATCH_FAILED` with HTTP status 409. The first attempt under that key may be applied
|
|
8125
|
+
* (`classifyFailure` says `unknown`), so the app confirms the key it holds instead of submitting
|
|
8126
|
+
* again or showing the server's text. It replaces `error.code === 'CHAIN_DISPATCH_FAILED' &&
|
|
8127
|
+
* error.status === 409` and the regex on "already saved". Accepts an SDK error or a plain-object
|
|
8128
|
+
* view ({@link FailureView}: `code` and `status`); every other value is `false`.
|
|
8129
|
+
*
|
|
8130
|
+
* @example
|
|
8131
|
+
* ```ts
|
|
8132
|
+
* if (isUniqueKeyConsumed(error)) return confirmAndShowResult(error.uniqueKey);
|
|
8133
|
+
* ```
|
|
8134
|
+
*/
|
|
8135
|
+
function isUniqueKeyConsumed(error) {
|
|
8136
|
+
const view = toFailureView(error);
|
|
8137
|
+
return (view === null || view === void 0 ? void 0 : view.code) === "CHAIN_DISPATCH_FAILED" && view.status === 409;
|
|
8138
|
+
}
|
|
8139
|
+
const UNPROVEN_ACKNOWLEDGEMENT_CODES = [
|
|
8140
|
+
"GATEWAY_DATA_MISSING",
|
|
8141
|
+
"GATEWAY_MODE_INVALID",
|
|
8142
|
+
"GATEWAY_SYNC_REQUEST_TRADE",
|
|
8143
|
+
"MISSING_UNIQUE_KEY",
|
|
8144
|
+
"UNIQUE_KEY_MISMATCH"
|
|
8145
|
+
];
|
|
8146
|
+
/**
|
|
8147
|
+
* True when a write got a 2xx answer that does NOT prove it was queued under the signed key: no
|
|
8148
|
+
* `data`, an unreadable `mode`, a synchronous RequestTrade, or a missing or foreign `uniqueKey`.
|
|
8149
|
+
* The outcome is `unknown` (it may have been queued: confirm `error.uniqueKey`), and the copy an
|
|
8150
|
+
* app shows is one line for all five ("the backend did not confirm it queued the request"), so
|
|
8151
|
+
* the app asks this instead of keeping its own list of the codes. A gateway that says
|
|
8152
|
+
* `error: true` (`GATEWAY_REPORTED_ERROR`) is a refusal with its own message, not in this set.
|
|
8153
|
+
*
|
|
8154
|
+
* @example
|
|
8155
|
+
* ```ts
|
|
8156
|
+
* if (isUnprovenAcknowledgement(error)) keepPendingAndConfirm(error.uniqueKey);
|
|
8157
|
+
* ```
|
|
8158
|
+
*/
|
|
8159
|
+
function isUnprovenAcknowledgement(error) {
|
|
8160
|
+
return hasCodeIn(error, UNPROVEN_ACKNOWLEDGEMENT_CODES);
|
|
8161
|
+
}
|
|
8162
|
+
/** True when `code` is one of `codes` (a list of catalog codes), by exact spelling. */
|
|
8163
|
+
function isCodeIn(code, codes) {
|
|
8164
|
+
return codes.some((known) => known === code);
|
|
8165
|
+
}
|
|
8166
|
+
/**
|
|
8167
|
+
* True when `error` is an SDK error OR a plain-object view of one (see {@link FailureView}) whose
|
|
8168
|
+
* `code` is one of `codes`. The code is compared with the catalog's own spelling, so a wallet
|
|
8169
|
+
* error (`{ code: 'ACTION_REJECTED' }`, a numeric `4001`) is never a member.
|
|
8170
|
+
*/
|
|
8171
|
+
function hasCodeIn(error, codes) {
|
|
8172
|
+
const view = toFailureView(error);
|
|
8173
|
+
return view !== void 0 && isCodeIn(view.code, codes);
|
|
8174
|
+
}
|
|
8175
|
+
/**
|
|
8176
|
+
* The codes whose `params.serverMessage` is the gateway's own answer to THIS write, which an app
|
|
8177
|
+
* may show as it is (and falls back to its own line when it is empty): a refusal the gateway made
|
|
8178
|
+
* (`GATEWAY_REPORTED_ERROR`, a 2xx with `error: true`) or a bounce it named (the gateway codes the
|
|
8179
|
+
* SDK knows, and `GATEWAY_REJECTED` for one it does not).
|
|
8180
|
+
*/
|
|
8181
|
+
const RELAYABLE_REFUSAL_CODES = [
|
|
8182
|
+
"GATEWAY_REPORTED_ERROR",
|
|
8183
|
+
"METHOD_NOT_ALLOWED",
|
|
8184
|
+
"SIGNATURE_INVALID",
|
|
8185
|
+
"SIGNER_MISMATCH",
|
|
8186
|
+
"DTO_INVALID",
|
|
8187
|
+
"BOUNDS_VIOLATION",
|
|
8188
|
+
"SYMBOL_CONFLICT",
|
|
8189
|
+
"RATE_LIMITED",
|
|
8190
|
+
"CHAIN_DISPATCH_FAILED",
|
|
8191
|
+
"GATEWAY_REJECTED"
|
|
8192
|
+
];
|
|
8193
|
+
function isRelayableRefusal(error) {
|
|
8194
|
+
return hasCodeIn(error, RELAYABLE_REFUSAL_CODES);
|
|
8195
|
+
}
|
|
8196
|
+
/**
|
|
8197
|
+
* True when a write got a 2xx answer the SDK refused to interpret, so the answer itself is in
|
|
8198
|
+
* `error.body` (or `error.bodyText`) for the app to read: the five unproven acknowledgements
|
|
8199
|
+
* (`isUnprovenAcknowledgement`) and `GATEWAY_REPORTED_ERROR` (a gateway that says `error: true`).
|
|
8200
|
+
* The outcome is `unknown` for all six. It replaces the app's own
|
|
8201
|
+
* `isUnprovenAcknowledgement(e) || isGSwapError(e, 'GATEWAY_REPORTED_ERROR')` pair.
|
|
8202
|
+
*/
|
|
8203
|
+
function isUninterpretedAnswer(error) {
|
|
8204
|
+
return isUnprovenAcknowledgement(error) || hasCodeIn(error, ["GATEWAY_REPORTED_ERROR"]);
|
|
8205
|
+
}
|
|
8206
|
+
/**
|
|
8207
|
+
* The chain's own machine-readable `ErrorKey` of a failure (`'TOKEN_NOT_FOUND'`,
|
|
8208
|
+
* `'NOT_ENOUGH_LIQUIDITY'`, ...), for an app that maps a chain refusal to its own copy: the
|
|
8209
|
+
* `params.errorKey` of a `CHAIN_REJECTED` (an apply result, or a body that carries the chain's
|
|
8210
|
+
* error) and of a `CHAIN_DISPATCH_FAILED` (the gateway adds the chain's key to the body it
|
|
8211
|
+
* answered). `undefined` when the failure is neither, or when it carries no key (the gateway sent
|
|
8212
|
+
* none: the SDK writes `''`, which is not a key). Map the KEY, never the message text.
|
|
8213
|
+
*
|
|
8214
|
+
* Accepts an SDK error or a plain-object view ({@link FailureView}: `code` and `params`); every
|
|
8215
|
+
* other value is `undefined`. Other codes are `undefined` even when they have an `errorKey`-named
|
|
8216
|
+
* param, so a stray field cannot pass for a chain verdict.
|
|
8217
|
+
*
|
|
8218
|
+
* @example
|
|
8219
|
+
* ```ts
|
|
8220
|
+
* const key = chainErrorKeyOf(error);
|
|
8221
|
+
* if (key === 'NOT_ENOUGH_LIQUIDITY') showTooThin(); else showGeneric(error);
|
|
8222
|
+
* ```
|
|
8223
|
+
*/
|
|
8224
|
+
function chainErrorKeyOf(error) {
|
|
8225
|
+
const view = toFailureView(error);
|
|
8226
|
+
if (view === void 0) return void 0;
|
|
8227
|
+
if (view.code !== "CHAIN_REJECTED" && view.code !== "CHAIN_DISPATCH_FAILED") return void 0;
|
|
8228
|
+
const errorKey = stringParamOf(view, "errorKey");
|
|
8229
|
+
return errorKey === void 0 || errorKey === "" ? void 0 : errorKey;
|
|
8230
|
+
}
|
|
8231
|
+
/** Codes that mean "there is no market for this" however the app reached them. */
|
|
8232
|
+
const NO_MARKET_CODES = [
|
|
8233
|
+
"NO_POOL_AVAILABLE",
|
|
8234
|
+
"INSUFFICIENT_LIQUIDITY",
|
|
8235
|
+
"UNKNOWN_TOKEN"
|
|
8236
|
+
];
|
|
8237
|
+
/**
|
|
8238
|
+
* True when a failure means "there is no market to trade this pair": `NO_POOL_AVAILABLE` (no pool
|
|
8239
|
+
* at any fee tier), `INSUFFICIENT_LIQUIDITY` (a pool too thin to quote), `UNKNOWN_TOKEN` (the DEX
|
|
8240
|
+
* has no trading symbol for the token), or a READ that was answered 404 (a quote the backend
|
|
8241
|
+
* cannot find, `error.notFound`). It replaces an app's own `code === ... || code === ... ||
|
|
8242
|
+
* notFound` list, so the empty-state ("No market for this pair") has one definition.
|
|
8243
|
+
*
|
|
8244
|
+
* A write that was answered 404 (it carries a `uniqueKey`) is a missing route, not a missing
|
|
8245
|
+
* market, and is not this. Accepts an SDK error or a plain-object view ({@link FailureView}); every
|
|
8246
|
+
* other value is `false`.
|
|
8247
|
+
*
|
|
8248
|
+
* @example
|
|
8249
|
+
* ```ts
|
|
8250
|
+
* if (isNoMarket(error)) showEmptyState(t('swap.noMarket')); else showError(error);
|
|
8251
|
+
* ```
|
|
8252
|
+
*/
|
|
8253
|
+
function isNoMarket(error) {
|
|
8254
|
+
const view = toFailureView(error);
|
|
8255
|
+
if (view === void 0) return false;
|
|
8256
|
+
if (isCodeIn(view.code, NO_MARKET_CODES)) return true;
|
|
8257
|
+
return !isWriteView(view) && (view.notFound === true || view.status === 404);
|
|
8258
|
+
}
|
|
8259
|
+
|
|
7961
8260
|
//#endregion
|
|
7962
8261
|
//#region src/utils/submit_state.ts
|
|
7963
8262
|
/** The `mode` of `envelope.data`, or `undefined` when there is no such field. */
|
|
@@ -7999,5 +8298,5 @@ function classifySubmitEnvelope(envelope) {
|
|
|
7999
8298
|
}
|
|
8000
8299
|
|
|
8001
8300
|
//#endregion
|
|
8002
|
-
export { ALL_FEE_TIERS, AppliedTradeError, Assets, BrowserWalletSigner, CanonicalSymbols, ChainGateway, DEFAULT_UNIQUE_KEY_PREFIX, DEX_FEE_METHODS, DRY_RUN_METHOD, DRY_RUN_UNIQUE_KEY_PREFIX, DexFees, EIP712_CAPABLE_METHODS, FAILURE_OUTCOMES, FEE_TIER, GC_MAX_TICK, GC_MIN_TICK, GSWAP_ENVIRONMENTS, GSWAP_ERROR_CATALOG, GSWAP_ERROR_PHASES, GSWAP_ERROR_PHASE_BY_CODE, GSwap, GSwapSDKError, GalaWalletSigner, GdexStreamError, GdexStreamService, INVALID_PRIVATE_KEY_REASONS, NOT_QUEUED_FINAL, PENDING_SWAPS_STORAGE_KEY, PENDING_SWAP_EXPIRY_MS, PENDING_SWAP_FATES, PENDING_SWAP_PRUNE_REASONS, PendingSwapStore, Pools, Positions, PrivateKeySigner, Quoting, SHADOW_FAILURE_KINDS, SHADOW_SUBMIT_CODES, SIGNING_FAILURE_REASONS, SUBMISSION_OUTCOME_UNKNOWN_REASONS, SubmittedTransaction, Swaps, Symbols, TICK_SPACING_BY_FEE, UPDATE_REQUIRED_STATUS, alignTickDown, alignTickUp, assertCanonicalPair, assertCanonicalV2Dto, assertTickRange, assertUniqueKey, buildAddLiquidityDto, buildCollectPositionFeesDto, buildCreatePoolDto, buildDryRunWrapper, buildEIP712Payload, buildRemoveLiquidityDto, buildRequestTradeDto, calculatePersonalSignPrefix, canonicalDecimalString, classification, classifyFailure, classifyShadowSubmitError, classifyShadowSubmitStatus, classifySubmitEnvelope, compositeKeyOf, confirmAppliedTrade, confirmationStateOf, createLazyPrivateKeySigner, createUniqueKey, eip1193ProviderFromEthers, eip712DomainFor, ethAddressOfPrivateKey, ethereumAddressOfAccount, fixpointPrefixFor, frameSlot0, generateEIP712Types, getObjectProperty, getPayloadToSign, getStringProperty, gswapErrorTemplates, hashTypedData, httpRequestorFromAxios, isConfirmationAborted, isConfirmationTimeout, isCurrentContractDexMessage, isDexFeeMethod, isFetchTransportFailure, isGSwapError, isGSwapErrorLike, isGdexLiquidityEvent, isNoMarket, isPreSendError, isProposableTradingSymbol, isRelayableRefusal, isShadowError, isSubmitExecuted, isSubmitQueued, isSubmitRejected, isUninterpretedAnswer, isUniqueKeyConsumed, isUnprovenAcknowledgement, isValidUniqueKey, isWalletUserRejection, isWriteView, mayHaveBeenQueued, normalizePrivateKey, notSentClassification, orderSymbols, parseJson, parseTokenClassKey, pendingSwapFateFor, pendingSwapFateOfOutcome, personalSignPrefixFor, queryTokenOf, rawTokenOf, readOrderedSymbols, readShadowSubmitOutcome, renderGSwapErrorTemplate, resolvePersonalSignChainDtoPayload, resolveUniqueKeyPrefix, serialize, signChainDtoHash, signChainDtoNative, signChainDtoPersonalSign, signNative, signPersonalMessage, signRawObject, signSerializedNative, signTypedDataPayload, sqrtPriceToTick, storageAdapterFromChromeStorage, stripEip712DomainType, swapRouteFromQuote, tickFromPrice, tickToPrice, tickToSqrtPrice, toChainDto, toFailureView, tokenClassDollarKey, tradingSymbolOf, tryParseCompositeKey, tryParseTokenClassKey, validateFee, validateNumericAmount, validatePriceValues, validateTickRange, validateTickSpacing, validateTokenDecimals, validateWalletAddress, walletDeclineCode, withPrivateKey };
|
|
8301
|
+
export { ALL_FEE_TIERS, AppliedTradeError, Assets, BrowserWalletSigner, CanonicalSymbols, ChainGateway, DEFAULT_UNIQUE_KEY_PREFIX, DEX_FEE_METHODS, DRY_RUN_METHOD, DRY_RUN_UNIQUE_KEY_PREFIX, DexFees, EIP712_CAPABLE_METHODS, FAILURE_OUTCOMES, FEE_TIER, GC_MAX_TICK, GC_MIN_TICK, GSWAP_ENVIRONMENTS, GSWAP_ERROR_CATALOG, GSWAP_ERROR_PHASES, GSWAP_ERROR_PHASE_BY_CODE, GSwap, GSwapSDKError, GalaWalletSigner, GdexStreamError, GdexStreamService, INVALID_PRIVATE_KEY_REASONS, NOT_QUEUED_FINAL, PENDING_SWAPS_STORAGE_KEY, PENDING_SWAP_EXPIRY_MS, PENDING_SWAP_FATES, PENDING_SWAP_PRUNE_REASONS, PendingSwapStore, Pools, Positions, PrivateKeySigner, Quoting, SHADOW_FAILURE_KINDS, SHADOW_SUBMIT_CODES, SIGNING_FAILURE_REASONS, SUBMISSION_OUTCOME_UNKNOWN_REASONS, SubmittedTransaction, Swaps, Symbols, TICK_SPACING_BY_FEE, UPDATE_REQUIRED_STATUS, alignTickDown, alignTickDownOrNaN, alignTickUp, alignTickUpOrNaN, assertCanonicalPair, assertCanonicalV2Dto, assertTickRange, assertUniqueKey, buildAddLiquidityDto, buildCollectPositionFeesDto, buildCreatePoolDto, buildDryRunWrapper, buildEIP712Payload, buildRemoveLiquidityDto, buildRequestTradeDto, calculatePersonalSignPrefix, canonicalDecimalString, chainErrorKeyOf, classification, classifyFailure, classifyShadowSubmitError, classifyShadowSubmitStatus, classifySubmitEnvelope, compositeKeyOf, confirmAppliedTrade, confirmationStateOf, createLazyPrivateKeySigner, createUniqueKey, eip1193ProviderFromEthers, eip712DomainFor, ethAddressOfPrivateKey, ethereumAddressOfAccount, fixpointPrefixFor, frameSlot0, generateEIP712Types, getObjectProperty, getPayloadToSign, getStringProperty, gswapErrorTemplates, hashTypedData, httpRequestorFromAxios, isConfirmationAborted, isConfirmationTimeout, isCurrentContractDexMessage, isDexFeeMethod, isFetchTransportFailure, isGSwapError, isGSwapErrorLike, isGdexLiquidityEvent, isNoMarket, isPreSendError, isProposableTradingSymbol, isRelayableRefusal, isShadowError, isSqrtPriceInRange, isSubmitExecuted, isSubmitQueued, isSubmitRejected, isTickInRange, isUninterpretedAnswer, isUniqueKeyConsumed, isUnprovenAcknowledgement, isValidUniqueKey, isWalletUserRejection, isWriteView, mayHaveBeenQueued, normalizePrivateKey, notSentClassification, orderSymbols, parseJson, parseTokenClassKey, pendingSwapFateFor, pendingSwapFateOfOutcome, personalSignPrefixFor, queryTokenOf, rawTokenOf, readOrderedSymbols, readShadowSubmitOutcome, renderGSwapErrorTemplate, resolvePersonalSignChainDtoPayload, resolveUniqueKeyPrefix, serialize, signChainDtoHash, signChainDtoNative, signChainDtoPersonalSign, signNative, signPersonalMessage, signRawObject, signSerializedNative, signTypedDataPayload, sqrtPriceToTick, storageAdapterFromChromeStorage, stripEip712DomainType, swapRouteFromQuote, tickFromPrice, tickToPrice, tickToSqrtPrice, toChainDto, toFailureView, tokenClassDollarKey, tradingSymbolOf, tryParseCompositeKey, tryParseTokenClassKey, validateFee, validateNumericAmount, validatePriceValues, validateTickRange, validateTickSpacing, validateTokenDecimals, validateWalletAddress, walletDeclineCode, webStorageAdapter, withPrivateKey };
|
|
8003
8302
|
//# sourceMappingURL=index.mjs.map
|