@polyester/sdk 0.4.5 → 0.6.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/CHANGELOG.md +20 -0
- package/dist/catalogs/readers.d.ts.map +1 -1
- package/dist/catalogs/readers.js +11 -3
- package/dist/catalogs/readers.js.map +1 -1
- package/dist/catalogs/types.d.ts +8 -0
- package/dist/catalogs/types.d.ts.map +1 -1
- package/dist/catalogs/types.js.map +1 -1
- package/dist/services/heatmap/heatmap.schemas.d.ts +4 -4
- package/dist/services/orderbook/orderbook.schemas.d.ts +1 -1
- package/dist/services/orders/orders-input.schemas.d.ts +1 -1
- package/dist/services/trailing-oneof-inputs.js +2 -3
- package/dist/services/trailing-oneof-inputs.js.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.d.ts.map +1 -1
- package/dist/services/triggers/trigger-input.schemas.js +2 -2
- package/dist/services/triggers/trigger-input.schemas.js.map +1 -1
- package/dist/shared/decimal-surface.d.ts.map +1 -1
- package/dist/shared/decimal-surface.js +12 -3
- package/dist/shared/decimal-surface.js.map +1 -1
- package/dist/shared/wire-bounds.js +9 -0
- package/dist/shared/wire-bounds.js.map +1 -0
- package/dist/smart-account/index.d.ts +2 -2
- package/dist/smart-account/index.js +2 -2
- package/dist/smart-account/smart-account.d.ts +22 -2
- package/dist/smart-account/smart-account.d.ts.map +1 -1
- package/dist/smart-account/smart-account.js +62 -19
- package/dist/smart-account/smart-account.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @polyester/sdk
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#68](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/68) [`a1a35ec`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/a1a35ecaa2948bfd6c9f0a392426ea83fadc166f) Thanks [@huntabyte](https://github.com/huntabyte)! - Reject decimal order and trigger inputs that exceed protobuf signed-integer bounds with `CatalogConversionError`. `getSpotOrderConstraints()` now exposes the derived `maxPrice`, `maxQtyBase`, `maxNotionalQuote`, and `maxQuoteSlippage` wire ceilings.
|
|
8
|
+
|
|
9
|
+
## 0.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#66](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/66) [`e8a5721`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/e8a5721b57be7ebd0b7edf80c4ed85919fccdb0a) Thanks [@huntabyte](https://github.com/huntabyte)! - `sendPolyesterUserOperation` now prepares the operation in a single pass, halving the network round-trips before the wallet signature prompt appears. Gas estimation errors now propagate instead of triggering a silent resend.
|
|
14
|
+
|
|
15
|
+
- [#66](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/66) [`e8a5721`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/e8a5721b57be7ebd0b7edf80c4ed85919fccdb0a) Thanks [@huntabyte](https://github.com/huntabyte)! - `sendPolyesterUserOperation` accepts a new `onWalletSignatureRequested` callback that fires right before the wallet is asked to sign, so UIs can show an accurate "confirm in your wallet" state.
|
|
16
|
+
|
|
17
|
+
- [#66](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/66) [`e8a5721`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/e8a5721b57be7ebd0b7edf80c4ed85919fccdb0a) Thanks [@huntabyte](https://github.com/huntabyte)! - New `warmPolyesterSmartAccountClient` helper pre-fetches the gas price and warms RPC connections ahead of a submission. The smart account client now caches gas prices, for 10 seconds by default, configurable via the new `options.gasPriceCacheTtlMs` setting.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [#66](https://github.com/Fabric-Labs/polyester-sdk-typescript/pull/66) [`e8a5721`](https://github.com/Fabric-Labs/polyester-sdk-typescript/commit/e8a5721b57be7ebd0b7edf80c4ed85919fccdb0a) Thanks [@huntabyte](https://github.com/huntabyte)! - The smart account client polls for UserOperation receipts every second instead of every 4 seconds, configurable via the new `options.pollingIntervalMs` setting.
|
|
22
|
+
|
|
3
23
|
## 0.4.5
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readers.d.ts","names":[],"sources":["../../src/catalogs/readers.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"readers.d.ts","names":[],"sources":["../../src/catalogs/readers.ts"],"mappings":";;iBA0wBgB,4BAA4B,UAAU,kBAAkB"}
|
package/dist/catalogs/readers.js
CHANGED
|
@@ -3,6 +3,7 @@ import { CatalogConversionError, CatalogLookupError, CatalogValidationFailedErro
|
|
|
3
3
|
import { indexesFor } from "./indexes.js";
|
|
4
4
|
import { resolveLedgerAssetByLedgerId, resolveZipperAssetByLedgerId } from "./unknown-asset.js";
|
|
5
5
|
import { parseCatalogSnapshot } from "./snapshot-validation.js";
|
|
6
|
+
import { PROTOBUF_INT32_MAX, PROTOBUF_INT64_MAX } from "../shared/wire-bounds.js";
|
|
6
7
|
function isListed(pair, nowMs) {
|
|
7
8
|
if (pair.listingAt === null || pair.listingAt > nowMs) return false;
|
|
8
9
|
if (pair.status === "disabled") return false;
|
|
@@ -306,6 +307,9 @@ var OrdersReader = class {
|
|
|
306
307
|
}
|
|
307
308
|
getSpotOrderConstraints(pair) {
|
|
308
309
|
const config = this.market.requirePair(pair);
|
|
310
|
+
const priceScale = 6;
|
|
311
|
+
const quantityScale = config.baseAsset.quantityScale;
|
|
312
|
+
const quoteAmountScale = config.quoteAsset.quantityScale;
|
|
309
313
|
return {
|
|
310
314
|
symbolId: config.symbolId,
|
|
311
315
|
symbol: config.symbol,
|
|
@@ -314,9 +318,13 @@ var OrdersReader = class {
|
|
|
314
318
|
stepSize: config.stepSize,
|
|
315
319
|
minQtyBase: config.minQtyBase,
|
|
316
320
|
minNotionalQuote: config.minNotionalQuote,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
321
|
+
maxPrice: scaledToDecimal(PROTOBUF_INT64_MAX, priceScale),
|
|
322
|
+
maxQtyBase: scaledToDecimal(PROTOBUF_INT64_MAX, quantityScale),
|
|
323
|
+
maxNotionalQuote: scaledToDecimal(PROTOBUF_INT64_MAX, quoteAmountScale),
|
|
324
|
+
maxQuoteSlippage: scaledToDecimal(PROTOBUF_INT32_MAX, priceScale),
|
|
325
|
+
priceScale,
|
|
326
|
+
quantityScale,
|
|
327
|
+
quoteAmountScale,
|
|
320
328
|
priceDisplayDecimals: priceConverter(config).displayDecimals,
|
|
321
329
|
quantityDisplayDecimals: config.baseAsset.quantityDisplayDecimals,
|
|
322
330
|
quoteAmountDisplayDecimals: config.quoteAsset.quantityDisplayDecimals
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"readers.js","names":[],"sources":["../../src/catalogs/readers.ts"],"sourcesContent":["import type {\n AssetConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport {\n scaledToDecimal,\n scaledToDisplay,\n significantDecimalPlaces,\n tryDecimalToScaled,\n tryNormalizeDecimalInput,\n tryToScaledBigInt,\n type DecimalToScaledFailure,\n type ScaledIntegerLike,\n} from \"./decimal.js\";\nimport { indexesFor } from \"./indexes.js\";\nimport type { EnrichedPairConfig } from \"./market-data-catalog.js\";\nimport {\n resolveLedgerAssetByLedgerId,\n resolveZipperAssetByLedgerId,\n UNKNOWN_LEDGER_ASSET_ID,\n} from \"./unknown-asset.js\";\nimport type { ZipperContractName, ZipperEnrichedAssetConfig } from \"./zipper-catalog.js\";\nimport {\n CatalogConversionError,\n CatalogLookupError,\n CatalogValidationFailedError,\n type AssetCatalogKey,\n type CatalogLookupDomain,\n type CatalogReader,\n type CatalogSnapshot,\n type CatalogValidationError,\n type CatalogValidationResult,\n type ChainCatalogKey,\n type LedgerCatalogReader,\n type MarketCatalogReader,\n type OrdersCatalogReader,\n type PairCatalogKey,\n type ParsedCatalogAmount,\n type SpotOrderConstraints,\n type SpotOrderDecimalInput,\n type ZipperAssetChainRoute,\n type ZipperCatalogReader,\n} from \"./types.js\";\nimport { parseCatalogSnapshot } from \"./snapshot-validation.js\";\n\n/** Price ticks are always quoted at 6 decimal places. */\nexport const PRICE_SCALE = 6;\n\ntype SnapshotGetter = () => CatalogSnapshot;\n\nfunction isListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n if (pair.listingAt === null || pair.listingAt > nowMs) return false;\n if (pair.status === \"disabled\") return false;\n if (pair.delistingAt !== null && pair.delistingAt < nowMs) return false;\n return true;\n}\n\nfunction isEverListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n return pair.listingAt !== null && pair.listingAt < nowMs;\n}\n\nfunction requireFound<T>(\n domain: CatalogLookupDomain,\n lookup: string,\n value: string | number,\n found: T | null,\n): T {\n if (found === null) throw new CatalogLookupError(domain, lookup, value);\n return found;\n}\n\ntype ResolvedKey<TByName extends string, TById extends string> =\n | { lookup: TByName; value: string }\n | { lookup: TById; value: number };\n\nfunction resolvePairKey(key: PairCatalogKey): ResolvedKey<\"symbol\", \"symbolId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"symbolId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"symbolId\", value: key.symbolId };\n}\n\nfunction resolveAssetKey(key: AssetCatalogKey): ResolvedKey<\"symbol\", \"ledgerId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"ledgerId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"ledgerId\", value: key.ledgerId };\n}\n\nfunction resolveChainKey(key: ChainCatalogKey): ResolvedKey<\"chainCode\", \"chainId\"> {\n if (typeof key === \"string\") return { lookup: \"chainCode\", value: key };\n if (typeof key === \"number\") return { lookup: \"chainId\", value: key };\n if (\"code\" in key) return { lookup: \"chainCode\", value: key.code };\n return { lookup: \"chainId\", value: key.chainId };\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/** Shared conversion core used by the market and ledger readers. */\nclass DecimalConverter {\n constructor(\n readonly field: string,\n readonly scale: number,\n readonly displayDecimals: number,\n ) {}\n\n parse(decimal: string): ParsedCatalogAmount {\n const result = tryDecimalToScaled(decimal, this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return {\n scaledValue: result.scaled.toString(),\n decimal: scaledToDecimal(result.scaled, this.scale),\n display: scaledToDisplay(result.scaled, this.scale, this.displayDecimals),\n scale: this.scale,\n };\n }\n\n normalizeInput(raw: string): string {\n const normalized = tryNormalizeDecimalInput(raw, this.scale);\n if (normalized === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a non-negative decimal number: ${raw}`,\n );\n }\n return normalized;\n }\n\n toDecimalString(scaled: ScaledIntegerLike): string {\n return scaledToDecimal(this.toBigInt(scaled), this.scale);\n }\n\n toDisplayString(scaled: ScaledIntegerLike): string {\n return scaledToDisplay(this.toBigInt(scaled), this.scale, this.displayDecimals);\n }\n\n formatDecimal(decimal: string): string {\n const result = tryDecimalToScaled(decimal.trim(), this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return scaledToDisplay(result.scaled, this.scale, this.displayDecimals);\n }\n\n private toBigInt(scaled: ScaledIntegerLike): bigint {\n const value = tryToScaledBigInt(scaled);\n if (value === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a raw scaled integer: ${String(scaled)}`,\n );\n }\n return value;\n }\n}\n\nfunction priceConverter(pair: EnrichedPairConfig): DecimalConverter {\n const tickDecimals = significantDecimalPlaces(pair.tickSize);\n const displayDecimals = tickDecimals > 0 ? tickDecimals : PRICE_SCALE;\n return new DecimalConverter(\"price\", PRICE_SCALE, displayDecimals);\n}\n\nfunction quantityConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quantity\",\n pair.baseAsset.quantityScale,\n pair.baseAsset.quantityDisplayDecimals,\n );\n}\n\nfunction quoteAmountConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quoteAmount\",\n pair.quoteAsset.quantityScale,\n pair.quoteAsset.quantityDisplayDecimals,\n );\n}\n\nfunction ledgerAmountConverter(asset: AssetConfig): DecimalConverter {\n return new DecimalConverter(\"amount\", asset.quantityScale, asset.quantityDisplayDecimals);\n}\n\nclass MarketReader implements MarketCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listAssets(): readonly AssetConfig[] {\n return this.getSnapshot().market.assets;\n }\n\n getAsset(asset: AssetCatalogKey): AssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"market\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"market\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return resolveLedgerAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[] {\n const pairs = this.getSnapshot().market.pairs;\n if (!filter) return pairs;\n const nowMs = filter.atMs ?? Date.now();\n return pairs.filter((pair) => {\n if (filter.listed !== undefined && isListed(pair, nowMs) !== filter.listed)\n return false;\n if (filter.everListed !== undefined && isEverListed(pair, nowMs) !== filter.everListed)\n return false;\n return true;\n });\n }\n\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null {\n const key = resolvePairKey(pair);\n return key.lookup === \"symbol\"\n ? this.getPairBySymbol(key.value)\n : this.getPairBySymbolId(key.value);\n }\n\n requirePair(pair: PairCatalogKey): EnrichedPairConfig {\n const key = resolvePairKey(pair);\n return requireFound(\"market\", key.lookup, key.value, this.getPair(pair));\n }\n\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbol.get(pairSymbol) ?? null;\n }\n\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig {\n return requireFound(\"market\", \"symbol\", pairSymbol, this.getPairBySymbol(pairSymbol));\n }\n\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbolId.get(pairSymbolId) ?? null;\n }\n\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig {\n return requireFound(\n \"market\",\n \"symbolId\",\n pairSymbolId,\n this.getPairBySymbolId(pairSymbolId),\n );\n }\n\n getSymbolIdByPairSymbol(pairSymbol: string): number | null {\n return this.getPairBySymbol(pairSymbol)?.symbolId ?? null;\n }\n\n requireSymbolIdByPairSymbol(pairSymbol: string): number {\n return this.requirePairBySymbol(pairSymbol).symbolId;\n }\n\n getPairSymbolBySymbolId(pairSymbolId: number): string | null {\n return this.getPairBySymbolId(pairSymbolId)?.symbol ?? null;\n }\n\n requirePairSymbolBySymbolId(pairSymbolId: number): string {\n return this.requirePairBySymbolId(pairSymbolId).symbol;\n }\n\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return priceConverter(this.requirePair(pair)).parse(price);\n }\n\n normalizePriceInput(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).normalizeInput(price);\n }\n\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDecimalString(priceTicks);\n }\n\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDisplayString(priceTicks);\n }\n\n formatPrice(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).formatDecimal(price);\n }\n\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quantityConverter(this.requirePair(pair)).parse(quantity);\n }\n\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).normalizeInput(quantity);\n }\n\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDecimalString(quantityScaled);\n }\n\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDisplayString(quantityScaled);\n }\n\n formatQuantity(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).formatDecimal(quantity);\n }\n\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quoteAmountConverter(this.requirePair(pair)).parse(amount);\n }\n\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).normalizeInput(amount);\n }\n\n quoteAmountScaledToDecimalString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDecimalString(amountScaled);\n }\n\n quoteAmountScaledToDisplayString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDisplayString(amountScaled);\n }\n\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).formatDecimal(amount);\n }\n}\n\nclass LedgerReader implements LedgerCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.market.getAssetByLedgerId(ledgerAssetId);\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return this.market.getAssetBySymbol(assetSymbol);\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"ledger\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getLedgerIdBySymbol(assetSymbol: string): number | null {\n return this.getAssetBySymbol(assetSymbol)?.ledgerId ?? null;\n }\n\n requireLedgerIdBySymbol(assetSymbol: string): number {\n return this.requireAssetBySymbol(assetSymbol).ledgerId;\n }\n\n requireSymbolByLedgerId(ledgerAssetId: number): string {\n return this.requireAssetByLedgerId(ledgerAssetId).symbol;\n }\n\n isKnownAssetId(ledgerAssetId: number): boolean {\n if (!Number.isInteger(ledgerAssetId) || ledgerAssetId <= 0) return false;\n if (ledgerAssetId === UNKNOWN_LEDGER_ASSET_ID) return false;\n return this.market.lookupAssetByLedgerId(ledgerAssetId) !== null;\n }\n\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount {\n return ledgerAmountConverter(this.requireAsset(asset)).parse(amount);\n }\n\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).normalizeInput(amount);\n }\n\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDecimalString(amountScaled);\n }\n\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDisplayString(amountScaled);\n }\n\n formatAmount(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).formatDecimal(amount);\n }\n\n private requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n const found =\n key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n return requireFound(\"ledger\", key.lookup, key.value, found);\n }\n}\n\nclass OrdersReader implements OrdersCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints {\n const config = this.market.requirePair(pair);\n return {\n symbolId: config.symbolId,\n symbol: config.symbol,\n status: config.status,\n tickSize: config.tickSize,\n stepSize: config.stepSize,\n minQtyBase: config.minQtyBase,\n minNotionalQuote: config.minNotionalQuote,\n priceScale: PRICE_SCALE,\n quantityScale: config.baseAsset.quantityScale,\n quoteAmountScale: config.quoteAsset.quantityScale,\n priceDisplayDecimals: priceConverter(config).displayDecimals,\n quantityDisplayDecimals: config.baseAsset.quantityDisplayDecimals,\n quoteAmountDisplayDecimals: config.quoteAsset.quantityDisplayDecimals,\n };\n }\n\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult {\n const pair = this.market.requirePair(input.pair);\n const errors: CatalogValidationError[] = [];\n\n const quantityScaled = this.validateQuantity(pair, input.quantity, errors);\n const priceTicks =\n input.price === undefined ? null : this.validatePrice(pair, input.price, errors);\n\n if (quantityScaled !== null && priceTicks !== null) {\n this.validateMinNotional(pair, quantityScaled, priceTicks, errors);\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void {\n const result = this.validateSpotOrderDecimalInput(input);\n if (!result.valid) throw new CatalogValidationFailedError(result.errors);\n }\n\n private validateQuantity(\n pair: EnrichedPairConfig,\n quantity: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const scale = pair.baseAsset.quantityScale;\n const parsed = tryDecimalToScaled(quantity, scale);\n if (!parsed.ok) {\n errors.push({\n field: \"quantity\",\n rule: \"parse\",\n message: conversionFailureMessage(\"quantity\", quantity, parsed.failure),\n actual: quantity,\n });\n return null;\n }\n\n const step = this.requireConstraintScaled(pair.stepSize, scale, \"stepSize\");\n if (step > 0n && parsed.scaled % step !== 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"stepSize\",\n message: `quantity must be a multiple of the pair step size ${pair.stepSize}`,\n expected: pair.stepSize,\n actual: quantity,\n });\n }\n\n const minQty = this.requireConstraintScaled(pair.minQtyBase, scale, \"minQtyBase\");\n if (parsed.scaled < minQty || parsed.scaled === 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"minQty\",\n message: `quantity is below the pair minimum of ${pair.minQtyBase}`,\n expected: pair.minQtyBase,\n actual: quantity,\n });\n }\n\n return parsed.scaled;\n }\n\n private validatePrice(\n pair: EnrichedPairConfig,\n price: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const parsed = tryDecimalToScaled(price, PRICE_SCALE);\n if (!parsed.ok) {\n errors.push({\n field: \"price\",\n rule: \"parse\",\n message: conversionFailureMessage(\"price\", price, parsed.failure),\n actual: price,\n });\n return null;\n }\n\n const tick = this.requireConstraintScaled(pair.tickSize, PRICE_SCALE, \"tickSize\");\n if (tick > 0n && parsed.scaled % tick !== 0n) {\n errors.push({\n field: \"price\",\n rule: \"tickSize\",\n message: `price must be a multiple of the pair tick size ${pair.tickSize}`,\n expected: pair.tickSize,\n actual: price,\n });\n }\n\n return parsed.scaled;\n }\n\n private validateMinNotional(\n pair: EnrichedPairConfig,\n quantityScaled: bigint,\n priceTicks: bigint,\n errors: CatalogValidationError[],\n ): void {\n const notionalScale = pair.baseAsset.quantityScale + PRICE_SCALE;\n const minNotional = this.requireConstraintScaled(\n pair.minNotionalQuote,\n notionalScale,\n \"minNotionalQuote\",\n );\n const notional = quantityScaled * priceTicks;\n if (notional < minNotional) {\n errors.push({\n field: \"notional\",\n rule: \"minNotional\",\n message: `order notional is below the pair minimum of ${pair.minNotionalQuote}`,\n expected: pair.minNotionalQuote,\n actual: scaledToDecimal(notional, notionalScale),\n });\n }\n }\n\n /** Pair constraint strings come from the catalog itself, so failures are data bugs. */\n private requireConstraintScaled(decimal: string, scale: number, field: string): bigint {\n const result = tryDecimalToScaled(decimal, scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, decimal, result.failure),\n );\n }\n return result.scaled;\n }\n}\n\nclass ZipperReader implements ZipperCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listChains(): readonly ZipperChainConfig[] {\n return this.getSnapshot().zipper.chains;\n }\n\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null {\n const key = resolveChainKey(chain);\n return key.lookup === \"chainCode\"\n ? this.getChainByCode(key.value)\n : this.getChainById(key.value);\n }\n\n requireChain(chain: ChainCatalogKey): ZipperChainConfig {\n const key = resolveChainKey(chain);\n return requireFound(\"zipper\", key.lookup, key.value, this.getChain(chain));\n }\n\n getChainByCode(chainCode: string): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainByCode.get(chainCode) ?? null;\n }\n\n requireChainByCode(chainCode: string): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainCode\", chainCode, this.getChainByCode(chainCode));\n }\n\n getChainById(chainId: number): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainById.get(chainId) ?? null;\n }\n\n requireChainById(chainId: number): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainId\", chainId, this.getChainById(chainId));\n }\n\n getChainIdByCode(chainCode: string): number | null {\n return this.getChainByCode(chainCode)?.chainId ?? null;\n }\n\n requireChainIdByCode(chainCode: string): number {\n return this.requireChainByCode(chainCode).chainId;\n }\n\n listAssets(): readonly ZipperEnrichedAssetConfig[] {\n return this.getSnapshot().zipper.assets;\n }\n\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"zipper\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return resolveZipperAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByUAssetId.get(uAssetId) ?? null;\n }\n\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"uAssetId\", uAssetId, this.getAssetByUAssetId(uAssetId));\n }\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null {\n const zipperAsset = this.getAsset(asset);\n const zipperChain = this.getChain(chain);\n if (!zipperAsset || !zipperChain) return null;\n const route = zipperAsset.chains.find(\n (candidate) => candidate.chainId === zipperChain.chainId,\n );\n return route ? { asset: zipperAsset, chain: route } : null;\n }\n\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute {\n const route = this.getAssetChain(asset, chain);\n if (!route) {\n throw new CatalogLookupError(\n \"zipper\",\n \"assetChain\",\n `${formatKey(resolveAssetKey(asset))}:${formatKey(resolveChainKey(chain))}`,\n );\n }\n return route;\n }\n\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null {\n return indexesFor(this.getSnapshot()).zipperRouteByZippedAssetId.get(zippedAssetId) ?? null;\n }\n\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute {\n return requireFound(\n \"zipper\",\n \"zippedAssetId\",\n zippedAssetId,\n this.getAssetChainByZippedAssetId(zippedAssetId),\n );\n }\n\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null {\n return this.getAssetChain(asset, chain)?.chain.zippedAssetId ?? null;\n }\n\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number {\n return this.requireAssetChain(asset, chain).chain.zippedAssetId;\n }\n\n listContracts(): readonly ZipperChainContractConfig[] {\n return this.getSnapshot().zipper.contracts;\n }\n\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return this.getContractByName(contractName);\n }\n\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig {\n return this.requireContractByName(contractName);\n }\n\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return indexesFor(this.getSnapshot()).zipperContractByName.get(contractName) ?? null;\n }\n\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig {\n return requireFound(\n \"zipper\",\n \"contractName\",\n contractName,\n this.getContractByName(contractName),\n );\n }\n}\n\nfunction formatKey(key: { lookup: string; value: string | number }): string {\n return String(key.value);\n}\n\nclass SnapshotCatalogReader implements CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n readonly snapshot: () => CatalogSnapshot;\n\n constructor(getSnapshot: SnapshotGetter) {\n const market = new MarketReader(getSnapshot);\n this.market = market;\n this.ledger = new LedgerReader(market);\n this.orders = new OrdersReader(market);\n this.zipper = new ZipperReader(getSnapshot);\n this.snapshot = () => getSnapshot();\n }\n}\n\nexport function createReader(getSnapshot: () => CatalogSnapshot): CatalogReader {\n return new SnapshotCatalogReader(getSnapshot);\n}\n\nexport function createCatalogSnapshotReader(snapshot: CatalogSnapshot): CatalogReader {\n const parsed = parseCatalogSnapshot(snapshot);\n return createReader(() => parsed);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"readers.js","names":[],"sources":["../../src/catalogs/readers.ts"],"sourcesContent":["import type {\n AssetConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport {\n scaledToDecimal,\n scaledToDisplay,\n significantDecimalPlaces,\n tryDecimalToScaled,\n tryNormalizeDecimalInput,\n tryToScaledBigInt,\n type DecimalToScaledFailure,\n type ScaledIntegerLike,\n} from \"./decimal.js\";\nimport { indexesFor } from \"./indexes.js\";\nimport type { EnrichedPairConfig } from \"./market-data-catalog.js\";\nimport {\n resolveLedgerAssetByLedgerId,\n resolveZipperAssetByLedgerId,\n UNKNOWN_LEDGER_ASSET_ID,\n} from \"./unknown-asset.js\";\nimport type { ZipperContractName, ZipperEnrichedAssetConfig } from \"./zipper-catalog.js\";\nimport {\n CatalogConversionError,\n CatalogLookupError,\n CatalogValidationFailedError,\n type AssetCatalogKey,\n type CatalogLookupDomain,\n type CatalogReader,\n type CatalogSnapshot,\n type CatalogValidationError,\n type CatalogValidationResult,\n type ChainCatalogKey,\n type LedgerCatalogReader,\n type MarketCatalogReader,\n type OrdersCatalogReader,\n type PairCatalogKey,\n type ParsedCatalogAmount,\n type SpotOrderConstraints,\n type SpotOrderDecimalInput,\n type ZipperAssetChainRoute,\n type ZipperCatalogReader,\n} from \"./types.js\";\nimport { parseCatalogSnapshot } from \"./snapshot-validation.js\";\nimport { PROTOBUF_INT32_MAX, PROTOBUF_INT64_MAX } from \"../shared/wire-bounds.js\";\n\n/** Price ticks are always quoted at 6 decimal places. */\nexport const PRICE_SCALE = 6;\n\ntype SnapshotGetter = () => CatalogSnapshot;\n\nfunction isListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n if (pair.listingAt === null || pair.listingAt > nowMs) return false;\n if (pair.status === \"disabled\") return false;\n if (pair.delistingAt !== null && pair.delistingAt < nowMs) return false;\n return true;\n}\n\nfunction isEverListed(pair: EnrichedPairConfig, nowMs: number): boolean {\n return pair.listingAt !== null && pair.listingAt < nowMs;\n}\n\nfunction requireFound<T>(\n domain: CatalogLookupDomain,\n lookup: string,\n value: string | number,\n found: T | null,\n): T {\n if (found === null) throw new CatalogLookupError(domain, lookup, value);\n return found;\n}\n\ntype ResolvedKey<TByName extends string, TById extends string> =\n | { lookup: TByName; value: string }\n | { lookup: TById; value: number };\n\nfunction resolvePairKey(key: PairCatalogKey): ResolvedKey<\"symbol\", \"symbolId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"symbolId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"symbolId\", value: key.symbolId };\n}\n\nfunction resolveAssetKey(key: AssetCatalogKey): ResolvedKey<\"symbol\", \"ledgerId\"> {\n if (typeof key === \"string\") return { lookup: \"symbol\", value: key };\n if (typeof key === \"number\") return { lookup: \"ledgerId\", value: key };\n if (\"symbol\" in key) return { lookup: \"symbol\", value: key.symbol };\n return { lookup: \"ledgerId\", value: key.ledgerId };\n}\n\nfunction resolveChainKey(key: ChainCatalogKey): ResolvedKey<\"chainCode\", \"chainId\"> {\n if (typeof key === \"string\") return { lookup: \"chainCode\", value: key };\n if (typeof key === \"number\") return { lookup: \"chainId\", value: key };\n if (\"code\" in key) return { lookup: \"chainCode\", value: key.code };\n return { lookup: \"chainId\", value: key.chainId };\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/** Shared conversion core used by the market and ledger readers. */\nclass DecimalConverter {\n constructor(\n readonly field: string,\n readonly scale: number,\n readonly displayDecimals: number,\n ) {}\n\n parse(decimal: string): ParsedCatalogAmount {\n const result = tryDecimalToScaled(decimal, this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return {\n scaledValue: result.scaled.toString(),\n decimal: scaledToDecimal(result.scaled, this.scale),\n display: scaledToDisplay(result.scaled, this.scale, this.displayDecimals),\n scale: this.scale,\n };\n }\n\n normalizeInput(raw: string): string {\n const normalized = tryNormalizeDecimalInput(raw, this.scale);\n if (normalized === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a non-negative decimal number: ${raw}`,\n );\n }\n return normalized;\n }\n\n toDecimalString(scaled: ScaledIntegerLike): string {\n return scaledToDecimal(this.toBigInt(scaled), this.scale);\n }\n\n toDisplayString(scaled: ScaledIntegerLike): string {\n return scaledToDisplay(this.toBigInt(scaled), this.scale, this.displayDecimals);\n }\n\n formatDecimal(decimal: string): string {\n const result = tryDecimalToScaled(decimal.trim(), this.scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n this.field,\n conversionFailureMessage(this.field, decimal, result.failure),\n );\n }\n return scaledToDisplay(result.scaled, this.scale, this.displayDecimals);\n }\n\n private toBigInt(scaled: ScaledIntegerLike): bigint {\n const value = tryToScaledBigInt(scaled);\n if (value === null) {\n throw new CatalogConversionError(\n this.field,\n `${this.field} must be a raw scaled integer: ${String(scaled)}`,\n );\n }\n return value;\n }\n}\n\nfunction priceConverter(pair: EnrichedPairConfig): DecimalConverter {\n const tickDecimals = significantDecimalPlaces(pair.tickSize);\n const displayDecimals = tickDecimals > 0 ? tickDecimals : PRICE_SCALE;\n return new DecimalConverter(\"price\", PRICE_SCALE, displayDecimals);\n}\n\nfunction quantityConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quantity\",\n pair.baseAsset.quantityScale,\n pair.baseAsset.quantityDisplayDecimals,\n );\n}\n\nfunction quoteAmountConverter(pair: EnrichedPairConfig): DecimalConverter {\n return new DecimalConverter(\n \"quoteAmount\",\n pair.quoteAsset.quantityScale,\n pair.quoteAsset.quantityDisplayDecimals,\n );\n}\n\nfunction ledgerAmountConverter(asset: AssetConfig): DecimalConverter {\n return new DecimalConverter(\"amount\", asset.quantityScale, asset.quantityDisplayDecimals);\n}\n\nclass MarketReader implements MarketCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listAssets(): readonly AssetConfig[] {\n return this.getSnapshot().market.assets;\n }\n\n getAsset(asset: AssetCatalogKey): AssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"market\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"market\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return resolveLedgerAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): AssetConfig | null {\n return indexesFor(this.getSnapshot()).assetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[] {\n const pairs = this.getSnapshot().market.pairs;\n if (!filter) return pairs;\n const nowMs = filter.atMs ?? Date.now();\n return pairs.filter((pair) => {\n if (filter.listed !== undefined && isListed(pair, nowMs) !== filter.listed)\n return false;\n if (filter.everListed !== undefined && isEverListed(pair, nowMs) !== filter.everListed)\n return false;\n return true;\n });\n }\n\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null {\n const key = resolvePairKey(pair);\n return key.lookup === \"symbol\"\n ? this.getPairBySymbol(key.value)\n : this.getPairBySymbolId(key.value);\n }\n\n requirePair(pair: PairCatalogKey): EnrichedPairConfig {\n const key = resolvePairKey(pair);\n return requireFound(\"market\", key.lookup, key.value, this.getPair(pair));\n }\n\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbol.get(pairSymbol) ?? null;\n }\n\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig {\n return requireFound(\"market\", \"symbol\", pairSymbol, this.getPairBySymbol(pairSymbol));\n }\n\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null {\n return indexesFor(this.getSnapshot()).pairBySymbolId.get(pairSymbolId) ?? null;\n }\n\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig {\n return requireFound(\n \"market\",\n \"symbolId\",\n pairSymbolId,\n this.getPairBySymbolId(pairSymbolId),\n );\n }\n\n getSymbolIdByPairSymbol(pairSymbol: string): number | null {\n return this.getPairBySymbol(pairSymbol)?.symbolId ?? null;\n }\n\n requireSymbolIdByPairSymbol(pairSymbol: string): number {\n return this.requirePairBySymbol(pairSymbol).symbolId;\n }\n\n getPairSymbolBySymbolId(pairSymbolId: number): string | null {\n return this.getPairBySymbolId(pairSymbolId)?.symbol ?? null;\n }\n\n requirePairSymbolBySymbolId(pairSymbolId: number): string {\n return this.requirePairBySymbolId(pairSymbolId).symbol;\n }\n\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return priceConverter(this.requirePair(pair)).parse(price);\n }\n\n normalizePriceInput(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).normalizeInput(price);\n }\n\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDecimalString(priceTicks);\n }\n\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).toDisplayString(priceTicks);\n }\n\n formatPrice(price: string, pair: PairCatalogKey): string {\n return priceConverter(this.requirePair(pair)).formatDecimal(price);\n }\n\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quantityConverter(this.requirePair(pair)).parse(quantity);\n }\n\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).normalizeInput(quantity);\n }\n\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDecimalString(quantityScaled);\n }\n\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).toDisplayString(quantityScaled);\n }\n\n formatQuantity(quantity: string, pair: PairCatalogKey): string {\n return quantityConverter(this.requirePair(pair)).formatDecimal(quantity);\n }\n\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount {\n return quoteAmountConverter(this.requirePair(pair)).parse(amount);\n }\n\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).normalizeInput(amount);\n }\n\n quoteAmountScaledToDecimalString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDecimalString(amountScaled);\n }\n\n quoteAmountScaledToDisplayString(\n amountScaled: ScaledIntegerLike,\n pair: PairCatalogKey,\n ): string {\n return quoteAmountConverter(this.requirePair(pair)).toDisplayString(amountScaled);\n }\n\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string {\n return quoteAmountConverter(this.requirePair(pair)).formatDecimal(amount);\n }\n}\n\nclass LedgerReader implements LedgerCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.market.getAssetByLedgerId(ledgerAssetId);\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetBySymbol(assetSymbol: string): AssetConfig | null {\n return this.market.getAssetBySymbol(assetSymbol);\n }\n\n requireAssetBySymbol(assetSymbol: string): AssetConfig {\n return requireFound(\"ledger\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getLedgerIdBySymbol(assetSymbol: string): number | null {\n return this.getAssetBySymbol(assetSymbol)?.ledgerId ?? null;\n }\n\n requireLedgerIdBySymbol(assetSymbol: string): number {\n return this.requireAssetBySymbol(assetSymbol).ledgerId;\n }\n\n requireSymbolByLedgerId(ledgerAssetId: number): string {\n return this.requireAssetByLedgerId(ledgerAssetId).symbol;\n }\n\n isKnownAssetId(ledgerAssetId: number): boolean {\n if (!Number.isInteger(ledgerAssetId) || ledgerAssetId <= 0) return false;\n if (ledgerAssetId === UNKNOWN_LEDGER_ASSET_ID) return false;\n return this.market.lookupAssetByLedgerId(ledgerAssetId) !== null;\n }\n\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount {\n return ledgerAmountConverter(this.requireAsset(asset)).parse(amount);\n }\n\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).normalizeInput(amount);\n }\n\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDecimalString(amountScaled);\n }\n\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).toDisplayString(amountScaled);\n }\n\n formatAmount(amount: string, asset: AssetCatalogKey): string {\n return ledgerAmountConverter(this.requireAsset(asset)).formatDecimal(amount);\n }\n\n private requireAsset(asset: AssetCatalogKey): AssetConfig {\n const key = resolveAssetKey(asset);\n const found =\n key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n return requireFound(\"ledger\", key.lookup, key.value, found);\n }\n}\n\nclass OrdersReader implements OrdersCatalogReader {\n constructor(private readonly market: MarketReader) {}\n\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints {\n const config = this.market.requirePair(pair);\n const priceScale = PRICE_SCALE;\n const quantityScale = config.baseAsset.quantityScale;\n const quoteAmountScale = config.quoteAsset.quantityScale;\n return {\n symbolId: config.symbolId,\n symbol: config.symbol,\n status: config.status,\n tickSize: config.tickSize,\n stepSize: config.stepSize,\n minQtyBase: config.minQtyBase,\n minNotionalQuote: config.minNotionalQuote,\n maxPrice: scaledToDecimal(PROTOBUF_INT64_MAX, priceScale),\n maxQtyBase: scaledToDecimal(PROTOBUF_INT64_MAX, quantityScale),\n maxNotionalQuote: scaledToDecimal(PROTOBUF_INT64_MAX, quoteAmountScale),\n maxQuoteSlippage: scaledToDecimal(PROTOBUF_INT32_MAX, priceScale),\n priceScale,\n quantityScale,\n quoteAmountScale,\n priceDisplayDecimals: priceConverter(config).displayDecimals,\n quantityDisplayDecimals: config.baseAsset.quantityDisplayDecimals,\n quoteAmountDisplayDecimals: config.quoteAsset.quantityDisplayDecimals,\n };\n }\n\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult {\n const pair = this.market.requirePair(input.pair);\n const errors: CatalogValidationError[] = [];\n\n const quantityScaled = this.validateQuantity(pair, input.quantity, errors);\n const priceTicks =\n input.price === undefined ? null : this.validatePrice(pair, input.price, errors);\n\n if (quantityScaled !== null && priceTicks !== null) {\n this.validateMinNotional(pair, quantityScaled, priceTicks, errors);\n }\n\n return { valid: errors.length === 0, errors };\n }\n\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void {\n const result = this.validateSpotOrderDecimalInput(input);\n if (!result.valid) throw new CatalogValidationFailedError(result.errors);\n }\n\n private validateQuantity(\n pair: EnrichedPairConfig,\n quantity: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const scale = pair.baseAsset.quantityScale;\n const parsed = tryDecimalToScaled(quantity, scale);\n if (!parsed.ok) {\n errors.push({\n field: \"quantity\",\n rule: \"parse\",\n message: conversionFailureMessage(\"quantity\", quantity, parsed.failure),\n actual: quantity,\n });\n return null;\n }\n\n const step = this.requireConstraintScaled(pair.stepSize, scale, \"stepSize\");\n if (step > 0n && parsed.scaled % step !== 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"stepSize\",\n message: `quantity must be a multiple of the pair step size ${pair.stepSize}`,\n expected: pair.stepSize,\n actual: quantity,\n });\n }\n\n const minQty = this.requireConstraintScaled(pair.minQtyBase, scale, \"minQtyBase\");\n if (parsed.scaled < minQty || parsed.scaled === 0n) {\n errors.push({\n field: \"quantity\",\n rule: \"minQty\",\n message: `quantity is below the pair minimum of ${pair.minQtyBase}`,\n expected: pair.minQtyBase,\n actual: quantity,\n });\n }\n\n return parsed.scaled;\n }\n\n private validatePrice(\n pair: EnrichedPairConfig,\n price: string,\n errors: CatalogValidationError[],\n ): bigint | null {\n const parsed = tryDecimalToScaled(price, PRICE_SCALE);\n if (!parsed.ok) {\n errors.push({\n field: \"price\",\n rule: \"parse\",\n message: conversionFailureMessage(\"price\", price, parsed.failure),\n actual: price,\n });\n return null;\n }\n\n const tick = this.requireConstraintScaled(pair.tickSize, PRICE_SCALE, \"tickSize\");\n if (tick > 0n && parsed.scaled % tick !== 0n) {\n errors.push({\n field: \"price\",\n rule: \"tickSize\",\n message: `price must be a multiple of the pair tick size ${pair.tickSize}`,\n expected: pair.tickSize,\n actual: price,\n });\n }\n\n return parsed.scaled;\n }\n\n private validateMinNotional(\n pair: EnrichedPairConfig,\n quantityScaled: bigint,\n priceTicks: bigint,\n errors: CatalogValidationError[],\n ): void {\n const notionalScale = pair.baseAsset.quantityScale + PRICE_SCALE;\n const minNotional = this.requireConstraintScaled(\n pair.minNotionalQuote,\n notionalScale,\n \"minNotionalQuote\",\n );\n const notional = quantityScaled * priceTicks;\n if (notional < minNotional) {\n errors.push({\n field: \"notional\",\n rule: \"minNotional\",\n message: `order notional is below the pair minimum of ${pair.minNotionalQuote}`,\n expected: pair.minNotionalQuote,\n actual: scaledToDecimal(notional, notionalScale),\n });\n }\n }\n\n /** Pair constraint strings come from the catalog itself, so failures are data bugs. */\n private requireConstraintScaled(decimal: string, scale: number, field: string): bigint {\n const result = tryDecimalToScaled(decimal, scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, decimal, result.failure),\n );\n }\n return result.scaled;\n }\n}\n\nclass ZipperReader implements ZipperCatalogReader {\n constructor(private readonly getSnapshot: SnapshotGetter) {}\n\n listChains(): readonly ZipperChainConfig[] {\n return this.getSnapshot().zipper.chains;\n }\n\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null {\n const key = resolveChainKey(chain);\n return key.lookup === \"chainCode\"\n ? this.getChainByCode(key.value)\n : this.getChainById(key.value);\n }\n\n requireChain(chain: ChainCatalogKey): ZipperChainConfig {\n const key = resolveChainKey(chain);\n return requireFound(\"zipper\", key.lookup, key.value, this.getChain(chain));\n }\n\n getChainByCode(chainCode: string): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainByCode.get(chainCode) ?? null;\n }\n\n requireChainByCode(chainCode: string): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainCode\", chainCode, this.getChainByCode(chainCode));\n }\n\n getChainById(chainId: number): ZipperChainConfig | null {\n return indexesFor(this.getSnapshot()).zipperChainById.get(chainId) ?? null;\n }\n\n requireChainById(chainId: number): ZipperChainConfig {\n return requireFound(\"zipper\", \"chainId\", chainId, this.getChainById(chainId));\n }\n\n getChainIdByCode(chainCode: string): number | null {\n return this.getChainByCode(chainCode)?.chainId ?? null;\n }\n\n requireChainIdByCode(chainCode: string): number {\n return this.requireChainByCode(chainCode).chainId;\n }\n\n listAssets(): readonly ZipperEnrichedAssetConfig[] {\n return this.getSnapshot().zipper.assets;\n }\n\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null {\n const key = resolveAssetKey(asset);\n return key.lookup === \"symbol\"\n ? this.getAssetBySymbol(key.value)\n : this.getAssetByLedgerId(key.value);\n }\n\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig {\n const key = resolveAssetKey(asset);\n return requireFound(\"zipper\", key.lookup, key.value, this.getAsset(asset));\n }\n\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetBySymbol.get(assetSymbol) ?? null;\n }\n\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"symbol\", assetSymbol, this.getAssetBySymbol(assetSymbol));\n }\n\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return resolveZipperAssetByLedgerId(ledgerAssetId, (id) => this.lookupAssetByLedgerId(id));\n }\n\n lookupAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByLedgerId.get(ledgerAssetId) ?? null;\n }\n\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig {\n return this.getAssetByLedgerId(ledgerAssetId);\n }\n\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null {\n return indexesFor(this.getSnapshot()).zipperAssetByUAssetId.get(uAssetId) ?? null;\n }\n\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig {\n return requireFound(\"zipper\", \"uAssetId\", uAssetId, this.getAssetByUAssetId(uAssetId));\n }\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null {\n const zipperAsset = this.getAsset(asset);\n const zipperChain = this.getChain(chain);\n if (!zipperAsset || !zipperChain) return null;\n const route = zipperAsset.chains.find(\n (candidate) => candidate.chainId === zipperChain.chainId,\n );\n return route ? { asset: zipperAsset, chain: route } : null;\n }\n\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute {\n const route = this.getAssetChain(asset, chain);\n if (!route) {\n throw new CatalogLookupError(\n \"zipper\",\n \"assetChain\",\n `${formatKey(resolveAssetKey(asset))}:${formatKey(resolveChainKey(chain))}`,\n );\n }\n return route;\n }\n\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null {\n return indexesFor(this.getSnapshot()).zipperRouteByZippedAssetId.get(zippedAssetId) ?? null;\n }\n\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute {\n return requireFound(\n \"zipper\",\n \"zippedAssetId\",\n zippedAssetId,\n this.getAssetChainByZippedAssetId(zippedAssetId),\n );\n }\n\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null {\n return this.getAssetChain(asset, chain)?.chain.zippedAssetId ?? null;\n }\n\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number {\n return this.requireAssetChain(asset, chain).chain.zippedAssetId;\n }\n\n listContracts(): readonly ZipperChainContractConfig[] {\n return this.getSnapshot().zipper.contracts;\n }\n\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return this.getContractByName(contractName);\n }\n\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig {\n return this.requireContractByName(contractName);\n }\n\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null {\n return indexesFor(this.getSnapshot()).zipperContractByName.get(contractName) ?? null;\n }\n\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig {\n return requireFound(\n \"zipper\",\n \"contractName\",\n contractName,\n this.getContractByName(contractName),\n );\n }\n}\n\nfunction formatKey(key: { lookup: string; value: string | number }): string {\n return String(key.value);\n}\n\nclass SnapshotCatalogReader implements CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n readonly snapshot: () => CatalogSnapshot;\n\n constructor(getSnapshot: SnapshotGetter) {\n const market = new MarketReader(getSnapshot);\n this.market = market;\n this.ledger = new LedgerReader(market);\n this.orders = new OrdersReader(market);\n this.zipper = new ZipperReader(getSnapshot);\n this.snapshot = () => getSnapshot();\n }\n}\n\nexport function createReader(getSnapshot: () => CatalogSnapshot): CatalogReader {\n return new SnapshotCatalogReader(getSnapshot);\n}\n\nexport function createCatalogSnapshotReader(snapshot: CatalogSnapshot): CatalogReader {\n const parsed = parseCatalogSnapshot(snapshot);\n return createReader(() => parsed);\n}\n"],"mappings":";;;;;;AAoDA,SAAS,SAAS,MAA0B,OAAwB;CAChE,IAAI,KAAK,cAAc,QAAQ,KAAK,YAAY,OAAO,OAAO;CAC9D,IAAI,KAAK,WAAW,YAAY,OAAO;CACvC,IAAI,KAAK,gBAAgB,QAAQ,KAAK,cAAc,OAAO,OAAO;CAClE,OAAO;AACX;AAEA,SAAS,aAAa,MAA0B,OAAwB;CACpE,OAAO,KAAK,cAAc,QAAQ,KAAK,YAAY;AACvD;AAEA,SAAS,aACL,QACA,QACA,OACA,OACC;CACD,IAAI,UAAU,MAAM,MAAM,IAAI,mBAAmB,QAAQ,QAAQ,KAAK;CACtE,OAAO;AACX;AAMA,SAAS,eAAe,KAAwD;CAC5E,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAU,OAAO;CAAI;CACnE,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAY,OAAO;CAAI;CACrE,IAAI,YAAY,KAAK,OAAO;EAAE,QAAQ;EAAU,OAAO,IAAI;CAAO;CAClE,OAAO;EAAE,QAAQ;EAAY,OAAO,IAAI;CAAS;AACrD;AAEA,SAAS,gBAAgB,KAAyD;CAC9E,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAU,OAAO;CAAI;CACnE,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAY,OAAO;CAAI;CACrE,IAAI,YAAY,KAAK,OAAO;EAAE,QAAQ;EAAU,OAAO,IAAI;CAAO;CAClE,OAAO;EAAE,QAAQ;EAAY,OAAO,IAAI;CAAS;AACrD;AAEA,SAAS,gBAAgB,KAA2D;CAChF,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAa,OAAO;CAAI;CACtE,IAAI,OAAO,QAAQ,UAAU,OAAO;EAAE,QAAQ;EAAW,OAAO;CAAI;CACpE,IAAI,UAAU,KAAK,OAAO;EAAE,QAAQ;EAAa,OAAO,IAAI;CAAK;CACjE,OAAO;EAAE,QAAQ;EAAW,OAAO,IAAI;CAAQ;AACnD;AAEA,SAAS,yBACL,OACA,OACA,SACM;CACN,OAAO,QAAQ,WAAW,cACpB,GAAG,MAAM,oBAAoB,QAAQ,YAAY,mBAAmB,UACpE,GAAG,MAAM,0CAA0C;AAC7D;;AAGA,IAAM,mBAAN,MAAuB;CAEN;CACA;CACA;CAHb,YACI,OACA,OACA,iBACF;EAHW,KAAA,QAAA;EACA,KAAA,QAAA;EACA,KAAA,kBAAA;CACV;CAEH,MAAM,SAAsC;EACxC,MAAM,SAAS,mBAAmB,SAAS,KAAK,KAAK;EACrD,IAAI,CAAC,OAAO,IACR,MAAM,IAAI,uBACN,KAAK,OACL,yBAAyB,KAAK,OAAO,SAAS,OAAO,OAAO,CAChE;EAEJ,OAAO;GACH,aAAa,OAAO,OAAO,SAAS;GACpC,SAAS,gBAAgB,OAAO,QAAQ,KAAK,KAAK;GAClD,SAAS,gBAAgB,OAAO,QAAQ,KAAK,OAAO,KAAK,eAAe;GACxE,OAAO,KAAK;EAChB;CACJ;CAEA,eAAe,KAAqB;EAChC,MAAM,aAAa,yBAAyB,KAAK,KAAK,KAAK;EAC3D,IAAI,eAAe,MACf,MAAM,IAAI,uBACN,KAAK,OACL,GAAG,KAAK,MAAM,0CAA0C,KAC5D;EAEJ,OAAO;CACX;CAEA,gBAAgB,QAAmC;EAC/C,OAAO,gBAAgB,KAAK,SAAS,MAAM,GAAG,KAAK,KAAK;CAC5D;CAEA,gBAAgB,QAAmC;EAC/C,OAAO,gBAAgB,KAAK,SAAS,MAAM,GAAG,KAAK,OAAO,KAAK,eAAe;CAClF;CAEA,cAAc,SAAyB;EACnC,MAAM,SAAS,mBAAmB,QAAQ,KAAK,GAAG,KAAK,KAAK;EAC5D,IAAI,CAAC,OAAO,IACR,MAAM,IAAI,uBACN,KAAK,OACL,yBAAyB,KAAK,OAAO,SAAS,OAAO,OAAO,CAChE;EAEJ,OAAO,gBAAgB,OAAO,QAAQ,KAAK,OAAO,KAAK,eAAe;CAC1E;CAEA,SAAiB,QAAmC;EAChD,MAAM,QAAQ,kBAAkB,MAAM;EACtC,IAAI,UAAU,MACV,MAAM,IAAI,uBACN,KAAK,OACL,GAAG,KAAK,MAAM,iCAAiC,OAAO,MAAM,GAChE;EAEJ,OAAO;CACX;AACJ;AAEA,SAAS,eAAe,MAA4C;CAChE,MAAM,eAAe,yBAAyB,KAAK,QAAQ;CAE3D,OAAO,IAAI,iBAAiB,SAAA,GADJ,eAAe,IAAI,eAAA,CACsB;AACrE;AAEA,SAAS,kBAAkB,MAA4C;CACnE,OAAO,IAAI,iBACP,YACA,KAAK,UAAU,eACf,KAAK,UAAU,uBACnB;AACJ;AAEA,SAAS,qBAAqB,MAA4C;CACtE,OAAO,IAAI,iBACP,eACA,KAAK,WAAW,eAChB,KAAK,WAAW,uBACpB;AACJ;AAEA,SAAS,sBAAsB,OAAsC;CACjE,OAAO,IAAI,iBAAiB,UAAU,MAAM,eAAe,MAAM,uBAAuB;AAC5F;AAEA,IAAM,eAAN,MAAkD;CACjB;CAA7B,YAAY,aAA8C;EAA7B,KAAA,cAAA;CAA8B;CAE3D,aAAqC;EACjC,OAAO,KAAK,YAAY,CAAC,CAAC,OAAO;CACrC;CAEA,SAAS,OAA4C;EACjD,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,IAAI,WAAW,WAChB,KAAK,iBAAiB,IAAI,KAAK,IAC/B,KAAK,mBAAmB,IAAI,KAAK;CAC3C;CAEA,aAAa,OAAqC;EAC9C,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI,OAAO,KAAK,SAAS,KAAK,CAAC;CAC7E;CAEA,iBAAiB,aAAyC;EACtD,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,cAAc,IAAI,WAAW,KAAK;CAC5E;CAEA,qBAAqB,aAAkC;EACnD,OAAO,aAAa,UAAU,UAAU,aAAa,KAAK,iBAAiB,WAAW,CAAC;CAC3F;CAEA,mBAAmB,eAAoC;EACnD,OAAO,6BAA6B,gBAAgB,OAAO,KAAK,sBAAsB,EAAE,CAAC;CAC7F;CAEA,sBAAsB,eAA2C;EAC7D,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,gBAAgB,IAAI,aAAa,KAAK;CAChF;CAEA,uBAAuB,eAAoC;EACvD,OAAO,KAAK,mBAAmB,aAAa;CAChD;CAEA,UAAU,QAIwB;EAC9B,MAAM,QAAQ,KAAK,YAAY,CAAC,CAAC,OAAO;EACxC,IAAI,CAAC,QAAQ,OAAO;EACpB,MAAM,QAAQ,OAAO,QAAQ,KAAK,IAAI;EACtC,OAAO,MAAM,QAAQ,SAAS;GAC1B,IAAI,OAAO,WAAW,KAAA,KAAa,SAAS,MAAM,KAAK,MAAM,OAAO,QAChE,OAAO;GACX,IAAI,OAAO,eAAe,KAAA,KAAa,aAAa,MAAM,KAAK,MAAM,OAAO,YACxE,OAAO;GACX,OAAO;EACX,CAAC;CACL;CAEA,QAAQ,MAAiD;EACrD,MAAM,MAAM,eAAe,IAAI;EAC/B,OAAO,IAAI,WAAW,WAChB,KAAK,gBAAgB,IAAI,KAAK,IAC9B,KAAK,kBAAkB,IAAI,KAAK;CAC1C;CAEA,YAAY,MAA0C;EAClD,MAAM,MAAM,eAAe,IAAI;EAC/B,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI,OAAO,KAAK,QAAQ,IAAI,CAAC;CAC3E;CAEA,gBAAgB,YAA+C;EAC3D,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,aAAa,IAAI,UAAU,KAAK;CAC1E;CAEA,oBAAoB,YAAwC;EACxD,OAAO,aAAa,UAAU,UAAU,YAAY,KAAK,gBAAgB,UAAU,CAAC;CACxF;CAEA,kBAAkB,cAAiD;EAC/D,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,eAAe,IAAI,YAAY,KAAK;CAC9E;CAEA,sBAAsB,cAA0C;EAC5D,OAAO,aACH,UACA,YACA,cACA,KAAK,kBAAkB,YAAY,CACvC;CACJ;CAEA,wBAAwB,YAAmC;EACvD,OAAO,KAAK,gBAAgB,UAAU,CAAC,EAAE,YAAY;CACzD;CAEA,4BAA4B,YAA4B;EACpD,OAAO,KAAK,oBAAoB,UAAU,CAAC,CAAC;CAChD;CAEA,wBAAwB,cAAqC;EACzD,OAAO,KAAK,kBAAkB,YAAY,CAAC,EAAE,UAAU;CAC3D;CAEA,4BAA4B,cAA8B;EACtD,OAAO,KAAK,sBAAsB,YAAY,CAAC,CAAC;CACpD;CAEA,oBAAoB,OAAe,MAA2C;EAC1E,OAAO,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK;CAC7D;CAEA,oBAAoB,OAAe,MAA8B;EAC7D,OAAO,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,KAAK;CACtE;CAEA,0BAA0B,YAA+B,MAA8B;EACnF,OAAO,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,UAAU;CAC5E;CAEA,0BAA0B,YAA+B,MAA8B;EACnF,OAAO,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,UAAU;CAC5E;CAEA,YAAY,OAAe,MAA8B;EACrD,OAAO,eAAe,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,cAAc,KAAK;CACrE;CAEA,wBAAwB,UAAkB,MAA2C;EACjF,OAAO,kBAAkB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,MAAM,QAAQ;CACnE;CAEA,uBAAuB,UAAkB,MAA8B;EACnE,OAAO,kBAAkB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,QAAQ;CAC5E;CAEA,8BAA8B,gBAAmC,MAA8B;EAC3F,OAAO,kBAAkB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,cAAc;CACnF;CAEA,8BAA8B,gBAAmC,MAA8B;EAC3F,OAAO,kBAAkB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,cAAc;CACnF;CAEA,eAAe,UAAkB,MAA8B;EAC3D,OAAO,kBAAkB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,cAAc,QAAQ;CAC3E;CAEA,2BAA2B,QAAgB,MAA2C;EAClF,OAAO,qBAAqB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,MAAM,MAAM;CACpE;CAEA,0BAA0B,QAAgB,MAA8B;EACpE,OAAO,qBAAqB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,eAAe,MAAM;CAC7E;CAEA,iCACI,cACA,MACM;EACN,OAAO,qBAAqB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,YAAY;CACpF;CAEA,iCACI,cACA,MACM;EACN,OAAO,qBAAqB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,gBAAgB,YAAY;CACpF;CAEA,kBAAkB,QAAgB,MAA8B;EAC5D,OAAO,qBAAqB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,cAAc,MAAM;CAC5E;AACJ;AAEA,IAAM,eAAN,MAAkD;CACjB;CAA7B,YAAY,QAAuC;EAAtB,KAAA,SAAA;CAAuB;CAEpD,mBAAmB,eAAoC;EACnD,OAAO,KAAK,OAAO,mBAAmB,aAAa;CACvD;CAEA,uBAAuB,eAAoC;EACvD,OAAO,KAAK,mBAAmB,aAAa;CAChD;CAEA,iBAAiB,aAAyC;EACtD,OAAO,KAAK,OAAO,iBAAiB,WAAW;CACnD;CAEA,qBAAqB,aAAkC;EACnD,OAAO,aAAa,UAAU,UAAU,aAAa,KAAK,iBAAiB,WAAW,CAAC;CAC3F;CAEA,oBAAoB,aAAoC;EACpD,OAAO,KAAK,iBAAiB,WAAW,CAAC,EAAE,YAAY;CAC3D;CAEA,wBAAwB,aAA6B;EACjD,OAAO,KAAK,qBAAqB,WAAW,CAAC,CAAC;CAClD;CAEA,wBAAwB,eAA+B;EACnD,OAAO,KAAK,uBAAuB,aAAa,CAAC,CAAC;CACtD;CAEA,eAAe,eAAgC;EAC3C,IAAI,CAAC,OAAO,UAAU,aAAa,KAAK,iBAAiB,GAAG,OAAO;EACnE,IAAI,kBAAA,MAA2C,OAAO;EACtD,OAAO,KAAK,OAAO,sBAAsB,aAAa,MAAM;CAChE;CAEA,sBAAsB,QAAgB,OAA6C;EAC/E,OAAO,sBAAsB,KAAK,aAAa,KAAK,CAAC,CAAC,CAAC,MAAM,MAAM;CACvE;CAEA,qBAAqB,QAAgB,OAAgC;EACjE,OAAO,sBAAsB,KAAK,aAAa,KAAK,CAAC,CAAC,CAAC,eAAe,MAAM;CAChF;CAEA,4BAA4B,cAAiC,OAAgC;EACzF,OAAO,sBAAsB,KAAK,aAAa,KAAK,CAAC,CAAC,CAAC,gBAAgB,YAAY;CACvF;CAEA,4BAA4B,cAAiC,OAAgC;EACzF,OAAO,sBAAsB,KAAK,aAAa,KAAK,CAAC,CAAC,CAAC,gBAAgB,YAAY;CACvF;CAEA,aAAa,QAAgB,OAAgC;EACzD,OAAO,sBAAsB,KAAK,aAAa,KAAK,CAAC,CAAC,CAAC,cAAc,MAAM;CAC/E;CAEA,aAAqB,OAAqC;EACtD,MAAM,MAAM,gBAAgB,KAAK;EACjC,MAAM,QACF,IAAI,WAAW,WACT,KAAK,iBAAiB,IAAI,KAAK,IAC/B,KAAK,mBAAmB,IAAI,KAAK;EAC3C,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI,OAAO,KAAK;CAC9D;AACJ;AAEA,IAAM,eAAN,MAAkD;CACjB;CAA7B,YAAY,QAAuC;EAAtB,KAAA,SAAA;CAAuB;CAEpD,wBAAwB,MAA4C;EAChE,MAAM,SAAS,KAAK,OAAO,YAAY,IAAI;EAC3C,MAAM,aAAA;EACN,MAAM,gBAAgB,OAAO,UAAU;EACvC,MAAM,mBAAmB,OAAO,WAAW;EAC3C,OAAO;GACH,UAAU,OAAO;GACjB,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,UAAU,OAAO;GACjB,YAAY,OAAO;GACnB,kBAAkB,OAAO;GACzB,UAAU,gBAAgB,oBAAoB,UAAU;GACxD,YAAY,gBAAgB,oBAAoB,aAAa;GAC7D,kBAAkB,gBAAgB,oBAAoB,gBAAgB;GACtE,kBAAkB,gBAAgB,oBAAoB,UAAU;GAChE;GACA;GACA;GACA,sBAAsB,eAAe,MAAM,CAAC,CAAC;GAC7C,yBAAyB,OAAO,UAAU;GAC1C,4BAA4B,OAAO,WAAW;EAClD;CACJ;CAEA,8BAA8B,OAAuD;EACjF,MAAM,OAAO,KAAK,OAAO,YAAY,MAAM,IAAI;EAC/C,MAAM,SAAmC,CAAC;EAE1C,MAAM,iBAAiB,KAAK,iBAAiB,MAAM,MAAM,UAAU,MAAM;EACzE,MAAM,aACF,MAAM,UAAU,KAAA,IAAY,OAAO,KAAK,cAAc,MAAM,MAAM,OAAO,MAAM;EAEnF,IAAI,mBAAmB,QAAQ,eAAe,MAC1C,KAAK,oBAAoB,MAAM,gBAAgB,YAAY,MAAM;EAGrE,OAAO;GAAE,OAAO,OAAO,WAAW;GAAG;EAAO;CAChD;CAEA,4BAA4B,OAAoC;EAC5D,MAAM,SAAS,KAAK,8BAA8B,KAAK;EACvD,IAAI,CAAC,OAAO,OAAO,MAAM,IAAI,6BAA6B,OAAO,MAAM;CAC3E;CAEA,iBACI,MACA,UACA,QACa;EACb,MAAM,QAAQ,KAAK,UAAU;EAC7B,MAAM,SAAS,mBAAmB,UAAU,KAAK;EACjD,IAAI,CAAC,OAAO,IAAI;GACZ,OAAO,KAAK;IACR,OAAO;IACP,MAAM;IACN,SAAS,yBAAyB,YAAY,UAAU,OAAO,OAAO;IACtE,QAAQ;GACZ,CAAC;GACD,OAAO;EACX;EAEA,MAAM,OAAO,KAAK,wBAAwB,KAAK,UAAU,OAAO,UAAU;EAC1E,IAAI,OAAO,MAAM,OAAO,SAAS,SAAS,IACtC,OAAO,KAAK;GACR,OAAO;GACP,MAAM;GACN,SAAS,qDAAqD,KAAK;GACnE,UAAU,KAAK;GACf,QAAQ;EACZ,CAAC;EAGL,MAAM,SAAS,KAAK,wBAAwB,KAAK,YAAY,OAAO,YAAY;EAChF,IAAI,OAAO,SAAS,UAAU,OAAO,WAAW,IAC5C,OAAO,KAAK;GACR,OAAO;GACP,MAAM;GACN,SAAS,yCAAyC,KAAK;GACvD,UAAU,KAAK;GACf,QAAQ;EACZ,CAAC;EAGL,OAAO,OAAO;CAClB;CAEA,cACI,MACA,OACA,QACa;EACb,MAAM,SAAS,mBAAmB,OAAA,CAAkB;EACpD,IAAI,CAAC,OAAO,IAAI;GACZ,OAAO,KAAK;IACR,OAAO;IACP,MAAM;IACN,SAAS,yBAAyB,SAAS,OAAO,OAAO,OAAO;IAChE,QAAQ;GACZ,CAAC;GACD,OAAO;EACX;EAEA,MAAM,OAAO,KAAK,wBAAwB,KAAK,UAAA,GAAuB,UAAU;EAChF,IAAI,OAAO,MAAM,OAAO,SAAS,SAAS,IACtC,OAAO,KAAK;GACR,OAAO;GACP,MAAM;GACN,SAAS,kDAAkD,KAAK;GAChE,UAAU,KAAK;GACf,QAAQ;EACZ,CAAC;EAGL,OAAO,OAAO;CAClB;CAEA,oBACI,MACA,gBACA,YACA,QACI;EACJ,MAAM,gBAAgB,KAAK,UAAU,gBAAA;EACrC,MAAM,cAAc,KAAK,wBACrB,KAAK,kBACL,eACA,kBACJ;EACA,MAAM,WAAW,iBAAiB;EAClC,IAAI,WAAW,aACX,OAAO,KAAK;GACR,OAAO;GACP,MAAM;GACN,SAAS,+CAA+C,KAAK;GAC7D,UAAU,KAAK;GACf,QAAQ,gBAAgB,UAAU,aAAa;EACnD,CAAC;CAET;;CAGA,wBAAgC,SAAiB,OAAe,OAAuB;EACnF,MAAM,SAAS,mBAAmB,SAAS,KAAK;EAChD,IAAI,CAAC,OAAO,IACR,MAAM,IAAI,uBACN,OACA,yBAAyB,OAAO,SAAS,OAAO,OAAO,CAC3D;EAEJ,OAAO,OAAO;CAClB;AACJ;AAEA,IAAM,eAAN,MAAkD;CACjB;CAA7B,YAAY,aAA8C;EAA7B,KAAA,cAAA;CAA8B;CAE3D,aAA2C;EACvC,OAAO,KAAK,YAAY,CAAC,CAAC,OAAO;CACrC;CAEA,SAAS,OAAkD;EACvD,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,IAAI,WAAW,cAChB,KAAK,eAAe,IAAI,KAAK,IAC7B,KAAK,aAAa,IAAI,KAAK;CACrC;CAEA,aAAa,OAA2C;EACpD,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI,OAAO,KAAK,SAAS,KAAK,CAAC;CAC7E;CAEA,eAAe,WAA6C;EACxD,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,kBAAkB,IAAI,SAAS,KAAK;CAC9E;CAEA,mBAAmB,WAAsC;EACrD,OAAO,aAAa,UAAU,aAAa,WAAW,KAAK,eAAe,SAAS,CAAC;CACxF;CAEA,aAAa,SAA2C;EACpD,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,gBAAgB,IAAI,OAAO,KAAK;CAC1E;CAEA,iBAAiB,SAAoC;EACjD,OAAO,aAAa,UAAU,WAAW,SAAS,KAAK,aAAa,OAAO,CAAC;CAChF;CAEA,iBAAiB,WAAkC;EAC/C,OAAO,KAAK,eAAe,SAAS,CAAC,EAAE,WAAW;CACtD;CAEA,qBAAqB,WAA2B;EAC5C,OAAO,KAAK,mBAAmB,SAAS,CAAC,CAAC;CAC9C;CAEA,aAAmD;EAC/C,OAAO,KAAK,YAAY,CAAC,CAAC,OAAO;CACrC;CAEA,SAAS,OAA0D;EAC/D,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,IAAI,WAAW,WAChB,KAAK,iBAAiB,IAAI,KAAK,IAC/B,KAAK,mBAAmB,IAAI,KAAK;CAC3C;CAEA,aAAa,OAAmD;EAC5D,MAAM,MAAM,gBAAgB,KAAK;EACjC,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI,OAAO,KAAK,SAAS,KAAK,CAAC;CAC7E;CAEA,iBAAiB,aAAuD;EACpE,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,oBAAoB,IAAI,WAAW,KAAK;CAClF;CAEA,qBAAqB,aAAgD;EACjE,OAAO,aAAa,UAAU,UAAU,aAAa,KAAK,iBAAiB,WAAW,CAAC;CAC3F;CAEA,mBAAmB,eAAkD;EACjE,OAAO,6BAA6B,gBAAgB,OAAO,KAAK,sBAAsB,EAAE,CAAC;CAC7F;CAEA,sBAAsB,eAAyD;EAC3E,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,sBAAsB,IAAI,aAAa,KAAK;CACtF;CAEA,uBAAuB,eAAkD;EACrE,OAAO,KAAK,mBAAmB,aAAa;CAChD;CAEA,mBAAmB,UAAoD;EACnE,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,sBAAsB,IAAI,QAAQ,KAAK;CACjF;CAEA,uBAAuB,UAA6C;EAChE,OAAO,aAAa,UAAU,YAAY,UAAU,KAAK,mBAAmB,QAAQ,CAAC;CACzF;CAEA,cAAc,OAAwB,OAAsD;EACxF,MAAM,cAAc,KAAK,SAAS,KAAK;EACvC,MAAM,cAAc,KAAK,SAAS,KAAK;EACvC,IAAI,CAAC,eAAe,CAAC,aAAa,OAAO;EACzC,MAAM,QAAQ,YAAY,OAAO,MAC5B,cAAc,UAAU,YAAY,YAAY,OACrD;EACA,OAAO,QAAQ;GAAE,OAAO;GAAa,OAAO;EAAM,IAAI;CAC1D;CAEA,kBAAkB,OAAwB,OAA+C;EACrF,MAAM,QAAQ,KAAK,cAAc,OAAO,KAAK;EAC7C,IAAI,CAAC,OACD,MAAM,IAAI,mBACN,UACA,cACA,GAAG,UAAU,gBAAgB,KAAK,CAAC,EAAE,GAAG,UAAU,gBAAgB,KAAK,CAAC,GAC5E;EAEJ,OAAO;CACX;CAEA,6BAA6B,eAAqD;EAC9E,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,2BAA2B,IAAI,aAAa,KAAK;CAC3F;CAEA,iCAAiC,eAA8C;EAC3E,OAAO,aACH,UACA,iBACA,eACA,KAAK,6BAA6B,aAAa,CACnD;CACJ;CAEA,iBAAiB,OAAwB,OAAuC;EAC5E,OAAO,KAAK,cAAc,OAAO,KAAK,CAAC,EAAE,MAAM,iBAAiB;CACpE;CAEA,qBAAqB,OAAwB,OAAgC;EACzE,OAAO,KAAK,kBAAkB,OAAO,KAAK,CAAC,CAAC,MAAM;CACtD;CAEA,gBAAsD;EAClD,OAAO,KAAK,YAAY,CAAC,CAAC,OAAO;CACrC;CAEA,YAAY,cAAoE;EAC5E,OAAO,KAAK,kBAAkB,YAAY;CAC9C;CAEA,gBAAgB,cAA6D;EACzE,OAAO,KAAK,sBAAsB,YAAY;CAClD;CAEA,kBAAkB,cAAoE;EAClF,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,qBAAqB,IAAI,YAAY,KAAK;CACpF;CAEA,sBAAsB,cAA6D;EAC/E,OAAO,aACH,UACA,gBACA,cACA,KAAK,kBAAkB,YAAY,CACvC;CACJ;AACJ;AAEA,SAAS,UAAU,KAAyD;CACxE,OAAO,OAAO,IAAI,KAAK;AAC3B;AAEA,IAAM,wBAAN,MAAqD;CACjD;CACA;CACA;CACA;CACA;CAEA,YAAY,aAA6B;EACrC,MAAM,SAAS,IAAI,aAAa,WAAW;EAC3C,KAAK,SAAS;EACd,KAAK,SAAS,IAAI,aAAa,MAAM;EACrC,KAAK,SAAS,IAAI,aAAa,MAAM;EACrC,KAAK,SAAS,IAAI,aAAa,WAAW;EAC1C,KAAK,iBAAiB,YAAY;CACtC;AACJ;AAEA,SAAgB,aAAa,aAAmD;CAC5E,OAAO,IAAI,sBAAsB,WAAW;AAChD;AAEA,SAAgB,4BAA4B,UAA0C;CAClF,MAAM,SAAS,qBAAqB,QAAQ;CAC5C,OAAO,mBAAmB,MAAM;AACpC"}
|
package/dist/catalogs/types.d.ts
CHANGED
|
@@ -82,6 +82,14 @@ interface SpotOrderConstraints {
|
|
|
82
82
|
readonly stepSize: string;
|
|
83
83
|
readonly minQtyBase: string;
|
|
84
84
|
readonly minNotionalQuote: string;
|
|
85
|
+
/** Price wire-format ceiling. This is not an exchange trading limit. */
|
|
86
|
+
readonly maxPrice: string;
|
|
87
|
+
/** Base-quantity wire-format ceiling. This is not an exchange trading limit. */
|
|
88
|
+
readonly maxQtyBase: string;
|
|
89
|
+
/** Quote-amount wire-format ceiling. This is not an exchange trading limit. */
|
|
90
|
+
readonly maxNotionalQuote: string;
|
|
91
|
+
/** Quote-denominated slippage wire-format ceiling. This is not an exchange trading limit. */
|
|
92
|
+
readonly maxQuoteSlippage: string;
|
|
85
93
|
readonly priceScale: number;
|
|
86
94
|
readonly quantityScale: number;
|
|
87
95
|
readonly quoteAmountScale: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/catalogs/types.ts"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/catalogs/types.ts"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","names":[],"sources":["../../src/catalogs/types.ts"],"sourcesContent":["import type {\n AssetConfig,\n DepositWithdrawConfig,\n PairStatus,\n SpotConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport { RequestError, ValidationError } from \"../shared/errors.js\";\nimport type { EnrichedPairConfig, MarketCatalogData } from \"./market-data-catalog.js\";\nimport type {\n ZipperCatalogData,\n ZipperContractName,\n ZipperEnrichedAssetChain,\n ZipperEnrichedAssetConfig,\n} from \"./zipper-catalog.js\";\n\n/** Pair lookup key: symbol, symbolId, or an explicit object form. */\nexport type PairCatalogKey = string | number | { symbol: string } | { symbolId: number };\n/** Asset lookup key: symbol, ledger id, or an explicit object form. */\nexport type AssetCatalogKey = string | number | { symbol: string } | { ledgerId: number };\n/** Chain lookup key: chain code, chain id, or an explicit object form. */\nexport type ChainCatalogKey = string | number | { code: string } | { chainId: number };\n\n/** Raw scaled integer accepted on the SDK side of catalog conversions. */\nexport type ScaledIntegerLike = bigint | number | string;\n\nexport type CatalogLookupDomain = \"market\" | \"ledger\" | \"orders\" | \"zipper\";\nexport type CatalogSnapshotSource = \"api\" | \"snapshot\";\nexport type CatalogStateSource = CatalogSnapshotSource | \"empty\";\n\n/** A catalog lookup key (pair, asset, chain, …) did not match any entry. */\nexport class CatalogLookupError extends RequestError {\n override readonly code = \"CATALOG_LOOKUP_MISS\";\n\n constructor(\n readonly domain: CatalogLookupDomain,\n readonly lookup: string,\n readonly value: string | number,\n ) {\n super(`[catalog] ${domain} ${lookup} not found: ${String(value)}`);\n this.name = \"CatalogLookupError\";\n }\n}\n\n/** The catalog has no snapshot yet — call `catalog.ensureReady()` first. */\nexport class CatalogNotReadyError extends RequestError {\n override readonly code = \"CATALOG_NOT_READY\";\n\n constructor() {\n super(\"[catalog] no catalog snapshot has been loaded\");\n this.name = \"CatalogNotReadyError\";\n }\n}\n\n/** A decimal/scaled conversion failed (bad input or excess precision). */\nexport class CatalogConversionError extends ValidationError {\n override readonly code = \"CATALOG_CONVERSION_INVALID\";\n\n constructor(\n readonly field: string,\n message: string,\n ) {\n super(`[catalog] ${message}`);\n this.name = \"CatalogConversionError\";\n }\n}\n\n/** Order input failed validation against pair constraints. */\nexport class CatalogValidationFailedError extends ValidationError {\n override readonly code = \"CATALOG_VALIDATION_FAILED\";\n\n constructor(readonly errors: readonly CatalogValidationError[]) {\n super(\n `[catalog] order input validation failed: ${errors\n .map((error) => error.message)\n .join(\"; \")}`,\n );\n this.name = \"CatalogValidationFailedError\";\n }\n}\n\n/**\n * Result of a strict decimal-to-SDK conversion. `scaledValue` is the raw\n * JSON-safe integer string for service calls; `decimal` is the exact decimal\n * string; `display` is the display-normalized decimal string.\n */\nexport interface ParsedCatalogAmount {\n readonly scaledValue: string;\n readonly decimal: string;\n readonly display: string;\n readonly scale: number;\n}\n\nexport interface CatalogValidationError {\n readonly field: string;\n readonly rule: string;\n readonly message: string;\n readonly expected?: string;\n readonly actual?: string;\n}\n\nexport interface CatalogValidationResult {\n readonly valid: boolean;\n readonly errors: readonly CatalogValidationError[];\n}\n\n/** Trading constraints for a spot pair, for UI decisions and input validation. */\nexport interface SpotOrderConstraints {\n readonly symbolId: number;\n readonly symbol: string;\n readonly status: PairStatus;\n readonly tickSize: string;\n readonly stepSize: string;\n readonly minQtyBase: string;\n readonly minNotionalQuote: string;\n readonly priceScale: number;\n readonly quantityScale: number;\n readonly quoteAmountScale: number;\n readonly priceDisplayDecimals: number;\n readonly quantityDisplayDecimals: number;\n readonly quoteAmountDisplayDecimals: number;\n}\n\nexport interface SpotOrderDecimalInput {\n readonly pair: PairCatalogKey;\n readonly quantity: string;\n readonly price?: string;\n}\n\nexport interface ZipperAssetChainRoute {\n readonly asset: ZipperEnrichedAssetConfig;\n readonly chain: ZipperEnrichedAssetChain;\n}\n\nexport interface CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n snapshot(): CatalogSnapshot;\n}\n\nexport interface ClientCatalog extends CatalogReader {\n state(): CatalogState;\n /** Passive: resolves the current snapshot or in-flight refresh; never starts one. */\n ready(): Promise<CatalogSnapshot | null>;\n /** Resolves the current snapshot, starting a refresh when the catalog is empty. */\n ensureReady(): Promise<CatalogSnapshot>;\n refresh(): Promise<CatalogSnapshot>;\n setSnapshot(snapshot: CatalogSnapshot): void;\n}\n\nexport interface CatalogSnapshot {\n readonly source: CatalogSnapshotSource;\n readonly tsMs: number;\n readonly version: number;\n readonly market: MarketCatalogData;\n readonly zipper: ZipperCatalogData;\n}\n\nexport type CatalogState =\n | { status: \"empty\" }\n | { status: \"refreshing\"; previousSource: CatalogStateSource }\n | { status: \"fresh\"; source: CatalogSnapshotSource }\n | { status: \"stale\"; source: CatalogStateSource; error: unknown };\n\nexport interface CatalogRefreshSource {\n market(): Promise<SpotConfig>;\n zipper(): Promise<DepositWithdrawConfig>;\n}\n\n/**\n * External storage for the catalog's current snapshot. Injecting a cell lets the host\n * own where the snapshot lives (e.g. a reactive signal) while the catalog keeps owning\n * all logic — refresh, dedup, state, readers. Every reader lookup goes through\n * `get()`, so a host whose `get()` reads a reactive source makes every catalog read\n * reactive by construction.\n */\nexport interface CatalogSnapshotCell {\n get(): CatalogSnapshot | undefined;\n set(snapshot: CatalogSnapshot): void;\n}\n\nexport interface CreatePolyesterCatalogOptions {\n snapshot?: CatalogSnapshot;\n refresh?: false | CatalogRefreshSource;\n /** When provided, the catalog reads/writes its snapshot through this cell. */\n cell?: CatalogSnapshotCell;\n}\n\nexport interface MarketCatalogReader {\n listAssets(): readonly AssetConfig[];\n getAsset(asset: AssetCatalogKey): AssetConfig | null;\n requireAsset(asset: AssetCatalogKey): AssetConfig;\n getAssetBySymbol(assetSymbol: string): AssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): AssetConfig;\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[];\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null;\n requirePair(pair: PairCatalogKey): EnrichedPairConfig;\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null;\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig;\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null;\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig;\n getSymbolIdByPairSymbol(pairSymbol: string): number | null;\n requireSymbolIdByPairSymbol(pairSymbol: string): number;\n getPairSymbolBySymbolId(pairSymbolId: number): string | null;\n requirePairSymbolBySymbolId(pairSymbolId: number): string;\n\n /** Strictly converts a decimal price into raw price ticks. */\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw price input to the pair's price precision. */\n normalizePriceInput(price: string, pair: PairCatalogKey): string;\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string;\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal price string (grouping-free) for UI rendering. */\n formatPrice(price: string, pair: PairCatalogKey): string;\n\n /** Strictly converts a decimal base quantity into the pair's scaled quantity. */\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw quantity input to the base asset's quantity scale. */\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string;\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal base-quantity string for UI rendering. */\n formatQuantity(quantity: string, pair: PairCatalogKey): string;\n\n /** Strictly converts a decimal quote amount into the quote asset's scaled amount. */\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw quote amount input to the quote asset's quantity scale. */\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string;\n quoteAmountScaledToDecimalString(amountScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n quoteAmountScaledToDisplayString(amountScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal quote-amount string for UI rendering. */\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string;\n}\n\nexport interface LedgerCatalogReader {\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n getAssetBySymbol(assetSymbol: string): AssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): AssetConfig;\n getLedgerIdBySymbol(assetSymbol: string): number | null;\n requireLedgerIdBySymbol(assetSymbol: string): number;\n requireSymbolByLedgerId(ledgerAssetId: number): string;\n isKnownAssetId(ledgerAssetId: number): boolean;\n\n /** Strictly converts a decimal amount into the asset's scaled amount. */\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw amount input to the asset's quantity scale. */\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string;\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string;\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string;\n /** Display-rounds a decimal ledger-amount string for UI rendering. */\n formatAmount(amount: string, asset: AssetCatalogKey): string;\n}\n\nexport interface OrdersCatalogReader {\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints;\n /**\n * Validates decimal order input against pair constraints: parseability,\n * tick size, step size, min quantity, and min notional when a price is\n * present. Pair status is exposed via constraints, not enforced here.\n */\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult;\n /** Like {@link validateSpotOrderDecimalInput} but throws {@link CatalogValidationFailedError}. */\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void;\n}\n\nexport interface ZipperCatalogReader {\n listChains(): readonly ZipperChainConfig[];\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null;\n requireChain(chain: ChainCatalogKey): ZipperChainConfig;\n getChainByCode(chainCode: string): ZipperChainConfig | null;\n requireChainByCode(chainCode: string): ZipperChainConfig;\n getChainById(chainId: number): ZipperChainConfig | null;\n requireChainById(chainId: number): ZipperChainConfig;\n getChainIdByCode(chainCode: string): number | null;\n requireChainIdByCode(chainCode: string): number;\n\n listAssets(): readonly ZipperEnrichedAssetConfig[];\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null;\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig;\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig;\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig;\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null;\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig;\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null;\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute;\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null;\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute;\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null;\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number;\n\n listContracts(): readonly ZipperChainContractConfig[];\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null;\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig;\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null;\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig;\n}\n"],"mappings":";;;AAgCA,IAAa,qBAAb,cAAwC,aAAa;CAIpC;CACA;CACA;CALb,OAAyB;CAEzB,YACI,QACA,QACA,OACF;EACE,MAAM,aAAa,OAAO,GAAG,OAAO,cAAc,OAAO,KAAK,GAAG;EAJxD,KAAA,SAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EAGT,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,uBAAb,cAA0C,aAAa;CACnD,OAAyB;CAEzB,cAAc;EACV,MAAM,+CAA+C;EACrD,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,yBAAb,cAA4C,gBAAgB;CAI3C;CAHb,OAAyB;CAEzB,YACI,OACA,SACF;EACE,MAAM,aAAa,SAAS;EAHnB,KAAA,QAAA;EAIT,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,+BAAb,cAAkD,gBAAgB;CAGzC;CAFrB,OAAyB;CAEzB,YAAY,QAAoD;EAC5D,MACI,4CAA4C,OACvC,KAAK,UAAU,MAAM,OAAO,CAAC,CAC7B,KAAK,IAAI,GAClB;EALiB,KAAA,SAAA;EAMjB,KAAK,OAAO;CAChB;AACJ"}
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/catalogs/types.ts"],"sourcesContent":["import type {\n AssetConfig,\n DepositWithdrawConfig,\n PairStatus,\n SpotConfig,\n ZipperChainConfig,\n ZipperChainContractConfig,\n} from \"../shared/catalog-config.js\";\nimport { RequestError, ValidationError } from \"../shared/errors.js\";\nimport type { EnrichedPairConfig, MarketCatalogData } from \"./market-data-catalog.js\";\nimport type {\n ZipperCatalogData,\n ZipperContractName,\n ZipperEnrichedAssetChain,\n ZipperEnrichedAssetConfig,\n} from \"./zipper-catalog.js\";\n\n/** Pair lookup key: symbol, symbolId, or an explicit object form. */\nexport type PairCatalogKey = string | number | { symbol: string } | { symbolId: number };\n/** Asset lookup key: symbol, ledger id, or an explicit object form. */\nexport type AssetCatalogKey = string | number | { symbol: string } | { ledgerId: number };\n/** Chain lookup key: chain code, chain id, or an explicit object form. */\nexport type ChainCatalogKey = string | number | { code: string } | { chainId: number };\n\n/** Raw scaled integer accepted on the SDK side of catalog conversions. */\nexport type ScaledIntegerLike = bigint | number | string;\n\nexport type CatalogLookupDomain = \"market\" | \"ledger\" | \"orders\" | \"zipper\";\nexport type CatalogSnapshotSource = \"api\" | \"snapshot\";\nexport type CatalogStateSource = CatalogSnapshotSource | \"empty\";\n\n/** A catalog lookup key (pair, asset, chain, …) did not match any entry. */\nexport class CatalogLookupError extends RequestError {\n override readonly code = \"CATALOG_LOOKUP_MISS\";\n\n constructor(\n readonly domain: CatalogLookupDomain,\n readonly lookup: string,\n readonly value: string | number,\n ) {\n super(`[catalog] ${domain} ${lookup} not found: ${String(value)}`);\n this.name = \"CatalogLookupError\";\n }\n}\n\n/** The catalog has no snapshot yet — call `catalog.ensureReady()` first. */\nexport class CatalogNotReadyError extends RequestError {\n override readonly code = \"CATALOG_NOT_READY\";\n\n constructor() {\n super(\"[catalog] no catalog snapshot has been loaded\");\n this.name = \"CatalogNotReadyError\";\n }\n}\n\n/** A decimal/scaled conversion failed (bad input or excess precision). */\nexport class CatalogConversionError extends ValidationError {\n override readonly code = \"CATALOG_CONVERSION_INVALID\";\n\n constructor(\n readonly field: string,\n message: string,\n ) {\n super(`[catalog] ${message}`);\n this.name = \"CatalogConversionError\";\n }\n}\n\n/** Order input failed validation against pair constraints. */\nexport class CatalogValidationFailedError extends ValidationError {\n override readonly code = \"CATALOG_VALIDATION_FAILED\";\n\n constructor(readonly errors: readonly CatalogValidationError[]) {\n super(\n `[catalog] order input validation failed: ${errors\n .map((error) => error.message)\n .join(\"; \")}`,\n );\n this.name = \"CatalogValidationFailedError\";\n }\n}\n\n/**\n * Result of a strict decimal-to-SDK conversion. `scaledValue` is the raw\n * JSON-safe integer string for service calls; `decimal` is the exact decimal\n * string; `display` is the display-normalized decimal string.\n */\nexport interface ParsedCatalogAmount {\n readonly scaledValue: string;\n readonly decimal: string;\n readonly display: string;\n readonly scale: number;\n}\n\nexport interface CatalogValidationError {\n readonly field: string;\n readonly rule: string;\n readonly message: string;\n readonly expected?: string;\n readonly actual?: string;\n}\n\nexport interface CatalogValidationResult {\n readonly valid: boolean;\n readonly errors: readonly CatalogValidationError[];\n}\n\n/** Trading constraints for a spot pair, for UI decisions and input validation. */\nexport interface SpotOrderConstraints {\n readonly symbolId: number;\n readonly symbol: string;\n readonly status: PairStatus;\n readonly tickSize: string;\n readonly stepSize: string;\n readonly minQtyBase: string;\n readonly minNotionalQuote: string;\n /** Price wire-format ceiling. This is not an exchange trading limit. */\n readonly maxPrice: string;\n /** Base-quantity wire-format ceiling. This is not an exchange trading limit. */\n readonly maxQtyBase: string;\n /** Quote-amount wire-format ceiling. This is not an exchange trading limit. */\n readonly maxNotionalQuote: string;\n /** Quote-denominated slippage wire-format ceiling. This is not an exchange trading limit. */\n readonly maxQuoteSlippage: string;\n readonly priceScale: number;\n readonly quantityScale: number;\n readonly quoteAmountScale: number;\n readonly priceDisplayDecimals: number;\n readonly quantityDisplayDecimals: number;\n readonly quoteAmountDisplayDecimals: number;\n}\n\nexport interface SpotOrderDecimalInput {\n readonly pair: PairCatalogKey;\n readonly quantity: string;\n readonly price?: string;\n}\n\nexport interface ZipperAssetChainRoute {\n readonly asset: ZipperEnrichedAssetConfig;\n readonly chain: ZipperEnrichedAssetChain;\n}\n\nexport interface CatalogReader {\n readonly market: MarketCatalogReader;\n readonly ledger: LedgerCatalogReader;\n readonly orders: OrdersCatalogReader;\n readonly zipper: ZipperCatalogReader;\n snapshot(): CatalogSnapshot;\n}\n\nexport interface ClientCatalog extends CatalogReader {\n state(): CatalogState;\n /** Passive: resolves the current snapshot or in-flight refresh; never starts one. */\n ready(): Promise<CatalogSnapshot | null>;\n /** Resolves the current snapshot, starting a refresh when the catalog is empty. */\n ensureReady(): Promise<CatalogSnapshot>;\n refresh(): Promise<CatalogSnapshot>;\n setSnapshot(snapshot: CatalogSnapshot): void;\n}\n\nexport interface CatalogSnapshot {\n readonly source: CatalogSnapshotSource;\n readonly tsMs: number;\n readonly version: number;\n readonly market: MarketCatalogData;\n readonly zipper: ZipperCatalogData;\n}\n\nexport type CatalogState =\n | { status: \"empty\" }\n | { status: \"refreshing\"; previousSource: CatalogStateSource }\n | { status: \"fresh\"; source: CatalogSnapshotSource }\n | { status: \"stale\"; source: CatalogStateSource; error: unknown };\n\nexport interface CatalogRefreshSource {\n market(): Promise<SpotConfig>;\n zipper(): Promise<DepositWithdrawConfig>;\n}\n\n/**\n * External storage for the catalog's current snapshot. Injecting a cell lets the host\n * own where the snapshot lives (e.g. a reactive signal) while the catalog keeps owning\n * all logic — refresh, dedup, state, readers. Every reader lookup goes through\n * `get()`, so a host whose `get()` reads a reactive source makes every catalog read\n * reactive by construction.\n */\nexport interface CatalogSnapshotCell {\n get(): CatalogSnapshot | undefined;\n set(snapshot: CatalogSnapshot): void;\n}\n\nexport interface CreatePolyesterCatalogOptions {\n snapshot?: CatalogSnapshot;\n refresh?: false | CatalogRefreshSource;\n /** When provided, the catalog reads/writes its snapshot through this cell. */\n cell?: CatalogSnapshotCell;\n}\n\nexport interface MarketCatalogReader {\n listAssets(): readonly AssetConfig[];\n getAsset(asset: AssetCatalogKey): AssetConfig | null;\n requireAsset(asset: AssetCatalogKey): AssetConfig;\n getAssetBySymbol(assetSymbol: string): AssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): AssetConfig;\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n\n listPairs(filter?: {\n listed?: boolean;\n everListed?: boolean;\n atMs?: number;\n }): readonly EnrichedPairConfig[];\n getPair(pair: PairCatalogKey): EnrichedPairConfig | null;\n requirePair(pair: PairCatalogKey): EnrichedPairConfig;\n getPairBySymbol(pairSymbol: string): EnrichedPairConfig | null;\n requirePairBySymbol(pairSymbol: string): EnrichedPairConfig;\n getPairBySymbolId(pairSymbolId: number): EnrichedPairConfig | null;\n requirePairBySymbolId(pairSymbolId: number): EnrichedPairConfig;\n getSymbolIdByPairSymbol(pairSymbol: string): number | null;\n requireSymbolIdByPairSymbol(pairSymbol: string): number;\n getPairSymbolBySymbolId(pairSymbolId: number): string | null;\n requirePairSymbolBySymbolId(pairSymbolId: number): string;\n\n /** Strictly converts a decimal price into raw price ticks. */\n decimalPriceToTicks(price: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw price input to the pair's price precision. */\n normalizePriceInput(price: string, pair: PairCatalogKey): string;\n priceTicksToDecimalString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string;\n priceTicksToDisplayString(priceTicks: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal price string (grouping-free) for UI rendering. */\n formatPrice(price: string, pair: PairCatalogKey): string;\n\n /** Strictly converts a decimal base quantity into the pair's scaled quantity. */\n decimalQuantityToScaled(quantity: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw quantity input to the base asset's quantity scale. */\n normalizeQuantityInput(quantity: string, pair: PairCatalogKey): string;\n quantityScaledToDecimalString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n quantityScaledToDisplayString(quantityScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal base-quantity string for UI rendering. */\n formatQuantity(quantity: string, pair: PairCatalogKey): string;\n\n /** Strictly converts a decimal quote amount into the quote asset's scaled amount. */\n decimalQuoteAmountToScaled(amount: string, pair: PairCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw quote amount input to the quote asset's quantity scale. */\n normalizeQuoteAmountInput(amount: string, pair: PairCatalogKey): string;\n quoteAmountScaledToDecimalString(amountScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n quoteAmountScaledToDisplayString(amountScaled: ScaledIntegerLike, pair: PairCatalogKey): string;\n /** Display-rounds a decimal quote-amount string for UI rendering. */\n formatQuoteAmount(amount: string, pair: PairCatalogKey): string;\n}\n\nexport interface LedgerCatalogReader {\n getAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): AssetConfig;\n getAssetBySymbol(assetSymbol: string): AssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): AssetConfig;\n getLedgerIdBySymbol(assetSymbol: string): number | null;\n requireLedgerIdBySymbol(assetSymbol: string): number;\n requireSymbolByLedgerId(ledgerAssetId: number): string;\n isKnownAssetId(ledgerAssetId: number): boolean;\n\n /** Strictly converts a decimal amount into the asset's scaled amount. */\n decimalAmountToScaled(amount: string, asset: AssetCatalogKey): ParsedCatalogAmount;\n /** Truncates a raw amount input to the asset's quantity scale. */\n normalizeAmountInput(amount: string, asset: AssetCatalogKey): string;\n amountScaledToDecimalString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string;\n amountScaledToDisplayString(amountScaled: ScaledIntegerLike, asset: AssetCatalogKey): string;\n /** Display-rounds a decimal ledger-amount string for UI rendering. */\n formatAmount(amount: string, asset: AssetCatalogKey): string;\n}\n\nexport interface OrdersCatalogReader {\n getSpotOrderConstraints(pair: PairCatalogKey): SpotOrderConstraints;\n /**\n * Validates decimal order input against pair constraints: parseability,\n * tick size, step size, min quantity, and min notional when a price is\n * present. Pair status is exposed via constraints, not enforced here.\n */\n validateSpotOrderDecimalInput(input: SpotOrderDecimalInput): CatalogValidationResult;\n /** Like {@link validateSpotOrderDecimalInput} but throws {@link CatalogValidationFailedError}. */\n assertSpotOrderDecimalInput(input: SpotOrderDecimalInput): void;\n}\n\nexport interface ZipperCatalogReader {\n listChains(): readonly ZipperChainConfig[];\n getChain(chain: ChainCatalogKey): ZipperChainConfig | null;\n requireChain(chain: ChainCatalogKey): ZipperChainConfig;\n getChainByCode(chainCode: string): ZipperChainConfig | null;\n requireChainByCode(chainCode: string): ZipperChainConfig;\n getChainById(chainId: number): ZipperChainConfig | null;\n requireChainById(chainId: number): ZipperChainConfig;\n getChainIdByCode(chainCode: string): number | null;\n requireChainIdByCode(chainCode: string): number;\n\n listAssets(): readonly ZipperEnrichedAssetConfig[];\n getAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig | null;\n requireAsset(asset: AssetCatalogKey): ZipperEnrichedAssetConfig;\n getAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig | null;\n requireAssetBySymbol(assetSymbol: string): ZipperEnrichedAssetConfig;\n getAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig;\n requireAssetByLedgerId(ledgerAssetId: number): ZipperEnrichedAssetConfig;\n getAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig | null;\n requireAssetByUAssetId(uAssetId: string): ZipperEnrichedAssetConfig;\n\n getAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute | null;\n requireAssetChain(asset: AssetCatalogKey, chain: ChainCatalogKey): ZipperAssetChainRoute;\n getAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute | null;\n requireAssetChainByZippedAssetId(zippedAssetId: number): ZipperAssetChainRoute;\n getZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number | null;\n requireZippedAssetId(asset: AssetCatalogKey, chain: ChainCatalogKey): number;\n\n listContracts(): readonly ZipperChainContractConfig[];\n getContract(contractName: ZipperContractName): ZipperChainContractConfig | null;\n requireContract(contractName: ZipperContractName): ZipperChainContractConfig;\n getContractByName(contractName: ZipperContractName): ZipperChainContractConfig | null;\n requireContractByName(contractName: ZipperContractName): ZipperChainContractConfig;\n}\n"],"mappings":";;;AAgCA,IAAa,qBAAb,cAAwC,aAAa;CAIpC;CACA;CACA;CALb,OAAyB;CAEzB,YACI,QACA,QACA,OACF;EACE,MAAM,aAAa,OAAO,GAAG,OAAO,cAAc,OAAO,KAAK,GAAG;EAJxD,KAAA,SAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EAGT,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,uBAAb,cAA0C,aAAa;CACnD,OAAyB;CAEzB,cAAc;EACV,MAAM,+CAA+C;EACrD,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,yBAAb,cAA4C,gBAAgB;CAI3C;CAHb,OAAyB;CAEzB,YACI,OACA,SACF;EACE,MAAM,aAAa,SAAS;EAHnB,KAAA,QAAA;EAIT,KAAK,OAAO;CAChB;AACJ;;AAGA,IAAa,+BAAb,cAAkD,gBAAgB;CAGzC;CAFrB,OAAyB;CAEzB,YAAY,QAAoD;EAC5D,MACI,4CAA4C,OACvC,KAAK,UAAU,MAAM,OAAO,CAAC,CAC7B,KAAK,IAAI,GAClB;EALiB,KAAA,SAAA;EAMjB,KAAK,OAAO;CAChB;AACJ"}
|
|
@@ -14,7 +14,7 @@ type TimestampInit = {
|
|
|
14
14
|
declare const GetOrderbookHeatmapInputSchema: v.SchemaWithPipe<readonly [v.ObjectSchema<{
|
|
15
15
|
readonly symbolId: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.GtValueAction<number, 0, undefined>]>;
|
|
16
16
|
readonly interval: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly ["1s", "1m", "5m", "1h"], undefined>, "1s">, v.TransformAction<"1s" | "1m" | "5m" | "1h", HeatmapInterval>]>;
|
|
17
|
-
readonly depth: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly [1, 5, 10, 20, 50, 100, 200, 500, 1000], undefined>, 50>, v.TransformAction<5 | 10 | 20 | 1 | 200 | 500 | 100 | 50
|
|
17
|
+
readonly depth: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly [1, 5, 10, 20, 50, 100, 200, 500, 1000], undefined>, 50>, v.TransformAction<5 | 10 | 20 | 1 | 200 | 1000 | 500 | 100 | 50, HeatmapDepth>]>;
|
|
18
18
|
readonly quantityMode: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly ["close", "peak"], undefined>, "close">, v.TransformAction<"close" | "peak", HeatmapQuantityMode>]>;
|
|
19
19
|
readonly limit: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.GtValueAction<number, 0, undefined>, v.MaxValueAction<number, 20000, undefined>]>;
|
|
20
20
|
readonly startTsSec: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>, v.MaxValueAction<number, number, undefined>, v.TransformAction<number, bigint>]>, undefined>;
|
|
@@ -227,7 +227,7 @@ type OrderbookHeatmapDeltaChain = ReturnType<typeof convertHeatmapDeltaChain>;
|
|
|
227
227
|
declare function createOrderbookHeatmapResponseSchema(scales: SdkScales): v.SchemaWithPipe<readonly [v.ObjectSchema<{
|
|
228
228
|
readonly symbolId: v.NumberSchema<undefined>;
|
|
229
229
|
readonly interval: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.TransformAction<number, DecodedEnum<"1s" | "1m" | "5m" | "1h">>]>;
|
|
230
|
-
readonly depth: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.TransformAction<number, 5 | 10 | 20 | 1 | "unspecified" | 200 | 500 | 100 | 50
|
|
230
|
+
readonly depth: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.TransformAction<number, 5 | 10 | 20 | 1 | "unspecified" | 200 | 1000 | 500 | 100 | 50>]>;
|
|
231
231
|
readonly chain: v.OptionalSchema<v.ObjectSchema<{
|
|
232
232
|
readonly baseKeyframe: v.OptionalSchema<v.ObjectSchema<{
|
|
233
233
|
readonly tsSec: v.SchemaWithPipe<readonly [v.BigintSchema<undefined>, v.TransformAction<bigint, number>]>;
|
|
@@ -287,7 +287,7 @@ declare function createOrderbookHeatmapResponseSchema(scales: SdkScales): v.Sche
|
|
|
287
287
|
}, undefined>, v.TransformAction<{
|
|
288
288
|
symbolId: number;
|
|
289
289
|
interval: DecodedEnum<"1s" | "1m" | "5m" | "1h">;
|
|
290
|
-
depth: 5 | 10 | 20 | 1 | "unspecified" | 200 | 500 | 100 | 50
|
|
290
|
+
depth: 5 | 10 | 20 | 1 | "unspecified" | 200 | 1000 | 500 | 100 | 50;
|
|
291
291
|
chain?: {
|
|
292
292
|
baseKeyframe?: {
|
|
293
293
|
tsSec: number;
|
|
@@ -347,7 +347,7 @@ declare function createOrderbookHeatmapResponseSchema(scales: SdkScales): v.Sche
|
|
|
347
347
|
}, {
|
|
348
348
|
symbolId: number;
|
|
349
349
|
interval: DecodedEnum<"1s" | "1m" | "5m" | "1h">;
|
|
350
|
-
depth: 5 | 10 | 20 | 1 | "unspecified" | 200 | 500 | 100 | 50
|
|
350
|
+
depth: 5 | 10 | 20 | 1 | "unspecified" | 200 | 1000 | 500 | 100 | 50;
|
|
351
351
|
chain: {
|
|
352
352
|
baseKeyframe: {
|
|
353
353
|
tsSec: number;
|
|
@@ -11,7 +11,7 @@ declare const GetOrderbookInputSchema: v.SchemaWithPipe<readonly [v.ObjectSchema
|
|
|
11
11
|
depth: number;
|
|
12
12
|
}, {
|
|
13
13
|
symbol: string;
|
|
14
|
-
depth: 5 | 10 | 20 | 1 | 200 | 500 | 100 | 50
|
|
14
|
+
depth: 5 | 10 | 20 | 1 | 200 | 1000 | 500 | 100 | 50;
|
|
15
15
|
protoDepth: Depth;
|
|
16
16
|
}>]>;
|
|
17
17
|
type GetOrderbookInput = v.InferInput<typeof GetOrderbookInputSchema>;
|
|
@@ -40,7 +40,7 @@ type OpenOrdersInput = v.InferInput<typeof OpenOrdersInputSchema>;
|
|
|
40
40
|
declare const OrderHistoryInputSchema: v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
41
41
|
readonly includeAttachedRisk: v.OptionalSchema<v.BooleanSchema<undefined>, true>;
|
|
42
42
|
readonly includeAttachedRiskState: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
|
|
43
|
-
readonly status: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly ["FILLED", "CANCELED", "REJECTED"], undefined>, undefined>, v.TransformAction<"
|
|
43
|
+
readonly status: v.SchemaWithPipe<readonly [v.OptionalSchema<v.PicklistSchema<readonly ["FILLED", "CANCELED", "REJECTED"], undefined>, undefined>, v.TransformAction<"FILLED" | "CANCELED" | "REJECTED" | undefined, OrderStatus.FILLED | OrderStatus.CANCELED | OrderStatus.REJECTED | undefined>]>;
|
|
44
44
|
readonly startTsNs: v.SchemaWithPipe<readonly [v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction]>, undefined>, v.TransformAction<string | undefined, bigint | undefined>]>;
|
|
45
45
|
readonly endTsNs: v.SchemaWithPipe<readonly [v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction]>, undefined>, v.TransformAction<string | undefined, bigint | undefined>]>;
|
|
46
46
|
readonly symbolId: v.OptionalSchema<v.ArraySchema<v.NumberSchema<undefined>, undefined>, undefined>;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { parseOptionalPositiveIntLike } from "../utils/numbers.js";
|
|
2
2
|
import { CatalogConversionError } from "../catalogs/types.js";
|
|
3
|
+
import "../shared/wire-bounds.js";
|
|
3
4
|
import { positiveDecimalInputToScaled } from "../shared/decimal-surface.js";
|
|
4
5
|
//#region src/services/trailing-oneof-inputs.ts
|
|
5
|
-
/** Slippage ticks travel as int32 on the wire. */
|
|
6
|
-
const MAX_INT32_TICKS = 2147483647n;
|
|
7
6
|
function parseTrailingDistanceInput(scales, distance, fieldName) {
|
|
8
7
|
if (distance.kind === "none") return {
|
|
9
8
|
case: void 0,
|
|
@@ -27,7 +26,7 @@ function parseSlippageInput(scales, slippage, options) {
|
|
|
27
26
|
};
|
|
28
27
|
if (slippage.kind === "slippage") {
|
|
29
28
|
const ticks = positiveDecimalInputToScaled(`${options.fieldName}.slippage`, slippage.slippage, scales.price());
|
|
30
|
-
if (ticks >
|
|
29
|
+
if (ticks > 2147483647n) throw new CatalogConversionError(`${options.fieldName}.slippage`, `${options.fieldName}.slippage exceeds the maximum supported price distance: ${slippage.slippage}`);
|
|
31
30
|
return {
|
|
32
31
|
case: options.ticksCase,
|
|
33
32
|
value: Number(ticks)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trailing-oneof-inputs.js","names":[],"sources":["../../src/services/trailing-oneof-inputs.ts"],"sourcesContent":["import { positiveDecimalInputToScaled, type SdkScales } from \"../shared/decimal-surface.js\";\nimport { CatalogConversionError } from \"../catalogs/types.js\";\nimport { parseOptionalPositiveIntLike } from \"../utils/numbers.js\";\n\ntype PositiveIntLikeInput = string | number;\n\n/**\n * Trailing distance and slippage inputs: absolute price distances and\n * slippages are decimal price strings (e.g. \"0.50\"), converted to wire ticks\n * via the price scale; basis points are integers.\n */\nexport type TrailingDistanceInput =\n | { kind: \"distance\"; distance: string }\n | { kind: \"bps\"; bps: PositiveIntLikeInput }\n | { kind: \"none\" };\n\nexport type SlippageInput =\n | { kind: \"slippage\"; slippage: string }\n | { kind: \"bps\"; bps: PositiveIntLikeInput }\n | { kind: \"none\" };\n\ntype UnsetOneof = { case: undefined; value: undefined };\n\ntype TrailingDistanceOneof =\n | { case: \"trailingDistanceTicks\"; value: bigint }\n | { case: \"trailingDistanceBps\"; value: number }\n | UnsetOneof;\n\ntype SlippageOneof<TicksCase extends string, BpsCase extends string> =\n | { case: TicksCase; value: number }\n | { case: BpsCase; value: number }\n | UnsetOneof;\n\ntype SlippageOptions<TicksCase extends string, BpsCase extends string> = {\n fieldName: string;\n ticksCase: TicksCase;\n bpsCase: BpsCase;\n maxBps?: number;\n};\n\
|
|
1
|
+
{"version":3,"file":"trailing-oneof-inputs.js","names":[],"sources":["../../src/services/trailing-oneof-inputs.ts"],"sourcesContent":["import { positiveDecimalInputToScaled, type SdkScales } from \"../shared/decimal-surface.js\";\nimport { CatalogConversionError } from \"../catalogs/types.js\";\nimport { parseOptionalPositiveIntLike } from \"../utils/numbers.js\";\nimport { PROTOBUF_INT32_MAX } from \"../shared/wire-bounds.js\";\n\ntype PositiveIntLikeInput = string | number;\n\n/**\n * Trailing distance and slippage inputs: absolute price distances and\n * slippages are decimal price strings (e.g. \"0.50\"), converted to wire ticks\n * via the price scale; basis points are integers.\n */\nexport type TrailingDistanceInput =\n | { kind: \"distance\"; distance: string }\n | { kind: \"bps\"; bps: PositiveIntLikeInput }\n | { kind: \"none\" };\n\nexport type SlippageInput =\n | { kind: \"slippage\"; slippage: string }\n | { kind: \"bps\"; bps: PositiveIntLikeInput }\n | { kind: \"none\" };\n\ntype UnsetOneof = { case: undefined; value: undefined };\n\ntype TrailingDistanceOneof =\n | { case: \"trailingDistanceTicks\"; value: bigint }\n | { case: \"trailingDistanceBps\"; value: number }\n | UnsetOneof;\n\ntype SlippageOneof<TicksCase extends string, BpsCase extends string> =\n | { case: TicksCase; value: number }\n | { case: BpsCase; value: number }\n | UnsetOneof;\n\ntype SlippageOptions<TicksCase extends string, BpsCase extends string> = {\n fieldName: string;\n ticksCase: TicksCase;\n bpsCase: BpsCase;\n maxBps?: number;\n};\n\nexport function parseTrailingDistanceInput(\n scales: SdkScales,\n distance: TrailingDistanceInput,\n fieldName: string,\n): TrailingDistanceOneof {\n if (distance.kind === \"none\") {\n return { case: undefined, value: undefined };\n }\n if (distance.kind === \"distance\") {\n return {\n case: \"trailingDistanceTicks\",\n value: positiveDecimalInputToScaled(\n `${fieldName}.distance`,\n distance.distance,\n scales.price(),\n ),\n };\n }\n\n const bps = parseOptionalPositiveIntLike(distance.bps);\n if (bps === undefined || bps <= 0) {\n throw new Error(`${fieldName}Bps must be a positive integer`);\n }\n return { case: \"trailingDistanceBps\", value: bps };\n}\n\nexport function parseSlippageInput<const TicksCase extends string, const BpsCase extends string>(\n scales: SdkScales,\n slippage: SlippageInput | undefined,\n options: SlippageOptions<TicksCase, BpsCase>,\n): SlippageOneof<TicksCase, BpsCase> {\n if (!slippage || slippage.kind === \"none\") {\n return { case: undefined, value: undefined };\n }\n if (slippage.kind === \"slippage\") {\n const ticks = positiveDecimalInputToScaled(\n `${options.fieldName}.slippage`,\n slippage.slippage,\n scales.price(),\n );\n if (ticks > PROTOBUF_INT32_MAX) {\n throw new CatalogConversionError(\n `${options.fieldName}.slippage`,\n `${options.fieldName}.slippage exceeds the maximum supported price distance: ${slippage.slippage}`,\n );\n }\n return { case: options.ticksCase, value: Number(ticks) };\n }\n\n const bps = parseOptionalPositiveIntLike(slippage.bps);\n if (bps === undefined || bps <= 0 || exceedsMax(bps, options.maxBps)) {\n throw new Error(\n `${options.fieldName}Bps must be ${\n options.maxBps === undefined\n ? \"a positive integer\"\n : `between 1 and ${options.maxBps}`\n }`,\n );\n }\n return { case: options.bpsCase, value: bps };\n}\n\nfunction exceedsMax(value: number, max: number | undefined): boolean {\n return max !== undefined && value > max;\n}\n"],"mappings":";;;;;AAyCA,SAAgB,2BACZ,QACA,UACA,WACqB;CACrB,IAAI,SAAS,SAAS,QAClB,OAAO;EAAE,MAAM,KAAA;EAAW,OAAO,KAAA;CAAU;CAE/C,IAAI,SAAS,SAAS,YAClB,OAAO;EACH,MAAM;EACN,OAAO,6BACH,GAAG,UAAU,YACb,SAAS,UACT,OAAO,MAAM,CACjB;CACJ;CAGJ,MAAM,MAAM,6BAA6B,SAAS,GAAG;CACrD,IAAI,QAAQ,KAAA,KAAa,OAAO,GAC5B,MAAM,IAAI,MAAM,GAAG,UAAU,+BAA+B;CAEhE,OAAO;EAAE,MAAM;EAAuB,OAAO;CAAI;AACrD;AAEA,SAAgB,mBACZ,QACA,UACA,SACiC;CACjC,IAAI,CAAC,YAAY,SAAS,SAAS,QAC/B,OAAO;EAAE,MAAM,KAAA;EAAW,OAAO,KAAA;CAAU;CAE/C,IAAI,SAAS,SAAS,YAAY;EAC9B,MAAM,QAAQ,6BACV,GAAG,QAAQ,UAAU,YACrB,SAAS,UACT,OAAO,MAAM,CACjB;EACA,IAAI,QAAA,aACA,MAAM,IAAI,uBACN,GAAG,QAAQ,UAAU,YACrB,GAAG,QAAQ,UAAU,0DAA0D,SAAS,UAC5F;EAEJ,OAAO;GAAE,MAAM,QAAQ;GAAW,OAAO,OAAO,KAAK;EAAE;CAC3D;CAEA,MAAM,MAAM,6BAA6B,SAAS,GAAG;CACrD,IAAI,QAAQ,KAAA,KAAa,OAAO,KAAK,WAAW,KAAK,QAAQ,MAAM,GAC/D,MAAM,IAAI,MACN,GAAG,QAAQ,UAAU,cACjB,QAAQ,WAAW,KAAA,IACb,uBACA,iBAAiB,QAAQ,UAEvC;CAEJ,OAAO;EAAE,MAAM,QAAQ;EAAS,OAAO;CAAI;AAC/C;AAEA,SAAS,WAAW,OAAe,KAAkC;CACjE,OAAO,QAAQ,KAAA,KAAa,QAAQ;AACxC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-input.schemas.d.ts","names":[],"sources":["../../../src/services/triggers/trigger-input.schemas.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"trigger-input.schemas.d.ts","names":[],"sources":["../../../src/services/triggers/trigger-input.schemas.ts"],"mappings":";;;;;iBAyVgB,+BAA+B,QAAQ,YAAS,EAAA,aAAA,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAUpD,qBAAqB,EAAE,WAAW,kBAAkB;cAEnD,yBAAuB,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA+BxB,oBAAoB,EAAE,kBAAkB;cAEvC,0BAAwB,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;KACzB,qBAAqB,EAAE,kBAAkB;cAExC,uBAAqB,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;KACtB,kBAAkB,EAAE,kBAAkB;cAErC,yBAAuB,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;KACxB,oBAAoB,EAAE,kBAAkB;cAEvC,0BAAwB,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;KACzB,qBAAqB,EAAE,kBAAkB;iBAErC,+BAA+B,QAAQ,YAAS,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsDpD,qBAAqB,EAAE,WAAW,kBAAkB;cAEnD,8BAA4B,EAAA,yBAAA,EAAA;;;;;;;;;;;;;;;;;;;;;;;KAiB7B,yBAAyB,EAAE,kBAAkB"}
|
|
@@ -4,6 +4,7 @@ import { parseOptionalPositiveIntLike } from "../../utils/numbers.js";
|
|
|
4
4
|
import { idInputSchema } from "../../shared/schemas.js";
|
|
5
5
|
import { AccountScopeInputEntries, accountScopeToSubaccountId } from "../../shared/account-scope.js";
|
|
6
6
|
import { CatalogConversionError } from "../../catalogs/types.js";
|
|
7
|
+
import "../../shared/wire-bounds.js";
|
|
7
8
|
import { positiveDecimalInputToScaled } from "../../shared/decimal-surface.js";
|
|
8
9
|
import { BpsStringOrNumberInputSchema, NoneInputSchema } from "../shared.js";
|
|
9
10
|
import { OrderSideCodec } from "../orders/order-enums.codecs.js";
|
|
@@ -39,7 +40,6 @@ const MaxSlippageInputSchema = v.union([
|
|
|
39
40
|
BpsStringOrNumberInputSchema,
|
|
40
41
|
NoneInputSchema
|
|
41
42
|
]);
|
|
42
|
-
const MAX_INT32 = 2147483647n;
|
|
43
43
|
function parseTrailingDistance(scales, distance) {
|
|
44
44
|
if (distance.kind === "distance") return {
|
|
45
45
|
case: "trailingDistanceTicks",
|
|
@@ -59,7 +59,7 @@ function parseMaxSlippage(scales, slippage) {
|
|
|
59
59
|
};
|
|
60
60
|
if (slippage.kind === "slippage") {
|
|
61
61
|
const ticks = positiveDecimalInputToScaled("maxSlippage.slippage", slippage.slippage, scales.price());
|
|
62
|
-
if (ticks >
|
|
62
|
+
if (ticks > 2147483647n) throw new CatalogConversionError("maxSlippage.slippage", `maxSlippage.slippage exceeds the maximum supported price distance: ${slippage.slippage}`);
|
|
63
63
|
return {
|
|
64
64
|
case: "maxSlippageTicks",
|
|
65
65
|
value: Number(ticks)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger-input.schemas.js","names":["TriggerSideCodec"],"sources":["../../../src/services/triggers/trigger-input.schemas.ts"],"sourcesContent":["import * as Proto from \"../../gen/triggers/v1/triggers_pb.js\";\nimport * as ProtoOrders from \"../../gen/orders/v1/orders_pb.js\";\nimport * as v from \"valibot\";\nimport { idInputSchema } from \"../../shared/schemas.js\";\nimport {\n AccountScopeInputEntries,\n accountScopeToSubaccountId,\n} from \"../../shared/account-scope.js\";\nimport { positiveDecimalInputToScaled, type SdkScales } from \"../../shared/decimal-surface.js\";\nimport { CatalogConversionError } from \"../../catalogs/types.js\";\nimport { parseOptionalPositiveIntLike } from \"../../utils/numbers.js\";\nimport { idToBigInt } from \"../../utils/base58-id.js\";\nimport {\n TRIGGER_EVENT_TYPE_VALUES,\n TRIGGER_STATUS_FILTER_VALUES,\n TRIGGER_TYPE_VALUES,\n TriggerEventTypeCodec,\n TriggerSideCodec,\n TriggerTypeCodec,\n TriggerStatusCodec,\n} from \"./triggers.codecs.js\";\nimport { BpsStringOrNumberInputSchema, NoneInputSchema } from \"../shared.js\";\nimport {\n BaseTriggerFieldsSchema,\n ConditionalExecutionInputSchema,\n DecimalInputStringSchema,\n LimitConditionalExecutionInputSchema,\n TriggerSideInputSchema,\n TwapExecutionInputSchema,\n buildConditionalExecution,\n buildTriggerIntentBase,\n buildTwapExecution,\n type MaxSlippageOneof,\n type TrailingDistanceOneof,\n} from \"./trigger-child-order.schemas.js\";\n\nconst TriggerTypeSchema = v.picklist(TRIGGER_TYPE_VALUES);\nconst TriggerStatusFilterSchema = v.picklist(TRIGGER_STATUS_FILTER_VALUES);\nconst TriggerEventTypeSchema = v.picklist(TRIGGER_EVENT_TYPE_VALUES);\nconst TriggerIdInputSchema = idInputSchema(\"triggerId\");\n\nconst TriggerScopedInputEntries = {\n triggerId: TriggerIdInputSchema,\n ...AccountScopeInputEntries,\n};\n\nconst TriggerScopedInputSchema = v.pipe(\n v.strictObject(TriggerScopedInputEntries),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n })),\n);\n\n/** Absolute price distance, as a decimal price string (e.g. \"0.50\"). */\nconst PriceDistanceInputSchema = v.strictObject({\n kind: v.literal(\"distance\"),\n distance: DecimalInputStringSchema,\n});\n\n/** Absolute price slippage, as a decimal price string (e.g. \"0.25\"). */\nconst PriceSlippageInputSchema = v.strictObject({\n kind: v.literal(\"slippage\"),\n slippage: DecimalInputStringSchema,\n});\n\nconst TrailingDistanceInputSchema = v.union([\n PriceDistanceInputSchema,\n BpsStringOrNumberInputSchema,\n]);\n\nconst MaxSlippageInputSchema = v.union([\n PriceSlippageInputSchema,\n BpsStringOrNumberInputSchema,\n NoneInputSchema,\n]);\n\nconst MAX_INT32 = 2_147_483_647n;\n\nfunction parseTrailingDistance(\n scales: SdkScales,\n distance: v.InferOutput<typeof TrailingDistanceInputSchema>,\n): TrailingDistanceOneof {\n if (distance.kind === \"distance\") {\n return {\n case: \"trailingDistanceTicks\",\n value: positiveDecimalInputToScaled(\n \"trailingDistance.distance\",\n distance.distance,\n scales.price(),\n ),\n };\n }\n const bps = parseOptionalPositiveIntLike(distance.bps);\n if (bps === undefined || bps <= 0) {\n throw new Error(\"trailingDistanceBps must be a positive integer\");\n }\n return { case: \"trailingDistanceBps\", value: bps };\n}\n\nfunction parseMaxSlippage(\n scales: SdkScales,\n slippage: v.InferOutput<typeof MaxSlippageInputSchema> | undefined,\n): MaxSlippageOneof {\n if (!slippage || slippage.kind === \"none\") {\n return { case: undefined, value: undefined };\n }\n if (slippage.kind === \"slippage\") {\n const ticks = positiveDecimalInputToScaled(\n \"maxSlippage.slippage\",\n slippage.slippage,\n scales.price(),\n );\n if (ticks > MAX_INT32) {\n throw new CatalogConversionError(\n \"maxSlippage.slippage\",\n `maxSlippage.slippage exceeds the maximum supported price distance: ${slippage.slippage}`,\n );\n }\n return { case: \"maxSlippageTicks\", value: Number(ticks) };\n }\n const bps = parseOptionalPositiveIntLike(slippage.bps);\n if (bps === undefined || bps <= 0) {\n throw new Error(\"maxSlippageBps must be a positive integer\");\n }\n return { case: \"maxSlippageBps\", value: bps };\n}\n\nfunction createConditionalTriggerInputSchema<const TriggerType extends \"stop_loss\" | \"take_profit\">(\n scales: SdkScales,\n triggerType: TriggerType,\n) {\n const sharedEntries = {\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(triggerType),\n triggerPrice: DecimalInputStringSchema,\n };\n\n const sellInputSchema = v.strictObject({\n ...sharedEntries,\n side: v.literal(\"sell\"),\n execution: ConditionalExecutionInputSchema,\n });\n const buyInputSchema = v.strictObject({\n ...sharedEntries,\n side: v.literal(\"buy\"),\n execution: LimitConditionalExecutionInputSchema,\n });\n\n function transformInput(\n input: v.InferOutput<typeof sellInputSchema> | v.InferOutput<typeof buyInputSchema>,\n ) {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n const strategy = {\n triggerPriceTicks: positiveDecimalInputToScaled(\n \"triggerPrice\",\n input.triggerPrice,\n scales.price(),\n ),\n side: TriggerSideCodec.inputToProto[input.side],\n child: buildConditionalExecution(input.execution, scales),\n };\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy:\n triggerType === \"stop_loss\"\n ? ({ case: \"stopLoss\", value: strategy } as const)\n : ({ case: \"takeProfit\", value: strategy } as const),\n },\n };\n }\n\n return [\n v.pipe(\n sellInputSchema,\n v.check(\n (input) => input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.transform((input: v.InferOutput<typeof sellInputSchema>) => transformInput(input)),\n ),\n v.pipe(\n buyInputSchema,\n v.transform((input: v.InferOutput<typeof buyInputSchema>) => transformInput(input)),\n ),\n ] as const;\n}\n\nfunction createTrailingStopTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"trailing_stop\"),\n trailingDistance: TrailingDistanceInputSchema,\n activationPrice: v.optional(DecimalInputStringSchema),\n maxSlippage: v.optional(MaxSlippageInputSchema),\n }),\n v.check(\n (input) => input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"Trailing-stop triggers must use the quote fee asset\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"trailingStop\",\n value: {\n trailingDistance: parseTrailingDistance(scales, input.trailingDistance),\n activationPriceTicks:\n input.activationPrice === undefined\n ? 0n\n : positiveDecimalInputToScaled(\n \"activationPrice\",\n input.activationPrice,\n scales.price(),\n ),\n maxSlippage: parseMaxSlippage(scales, input.maxSlippage),\n side: ProtoOrders.Side.SELL,\n },\n } as const,\n },\n };\n }),\n );\n}\n\nfunction createTwapTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"twap\"),\n side: TriggerSideInputSchema,\n durationMs: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.number()]),\n v.transform((value) => {\n const durationMs = parseOptionalPositiveIntLike(value);\n if (!durationMs || durationMs < 1000) {\n throw new Error(\"durationMs must be at least 1000ms\");\n }\n return BigInt(durationMs);\n }),\n ),\n sliceIntervalMs: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.number()]),\n v.transform((value) => {\n const sliceIntervalMs = parseOptionalPositiveIntLike(value);\n if (!sliceIntervalMs || sliceIntervalMs < 100) {\n throw new Error(\"sliceIntervalMs must be at least 100ms\");\n }\n return BigInt(sliceIntervalMs);\n }),\n ),\n execution: TwapExecutionInputSchema,\n }),\n v.check(\n (input) =>\n input.side !== ProtoOrders.Side.SELL ||\n input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.check(\n (input) => input.sliceIntervalMs <= input.durationMs,\n \"sliceIntervalMs cannot exceed durationMs\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"twap\",\n value: {\n side: input.side,\n durationMs: input.durationMs,\n sliceIntervalMs: input.sliceIntervalMs,\n execution: buildTwapExecution(input.execution, scales),\n },\n } as const,\n },\n };\n }),\n );\n}\n\nfunction createLadderTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"ladder\"),\n side: TriggerSideInputSchema,\n priceMin: DecimalInputStringSchema,\n priceMax: DecimalInputStringSchema,\n levels: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.pipe(v.number(), v.integer())]),\n v.transform((value) => {\n const levels = parseOptionalPositiveIntLike(value);\n if (!levels || levels < 2 || levels > 100) {\n throw new Error(\"levels must be between 2 and 100\");\n }\n return levels;\n }),\n ),\n postOnly: v.optional(v.boolean(), false),\n }),\n v.check(\n (input) =>\n input.side !== ProtoOrders.Side.SELL ||\n input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"ladder\",\n value: {\n side: input.side,\n priceMinTicks: positiveDecimalInputToScaled(\n \"priceMin\",\n input.priceMin,\n scales.price(),\n ),\n priceMaxTicks: positiveDecimalInputToScaled(\n \"priceMax\",\n input.priceMax,\n scales.price(),\n ),\n levels: input.levels,\n postOnly: input.postOnly,\n },\n } as const,\n },\n };\n }),\n );\n}\n\nexport function createCreateTriggerInputSchema(scales: SdkScales) {\n return v.union([\n ...createConditionalTriggerInputSchema(scales, \"stop_loss\"),\n ...createConditionalTriggerInputSchema(scales, \"take_profit\"),\n createTrailingStopTriggerInputSchema(scales),\n createTwapTriggerInputSchema(scales),\n createLadderTriggerInputSchema(scales),\n ]);\n}\n\nexport type CreateTriggerInput = v.InferInput<ReturnType<typeof createCreateTriggerInputSchema>>;\n\nexport const ListTriggersInputSchema = v.pipe(\n v.strictObject({\n ...AccountScopeInputEntries,\n parentOrderId: v.pipe(\n v.optional(v.pipe(v.string(), v.trim())),\n v.transform((value) => (value ? idToBigInt(value, \"parentOrderId\") : undefined)),\n ),\n symbol: v.optional(v.pipe(v.string(), v.trim())),\n status: v.pipe(\n v.optional(v.array(TriggerStatusFilterSchema)),\n v.transform(\n (values) => values?.map((value) => TriggerStatusCodec.inputToProto[value]) ?? [],\n ),\n ),\n triggerType: v.pipe(\n v.optional(TriggerTypeSchema),\n v.transform((value) =>\n value\n ? TriggerTypeCodec.inputToProto[value]\n : Proto.TriggerType.TRIGGER_TYPE_UNSPECIFIED,\n ),\n ),\n limit: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0), v.maxValue(1000)), 50),\n pageToken: v.optional(v.pipe(v.string(), v.trim()), \"\"),\n }),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n })),\n);\n\nexport type ListTriggersInput = v.InferInput<typeof ListTriggersInputSchema>;\n\nexport const CancelTriggerInputSchema = TriggerScopedInputSchema;\nexport type CancelTriggerInput = v.InferInput<typeof CancelTriggerInputSchema>;\n\nexport const GetTriggerInputSchema = CancelTriggerInputSchema;\nexport type GetTriggerInput = v.InferInput<typeof GetTriggerInputSchema>;\n\nexport const PauseTriggerInputSchema = TriggerScopedInputSchema;\nexport type PauseTriggerInput = v.InferInput<typeof PauseTriggerInputSchema>;\n\nexport const ResumeTriggerInputSchema = TriggerScopedInputSchema;\nexport type ResumeTriggerInput = v.InferInput<typeof ResumeTriggerInputSchema>;\n\nexport function createModifyTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...TriggerScopedInputEntries,\n triggerPrice: v.optional(DecimalInputStringSchema),\n limitPrice: v.optional(DecimalInputStringSchema),\n trailingDistance: v.optional(TrailingDistanceInputSchema),\n activationPrice: v.optional(DecimalInputStringSchema),\n maxSlippage: v.optional(MaxSlippageInputSchema),\n }),\n v.check(\n (input) =>\n input.triggerPrice !== undefined ||\n input.limitPrice !== undefined ||\n input.trailingDistance !== undefined ||\n input.activationPrice !== undefined ||\n input.maxSlippage !== undefined,\n \"At least one patch field is required\",\n ),\n v.transform(({ account, ...input }) => ({\n triggerId: input.triggerId,\n subaccountId: accountScopeToSubaccountId(account),\n triggerPriceTicks:\n input.triggerPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\n \"triggerPrice\",\n input.triggerPrice,\n scales.price(),\n ),\n limitPriceTicks:\n input.limitPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\"limitPrice\", input.limitPrice, scales.price()),\n trailingDistance:\n input.trailingDistance === undefined\n ? ({ case: undefined, value: undefined } as const)\n : parseTrailingDistance(scales, input.trailingDistance),\n activationPriceTicks:\n input.activationPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\n \"activationPrice\",\n input.activationPrice,\n scales.price(),\n ),\n maxSlippage:\n input.maxSlippage === undefined\n ? ({ case: undefined, value: undefined } as const)\n : parseMaxSlippage(scales, input.maxSlippage),\n })),\n );\n}\n\nexport type ModifyTriggerInput = v.InferInput<ReturnType<typeof createModifyTriggerInputSchema>>;\n\nexport const ListTriggerEventsInputSchema = v.pipe(\n v.strictObject({\n ...TriggerScopedInputEntries,\n limit: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0), v.maxValue(1000))),\n eventType: v.optional(TriggerEventTypeSchema),\n pageToken: v.optional(v.pipe(v.string(), v.trim()), \"\"),\n }),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n eventType:\n input.eventType === undefined\n ? undefined\n : TriggerEventTypeCodec.inputToProto[input.eventType],\n })),\n);\n\nexport type ListTriggerEventsInput = v.InferInput<typeof ListTriggerEventsInputSchema>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"trigger-input.schemas.js","names":["TriggerSideCodec"],"sources":["../../../src/services/triggers/trigger-input.schemas.ts"],"sourcesContent":["import * as Proto from \"../../gen/triggers/v1/triggers_pb.js\";\nimport * as ProtoOrders from \"../../gen/orders/v1/orders_pb.js\";\nimport * as v from \"valibot\";\nimport { idInputSchema } from \"../../shared/schemas.js\";\nimport {\n AccountScopeInputEntries,\n accountScopeToSubaccountId,\n} from \"../../shared/account-scope.js\";\nimport { positiveDecimalInputToScaled, type SdkScales } from \"../../shared/decimal-surface.js\";\nimport { CatalogConversionError } from \"../../catalogs/types.js\";\nimport { PROTOBUF_INT32_MAX } from \"../../shared/wire-bounds.js\";\nimport { parseOptionalPositiveIntLike } from \"../../utils/numbers.js\";\nimport { idToBigInt } from \"../../utils/base58-id.js\";\nimport {\n TRIGGER_EVENT_TYPE_VALUES,\n TRIGGER_STATUS_FILTER_VALUES,\n TRIGGER_TYPE_VALUES,\n TriggerEventTypeCodec,\n TriggerSideCodec,\n TriggerTypeCodec,\n TriggerStatusCodec,\n} from \"./triggers.codecs.js\";\nimport { BpsStringOrNumberInputSchema, NoneInputSchema } from \"../shared.js\";\nimport {\n BaseTriggerFieldsSchema,\n ConditionalExecutionInputSchema,\n DecimalInputStringSchema,\n LimitConditionalExecutionInputSchema,\n TriggerSideInputSchema,\n TwapExecutionInputSchema,\n buildConditionalExecution,\n buildTriggerIntentBase,\n buildTwapExecution,\n type MaxSlippageOneof,\n type TrailingDistanceOneof,\n} from \"./trigger-child-order.schemas.js\";\n\nconst TriggerTypeSchema = v.picklist(TRIGGER_TYPE_VALUES);\nconst TriggerStatusFilterSchema = v.picklist(TRIGGER_STATUS_FILTER_VALUES);\nconst TriggerEventTypeSchema = v.picklist(TRIGGER_EVENT_TYPE_VALUES);\nconst TriggerIdInputSchema = idInputSchema(\"triggerId\");\n\nconst TriggerScopedInputEntries = {\n triggerId: TriggerIdInputSchema,\n ...AccountScopeInputEntries,\n};\n\nconst TriggerScopedInputSchema = v.pipe(\n v.strictObject(TriggerScopedInputEntries),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n })),\n);\n\n/** Absolute price distance, as a decimal price string (e.g. \"0.50\"). */\nconst PriceDistanceInputSchema = v.strictObject({\n kind: v.literal(\"distance\"),\n distance: DecimalInputStringSchema,\n});\n\n/** Absolute price slippage, as a decimal price string (e.g. \"0.25\"). */\nconst PriceSlippageInputSchema = v.strictObject({\n kind: v.literal(\"slippage\"),\n slippage: DecimalInputStringSchema,\n});\n\nconst TrailingDistanceInputSchema = v.union([\n PriceDistanceInputSchema,\n BpsStringOrNumberInputSchema,\n]);\n\nconst MaxSlippageInputSchema = v.union([\n PriceSlippageInputSchema,\n BpsStringOrNumberInputSchema,\n NoneInputSchema,\n]);\n\nfunction parseTrailingDistance(\n scales: SdkScales,\n distance: v.InferOutput<typeof TrailingDistanceInputSchema>,\n): TrailingDistanceOneof {\n if (distance.kind === \"distance\") {\n return {\n case: \"trailingDistanceTicks\",\n value: positiveDecimalInputToScaled(\n \"trailingDistance.distance\",\n distance.distance,\n scales.price(),\n ),\n };\n }\n const bps = parseOptionalPositiveIntLike(distance.bps);\n if (bps === undefined || bps <= 0) {\n throw new Error(\"trailingDistanceBps must be a positive integer\");\n }\n return { case: \"trailingDistanceBps\", value: bps };\n}\n\nfunction parseMaxSlippage(\n scales: SdkScales,\n slippage: v.InferOutput<typeof MaxSlippageInputSchema> | undefined,\n): MaxSlippageOneof {\n if (!slippage || slippage.kind === \"none\") {\n return { case: undefined, value: undefined };\n }\n if (slippage.kind === \"slippage\") {\n const ticks = positiveDecimalInputToScaled(\n \"maxSlippage.slippage\",\n slippage.slippage,\n scales.price(),\n );\n if (ticks > PROTOBUF_INT32_MAX) {\n throw new CatalogConversionError(\n \"maxSlippage.slippage\",\n `maxSlippage.slippage exceeds the maximum supported price distance: ${slippage.slippage}`,\n );\n }\n return { case: \"maxSlippageTicks\", value: Number(ticks) };\n }\n const bps = parseOptionalPositiveIntLike(slippage.bps);\n if (bps === undefined || bps <= 0) {\n throw new Error(\"maxSlippageBps must be a positive integer\");\n }\n return { case: \"maxSlippageBps\", value: bps };\n}\n\nfunction createConditionalTriggerInputSchema<const TriggerType extends \"stop_loss\" | \"take_profit\">(\n scales: SdkScales,\n triggerType: TriggerType,\n) {\n const sharedEntries = {\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(triggerType),\n triggerPrice: DecimalInputStringSchema,\n };\n\n const sellInputSchema = v.strictObject({\n ...sharedEntries,\n side: v.literal(\"sell\"),\n execution: ConditionalExecutionInputSchema,\n });\n const buyInputSchema = v.strictObject({\n ...sharedEntries,\n side: v.literal(\"buy\"),\n execution: LimitConditionalExecutionInputSchema,\n });\n\n function transformInput(\n input: v.InferOutput<typeof sellInputSchema> | v.InferOutput<typeof buyInputSchema>,\n ) {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n const strategy = {\n triggerPriceTicks: positiveDecimalInputToScaled(\n \"triggerPrice\",\n input.triggerPrice,\n scales.price(),\n ),\n side: TriggerSideCodec.inputToProto[input.side],\n child: buildConditionalExecution(input.execution, scales),\n };\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy:\n triggerType === \"stop_loss\"\n ? ({ case: \"stopLoss\", value: strategy } as const)\n : ({ case: \"takeProfit\", value: strategy } as const),\n },\n };\n }\n\n return [\n v.pipe(\n sellInputSchema,\n v.check(\n (input) => input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.transform((input: v.InferOutput<typeof sellInputSchema>) => transformInput(input)),\n ),\n v.pipe(\n buyInputSchema,\n v.transform((input: v.InferOutput<typeof buyInputSchema>) => transformInput(input)),\n ),\n ] as const;\n}\n\nfunction createTrailingStopTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"trailing_stop\"),\n trailingDistance: TrailingDistanceInputSchema,\n activationPrice: v.optional(DecimalInputStringSchema),\n maxSlippage: v.optional(MaxSlippageInputSchema),\n }),\n v.check(\n (input) => input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"Trailing-stop triggers must use the quote fee asset\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"trailingStop\",\n value: {\n trailingDistance: parseTrailingDistance(scales, input.trailingDistance),\n activationPriceTicks:\n input.activationPrice === undefined\n ? 0n\n : positiveDecimalInputToScaled(\n \"activationPrice\",\n input.activationPrice,\n scales.price(),\n ),\n maxSlippage: parseMaxSlippage(scales, input.maxSlippage),\n side: ProtoOrders.Side.SELL,\n },\n } as const,\n },\n };\n }),\n );\n}\n\nfunction createTwapTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"twap\"),\n side: TriggerSideInputSchema,\n durationMs: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.number()]),\n v.transform((value) => {\n const durationMs = parseOptionalPositiveIntLike(value);\n if (!durationMs || durationMs < 1000) {\n throw new Error(\"durationMs must be at least 1000ms\");\n }\n return BigInt(durationMs);\n }),\n ),\n sliceIntervalMs: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.number()]),\n v.transform((value) => {\n const sliceIntervalMs = parseOptionalPositiveIntLike(value);\n if (!sliceIntervalMs || sliceIntervalMs < 100) {\n throw new Error(\"sliceIntervalMs must be at least 100ms\");\n }\n return BigInt(sliceIntervalMs);\n }),\n ),\n execution: TwapExecutionInputSchema,\n }),\n v.check(\n (input) =>\n input.side !== ProtoOrders.Side.SELL ||\n input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.check(\n (input) => input.sliceIntervalMs <= input.durationMs,\n \"sliceIntervalMs cannot exceed durationMs\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"twap\",\n value: {\n side: input.side,\n durationMs: input.durationMs,\n sliceIntervalMs: input.sliceIntervalMs,\n execution: buildTwapExecution(input.execution, scales),\n },\n } as const,\n },\n };\n }),\n );\n}\n\nfunction createLadderTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...BaseTriggerFieldsSchema.entries,\n triggerType: v.literal(\"ladder\"),\n side: TriggerSideInputSchema,\n priceMin: DecimalInputStringSchema,\n priceMax: DecimalInputStringSchema,\n levels: v.pipe(\n v.union([v.pipe(v.string(), v.trim()), v.pipe(v.number(), v.integer())]),\n v.transform((value) => {\n const levels = parseOptionalPositiveIntLike(value);\n if (!levels || levels < 2 || levels > 100) {\n throw new Error(\"levels must be between 2 and 100\");\n }\n return levels;\n }),\n ),\n postOnly: v.optional(v.boolean(), false),\n }),\n v.check(\n (input) =>\n input.side !== ProtoOrders.Side.SELL ||\n input.feeAsset === ProtoOrders.FeeAsset.QUOTE,\n \"SELL triggers must use the quote fee asset\",\n ),\n v.transform((input) => {\n const { subaccountId, intent } = buildTriggerIntentBase(input, scales);\n return {\n subaccountId,\n trigger: {\n ...intent,\n strategy: {\n case: \"ladder\",\n value: {\n side: input.side,\n priceMinTicks: positiveDecimalInputToScaled(\n \"priceMin\",\n input.priceMin,\n scales.price(),\n ),\n priceMaxTicks: positiveDecimalInputToScaled(\n \"priceMax\",\n input.priceMax,\n scales.price(),\n ),\n levels: input.levels,\n postOnly: input.postOnly,\n },\n } as const,\n },\n };\n }),\n );\n}\n\nexport function createCreateTriggerInputSchema(scales: SdkScales) {\n return v.union([\n ...createConditionalTriggerInputSchema(scales, \"stop_loss\"),\n ...createConditionalTriggerInputSchema(scales, \"take_profit\"),\n createTrailingStopTriggerInputSchema(scales),\n createTwapTriggerInputSchema(scales),\n createLadderTriggerInputSchema(scales),\n ]);\n}\n\nexport type CreateTriggerInput = v.InferInput<ReturnType<typeof createCreateTriggerInputSchema>>;\n\nexport const ListTriggersInputSchema = v.pipe(\n v.strictObject({\n ...AccountScopeInputEntries,\n parentOrderId: v.pipe(\n v.optional(v.pipe(v.string(), v.trim())),\n v.transform((value) => (value ? idToBigInt(value, \"parentOrderId\") : undefined)),\n ),\n symbol: v.optional(v.pipe(v.string(), v.trim())),\n status: v.pipe(\n v.optional(v.array(TriggerStatusFilterSchema)),\n v.transform(\n (values) => values?.map((value) => TriggerStatusCodec.inputToProto[value]) ?? [],\n ),\n ),\n triggerType: v.pipe(\n v.optional(TriggerTypeSchema),\n v.transform((value) =>\n value\n ? TriggerTypeCodec.inputToProto[value]\n : Proto.TriggerType.TRIGGER_TYPE_UNSPECIFIED,\n ),\n ),\n limit: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0), v.maxValue(1000)), 50),\n pageToken: v.optional(v.pipe(v.string(), v.trim()), \"\"),\n }),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n })),\n);\n\nexport type ListTriggersInput = v.InferInput<typeof ListTriggersInputSchema>;\n\nexport const CancelTriggerInputSchema = TriggerScopedInputSchema;\nexport type CancelTriggerInput = v.InferInput<typeof CancelTriggerInputSchema>;\n\nexport const GetTriggerInputSchema = CancelTriggerInputSchema;\nexport type GetTriggerInput = v.InferInput<typeof GetTriggerInputSchema>;\n\nexport const PauseTriggerInputSchema = TriggerScopedInputSchema;\nexport type PauseTriggerInput = v.InferInput<typeof PauseTriggerInputSchema>;\n\nexport const ResumeTriggerInputSchema = TriggerScopedInputSchema;\nexport type ResumeTriggerInput = v.InferInput<typeof ResumeTriggerInputSchema>;\n\nexport function createModifyTriggerInputSchema(scales: SdkScales) {\n return v.pipe(\n v.strictObject({\n ...TriggerScopedInputEntries,\n triggerPrice: v.optional(DecimalInputStringSchema),\n limitPrice: v.optional(DecimalInputStringSchema),\n trailingDistance: v.optional(TrailingDistanceInputSchema),\n activationPrice: v.optional(DecimalInputStringSchema),\n maxSlippage: v.optional(MaxSlippageInputSchema),\n }),\n v.check(\n (input) =>\n input.triggerPrice !== undefined ||\n input.limitPrice !== undefined ||\n input.trailingDistance !== undefined ||\n input.activationPrice !== undefined ||\n input.maxSlippage !== undefined,\n \"At least one patch field is required\",\n ),\n v.transform(({ account, ...input }) => ({\n triggerId: input.triggerId,\n subaccountId: accountScopeToSubaccountId(account),\n triggerPriceTicks:\n input.triggerPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\n \"triggerPrice\",\n input.triggerPrice,\n scales.price(),\n ),\n limitPriceTicks:\n input.limitPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\"limitPrice\", input.limitPrice, scales.price()),\n trailingDistance:\n input.trailingDistance === undefined\n ? ({ case: undefined, value: undefined } as const)\n : parseTrailingDistance(scales, input.trailingDistance),\n activationPriceTicks:\n input.activationPrice === undefined\n ? undefined\n : positiveDecimalInputToScaled(\n \"activationPrice\",\n input.activationPrice,\n scales.price(),\n ),\n maxSlippage:\n input.maxSlippage === undefined\n ? ({ case: undefined, value: undefined } as const)\n : parseMaxSlippage(scales, input.maxSlippage),\n })),\n );\n}\n\nexport type ModifyTriggerInput = v.InferInput<ReturnType<typeof createModifyTriggerInputSchema>>;\n\nexport const ListTriggerEventsInputSchema = v.pipe(\n v.strictObject({\n ...TriggerScopedInputEntries,\n limit: v.optional(v.pipe(v.number(), v.integer(), v.gtValue(0), v.maxValue(1000))),\n eventType: v.optional(TriggerEventTypeSchema),\n pageToken: v.optional(v.pipe(v.string(), v.trim()), \"\"),\n }),\n v.transform(({ account, ...input }) => ({\n ...input,\n subaccountId: accountScopeToSubaccountId(account),\n eventType:\n input.eventType === undefined\n ? undefined\n : TriggerEventTypeCodec.inputToProto[input.eventType],\n })),\n);\n\nexport type ListTriggerEventsInput = v.InferInput<typeof ListTriggerEventsInputSchema>;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decimal-surface.d.ts","names":[],"sources":["../../src/shared/decimal-surface.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"decimal-surface.d.ts","names":[],"sources":["../../src/shared/decimal-surface.ts"],"mappings":";;;;;;;UA8BiB;EACb,SAAS;EACT;EACA,QAAQ,MAAM;EACd,YAAY,MAAM;EAClB,aAAa;EACb,kBAAkB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { scaledToDecimal, tryDecimalToScaled } from "../catalogs/decimal.js";
|
|
2
2
|
import { CatalogConversionError } from "../catalogs/types.js";
|
|
3
|
+
import "./wire-bounds.js";
|
|
3
4
|
/**
|
|
4
5
|
* Catalog-backed scale resolver. Takes a getter so it can be constructed
|
|
5
6
|
* before the owning client has assigned its catalog.
|
|
@@ -35,13 +36,21 @@ function decimalInputToScaled(field, value, scale) {
|
|
|
35
36
|
if (!result.ok) throw new CatalogConversionError(field, conversionFailureMessage(field, value, result.failure));
|
|
36
37
|
return result.scaled;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
function positiveDecimalInputToScaled(field, value, scale) {
|
|
39
|
+
function unboundedPositiveDecimalInputToScaled(field, value, scale) {
|
|
40
40
|
const scaled = decimalInputToScaled(field, value, scale);
|
|
41
41
|
if (scaled <= 0n) throw new CatalogConversionError(field, `${field} must be greater than 0: ${value}`);
|
|
42
42
|
return scaled;
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
|
+
* Converts a positive decimal input to a scaled protobuf `int64` value.
|
|
46
|
+
* Rejects values above the wire-format ceiling before serialization.
|
|
47
|
+
*/
|
|
48
|
+
function positiveDecimalInputToScaled(field, value, scale) {
|
|
49
|
+
const scaled = unboundedPositiveDecimalInputToScaled(field, value, scale);
|
|
50
|
+
if (scaled > 9223372036854775807n) throw new CatalogConversionError(field, `${field} exceeds the maximum supported value: ${value}`);
|
|
51
|
+
return scaled;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
45
54
|
* Decimal quantity → PolyesterChain E18 ledger units.
|
|
46
55
|
* Input precision is capped at the asset's quantityScale; the wire value is
|
|
47
56
|
* always upscaled to E18 (trading balances / amount_e18 convention).
|
|
@@ -50,7 +59,7 @@ function quantityInputToE18(params) {
|
|
|
50
59
|
const field = params.field ?? "quantity";
|
|
51
60
|
const assetScale = params.scales.ledgerAmount(params.assetId);
|
|
52
61
|
if (assetScale > 18) throw new CatalogConversionError(field, `${field} asset quantityScale ${assetScale} exceeds E18 ledger scale`);
|
|
53
|
-
return
|
|
62
|
+
return unboundedPositiveDecimalInputToScaled(field, params.quantity, assetScale) * 10n ** BigInt(18 - assetScale);
|
|
54
63
|
}
|
|
55
64
|
/**
|
|
56
65
|
* Orders event delivery behind catalog readiness. Events arriving before the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decimal-surface.js","names":[],"sources":["../../src/shared/decimal-surface.ts"],"sourcesContent":["/**\n * Internal scaled⇄decimal bridge for the SDK's public decimal-string surface.\n *\n * The wire protocol carries scaled integers (price ticks, per-asset scaled\n * quantities); the public SDK surface carries plain decimal strings. Output\n * schemas convert exactly (no rounding, trailing zeros trimmed); input schemas\n * convert strictly — excess precision is an error, never rounded away. Scaled\n * integers must not escape through any service input or output.\n */\nimport {\n scaledToDecimal,\n tryDecimalToScaled,\n type DecimalToScaledFailure,\n} from \"../catalogs/decimal.js\";\nimport {\n CatalogConversionError,\n type ClientCatalog,\n type PairCatalogKey,\n} from \"../catalogs/types.js\";\nimport { PRICE_SCALE } from \"../catalogs/readers.js\";\n\n/** On-chain unified-asset amounts (`amountE18`) are always 18-decimal scaled. */\nexport const E18_SCALE = 18;\n\n/**\n * Resolves wire scales for the SDK's internal decimal conversion. Backed by\n * the client catalog; `ready()` must be awaited before the synchronous lookups\n * are used so the catalog can answer them.\n */\nexport interface SdkScales {\n ready(): Promise<void>;\n price(): number;\n baseQty(pair: PairCatalogKey): number;\n quoteAmount(pair: PairCatalogKey): number;\n ledgerAmount(ledgerAssetId: number): number;\n zippedAssetAmount(zippedAssetId: number): number;\n}\n\n/**\n * Catalog-backed scale resolver. Takes a getter so it can be constructed\n * before the owning client has assigned its catalog.\n */\nexport function createCatalogSdkScales(getCatalog: () => ClientCatalog): SdkScales {\n return {\n ready: async () => {\n await getCatalog().ensureReady();\n },\n price: () => PRICE_SCALE,\n baseQty: (pair) => requirePair(getCatalog(), pair).baseAsset.quantityScale,\n quoteAmount: (pair) => requirePair(getCatalog(), pair).quoteAsset.quantityScale,\n ledgerAmount: (ledgerAssetId) =>\n getCatalog().ledger.requireAssetByLedgerId(ledgerAssetId).quantityScale,\n zippedAssetAmount: (zippedAssetId) =>\n getCatalog().zipper.requireAssetChainByZippedAssetId(zippedAssetId).asset.quantityScale,\n };\n}\n\nfunction requirePair(catalog: ClientCatalog, pair: PairCatalogKey) {\n return typeof pair === \"string\" || (typeof pair === \"object\" && \"symbol\" in pair)\n ? catalog.market.requirePairBySymbol(typeof pair === \"string\" ? pair : pair.symbol)\n : catalog.market.requirePairBySymbolId(typeof pair === \"number\" ? pair : pair.symbolId);\n}\n\n/** Output direction: exact scaled→decimal conversion (`1500000n`@6 → `\"1.5\"`). */\nexport function scaledToDecimalOutput(value: bigint, scale: number): string {\n return scaledToDecimal(value, scale);\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/**\n * Input direction: strict decimal→scaled conversion. Throws\n * CatalogConversionError for non-decimal input or excess precision.\n */\nexport function decimalInputToScaled(field: string, value: string, scale: number): bigint {\n const result = tryDecimalToScaled(value.trim(), scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, value, result.failure),\n );\n }\n return result.scaled;\n}\n\n
|
|
1
|
+
{"version":3,"file":"decimal-surface.js","names":[],"sources":["../../src/shared/decimal-surface.ts"],"sourcesContent":["/**\n * Internal scaled⇄decimal bridge for the SDK's public decimal-string surface.\n *\n * The wire protocol carries scaled integers (price ticks, per-asset scaled\n * quantities); the public SDK surface carries plain decimal strings. Output\n * schemas convert exactly (no rounding, trailing zeros trimmed); input schemas\n * convert strictly — excess precision is an error, never rounded away. Scaled\n * integers must not escape through any service input or output.\n */\nimport {\n scaledToDecimal,\n tryDecimalToScaled,\n type DecimalToScaledFailure,\n} from \"../catalogs/decimal.js\";\nimport {\n CatalogConversionError,\n type ClientCatalog,\n type PairCatalogKey,\n} from \"../catalogs/types.js\";\nimport { PRICE_SCALE } from \"../catalogs/readers.js\";\nimport { PROTOBUF_INT64_MAX } from \"./wire-bounds.js\";\n\n/** On-chain unified-asset amounts (`amountE18`) are always 18-decimal scaled. */\nexport const E18_SCALE = 18;\n\n/**\n * Resolves wire scales for the SDK's internal decimal conversion. Backed by\n * the client catalog; `ready()` must be awaited before the synchronous lookups\n * are used so the catalog can answer them.\n */\nexport interface SdkScales {\n ready(): Promise<void>;\n price(): number;\n baseQty(pair: PairCatalogKey): number;\n quoteAmount(pair: PairCatalogKey): number;\n ledgerAmount(ledgerAssetId: number): number;\n zippedAssetAmount(zippedAssetId: number): number;\n}\n\n/**\n * Catalog-backed scale resolver. Takes a getter so it can be constructed\n * before the owning client has assigned its catalog.\n */\nexport function createCatalogSdkScales(getCatalog: () => ClientCatalog): SdkScales {\n return {\n ready: async () => {\n await getCatalog().ensureReady();\n },\n price: () => PRICE_SCALE,\n baseQty: (pair) => requirePair(getCatalog(), pair).baseAsset.quantityScale,\n quoteAmount: (pair) => requirePair(getCatalog(), pair).quoteAsset.quantityScale,\n ledgerAmount: (ledgerAssetId) =>\n getCatalog().ledger.requireAssetByLedgerId(ledgerAssetId).quantityScale,\n zippedAssetAmount: (zippedAssetId) =>\n getCatalog().zipper.requireAssetChainByZippedAssetId(zippedAssetId).asset.quantityScale,\n };\n}\n\nfunction requirePair(catalog: ClientCatalog, pair: PairCatalogKey) {\n return typeof pair === \"string\" || (typeof pair === \"object\" && \"symbol\" in pair)\n ? catalog.market.requirePairBySymbol(typeof pair === \"string\" ? pair : pair.symbol)\n : catalog.market.requirePairBySymbolId(typeof pair === \"number\" ? pair : pair.symbolId);\n}\n\n/** Output direction: exact scaled→decimal conversion (`1500000n`@6 → `\"1.5\"`). */\nexport function scaledToDecimalOutput(value: bigint, scale: number): string {\n return scaledToDecimal(value, scale);\n}\n\nfunction conversionFailureMessage(\n field: string,\n value: string,\n failure: DecimalToScaledFailure,\n): string {\n return failure.reason === \"precision\"\n ? `${field} supports at most ${failure.maxDecimals} decimal places: ${value}`\n : `${field} must be a non-negative decimal number: ${value}`;\n}\n\n/**\n * Input direction: strict decimal→scaled conversion. Throws\n * CatalogConversionError for non-decimal input or excess precision.\n */\nexport function decimalInputToScaled(field: string, value: string, scale: number): bigint {\n const result = tryDecimalToScaled(value.trim(), scale);\n if (!result.ok) {\n throw new CatalogConversionError(\n field,\n conversionFailureMessage(field, value, result.failure),\n );\n }\n return result.scaled;\n}\n\nfunction unboundedPositiveDecimalInputToScaled(\n field: string,\n value: string,\n scale: number,\n): bigint {\n const scaled = decimalInputToScaled(field, value, scale);\n if (scaled <= 0n) {\n throw new CatalogConversionError(field, `${field} must be greater than 0: ${value}`);\n }\n return scaled;\n}\n\n/**\n * Converts a positive decimal input to a scaled protobuf `int64` value.\n * Rejects values above the wire-format ceiling before serialization.\n */\nexport function positiveDecimalInputToScaled(field: string, value: string, scale: number): bigint {\n const scaled = unboundedPositiveDecimalInputToScaled(field, value, scale);\n if (scaled > PROTOBUF_INT64_MAX) {\n throw new CatalogConversionError(\n field,\n `${field} exceeds the maximum supported value: ${value}`,\n );\n }\n return scaled;\n}\n\n/**\n * Decimal quantity → PolyesterChain E18 ledger units.\n * Input precision is capped at the asset's quantityScale; the wire value is\n * always upscaled to E18 (trading balances / amount_e18 convention).\n */\nexport function quantityInputToE18(params: {\n scales: SdkScales;\n assetId: number;\n quantity: string;\n field?: string;\n}): bigint {\n const field = params.field ?? \"quantity\";\n const assetScale = params.scales.ledgerAmount(params.assetId);\n if (assetScale > E18_SCALE) {\n throw new CatalogConversionError(\n field,\n `${field} asset quantityScale ${assetScale} exceeds E18 ledger scale`,\n );\n }\n return (\n unboundedPositiveDecimalInputToScaled(field, params.quantity, assetScale) *\n 10n ** BigInt(E18_SCALE - assetScale)\n );\n}\n\nexport interface ReadyGate {\n run(deliver: () => void): void;\n}\n\n/**\n * Orders event delivery behind catalog readiness. Events arriving before the\n * catalog can resolve scales are queued and flushed in arrival order once it\n * is ready; delivery errors (including post-flush ones) route to `onError`\n * instead of escaping into the transport, mirroring the realtime client's\n * consumer-handler isolation. If readiness itself fails, queued events are\n * dropped after `onError` fires — the stream cannot be decoded without scales.\n */\nexport function createReadyGate(\n ready: () => Promise<void>,\n onError?: (error: unknown) => void,\n): ReadyGate {\n let state: \"pending\" | \"open\" | \"failed\" = \"pending\";\n const queue: Array<() => void> = [];\n\n const deliverIsolated = (deliver: () => void) => {\n try {\n deliver();\n } catch (error) {\n onError?.(error);\n }\n };\n\n ready().then(\n () => {\n state = \"open\";\n for (const deliver of queue.splice(0)) deliverIsolated(deliver);\n },\n (error) => {\n state = \"failed\";\n queue.length = 0;\n onError?.(error);\n },\n );\n\n return {\n run(deliver) {\n if (state === \"open\") deliverIsolated(deliver);\n else if (state === \"pending\") queue.push(deliver);\n },\n };\n}\n"],"mappings":";;;;;;;AA2CA,SAAgB,uBAAuB,YAA4C;CAC/E,OAAO;EACH,OAAO,YAAY;GACf,MAAM,WAAW,CAAC,CAAC,YAAY;EACnC;EACA,aAAA;EACA,UAAU,SAAS,YAAY,WAAW,GAAG,IAAI,CAAC,CAAC,UAAU;EAC7D,cAAc,SAAS,YAAY,WAAW,GAAG,IAAI,CAAC,CAAC,WAAW;EAClE,eAAe,kBACX,WAAW,CAAC,CAAC,OAAO,uBAAuB,aAAa,CAAC,CAAC;EAC9D,oBAAoB,kBAChB,WAAW,CAAC,CAAC,OAAO,iCAAiC,aAAa,CAAC,CAAC,MAAM;CAClF;AACJ;AAEA,SAAS,YAAY,SAAwB,MAAsB;CAC/D,OAAO,OAAO,SAAS,YAAa,OAAO,SAAS,YAAY,YAAY,OACtE,QAAQ,OAAO,oBAAoB,OAAO,SAAS,WAAW,OAAO,KAAK,MAAM,IAChF,QAAQ,OAAO,sBAAsB,OAAO,SAAS,WAAW,OAAO,KAAK,QAAQ;AAC9F;;AAGA,SAAgB,sBAAsB,OAAe,OAAuB;CACxE,OAAO,gBAAgB,OAAO,KAAK;AACvC;AAEA,SAAS,yBACL,OACA,OACA,SACM;CACN,OAAO,QAAQ,WAAW,cACpB,GAAG,MAAM,oBAAoB,QAAQ,YAAY,mBAAmB,UACpE,GAAG,MAAM,0CAA0C;AAC7D;;;;;AAMA,SAAgB,qBAAqB,OAAe,OAAe,OAAuB;CACtF,MAAM,SAAS,mBAAmB,MAAM,KAAK,GAAG,KAAK;CACrD,IAAI,CAAC,OAAO,IACR,MAAM,IAAI,uBACN,OACA,yBAAyB,OAAO,OAAO,OAAO,OAAO,CACzD;CAEJ,OAAO,OAAO;AAClB;AAEA,SAAS,sCACL,OACA,OACA,OACM;CACN,MAAM,SAAS,qBAAqB,OAAO,OAAO,KAAK;CACvD,IAAI,UAAU,IACV,MAAM,IAAI,uBAAuB,OAAO,GAAG,MAAM,2BAA2B,OAAO;CAEvF,OAAO;AACX;;;;;AAMA,SAAgB,6BAA6B,OAAe,OAAe,OAAuB;CAC9F,MAAM,SAAS,sCAAsC,OAAO,OAAO,KAAK;CACxE,IAAI,SAAA,sBACA,MAAM,IAAI,uBACN,OACA,GAAG,MAAM,wCAAwC,OACrD;CAEJ,OAAO;AACX;;;;;;AAOA,SAAgB,mBAAmB,QAKxB;CACP,MAAM,QAAQ,OAAO,SAAS;CAC9B,MAAM,aAAa,OAAO,OAAO,aAAa,OAAO,OAAO;CAC5D,IAAI,aAAA,IACA,MAAM,IAAI,uBACN,OACA,GAAG,MAAM,uBAAuB,WAAW,0BAC/C;CAEJ,OACI,sCAAsC,OAAO,OAAO,UAAU,UAAU,IACxE,OAAO,OAAA,KAAmB,UAAU;AAE5C;;;;;;;;;AAcA,SAAgB,gBACZ,OACA,SACS;CACT,IAAI,QAAuC;CAC3C,MAAM,QAA2B,CAAC;CAElC,MAAM,mBAAmB,YAAwB;EAC7C,IAAI;GACA,QAAQ;EACZ,SAAS,OAAO;GACZ,UAAU,KAAK;EACnB;CACJ;CAEA,MAAM,CAAC,CAAC,WACE;EACF,QAAQ;EACR,KAAK,MAAM,WAAW,MAAM,OAAO,CAAC,GAAG,gBAAgB,OAAO;CAClE,IACC,UAAU;EACP,QAAQ;EACR,MAAM,SAAS;EACf,UAAU,KAAK;CACnB,CACJ;CAEA,OAAO,EACH,IAAI,SAAS;EACT,IAAI,UAAU,QAAQ,gBAAgB,OAAO;OACxC,IAAI,UAAU,WAAW,MAAM,KAAK,OAAO;CACpD,EACJ;AACJ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/shared/wire-bounds.ts
|
|
2
|
+
/** Largest value encodable by a protobuf `int64` field. */
|
|
3
|
+
const PROTOBUF_INT64_MAX = 9223372036854775807n;
|
|
4
|
+
/** Largest value encodable by a protobuf `int32` field. */
|
|
5
|
+
const PROTOBUF_INT32_MAX = 2147483647n;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { PROTOBUF_INT32_MAX, PROTOBUF_INT64_MAX };
|
|
8
|
+
|
|
9
|
+
//# sourceMappingURL=wire-bounds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wire-bounds.js","names":[],"sources":["../../src/shared/wire-bounds.ts"],"sourcesContent":["/** Largest value encodable by a protobuf `int64` field. */\nexport const PROTOBUF_INT64_MAX = 9_223_372_036_854_775_807n;\n\n/** Largest value encodable by a protobuf `int32` field. */\nexport const PROTOBUF_INT32_MAX = 2_147_483_647n;\n"],"mappings":";;AACA,MAAa,qBAAqB;;AAGlC,MAAa,qBAAqB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { CreateSmartAccountParams, PolyesterSmartAccountClient, PredictPolyesterSmartAccountAddressParams, SafeSmartAccountInstance, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation } from "./smart-account.js";
|
|
2
|
-
export { type CreateSmartAccountParams, type PolyesterSmartAccountClient, type PredictPolyesterSmartAccountAddressParams, type SafeSmartAccountInstance, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation };
|
|
1
|
+
import { CreateSmartAccountParams, PolyesterSmartAccountClient, PolyesterSmartAccountClientOptions, PredictPolyesterSmartAccountAddressParams, SafeSmartAccountInstance, SendPolyesterUserOperationOptions, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient } from "./smart-account.js";
|
|
2
|
+
export { type CreateSmartAccountParams, type PolyesterSmartAccountClient, type PolyesterSmartAccountClientOptions, type PredictPolyesterSmartAccountAddressParams, type SafeSmartAccountInstance, type SendPolyesterUserOperationOptions, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation } from "./smart-account.js";
|
|
2
|
-
export { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation };
|
|
1
|
+
import { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient } from "./smart-account.js";
|
|
2
|
+
export { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient };
|
|
@@ -20,11 +20,18 @@ declare function predictPolyesterSmartAccountAddress({ environment, ownerAddress
|
|
|
20
20
|
* Creates a Polyester smart account instance.
|
|
21
21
|
*/
|
|
22
22
|
declare function createPolyesterSmartAccount({ environment, owner, saltNonce, publicClient }: CreateSmartAccountParams): Promise<SafeSmartAccountInstance>;
|
|
23
|
+
interface PolyesterSmartAccountClientOptions {
|
|
24
|
+
/** How long a fetched gas price is reused, in milliseconds. Defaults to 10s. */
|
|
25
|
+
gasPriceCacheTtlMs?: number;
|
|
26
|
+
/** How often to poll for UserOperation receipts, in milliseconds. Defaults to 1s. */
|
|
27
|
+
pollingIntervalMs?: number;
|
|
28
|
+
}
|
|
23
29
|
/**
|
|
24
30
|
* Creates a viem client bound to a Polyester smart account.
|
|
25
31
|
*/
|
|
26
32
|
declare function createPolyesterSmartAccountClient(account: SafeSmartAccountInstance, params: {
|
|
27
33
|
environment: PolyesterEnvironment;
|
|
34
|
+
options?: PolyesterSmartAccountClientOptions;
|
|
28
35
|
}): import("permissionless").SmartAccountClient<import("viem").HttpTransport<undefined, false>, import("viem").Chain, (object & {
|
|
29
36
|
client: import("viem").Client<import("viem").Transport, import("viem").Chain | undefined, {
|
|
30
37
|
address: Address;
|
|
@@ -3087,7 +3094,20 @@ declare function createPolyesterSmartAccountClient(account: SafeSmartAccountInst
|
|
|
3087
3094
|
isDeployed: () => Promise<boolean>;
|
|
3088
3095
|
type: "smart";
|
|
3089
3096
|
}), undefined, undefined>;
|
|
3090
|
-
|
|
3097
|
+
/**
|
|
3098
|
+
* Warms the network path for an upcoming submission: primes the gas-price
|
|
3099
|
+
* cache and opens connections to the RPC endpoint. Never throws; the nonce is
|
|
3100
|
+
* intentionally not cached — fetching it here is connection warm-up only.
|
|
3101
|
+
*/
|
|
3102
|
+
declare function warmPolyesterSmartAccountClient(client: PolyesterSmartAccountClient): Promise<void>;
|
|
3103
|
+
interface SendPolyesterUserOperationOptions {
|
|
3104
|
+
/**
|
|
3105
|
+
* Fires once per submission, immediately before the wallet is asked to
|
|
3106
|
+
* sign the fully prepared operation — the prepare→sign boundary.
|
|
3107
|
+
*/
|
|
3108
|
+
onWalletSignatureRequested?: () => void;
|
|
3109
|
+
}
|
|
3110
|
+
declare function sendPolyesterUserOperation(client: PolyesterSmartAccountClient, parameters: Parameters<PolyesterSmartAccountClient["sendUserOperation"]>[0], options?: SendPolyesterUserOperationOptions): Promise<Awaited<ReturnType<PolyesterSmartAccountClient["sendUserOperation"]>>>;
|
|
3091
3111
|
//#endregion
|
|
3092
|
-
export { CreateSmartAccountParams, PolyesterSmartAccountClient, PredictPolyesterSmartAccountAddressParams, SafeSmartAccountInstance, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation };
|
|
3112
|
+
export { CreateSmartAccountParams, PolyesterSmartAccountClient, PolyesterSmartAccountClientOptions, PredictPolyesterSmartAccountAddressParams, SafeSmartAccountInstance, SendPolyesterUserOperationOptions, createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient };
|
|
3093
3113
|
//# sourceMappingURL=smart-account.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-account.d.ts","names":[],"sources":["../../src/smart-account/smart-account.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"smart-account.d.ts","names":[],"sources":["../../src/smart-account/smart-account.ts"],"mappings":";;;;KAUY,2BAA2B,QAAQ,kBAAkB;KACrD,8BAA8B,kBAAkB;UAiB3C;EACb,aAAa;EACb,OAAO;EACP;EACA,eAAe;;UAGF;EACb,aAAa;EACb,cAAc;EACd;;iBAGY,sCACZ,aACA,cACA,aACD,4CAA4C;;;;iBAuBzB,8BAClB,aACA,OACA,WACA,gBACD,2BAA2B,QAAQ;UAuBrB;;EAEb;;EAEA;;;;;iBAMY,kCACZ,SAAS,0BACT;EACI,aAAa;EACb,UAAU;6BACb,kCAAA,gDAAA;;;;;;;;;;;IA9EL,kBAAA,kCAAA,sCAAA,0CAAA,sCAAA,0BAAA,oBAAA,WAAA,iBAAA,WAAA,gBAAA,aAAA,aAAA;MAEmB,aAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6DwB,UAAC;IACZ,6BAAC;;EAO5B,aAAA;IAAgB;;EAUlB,mBAAA,4BAAC,qCAAA,uBAAA;;;;;;;;;;IAwCqC;;;IAGR,gBAAC,8BAAA,yBAAA,uBAAA,4BAAA;;;;;;;;;;;;;;;;;;;IA5HnC,kBAAA,kCAAA,sCAAA,0CAAA,sCAAA,0BAAA,oBAAA,WAAA,iBAAA,WAAA,gBAAA,aAAA,aAAA;MAEmB,aAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA6DwB,UAAC;IACZ,6BAAC;;EAO5B,aAAA;IAAgB;;EAUlB,mBAAA,4BAAC,qCAAA,uBAAA;;;;;;;;;;IAwCqC;;;IAGR,gBAAC,8BAAA,yBAAA,uBAAA,4BAAA;;;;;;;;;;;;;;;;;iBA6Bb,gCAClB,QAAQ,8BACT;UA2Cc;;;;;EAKb;;iBAGkB,2BAClB,QAAQ,6BACR,YAAY,WAAW,sDACvB,UAAS,oCACV,QAAQ,QAAQ,WAAW"}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { predictSafeAddress } from "../account-signer/predict-safe-address.js";
|
|
2
2
|
import { createPublicClient, http } from "viem";
|
|
3
|
+
import { estimateUserOperationGas, prepareUserOperation } from "viem/account-abstraction";
|
|
3
4
|
import { createSmartAccountClient } from "permissionless";
|
|
4
5
|
import { toSafeSmartAccount } from "permissionless/accounts";
|
|
5
6
|
import { createPimlicoClient } from "permissionless/clients/pimlico";
|
|
6
7
|
//#region src/smart-account/smart-account.ts
|
|
7
8
|
const smartAccountEnvironmentFingerprints = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
const smartAccountClientGasPricePrimers = /* @__PURE__ */ new WeakMap();
|
|
8
10
|
const USER_OPERATION_GAS_BUFFER_BPS = 2000n;
|
|
9
11
|
const USER_OPERATION_MIN_GAS_BUFFER = 50000n;
|
|
12
|
+
const USER_OPERATION_GAS_PRICE_TTL_MS = 1e4;
|
|
13
|
+
const USER_OPERATION_RECEIPT_POLLING_INTERVAL_MS = 1e3;
|
|
10
14
|
function predictPolyesterSmartAccountAddress({ environment, ownerAddress, saltNonce = 0n }) {
|
|
11
15
|
const { safeProxyFactoryAddress, safeSingletonAddress, safeModuleSetupAddress, safe4337ModuleAddress, multiSendAddress } = environment.accountAbstraction.safe;
|
|
12
16
|
return predictSafeAddress({
|
|
@@ -42,7 +46,8 @@ async function createPolyesterSmartAccount({ environment, owner, saltNonce, publ
|
|
|
42
46
|
* Creates a viem client bound to a Polyester smart account.
|
|
43
47
|
*/
|
|
44
48
|
function createPolyesterSmartAccountClient(account, params) {
|
|
45
|
-
const { environment } = params;
|
|
49
|
+
const { environment, options } = params;
|
|
50
|
+
const { gasPriceCacheTtlMs = USER_OPERATION_GAS_PRICE_TTL_MS, pollingIntervalMs = USER_OPERATION_RECEIPT_POLLING_INTERVAL_MS } = options ?? {};
|
|
46
51
|
const accountEnvironmentFingerprint = smartAccountEnvironmentFingerprints.get(account);
|
|
47
52
|
if (accountEnvironmentFingerprint && accountEnvironmentFingerprint !== environment.fingerprint) throw new Error("Smart account environment does not match client environment.");
|
|
48
53
|
const paymaster = createPimlicoClient({
|
|
@@ -50,13 +55,52 @@ function createPolyesterSmartAccountClient(account, params) {
|
|
|
50
55
|
transport: http(environment.accountAbstraction.paymasterUrl),
|
|
51
56
|
entryPoint: environment.accountAbstraction.entryPoint
|
|
52
57
|
});
|
|
53
|
-
|
|
58
|
+
let cachedGasPrice;
|
|
59
|
+
const getGasPrice = () => {
|
|
60
|
+
if (!cachedGasPrice || Date.now() - cachedGasPrice.fetchedAt >= gasPriceCacheTtlMs) {
|
|
61
|
+
const result = paymaster.getUserOperationGasPrice();
|
|
62
|
+
const entry = {
|
|
63
|
+
fetchedAt: Date.now(),
|
|
64
|
+
result
|
|
65
|
+
};
|
|
66
|
+
cachedGasPrice = entry;
|
|
67
|
+
result.catch(() => {
|
|
68
|
+
if (cachedGasPrice === entry) cachedGasPrice = void 0;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return cachedGasPrice.result;
|
|
72
|
+
};
|
|
73
|
+
const client = createSmartAccountClient({
|
|
54
74
|
account,
|
|
55
75
|
chain: environment.chain,
|
|
56
76
|
paymaster,
|
|
57
77
|
bundlerTransport: http(environment.accountAbstraction.bundlerUrl),
|
|
58
|
-
|
|
78
|
+
pollingInterval: pollingIntervalMs,
|
|
79
|
+
userOperation: {
|
|
80
|
+
estimateFeesPerGas: async () => (await getGasPrice()).fast,
|
|
81
|
+
prepareUserOperation: (prepareClient, prepareParameters) => {
|
|
82
|
+
const bufferingClient = {
|
|
83
|
+
...prepareClient,
|
|
84
|
+
estimateUserOperationGas: async (estimateParameters) => bufferPolyesterUserOperationGas(await estimateUserOperationGas(prepareClient, estimateParameters))
|
|
85
|
+
};
|
|
86
|
+
return prepareUserOperation(bufferingClient, prepareParameters);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
59
89
|
});
|
|
90
|
+
smartAccountClientGasPricePrimers.set(client, getGasPrice);
|
|
91
|
+
return client;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Warms the network path for an upcoming submission: primes the gas-price
|
|
95
|
+
* cache and opens connections to the RPC endpoint. Never throws; the nonce is
|
|
96
|
+
* intentionally not cached — fetching it here is connection warm-up only.
|
|
97
|
+
*/
|
|
98
|
+
async function warmPolyesterSmartAccountClient(client) {
|
|
99
|
+
await Promise.allSettled([
|
|
100
|
+
smartAccountClientGasPricePrimers.get(client)?.(),
|
|
101
|
+
client.account.getNonce(),
|
|
102
|
+
client.account.isDeployed()
|
|
103
|
+
]);
|
|
60
104
|
}
|
|
61
105
|
function addUserOperationGasBuffer(gas) {
|
|
62
106
|
const percentBuffer = gas * USER_OPERATION_GAS_BUFFER_BPS / 10000n;
|
|
@@ -72,23 +116,22 @@ function bufferPolyesterUserOperationGas(gas) {
|
|
|
72
116
|
...typeof gas.paymasterVerificationGasLimit === "bigint" ? { paymasterVerificationGasLimit: addUserOperationGasBuffer(gas.paymasterVerificationGasLimit) } : {}
|
|
73
117
|
};
|
|
74
118
|
}
|
|
75
|
-
async function sendPolyesterUserOperation(client, parameters) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
119
|
+
async function sendPolyesterUserOperation(client, parameters, options = {}) {
|
|
120
|
+
const { onWalletSignatureRequested } = options;
|
|
121
|
+
if (!onWalletSignatureRequested) return client.sendUserOperation(parameters);
|
|
122
|
+
const account = parameters.account ?? client.account;
|
|
123
|
+
return client.sendUserOperation({
|
|
124
|
+
...parameters,
|
|
125
|
+
account: {
|
|
126
|
+
...account,
|
|
127
|
+
signUserOperation: (userOperation) => {
|
|
128
|
+
onWalletSignatureRequested();
|
|
129
|
+
return account.signUserOperation(userOperation);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
90
133
|
}
|
|
91
134
|
//#endregion
|
|
92
|
-
export { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation };
|
|
135
|
+
export { createPolyesterSmartAccount, createPolyesterSmartAccountClient, predictPolyesterSmartAccountAddress, sendPolyesterUserOperation, warmPolyesterSmartAccountClient };
|
|
93
136
|
|
|
94
137
|
//# sourceMappingURL=smart-account.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-account.js","names":[],"sources":["../../src/smart-account/smart-account.ts"],"sourcesContent":["import type { Address, LocalAccount, PublicClient } from \"viem\";\nimport { createPublicClient, http } from \"viem\";\nimport { createSmartAccountClient } from \"permissionless\";\nimport { toSafeSmartAccount } from \"permissionless/accounts\";\nimport { createPimlicoClient } from \"permissionless/clients/pimlico\";\nimport type { PolyesterEnvironment } from \"../environment.js\";\nimport { predictSafeAddress } from \"../account-signer/predict-safe-address.js\";\n\nexport type SafeSmartAccountInstance = Awaited<ReturnType<typeof toSafeSmartAccount>>;\nexport type PolyesterSmartAccountClient = ReturnType<typeof createPolyesterSmartAccountClient>;\n\nconst smartAccountEnvironmentFingerprints = new WeakMap<SafeSmartAccountInstance, string>();\nconst USER_OPERATION_GAS_BUFFER_BPS = 2_000n;\nconst USER_OPERATION_MIN_GAS_BUFFER = 50_000n;\n\ntype PolyesterUserOperationGas = {\n callGasLimit?: bigint;\n preVerificationGas?: bigint;\n verificationGasLimit?: bigint;\n paymasterPostOpGasLimit?: bigint;\n paymasterVerificationGasLimit?: bigint;\n};\n\nexport interface CreateSmartAccountParams {\n environment: PolyesterEnvironment;\n owner: LocalAccount;\n saltNonce?: bigint;\n publicClient?: PublicClient;\n}\n\nexport interface PredictPolyesterSmartAccountAddressParams {\n environment: PolyesterEnvironment;\n ownerAddress: Address;\n saltNonce?: bigint;\n}\n\nexport function predictPolyesterSmartAccountAddress({\n environment,\n ownerAddress,\n saltNonce = 0n,\n}: PredictPolyesterSmartAccountAddressParams): Address {\n const {\n safeProxyFactoryAddress,\n safeSingletonAddress,\n safeModuleSetupAddress,\n safe4337ModuleAddress,\n multiSendAddress,\n } = environment.accountAbstraction.safe;\n\n return predictSafeAddress({\n owners: [ownerAddress],\n saltNonce,\n safeProxyFactoryAddress,\n safeSingletonAddress,\n safeModuleSetupAddress,\n safe4337ModuleAddress,\n multiSendAddress,\n });\n}\n\n/**\n * Creates a Polyester smart account instance.\n */\nexport async function createPolyesterSmartAccount({\n environment,\n owner,\n saltNonce,\n publicClient,\n}: CreateSmartAccountParams): Promise<SafeSmartAccountInstance> {\n const client =\n publicClient ??\n createPublicClient({\n chain: environment.chain,\n transport: http(environment.rpcUrl),\n });\n\n if (client.chain?.id && client.chain.id !== environment.chain.id) {\n throw new Error(\"Smart account public client chain does not match environment.\");\n }\n\n const account = await toSafeSmartAccount({\n client,\n owners: [owner],\n saltNonce,\n entryPoint: environment.accountAbstraction.entryPoint,\n ...environment.accountAbstraction.safe,\n });\n smartAccountEnvironmentFingerprints.set(account, environment.fingerprint);\n return account;\n}\n\n/**\n * Creates a viem client bound to a Polyester smart account.\n */\nexport function createPolyesterSmartAccountClient(\n account: SafeSmartAccountInstance,\n params: { environment: PolyesterEnvironment },\n) {\n const { environment } = params;\n const accountEnvironmentFingerprint = smartAccountEnvironmentFingerprints.get(account);\n if (\n accountEnvironmentFingerprint &&\n accountEnvironmentFingerprint !== environment.fingerprint\n ) {\n throw new Error(\"Smart account environment does not match client environment.\");\n }\n\n const paymaster = createPimlicoClient({\n chain: environment.chain,\n transport: http(environment.accountAbstraction.paymasterUrl),\n entryPoint: environment.accountAbstraction.entryPoint,\n });\n\n return createSmartAccountClient({\n account,\n chain: environment.chain,\n paymaster,\n bundlerTransport: http(environment.accountAbstraction.bundlerUrl),\n userOperation: {\n estimateFeesPerGas: async () => (await paymaster.getUserOperationGasPrice()).fast,\n },\n });\n}\n\nfunction addUserOperationGasBuffer(gas: bigint): bigint {\n const percentBuffer = (gas * USER_OPERATION_GAS_BUFFER_BPS) / 10_000n;\n return (\n gas +\n (percentBuffer > USER_OPERATION_MIN_GAS_BUFFER\n ? percentBuffer\n : USER_OPERATION_MIN_GAS_BUFFER)\n );\n}\n\nfunction bufferPolyesterUserOperationGas<T extends PolyesterUserOperationGas>(gas: T): T {\n return {\n ...gas,\n ...(typeof gas.callGasLimit === \"bigint\"\n ? { callGasLimit: addUserOperationGasBuffer(gas.callGasLimit) }\n : {}),\n ...(typeof gas.preVerificationGas === \"bigint\"\n ? { preVerificationGas: addUserOperationGasBuffer(gas.preVerificationGas) }\n : {}),\n ...(typeof gas.verificationGasLimit === \"bigint\"\n ? { verificationGasLimit: addUserOperationGasBuffer(gas.verificationGasLimit) }\n : {}),\n ...(typeof gas.paymasterPostOpGasLimit === \"bigint\"\n ? { paymasterPostOpGasLimit: addUserOperationGasBuffer(gas.paymasterPostOpGasLimit) }\n : {}),\n ...(typeof gas.paymasterVerificationGasLimit === \"bigint\"\n ? {\n paymasterVerificationGasLimit: addUserOperationGasBuffer(\n gas.paymasterVerificationGasLimit,\n ),\n }\n : {}),\n };\n}\n\nexport async function sendPolyesterUserOperation(\n client: PolyesterSmartAccountClient,\n parameters: Parameters<PolyesterSmartAccountClient[\"sendUserOperation\"]>[0],\n): Promise<Awaited<ReturnType<PolyesterSmartAccountClient[\"sendUserOperation\"]>>> {\n try {\n const gas = await client.estimateUserOperationGas({\n callGasLimit: 0n,\n preVerificationGas: 0n,\n verificationGasLimit: 0n,\n ...parameters,\n } as Parameters<PolyesterSmartAccountClient[\"estimateUserOperationGas\"]>[0]);\n return client.sendUserOperation({\n ...parameters,\n ...bufferPolyesterUserOperationGas(gas),\n } as Parameters<PolyesterSmartAccountClient[\"sendUserOperation\"]>[0]);\n } catch {\n return client.sendUserOperation(parameters);\n }\n}\n"],"mappings":";;;;;;AAWA,MAAM,sDAAsC,IAAI,QAA0C;AAC1F,MAAM,gCAAgC;AACtC,MAAM,gCAAgC;AAuBtC,SAAgB,oCAAoC,EAChD,aACA,cACA,YAAY,MACuC;CACnD,MAAM,EACF,yBACA,sBACA,wBACA,uBACA,qBACA,YAAY,mBAAmB;CAEnC,OAAO,mBAAmB;EACtB,QAAQ,CAAC,YAAY;EACrB;EACA;EACA;EACA;EACA;EACA;CACJ,CAAC;AACL;;;;AAKA,eAAsB,4BAA4B,EAC9C,aACA,OACA,WACA,gBAC4D;CAC5D,MAAM,SACF,gBACA,mBAAmB;EACf,OAAO,YAAY;EACnB,WAAW,KAAK,YAAY,MAAM;CACtC,CAAC;CAEL,IAAI,OAAO,OAAO,MAAM,OAAO,MAAM,OAAO,YAAY,MAAM,IAC1D,MAAM,IAAI,MAAM,+DAA+D;CAGnF,MAAM,UAAU,MAAM,mBAAmB;EACrC;EACA,QAAQ,CAAC,KAAK;EACd;EACA,YAAY,YAAY,mBAAmB;EAC3C,GAAG,YAAY,mBAAmB;CACtC,CAAC;CACD,oCAAoC,IAAI,SAAS,YAAY,WAAW;CACxE,OAAO;AACX;;;;AAKA,SAAgB,kCACZ,SACA,QACF;CACE,MAAM,EAAE,gBAAgB;CACxB,MAAM,gCAAgC,oCAAoC,IAAI,OAAO;CACrF,IACI,iCACA,kCAAkC,YAAY,aAE9C,MAAM,IAAI,MAAM,8DAA8D;CAGlF,MAAM,YAAY,oBAAoB;EAClC,OAAO,YAAY;EACnB,WAAW,KAAK,YAAY,mBAAmB,YAAY;EAC3D,YAAY,YAAY,mBAAmB;CAC/C,CAAC;CAED,OAAO,yBAAyB;EAC5B;EACA,OAAO,YAAY;EACnB;EACA,kBAAkB,KAAK,YAAY,mBAAmB,UAAU;EAChE,eAAe,EACX,oBAAoB,aAAa,MAAM,UAAU,yBAAyB,EAAA,CAAG,KACjF;CACJ,CAAC;AACL;AAEA,SAAS,0BAA0B,KAAqB;CACpD,MAAM,gBAAiB,MAAM,gCAAiC;CAC9D,OACI,OACC,gBAAgB,gCACX,gBACA;AAEd;AAEA,SAAS,gCAAqE,KAAW;CACrF,OAAO;EACH,GAAG;EACH,GAAI,OAAO,IAAI,iBAAiB,WAC1B,EAAE,cAAc,0BAA0B,IAAI,YAAY,EAAE,IAC5D,CAAC;EACP,GAAI,OAAO,IAAI,uBAAuB,WAChC,EAAE,oBAAoB,0BAA0B,IAAI,kBAAkB,EAAE,IACxE,CAAC;EACP,GAAI,OAAO,IAAI,yBAAyB,WAClC,EAAE,sBAAsB,0BAA0B,IAAI,oBAAoB,EAAE,IAC5E,CAAC;EACP,GAAI,OAAO,IAAI,4BAA4B,WACrC,EAAE,yBAAyB,0BAA0B,IAAI,uBAAuB,EAAE,IAClF,CAAC;EACP,GAAI,OAAO,IAAI,kCAAkC,WAC3C,EACI,+BAA+B,0BAC3B,IAAI,6BACR,EACJ,IACA,CAAC;CACX;AACJ;AAEA,eAAsB,2BAClB,QACA,YAC8E;CAC9E,IAAI;EACA,MAAM,MAAM,MAAM,OAAO,yBAAyB;GAC9C,cAAc;GACd,oBAAoB;GACpB,sBAAsB;GACtB,GAAG;EACP,CAA2E;EAC3E,OAAO,OAAO,kBAAkB;GAC5B,GAAG;GACH,GAAG,gCAAgC,GAAG;EAC1C,CAAoE;CACxE,QAAQ;EACJ,OAAO,OAAO,kBAAkB,UAAU;CAC9C;AACJ"}
|
|
1
|
+
{"version":3,"file":"smart-account.js","names":[],"sources":["../../src/smart-account/smart-account.ts"],"sourcesContent":["import type { Address, LocalAccount, PublicClient } from \"viem\";\nimport { createPublicClient, http } from \"viem\";\nimport type { EstimateUserOperationGasParameters } from \"viem/account-abstraction\";\nimport { estimateUserOperationGas, prepareUserOperation } from \"viem/account-abstraction\";\nimport { createSmartAccountClient } from \"permissionless\";\nimport { toSafeSmartAccount } from \"permissionless/accounts\";\nimport { createPimlicoClient } from \"permissionless/clients/pimlico\";\nimport type { PolyesterEnvironment } from \"../environment.js\";\nimport { predictSafeAddress } from \"../account-signer/predict-safe-address.js\";\n\nexport type SafeSmartAccountInstance = Awaited<ReturnType<typeof toSafeSmartAccount>>;\nexport type PolyesterSmartAccountClient = ReturnType<typeof createPolyesterSmartAccountClient>;\n\nconst smartAccountEnvironmentFingerprints = new WeakMap<SafeSmartAccountInstance, string>();\nconst smartAccountClientGasPricePrimers = new WeakMap<object, () => Promise<unknown>>();\nconst USER_OPERATION_GAS_BUFFER_BPS = 2_000n;\nconst USER_OPERATION_MIN_GAS_BUFFER = 50_000n;\nconst USER_OPERATION_GAS_PRICE_TTL_MS = 10_000;\nconst USER_OPERATION_RECEIPT_POLLING_INTERVAL_MS = 1_000;\n\ntype PolyesterUserOperationGas = {\n callGasLimit?: bigint;\n preVerificationGas?: bigint;\n verificationGasLimit?: bigint;\n paymasterPostOpGasLimit?: bigint;\n paymasterVerificationGasLimit?: bigint;\n};\n\nexport interface CreateSmartAccountParams {\n environment: PolyesterEnvironment;\n owner: LocalAccount;\n saltNonce?: bigint;\n publicClient?: PublicClient;\n}\n\nexport interface PredictPolyesterSmartAccountAddressParams {\n environment: PolyesterEnvironment;\n ownerAddress: Address;\n saltNonce?: bigint;\n}\n\nexport function predictPolyesterSmartAccountAddress({\n environment,\n ownerAddress,\n saltNonce = 0n,\n}: PredictPolyesterSmartAccountAddressParams): Address {\n const {\n safeProxyFactoryAddress,\n safeSingletonAddress,\n safeModuleSetupAddress,\n safe4337ModuleAddress,\n multiSendAddress,\n } = environment.accountAbstraction.safe;\n\n return predictSafeAddress({\n owners: [ownerAddress],\n saltNonce,\n safeProxyFactoryAddress,\n safeSingletonAddress,\n safeModuleSetupAddress,\n safe4337ModuleAddress,\n multiSendAddress,\n });\n}\n\n/**\n * Creates a Polyester smart account instance.\n */\nexport async function createPolyesterSmartAccount({\n environment,\n owner,\n saltNonce,\n publicClient,\n}: CreateSmartAccountParams): Promise<SafeSmartAccountInstance> {\n const client =\n publicClient ??\n createPublicClient({\n chain: environment.chain,\n transport: http(environment.rpcUrl),\n });\n\n if (client.chain?.id && client.chain.id !== environment.chain.id) {\n throw new Error(\"Smart account public client chain does not match environment.\");\n }\n\n const account = await toSafeSmartAccount({\n client,\n owners: [owner],\n saltNonce,\n entryPoint: environment.accountAbstraction.entryPoint,\n ...environment.accountAbstraction.safe,\n });\n smartAccountEnvironmentFingerprints.set(account, environment.fingerprint);\n return account;\n}\n\nexport interface PolyesterSmartAccountClientOptions {\n /** How long a fetched gas price is reused, in milliseconds. Defaults to 10s. */\n gasPriceCacheTtlMs?: number;\n /** How often to poll for UserOperation receipts, in milliseconds. Defaults to 1s. */\n pollingIntervalMs?: number;\n}\n\n/**\n * Creates a viem client bound to a Polyester smart account.\n */\nexport function createPolyesterSmartAccountClient(\n account: SafeSmartAccountInstance,\n params: {\n environment: PolyesterEnvironment;\n options?: PolyesterSmartAccountClientOptions;\n },\n) {\n const { environment, options } = params;\n const {\n gasPriceCacheTtlMs = USER_OPERATION_GAS_PRICE_TTL_MS,\n pollingIntervalMs = USER_OPERATION_RECEIPT_POLLING_INTERVAL_MS,\n } = options ?? {};\n const accountEnvironmentFingerprint = smartAccountEnvironmentFingerprints.get(account);\n if (\n accountEnvironmentFingerprint &&\n accountEnvironmentFingerprint !== environment.fingerprint\n ) {\n throw new Error(\"Smart account environment does not match client environment.\");\n }\n\n const paymaster = createPimlicoClient({\n chain: environment.chain,\n transport: http(environment.accountAbstraction.paymasterUrl),\n entryPoint: environment.accountAbstraction.entryPoint,\n });\n\n let cachedGasPrice:\n | { fetchedAt: number; result: ReturnType<typeof paymaster.getUserOperationGasPrice> }\n | undefined;\n const getGasPrice = () => {\n if (!cachedGasPrice || Date.now() - cachedGasPrice.fetchedAt >= gasPriceCacheTtlMs) {\n const result = paymaster.getUserOperationGasPrice();\n const entry = { fetchedAt: Date.now(), result };\n cachedGasPrice = entry;\n result.catch(() => {\n if (cachedGasPrice === entry) cachedGasPrice = undefined;\n });\n }\n return cachedGasPrice.result;\n };\n\n const client = createSmartAccountClient({\n account,\n chain: environment.chain,\n paymaster,\n bundlerTransport: http(environment.accountAbstraction.bundlerUrl),\n pollingInterval: pollingIntervalMs,\n userOperation: {\n estimateFeesPerGas: async () => (await getGasPrice()).fast,\n // Single prepare pass: viem resolves gas estimation via\n // `getAction(client, estimateUserOperationGas, ...)`, so handing\n // `prepareUserOperation` a client whose estimate action buffers the\n // result makes the buffered limits flow into `pm_getPaymasterData`\n // before signing — the sponsorship signature commits to them.\n prepareUserOperation: (prepareClient, prepareParameters) => {\n const bufferingClient = {\n ...prepareClient,\n estimateUserOperationGas: async (\n estimateParameters: EstimateUserOperationGasParameters,\n ) =>\n bufferPolyesterUserOperationGas(\n await estimateUserOperationGas(prepareClient, estimateParameters),\n ),\n };\n return prepareUserOperation(\n bufferingClient as typeof prepareClient,\n prepareParameters as Parameters<typeof prepareUserOperation>[1],\n );\n },\n },\n });\n smartAccountClientGasPricePrimers.set(client, getGasPrice);\n return client;\n}\n\n/**\n * Warms the network path for an upcoming submission: primes the gas-price\n * cache and opens connections to the RPC endpoint. Never throws; the nonce is\n * intentionally not cached — fetching it here is connection warm-up only.\n */\nexport async function warmPolyesterSmartAccountClient(\n client: PolyesterSmartAccountClient,\n): Promise<void> {\n await Promise.allSettled([\n smartAccountClientGasPricePrimers.get(client)?.(),\n client.account.getNonce(),\n client.account.isDeployed(),\n ]);\n}\n\nfunction addUserOperationGasBuffer(gas: bigint): bigint {\n const percentBuffer = (gas * USER_OPERATION_GAS_BUFFER_BPS) / 10_000n;\n return (\n gas +\n (percentBuffer > USER_OPERATION_MIN_GAS_BUFFER\n ? percentBuffer\n : USER_OPERATION_MIN_GAS_BUFFER)\n );\n}\n\nfunction bufferPolyesterUserOperationGas<T extends PolyesterUserOperationGas>(gas: T): T {\n return {\n ...gas,\n ...(typeof gas.callGasLimit === \"bigint\"\n ? { callGasLimit: addUserOperationGasBuffer(gas.callGasLimit) }\n : {}),\n ...(typeof gas.preVerificationGas === \"bigint\"\n ? { preVerificationGas: addUserOperationGasBuffer(gas.preVerificationGas) }\n : {}),\n ...(typeof gas.verificationGasLimit === \"bigint\"\n ? { verificationGasLimit: addUserOperationGasBuffer(gas.verificationGasLimit) }\n : {}),\n ...(typeof gas.paymasterPostOpGasLimit === \"bigint\"\n ? { paymasterPostOpGasLimit: addUserOperationGasBuffer(gas.paymasterPostOpGasLimit) }\n : {}),\n ...(typeof gas.paymasterVerificationGasLimit === \"bigint\"\n ? {\n paymasterVerificationGasLimit: addUserOperationGasBuffer(\n gas.paymasterVerificationGasLimit,\n ),\n }\n : {}),\n };\n}\n\nexport interface SendPolyesterUserOperationOptions {\n /**\n * Fires once per submission, immediately before the wallet is asked to\n * sign the fully prepared operation — the prepare→sign boundary.\n */\n onWalletSignatureRequested?: () => void;\n}\n\nexport async function sendPolyesterUserOperation(\n client: PolyesterSmartAccountClient,\n parameters: Parameters<PolyesterSmartAccountClient[\"sendUserOperation\"]>[0],\n options: SendPolyesterUserOperationOptions = {},\n): Promise<Awaited<ReturnType<PolyesterSmartAccountClient[\"sendUserOperation\"]>>> {\n const { onWalletSignatureRequested } = options;\n if (!onWalletSignatureRequested) return client.sendUserOperation(parameters);\n\n const account =\n (parameters as { account?: SafeSmartAccountInstance }).account ?? client.account;\n return client.sendUserOperation({\n ...parameters,\n account: {\n ...account,\n signUserOperation: (\n userOperation: Parameters<SafeSmartAccountInstance[\"signUserOperation\"]>[0],\n ) => {\n onWalletSignatureRequested();\n return account.signUserOperation(userOperation);\n },\n },\n } as Parameters<PolyesterSmartAccountClient[\"sendUserOperation\"]>[0]);\n}\n"],"mappings":";;;;;;;AAaA,MAAM,sDAAsC,IAAI,QAA0C;AAC1F,MAAM,oDAAoC,IAAI,QAAwC;AACtF,MAAM,gCAAgC;AACtC,MAAM,gCAAgC;AACtC,MAAM,kCAAkC;AACxC,MAAM,6CAA6C;AAuBnD,SAAgB,oCAAoC,EAChD,aACA,cACA,YAAY,MACuC;CACnD,MAAM,EACF,yBACA,sBACA,wBACA,uBACA,qBACA,YAAY,mBAAmB;CAEnC,OAAO,mBAAmB;EACtB,QAAQ,CAAC,YAAY;EACrB;EACA;EACA;EACA;EACA;EACA;CACJ,CAAC;AACL;;;;AAKA,eAAsB,4BAA4B,EAC9C,aACA,OACA,WACA,gBAC4D;CAC5D,MAAM,SACF,gBACA,mBAAmB;EACf,OAAO,YAAY;EACnB,WAAW,KAAK,YAAY,MAAM;CACtC,CAAC;CAEL,IAAI,OAAO,OAAO,MAAM,OAAO,MAAM,OAAO,YAAY,MAAM,IAC1D,MAAM,IAAI,MAAM,+DAA+D;CAGnF,MAAM,UAAU,MAAM,mBAAmB;EACrC;EACA,QAAQ,CAAC,KAAK;EACd;EACA,YAAY,YAAY,mBAAmB;EAC3C,GAAG,YAAY,mBAAmB;CACtC,CAAC;CACD,oCAAoC,IAAI,SAAS,YAAY,WAAW;CACxE,OAAO;AACX;;;;AAYA,SAAgB,kCACZ,SACA,QAIF;CACE,MAAM,EAAE,aAAa,YAAY;CACjC,MAAM,EACF,qBAAqB,iCACrB,oBAAoB,+CACpB,WAAW,CAAC;CAChB,MAAM,gCAAgC,oCAAoC,IAAI,OAAO;CACrF,IACI,iCACA,kCAAkC,YAAY,aAE9C,MAAM,IAAI,MAAM,8DAA8D;CAGlF,MAAM,YAAY,oBAAoB;EAClC,OAAO,YAAY;EACnB,WAAW,KAAK,YAAY,mBAAmB,YAAY;EAC3D,YAAY,YAAY,mBAAmB;CAC/C,CAAC;CAED,IAAI;CAGJ,MAAM,oBAAoB;EACtB,IAAI,CAAC,kBAAkB,KAAK,IAAI,IAAI,eAAe,aAAa,oBAAoB;GAChF,MAAM,SAAS,UAAU,yBAAyB;GAClD,MAAM,QAAQ;IAAE,WAAW,KAAK,IAAI;IAAG;GAAO;GAC9C,iBAAiB;GACjB,OAAO,YAAY;IACf,IAAI,mBAAmB,OAAO,iBAAiB,KAAA;GACnD,CAAC;EACL;EACA,OAAO,eAAe;CAC1B;CAEA,MAAM,SAAS,yBAAyB;EACpC;EACA,OAAO,YAAY;EACnB;EACA,kBAAkB,KAAK,YAAY,mBAAmB,UAAU;EAChE,iBAAiB;EACjB,eAAe;GACX,oBAAoB,aAAa,MAAM,YAAY,EAAA,CAAG;GAMtD,uBAAuB,eAAe,sBAAsB;IACxD,MAAM,kBAAkB;KACpB,GAAG;KACH,0BAA0B,OACtB,uBAEA,gCACI,MAAM,yBAAyB,eAAe,kBAAkB,CACpE;IACR;IACA,OAAO,qBACH,iBACA,iBACJ;GACJ;EACJ;CACJ,CAAC;CACD,kCAAkC,IAAI,QAAQ,WAAW;CACzD,OAAO;AACX;;;;;;AAOA,eAAsB,gCAClB,QACa;CACb,MAAM,QAAQ,WAAW;EACrB,kCAAkC,IAAI,MAAM,CAAC,GAAG;EAChD,OAAO,QAAQ,SAAS;EACxB,OAAO,QAAQ,WAAW;CAC9B,CAAC;AACL;AAEA,SAAS,0BAA0B,KAAqB;CACpD,MAAM,gBAAiB,MAAM,gCAAiC;CAC9D,OACI,OACC,gBAAgB,gCACX,gBACA;AAEd;AAEA,SAAS,gCAAqE,KAAW;CACrF,OAAO;EACH,GAAG;EACH,GAAI,OAAO,IAAI,iBAAiB,WAC1B,EAAE,cAAc,0BAA0B,IAAI,YAAY,EAAE,IAC5D,CAAC;EACP,GAAI,OAAO,IAAI,uBAAuB,WAChC,EAAE,oBAAoB,0BAA0B,IAAI,kBAAkB,EAAE,IACxE,CAAC;EACP,GAAI,OAAO,IAAI,yBAAyB,WAClC,EAAE,sBAAsB,0BAA0B,IAAI,oBAAoB,EAAE,IAC5E,CAAC;EACP,GAAI,OAAO,IAAI,4BAA4B,WACrC,EAAE,yBAAyB,0BAA0B,IAAI,uBAAuB,EAAE,IAClF,CAAC;EACP,GAAI,OAAO,IAAI,kCAAkC,WAC3C,EACI,+BAA+B,0BAC3B,IAAI,6BACR,EACJ,IACA,CAAC;CACX;AACJ;AAUA,eAAsB,2BAClB,QACA,YACA,UAA6C,CAAC,GACgC;CAC9E,MAAM,EAAE,+BAA+B;CACvC,IAAI,CAAC,4BAA4B,OAAO,OAAO,kBAAkB,UAAU;CAE3E,MAAM,UACD,WAAsD,WAAW,OAAO;CAC7E,OAAO,OAAO,kBAAkB;EAC5B,GAAG;EACH,SAAS;GACL,GAAG;GACH,oBACI,kBACC;IACD,2BAA2B;IAC3B,OAAO,QAAQ,kBAAkB,aAAa;GAClD;EACJ;CACJ,CAAoE;AACxE"}
|
package/package.json
CHANGED