@drift-labs/common 1.0.13 → 1.0.14

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../src/drift/base/actions/trade/openPerpOrder/dlobServer/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tDriftClient,\n\tUser,\n\tBN,\n\tPositionDirection,\n\tOptionalOrderParams,\n\tMarketType,\n\tUserAccount,\n\tPublicKey,\n\tdecodeUser,\n\tDefaultOrderParams,\n\tBASE_PRECISION,\n\tTEN,\n} from '@drift-labs/sdk';\nimport { ENUM_UTILS } from '../../../../../../utils';\nimport {\n\tmapAuctionParamsResponse,\n\tServerAuctionParamsResponse,\n\tMappedAuctionParams,\n} from '../../../../../utils/auctionParamsResponseMapper';\nimport { encodeQueryParams } from '../../../../../../utils/fetch';\nimport { MarketId, TradeOffsetPrice } from '../../../../../../types';\nimport {\n\tconvertToL2OrderBook,\n\tdeserializeL2Response,\n\tL2WithOracleAndMarketData,\n\tRawL2Output,\n\tcalculateDynamicSlippageFromL2,\n\tDynamicSlippageConfig,\n} from '../../../../../../utils/orderbook';\nimport { PollingSequenceGuard } from '../../../../../../utils/pollingSequenceGuard';\nimport { calculatePriceImpactFromL2 } from '../../../../../../utils/priceImpact';\nimport { COMMON_UI_UTILS } from '../../../../../../common-ui-utils';\nimport invariant from 'tiny-invariant';\n\nexport interface OptionalAuctionParamsRequestInputs {\n\t// Optional parameters that can override defaults or provide additional configuration\n\tmaxLeverageSelected?: boolean;\n\tmaxLeverageOrderSize?: BN;\n\treduceOnly?: boolean;\n\tauctionDuration?: number;\n\tauctionStartPriceOffset?: number;\n\tauctionEndPriceOffset?: number;\n\tauctionStartPriceOffsetFrom?: TradeOffsetPrice;\n\tauctionEndPriceOffsetFrom?: TradeOffsetPrice;\n\tslippageTolerance?: number | 'dynamic';\n\tauctionPriceCaps?: {\n\t\tmin: BN;\n\t\tmax: BN;\n\t};\n\tisOracleOrder?: boolean;\n\tadditionalEndPriceBuffer?: BN;\n\tforceUpToSlippage?: boolean;\n\torderType?: 'market' | 'oracle';\n}\n\ninterface RegularOrderParams {\n\tdriftClient: DriftClient;\n\tuser: User;\n\tassetType: 'base' | 'quote';\n\tmarketType: MarketType;\n\tmarketIndex: number;\n\tdirection: PositionDirection;\n\tamount: BN;\n\toptionalAuctionParamsInputs?: OptionalAuctionParamsRequestInputs;\n\tdlobServerHttpUrl: string;\n\tdynamicSlippageConfig?: DynamicSlippageConfig;\n}\n\nexport interface BulkL2FetchingQueryParams {\n\tmarketIndex: number;\n\tmarketType: string;\n\tdepth: number;\n\tincludeVamm: boolean;\n\tincludePhoenix: boolean;\n\tincludeOpenbook: boolean;\n\tincludeSerum: boolean;\n\tincludeOracle: boolean;\n\tincludeIndicative: boolean;\n}\n\nexport interface BulkL2FetchingParams {\n\tmarkets: BulkL2FetchingQueryParams[];\n\tgrouping?: number;\n}\n\nconst BACKGROUND_L2_POLLING_KEY = Symbol('BACKGROUND_L2_POLLING_KEY');\n\n/**\n * Fetches the L2 data for the given markets and their depth\n */\nexport function fetchBulkMarketsDlobL2Data(\n\tdlobServerHttpUrl: string,\n\tmarkets: {\n\t\tmarketId: MarketId;\n\t\tdepth: number;\n\t}[],\n\tgroupingSize?: number,\n\texcludeIndicativeLiquidity = false\n): Promise<L2WithOracleAndMarketData[]> {\n\tconst params: BulkL2FetchingParams = {\n\t\tmarkets: markets.map((m) => ({\n\t\t\tmarketIndex: m.marketId.marketIndex,\n\t\t\tmarketType: m.marketId.marketTypeStr,\n\t\t\tdepth: m.depth,\n\t\t\tincludeVamm: m.marketId.isPerp,\n\t\t\tincludePhoenix: m.marketId.isSpot,\n\t\t\tincludeSerum: m.marketId.isSpot,\n\t\t\tincludeOpenbook: m.marketId.isSpot,\n\t\t\tincludeOracle: true,\n\t\t\tincludeIndicative: !excludeIndicativeLiquidity,\n\t\t})),\n\t\tgrouping: groupingSize,\n\t};\n\n\tconst queryParamsMap: {\n\t\t[K in keyof BulkL2FetchingQueryParams]: string;\n\t} & {\n\t\tgrouping?: string;\n\t} = {\n\t\tmarketType: params.markets.map((market) => market.marketType).join(','),\n\t\tmarketIndex: params.markets.map((market) => market.marketIndex).join(','),\n\t\tdepth: params.markets.map((market) => market.depth).join(','),\n\t\tincludeVamm: params.markets.map((market) => market.includeVamm).join(','),\n\t\tincludePhoenix: params.markets\n\t\t\t.map((market) => market.includePhoenix)\n\t\t\t.join(','),\n\t\tincludeOpenbook: params.markets\n\t\t\t.map((market) => market.includeOpenbook)\n\t\t\t.join(','),\n\t\tincludeSerum: params.markets.map((market) => market.includeSerum).join(','),\n\t\tgrouping: params.grouping\n\t\t\t? params.markets.map(() => params.grouping).join(',')\n\t\t\t: undefined,\n\t\tincludeOracle: params.markets\n\t\t\t.map((market) => market.includeOracle)\n\t\t\t.join(','),\n\t\tincludeIndicative: params.markets\n\t\t\t.map((market) => market.includeIndicative)\n\t\t\t.join(','),\n\t};\n\n\tconst queryParams = encodeQueryParams(queryParamsMap);\n\n\t// Use cached endpoint when exclusively fetching background markets\n\tconst useCachedEndpoint = !params.markets.some(\n\t\t(market) => market.depth !== 1\n\t);\n\n\tconst endpoint = useCachedEndpoint\n\t\t? `${dlobServerHttpUrl}/batchL2Cache`\n\t\t: `${dlobServerHttpUrl}/batchL2`;\n\n\treturn new Promise<L2WithOracleAndMarketData[]>((resolve, reject) => {\n\t\tPollingSequenceGuard.fetch(BACKGROUND_L2_POLLING_KEY, () => {\n\t\t\treturn fetch(`${endpoint}?${queryParams}`);\n\t\t})\n\t\t\t.then(async (response) => {\n\t\t\t\tconst responseData = await response.json();\n\t\t\t\tconst resultsArray = responseData.l2s as RawL2Output[];\n\t\t\t\tconst deserializedL2 = resultsArray.map(deserializeL2Response);\n\t\t\t\tresolve(deserializedL2);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\treject(error);\n\t\t\t});\n\t});\n}\n\nexport async function fetchAuctionOrderParams(params: RegularOrderParams) {\n\ttry {\n\t\treturn await fetchAuctionOrderParamsFromDlob(params);\n\t} catch (error) {\n\t\tconsole.error(error);\n\t\tconsole.log('Falling back to L2 data');\n\t\treturn await fetchAuctionOrderParamsFromL2(params);\n\t}\n}\n\nconst calcBaseFromQuote = (\n\tdriftClient: DriftClient,\n\tmarketType: MarketType,\n\tmarketIndex: number,\n\tamount: BN\n) => {\n\tconst isPerp = ENUM_UTILS.match(marketType, MarketType.PERP);\n\n\tconst oraclePrice = isPerp\n\t\t? driftClient.getOracleDataForPerpMarket(marketIndex).price\n\t\t: driftClient.getOracleDataForSpotMarket(marketIndex).price;\n\n\tif (isPerp) {\n\t\treturn amount.mul(BASE_PRECISION).div(oraclePrice);\n\t} else {\n\t\tconst spotMarketAccount = driftClient.getSpotMarketAccount(marketIndex);\n\t\tinvariant(spotMarketAccount, 'Spot market account not found');\n\t\tconst precision = TEN.pow(new BN(spotMarketAccount.decimals));\n\t\treturn amount.mul(precision).div(oraclePrice);\n\t}\n};\n\n/**\n * Fetches auction order parameters from the auction params endpoint\n */\nexport async function fetchAuctionOrderParamsFromDlob({\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tamount,\n\tdlobServerHttpUrl,\n\tassetType,\n\tdriftClient,\n\toptionalAuctionParamsInputs = {},\n}: RegularOrderParams): Promise<OptionalOrderParams> {\n\tconst baseAmount =\n\t\tassetType === 'base'\n\t\t\t? amount\n\t\t\t: calcBaseFromQuote(driftClient, marketType, marketIndex, amount);\n\n\t// Build URL parameters for server request\n\tconst urlParamsObject: Record<string, string> = {\n\t\t// Required fields\n\t\tassetType: 'base',\n\t\tmarketType: ENUM_UTILS.toStr(marketType),\n\t\tmarketIndex: marketIndex.toString(),\n\t\tdirection: ENUM_UTILS.toStr(direction),\n\t\tamount: baseAmount.toString(),\n\t};\n\n\t// Add defined optional parameters\n\tObject.entries(optionalAuctionParamsInputs).forEach(([key, value]) => {\n\t\tif (value !== undefined) {\n\t\t\turlParamsObject[key] = value.toString();\n\t\t}\n\t});\n\n\tconst urlParams = encodeQueryParams(urlParamsObject);\n\n\t// Get order params from server\n\tconst requestUrl = `${dlobServerHttpUrl}/auctionParams?${urlParams.toString()}`;\n\tconst response = await fetch(requestUrl);\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Server responded with ${response.status}: ${response.statusText}`\n\t\t);\n\t}\n\n\tconst serverResponse: ServerAuctionParamsResponse = await response.json();\n\tconst serverAuctionParams = serverResponse?.data?.params;\n\tinvariant(serverAuctionParams, 'Server auction params are required');\n\tconst mappedParams: MappedAuctionParams =\n\t\tmapAuctionParamsResponse(serverAuctionParams);\n\n\t// Convert MappedAuctionParams to OptionalOrderParams\n\treturn {\n\t\torderType: mappedParams.orderType,\n\t\tmarketType: mappedParams.marketType,\n\t\tuserOrderId: mappedParams.userOrderId,\n\t\tdirection: mappedParams.direction,\n\t\tbaseAssetAmount: mappedParams.baseAssetAmount,\n\t\tmarketIndex: mappedParams.marketIndex,\n\t\treduceOnly: mappedParams.reduceOnly,\n\t\tpostOnly: mappedParams.postOnly ?? DefaultOrderParams.postOnly,\n\t\ttriggerPrice: mappedParams.triggerPrice || null,\n\t\ttriggerCondition:\n\t\t\tmappedParams.triggerCondition ?? DefaultOrderParams.triggerCondition,\n\t\toraclePriceOffset: mappedParams.oraclePriceOffset?.toNumber() || null,\n\t\tauctionDuration: mappedParams.auctionDuration || null,\n\t\tmaxTs: mappedParams.maxTs,\n\t\tauctionStartPrice: mappedParams.auctionStartPrice || null,\n\t\tauctionEndPrice: mappedParams.auctionEndPrice || null,\n\t\t// no price, because market orders don't need a price\n\t};\n}\n\nconst DEFAULT_L2_DEPTH_FOR_AUCTION_ORDER_PARAMS = 100;\n\n/**\n * Fetches auction order parameters from the L2 data\n */\nexport async function fetchAuctionOrderParamsFromL2({\n\tdlobServerHttpUrl,\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tassetType,\n\tamount,\n\toptionalAuctionParamsInputs,\n\tdriftClient,\n\tdynamicSlippageConfig,\n}: RegularOrderParams): Promise<OptionalOrderParams> {\n\tconst marketId = new MarketId(marketIndex, marketType);\n\tconst baseAmount =\n\t\tassetType === 'base'\n\t\t\t? amount\n\t\t\t: calcBaseFromQuote(driftClient, marketType, marketIndex, amount);\n\n\tconst l2DataResponse = await fetchBulkMarketsDlobL2Data(dlobServerHttpUrl, [\n\t\t{\n\t\t\tmarketId,\n\t\t\tdepth: DEFAULT_L2_DEPTH_FOR_AUCTION_ORDER_PARAMS,\n\t\t},\n\t]);\n\tconst oraclePriceData = l2DataResponse[0].oracleData;\n\tconst oraclePriceBn = oraclePriceData?.price;\n\tconst markPriceBn = l2DataResponse[0].markPrice;\n\tconst l2Data = convertToL2OrderBook(l2DataResponse);\n\n\tconst priceImpactData = calculatePriceImpactFromL2(\n\t\tmarketId,\n\t\tdirection,\n\t\tbaseAmount,\n\t\tl2Data,\n\t\toraclePriceBn\n\t);\n\n\tconst startPrices = COMMON_UI_UTILS.getPriceObject({\n\t\toraclePrice: oraclePriceBn,\n\t\tbestOffer: priceImpactData.bestPrice,\n\t\tentryPrice: priceImpactData.entryPrice,\n\t\tworstPrice: priceImpactData.worstPrice,\n\t\tmarkPrice: markPriceBn,\n\t\tdirection: direction,\n\t});\n\tconst slippageToleranceInput = optionalAuctionParamsInputs.slippageTolerance;\n\tconst derivedSlippage =\n\t\tslippageToleranceInput === 'dynamic'\n\t\t\t? calculateDynamicSlippageFromL2({\n\t\t\t\t\tl2Data,\n\t\t\t\t\tmarketId,\n\t\t\t\t\tstartPrice:\n\t\t\t\t\t\tstartPrices[\n\t\t\t\t\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffsetFrom as keyof typeof startPrices\n\t\t\t\t\t\t],\n\t\t\t\t\tworstPrice: priceImpactData.worstPrice,\n\t\t\t\t\toraclePrice: oraclePriceBn,\n\t\t\t\t\tdynamicSlippageConfig,\n\t\t\t })\n\t\t\t: typeof slippageToleranceInput === 'number'\n\t\t\t? slippageToleranceInput\n\t\t\t: 0.005;\n\n\tconst auctionOrderParams = COMMON_UI_UTILS.deriveMarketOrderParams({\n\t\tmarketType: marketType,\n\t\tmarketIndex: marketIndex,\n\t\tdirection: direction,\n\t\tmaxLeverageSelected: optionalAuctionParamsInputs.maxLeverageSelected,\n\t\tmaxLeverageOrderSize: optionalAuctionParamsInputs.maxLeverageOrderSize,\n\t\tbaseAmount: baseAmount,\n\t\treduceOnly: optionalAuctionParamsInputs.reduceOnly,\n\t\tallowInfSlippage: false,\n\t\toraclePrice: oraclePriceBn,\n\t\tbestPrice: priceImpactData.bestPrice,\n\t\tentryPrice: priceImpactData.entryPrice,\n\t\tworstPrice: priceImpactData.worstPrice,\n\t\tmarkPrice: markPriceBn,\n\t\tauctionDuration: optionalAuctionParamsInputs.auctionDuration,\n\t\tauctionStartPriceOffset:\n\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffset,\n\t\tauctionEndPriceOffset: optionalAuctionParamsInputs.auctionEndPriceOffset,\n\t\tauctionStartPriceOffsetFrom:\n\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffsetFrom,\n\t\tauctionEndPriceOffsetFrom:\n\t\t\toptionalAuctionParamsInputs.auctionEndPriceOffsetFrom,\n\t\tslippageTolerance: derivedSlippage,\n\t\tisOracleOrder: optionalAuctionParamsInputs.isOracleOrder,\n\t\tadditionalEndPriceBuffer:\n\t\t\toptionalAuctionParamsInputs.additionalEndPriceBuffer,\n\t\tforceUpToSlippage: optionalAuctionParamsInputs.forceUpToSlippage,\n\t});\n\n\tif (!auctionOrderParams) {\n\t\tthrow new Error('Failed to derive auction params from L2');\n\t}\n\n\treturn auctionOrderParams;\n}\n\ntype FetchTopMakersParams = {\n\tdlobServerHttpUrl: string;\n\tmarketIndex: number;\n\tmarketType: MarketType;\n\tside: 'bid' | 'ask';\n\tlimit: number;\n};\n\n/**\n * Fetches the top makers information, for use as inputs in placeAndTake market orders.\n * The side of the request should be opposite of the side of the placeAndTake market order.\n */\nexport async function fetchTopMakers(params: FetchTopMakersParams): Promise<\n\t{\n\t\tuserAccountPubKey: PublicKey;\n\t\tuserAccount: UserAccount;\n\t}[]\n> {\n\ttry {\n\t\tconst { dlobServerHttpUrl, marketIndex, marketType, side, limit } = params;\n\n\t\tconst urlParams = encodeQueryParams({\n\t\t\tmarketIndex: marketIndex.toString(),\n\t\t\tmarketType: ENUM_UTILS.toStr(marketType),\n\t\t\tside,\n\t\t\tlimit: limit.toString(),\n\t\t\tincludeAccounts: 'true',\n\t\t});\n\n\t\tconst requestUrl = `${dlobServerHttpUrl}/topMakers?${urlParams}`;\n\t\tconst response = await fetch(requestUrl);\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Server responded with ${response.status}: ${response.statusText}`\n\t\t\t);\n\t\t}\n\n\t\tconst serverResponse: {\n\t\t\tuserAccountPubKey: string;\n\t\t\taccountBase64: string;\n\t\t}[] = await response.json();\n\t\tconst mappedParams: {\n\t\t\tuserAccountPubKey: PublicKey;\n\t\t\tuserAccount: UserAccount;\n\t\t}[] = serverResponse.map((value) => ({\n\t\t\tuserAccountPubKey: new PublicKey(value.userAccountPubKey),\n\t\t\tuserAccount: decodeUser(Buffer.from(value.accountBase64, 'base64')),\n\t\t}));\n\n\t\treturn mappedParams;\n\t} catch (e) {\n\t\tconsole.error(e);\n\t\treturn [];\n\t}\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../src/drift/base/actions/trade/openPerpOrder/dlobServer/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tDriftClient,\n\tUser,\n\tBN,\n\tPositionDirection,\n\tOptionalOrderParams,\n\tMarketType,\n\tUserAccount,\n\tPublicKey,\n\tdecodeUser,\n\tDefaultOrderParams,\n\tBASE_PRECISION,\n\tTEN,\n} from '@drift-labs/sdk';\nimport { ENUM_UTILS } from '../../../../../../utils';\nimport {\n\tmapAuctionParamsResponse,\n\tServerAuctionParamsResponse,\n\tMappedAuctionParams,\n} from '../../../../../utils/auctionParamsResponseMapper';\nimport { encodeQueryParams } from '../../../../../../utils/fetch';\nimport { MarketId, TradeOffsetPrice } from '../../../../../../types';\nimport {\n\tconvertToL2OrderBook,\n\tdeserializeL2Response,\n\tL2WithOracleAndMarketData,\n\tRawL2Output,\n\tcalculateDynamicSlippageFromL2,\n\tDynamicSlippageConfig,\n} from '../../../../../../utils/orderbook';\nimport { PollingSequenceGuard } from '../../../../../../utils/pollingSequenceGuard';\nimport { calculatePriceImpactFromL2 } from '../../../../../../utils/priceImpact';\nimport { COMMON_UI_UTILS } from '../../../../../../common-ui-utils';\nimport invariant from 'tiny-invariant';\n\nexport interface OptionalAuctionParamsRequestInputs {\n\t// Optional parameters that can override defaults or provide additional configuration\n\tmaxLeverageSelected?: boolean;\n\tmaxLeverageOrderSize?: BN;\n\treduceOnly?: boolean;\n\tauctionDuration?: number;\n\tauctionStartPriceOffset?: number;\n\tauctionEndPriceOffset?: number;\n\tauctionStartPriceOffsetFrom?: TradeOffsetPrice;\n\tauctionEndPriceOffsetFrom?: TradeOffsetPrice;\n\tslippageTolerance?: number | 'dynamic';\n\tisOracleOrder?: boolean;\n\tadditionalEndPriceBuffer?: BN;\n\tforceUpToSlippage?: boolean;\n}\n\ninterface RegularOrderParams {\n\tdriftClient: DriftClient;\n\tuser: User;\n\tassetType: 'base' | 'quote';\n\tmarketType: MarketType;\n\tmarketIndex: number;\n\tdirection: PositionDirection;\n\tamount: BN;\n\toptionalAuctionParamsInputs?: OptionalAuctionParamsRequestInputs;\n\tdlobServerHttpUrl: string;\n\tdynamicSlippageConfig?: DynamicSlippageConfig;\n}\n\nexport interface BulkL2FetchingQueryParams {\n\tmarketIndex: number;\n\tmarketType: string;\n\tdepth: number;\n\tincludeVamm: boolean;\n\tincludePhoenix: boolean;\n\tincludeOpenbook: boolean;\n\tincludeSerum: boolean;\n\tincludeOracle: boolean;\n\tincludeIndicative: boolean;\n}\n\nexport interface BulkL2FetchingParams {\n\tmarkets: BulkL2FetchingQueryParams[];\n\tgrouping?: number;\n}\n\nconst BACKGROUND_L2_POLLING_KEY = Symbol('BACKGROUND_L2_POLLING_KEY');\n\n/**\n * Fetches the L2 data for the given markets and their depth\n */\nexport function fetchBulkMarketsDlobL2Data(\n\tdlobServerHttpUrl: string,\n\tmarkets: {\n\t\tmarketId: MarketId;\n\t\tdepth: number;\n\t}[],\n\tgroupingSize?: number,\n\texcludeIndicativeLiquidity = false\n): Promise<L2WithOracleAndMarketData[]> {\n\tconst params: BulkL2FetchingParams = {\n\t\tmarkets: markets.map((m) => ({\n\t\t\tmarketIndex: m.marketId.marketIndex,\n\t\t\tmarketType: m.marketId.marketTypeStr,\n\t\t\tdepth: m.depth,\n\t\t\tincludeVamm: m.marketId.isPerp,\n\t\t\tincludePhoenix: m.marketId.isSpot,\n\t\t\tincludeSerum: m.marketId.isSpot,\n\t\t\tincludeOpenbook: m.marketId.isSpot,\n\t\t\tincludeOracle: true,\n\t\t\tincludeIndicative: !excludeIndicativeLiquidity,\n\t\t})),\n\t\tgrouping: groupingSize,\n\t};\n\n\tconst queryParamsMap: {\n\t\t[K in keyof BulkL2FetchingQueryParams]: string;\n\t} & {\n\t\tgrouping?: string;\n\t} = {\n\t\tmarketType: params.markets.map((market) => market.marketType).join(','),\n\t\tmarketIndex: params.markets.map((market) => market.marketIndex).join(','),\n\t\tdepth: params.markets.map((market) => market.depth).join(','),\n\t\tincludeVamm: params.markets.map((market) => market.includeVamm).join(','),\n\t\tincludePhoenix: params.markets\n\t\t\t.map((market) => market.includePhoenix)\n\t\t\t.join(','),\n\t\tincludeOpenbook: params.markets\n\t\t\t.map((market) => market.includeOpenbook)\n\t\t\t.join(','),\n\t\tincludeSerum: params.markets.map((market) => market.includeSerum).join(','),\n\t\tgrouping: params.grouping\n\t\t\t? params.markets.map(() => params.grouping).join(',')\n\t\t\t: undefined,\n\t\tincludeOracle: params.markets\n\t\t\t.map((market) => market.includeOracle)\n\t\t\t.join(','),\n\t\tincludeIndicative: params.markets\n\t\t\t.map((market) => market.includeIndicative)\n\t\t\t.join(','),\n\t};\n\n\tconst queryParams = encodeQueryParams(queryParamsMap);\n\n\t// Use cached endpoint when exclusively fetching background markets\n\tconst useCachedEndpoint = !params.markets.some(\n\t\t(market) => market.depth !== 1\n\t);\n\n\tconst endpoint = useCachedEndpoint\n\t\t? `${dlobServerHttpUrl}/batchL2Cache`\n\t\t: `${dlobServerHttpUrl}/batchL2`;\n\n\treturn new Promise<L2WithOracleAndMarketData[]>((resolve, reject) => {\n\t\tPollingSequenceGuard.fetch(BACKGROUND_L2_POLLING_KEY, () => {\n\t\t\treturn fetch(`${endpoint}?${queryParams}`);\n\t\t})\n\t\t\t.then(async (response) => {\n\t\t\t\tconst responseData = await response.json();\n\t\t\t\tconst resultsArray = responseData.l2s as RawL2Output[];\n\t\t\t\tconst deserializedL2 = resultsArray.map(deserializeL2Response);\n\t\t\t\tresolve(deserializedL2);\n\t\t\t})\n\t\t\t.catch((error) => {\n\t\t\t\treject(error);\n\t\t\t});\n\t});\n}\n\nexport async function fetchAuctionOrderParams(params: RegularOrderParams) {\n\ttry {\n\t\treturn await fetchAuctionOrderParamsFromDlob(params);\n\t} catch (error) {\n\t\tconsole.error(error);\n\t\tconsole.log('Falling back to L2 data');\n\t\treturn await fetchAuctionOrderParamsFromL2(params);\n\t}\n}\n\nconst calcBaseFromQuote = (\n\tdriftClient: DriftClient,\n\tmarketType: MarketType,\n\tmarketIndex: number,\n\tamount: BN\n) => {\n\tconst isPerp = ENUM_UTILS.match(marketType, MarketType.PERP);\n\n\tconst oraclePrice = isPerp\n\t\t? driftClient.getOracleDataForPerpMarket(marketIndex).price\n\t\t: driftClient.getOracleDataForSpotMarket(marketIndex).price;\n\n\tif (isPerp) {\n\t\treturn amount.mul(BASE_PRECISION).div(oraclePrice);\n\t} else {\n\t\tconst spotMarketAccount = driftClient.getSpotMarketAccount(marketIndex);\n\t\tinvariant(spotMarketAccount, 'Spot market account not found');\n\t\tconst precision = TEN.pow(new BN(spotMarketAccount.decimals));\n\t\treturn amount.mul(precision).div(oraclePrice);\n\t}\n};\n\n/**\n * Fetches auction order parameters from the auction params endpoint\n */\nexport async function fetchAuctionOrderParamsFromDlob({\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tamount,\n\tdlobServerHttpUrl,\n\tassetType,\n\tdriftClient,\n\toptionalAuctionParamsInputs = {},\n}: RegularOrderParams): Promise<OptionalOrderParams> {\n\tconst baseAmount =\n\t\tassetType === 'base'\n\t\t\t? amount\n\t\t\t: calcBaseFromQuote(driftClient, marketType, marketIndex, amount);\n\n\t// Build URL parameters for server request\n\tconst urlParamsObject: Record<string, string> = {\n\t\t// Required fields\n\t\tassetType: 'base',\n\t\tmarketType: ENUM_UTILS.toStr(marketType),\n\t\tmarketIndex: marketIndex.toString(),\n\t\tdirection: ENUM_UTILS.toStr(direction),\n\t\tamount: baseAmount.toString(),\n\t};\n\n\t// Add defined optional parameters\n\tObject.entries(optionalAuctionParamsInputs).forEach(([key, value]) => {\n\t\tif (value !== undefined) {\n\t\t\turlParamsObject[key] = value.toString();\n\t\t}\n\t});\n\n\tconst urlParams = encodeQueryParams(urlParamsObject);\n\n\t// Get order params from server\n\tconst requestUrl = `${dlobServerHttpUrl}/auctionParams?${urlParams.toString()}`;\n\tconst response = await fetch(requestUrl);\n\n\tif (!response.ok) {\n\t\tthrow new Error(\n\t\t\t`Server responded with ${response.status}: ${response.statusText}`\n\t\t);\n\t}\n\n\tconst serverResponse: ServerAuctionParamsResponse = await response.json();\n\tconst serverAuctionParams = serverResponse?.data?.params;\n\tinvariant(serverAuctionParams, 'Server auction params are required');\n\tconst mappedParams: MappedAuctionParams =\n\t\tmapAuctionParamsResponse(serverAuctionParams);\n\n\t// Convert MappedAuctionParams to OptionalOrderParams\n\treturn {\n\t\torderType: mappedParams.orderType,\n\t\tmarketType: mappedParams.marketType,\n\t\tuserOrderId: mappedParams.userOrderId,\n\t\tdirection: mappedParams.direction,\n\t\tbaseAssetAmount: mappedParams.baseAssetAmount,\n\t\tmarketIndex: mappedParams.marketIndex,\n\t\treduceOnly: mappedParams.reduceOnly,\n\t\tpostOnly: mappedParams.postOnly ?? DefaultOrderParams.postOnly,\n\t\ttriggerPrice: mappedParams.triggerPrice || null,\n\t\ttriggerCondition:\n\t\t\tmappedParams.triggerCondition ?? DefaultOrderParams.triggerCondition,\n\t\toraclePriceOffset: mappedParams.oraclePriceOffset?.toNumber() || null,\n\t\tauctionDuration: mappedParams.auctionDuration || null,\n\t\tmaxTs: mappedParams.maxTs,\n\t\tauctionStartPrice: mappedParams.auctionStartPrice || null,\n\t\tauctionEndPrice: mappedParams.auctionEndPrice || null,\n\t\t// no price, because market orders don't need a price\n\t};\n}\n\nconst DEFAULT_L2_DEPTH_FOR_AUCTION_ORDER_PARAMS = 100;\n\n/**\n * Fetches auction order parameters from the L2 data\n */\nexport async function fetchAuctionOrderParamsFromL2({\n\tdlobServerHttpUrl,\n\tmarketIndex,\n\tmarketType,\n\tdirection,\n\tassetType,\n\tamount,\n\toptionalAuctionParamsInputs,\n\tdriftClient,\n\tdynamicSlippageConfig,\n}: RegularOrderParams): Promise<OptionalOrderParams> {\n\tconst marketId = new MarketId(marketIndex, marketType);\n\tconst baseAmount =\n\t\tassetType === 'base'\n\t\t\t? amount\n\t\t\t: calcBaseFromQuote(driftClient, marketType, marketIndex, amount);\n\n\tconst l2DataResponse = await fetchBulkMarketsDlobL2Data(dlobServerHttpUrl, [\n\t\t{\n\t\t\tmarketId,\n\t\t\tdepth: DEFAULT_L2_DEPTH_FOR_AUCTION_ORDER_PARAMS,\n\t\t},\n\t]);\n\tconst oraclePriceData = l2DataResponse[0].oracleData;\n\tconst oraclePriceBn = oraclePriceData?.price;\n\tconst markPriceBn = l2DataResponse[0].markPrice;\n\tconst l2Data = convertToL2OrderBook(l2DataResponse);\n\n\tconst priceImpactData = calculatePriceImpactFromL2(\n\t\tmarketId,\n\t\tdirection,\n\t\tbaseAmount,\n\t\tl2Data,\n\t\toraclePriceBn\n\t);\n\n\tconst startPrices = COMMON_UI_UTILS.getPriceObject({\n\t\toraclePrice: oraclePriceBn,\n\t\tbestOffer: priceImpactData.bestPrice,\n\t\tentryPrice: priceImpactData.entryPrice,\n\t\tworstPrice: priceImpactData.worstPrice,\n\t\tmarkPrice: markPriceBn,\n\t\tdirection: direction,\n\t});\n\tconst slippageToleranceInput = optionalAuctionParamsInputs.slippageTolerance;\n\tconst derivedSlippage =\n\t\tslippageToleranceInput === 'dynamic'\n\t\t\t? calculateDynamicSlippageFromL2({\n\t\t\t\t\tl2Data,\n\t\t\t\t\tmarketId,\n\t\t\t\t\tstartPrice:\n\t\t\t\t\t\tstartPrices[\n\t\t\t\t\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffsetFrom as keyof typeof startPrices\n\t\t\t\t\t\t],\n\t\t\t\t\tworstPrice: priceImpactData.worstPrice,\n\t\t\t\t\toraclePrice: oraclePriceBn,\n\t\t\t\t\tdynamicSlippageConfig,\n\t\t\t })\n\t\t\t: typeof slippageToleranceInput === 'number'\n\t\t\t? slippageToleranceInput\n\t\t\t: 0.005;\n\n\tconst auctionOrderParams = COMMON_UI_UTILS.deriveMarketOrderParams({\n\t\tmarketType: marketType,\n\t\tmarketIndex: marketIndex,\n\t\tdirection: direction,\n\t\tmaxLeverageSelected: optionalAuctionParamsInputs.maxLeverageSelected,\n\t\tmaxLeverageOrderSize: optionalAuctionParamsInputs.maxLeverageOrderSize,\n\t\tbaseAmount: baseAmount,\n\t\treduceOnly: optionalAuctionParamsInputs.reduceOnly,\n\t\tallowInfSlippage: false,\n\t\toraclePrice: oraclePriceBn,\n\t\tbestPrice: priceImpactData.bestPrice,\n\t\tentryPrice: priceImpactData.entryPrice,\n\t\tworstPrice: priceImpactData.worstPrice,\n\t\tmarkPrice: markPriceBn,\n\t\tauctionDuration: optionalAuctionParamsInputs.auctionDuration,\n\t\tauctionStartPriceOffset:\n\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffset,\n\t\tauctionEndPriceOffset: optionalAuctionParamsInputs.auctionEndPriceOffset,\n\t\tauctionStartPriceOffsetFrom:\n\t\t\toptionalAuctionParamsInputs.auctionStartPriceOffsetFrom,\n\t\tauctionEndPriceOffsetFrom:\n\t\t\toptionalAuctionParamsInputs.auctionEndPriceOffsetFrom,\n\t\tslippageTolerance: derivedSlippage,\n\t\tisOracleOrder: optionalAuctionParamsInputs.isOracleOrder,\n\t\tadditionalEndPriceBuffer:\n\t\t\toptionalAuctionParamsInputs.additionalEndPriceBuffer,\n\t\tforceUpToSlippage: optionalAuctionParamsInputs.forceUpToSlippage,\n\t});\n\n\tif (!auctionOrderParams) {\n\t\tthrow new Error('Failed to derive auction params from L2');\n\t}\n\n\treturn auctionOrderParams;\n}\n\ntype FetchTopMakersParams = {\n\tdlobServerHttpUrl: string;\n\tmarketIndex: number;\n\tmarketType: MarketType;\n\tside: 'bid' | 'ask';\n\tlimit: number;\n};\n\n/**\n * Fetches the top makers information, for use as inputs in placeAndTake market orders.\n * The side of the request should be opposite of the side of the placeAndTake market order.\n */\nexport async function fetchTopMakers(params: FetchTopMakersParams): Promise<\n\t{\n\t\tuserAccountPubKey: PublicKey;\n\t\tuserAccount: UserAccount;\n\t}[]\n> {\n\ttry {\n\t\tconst { dlobServerHttpUrl, marketIndex, marketType, side, limit } = params;\n\n\t\tconst urlParams = encodeQueryParams({\n\t\t\tmarketIndex: marketIndex.toString(),\n\t\t\tmarketType: ENUM_UTILS.toStr(marketType),\n\t\t\tside,\n\t\t\tlimit: limit.toString(),\n\t\t\tincludeAccounts: 'true',\n\t\t});\n\n\t\tconst requestUrl = `${dlobServerHttpUrl}/topMakers?${urlParams}`;\n\t\tconst response = await fetch(requestUrl);\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Server responded with ${response.status}: ${response.statusText}`\n\t\t\t);\n\t\t}\n\n\t\tconst serverResponse: {\n\t\t\tuserAccountPubKey: string;\n\t\t\taccountBase64: string;\n\t\t}[] = await response.json();\n\t\tconst mappedParams: {\n\t\t\tuserAccountPubKey: PublicKey;\n\t\t\tuserAccount: UserAccount;\n\t\t}[] = serverResponse.map((value) => ({\n\t\t\tuserAccountPubKey: new PublicKey(value.userAccountPubKey),\n\t\t\tuserAccount: decodeUser(Buffer.from(value.accountBase64, 'base64')),\n\t\t}));\n\n\t\treturn mappedParams;\n\t} catch (e) {\n\t\tconsole.error(e);\n\t\treturn [];\n\t}\n}\n"]}
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.prepSignAndSendSwiftOrder = exports.sendSwiftOrder = exports.signSwiftOrderMsg = exports.AuctionSlotExpiredError = exports.prepSwiftOrder = exports.MINIMUM_SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = exports.SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = void 0;
4
4
  const sdk_1 = require("@drift-labs/sdk");
5
5
  const sdk_2 = require("@drift-labs/sdk");
6
+ const utils_1 = require("../../../../../../utils");
6
7
  const swiftClient_1 = require("../../../../../../clients/swiftClient");
7
8
  const types_1 = require("../../../../../../types");
8
9
  const trading_1 = require("../../../../../../common-ui-utils/trading");
@@ -156,7 +157,7 @@ exports.signSwiftOrderMsg = signSwiftOrderMsg;
156
157
  */
157
158
  const sendSwiftOrder = ({ driftClient, marketId, hexEncodedSwiftOrderMessageString, signedMessage, signedMsgOrderUuid, takerAuthority, signingAuthority, auctionDuration, }) => {
158
159
  const signedMsgUserOrdersAccountPubkey = (0, sdk_1.getSignedMsgUserAccountPublicKey)(driftClient.program.programId, takerAuthority);
159
- const swiftOrderObservable = swiftClient_1.SwiftClient.sendAndConfirmSwiftOrderWS(driftClient.connection, driftClient, marketId.marketIndex, marketId.marketType, hexEncodedSwiftOrderMessageString, Buffer.from(signedMessage), takerAuthority, signedMsgUserOrdersAccountPubkey, signedMsgOrderUuid, ((auctionDuration !== null && auctionDuration !== void 0 ? auctionDuration : 0) + 15) * sdk_1.SLOT_TIME_ESTIMATE_MS, signingAuthority);
160
+ const swiftOrderObservable = swiftClient_1.SwiftClient.sendAndConfirmSwiftOrderWS(driftClient.connection, driftClient, marketId.marketIndex, marketId.marketType, hexEncodedSwiftOrderMessageString, Buffer.from(signedMessage), takerAuthority, signedMsgUserOrdersAccountPubkey, signedMsgOrderUuid, (0, utils_1.getSwiftConfirmationTimeoutMs)(auctionDuration !== null && auctionDuration !== void 0 ? auctionDuration : 0), signingAuthority);
160
161
  return swiftOrderObservable;
161
162
  };
162
163
  exports.sendSwiftOrder = sendSwiftOrder;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../src/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tgetSignedMsgUserAccountPublicKey,\n\tSignedMsgOrderParamsDelegateMessage,\n\tSignedMsgOrderParamsMessage,\n\tSLOT_TIME_ESTIMATE_MS,\n} from '@drift-labs/sdk';\nimport {\n\tBN,\n\tDriftClient,\n\tgenerateSignedMsgUuid,\n\tgetOrderParams,\n\tOptionalOrderParams,\n\tPublicKey,\n} from '@drift-labs/sdk';\nimport {\n\tSwiftClient,\n\tSwiftOrderConfirmedEvent,\n\tSwiftOrderErroredEvent,\n\tSwiftOrderEvent,\n\tSwiftOrderEventWithParams,\n\tSwiftOrderSentEvent,\n} from '../../../../../../clients/swiftClient';\nimport { MarketId } from '../../../../../../types';\nimport { Observable, Subscription } from 'rxjs';\nimport { OptionalTriggerOrderParams } from '../types';\nimport { TRADING_UTILS } from '../../../../../../common-ui-utils/trading';\n\nexport const SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = 5;\nexport const MINIMUM_SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = 5;\n\nexport interface SwiftOrderOptions {\n\twallet: {\n\t\tsignMessage: (message: Uint8Array) => Promise<Uint8Array>;\n\t\ttakerAuthority: PublicKey;\n\t\tsigningAuthority?: PublicKey;\n\t};\n\tswiftServerUrl: string;\n\tsignedMessageOrderSlotBuffer?: number;\n\tisDelegate?: boolean;\n\tcallbacks?: {\n\t\tonOrderParamsMessagePrepped?: (\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSigningExpiry?: (\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSigningSuccess?: (\n\t\t\tsignedMessage: Uint8Array,\n\t\t\t// we add the following here, because the onSigningSuccess callback is called before the order is sent to the swift server\n\t\t\torderUuid: Uint8Array,\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSent?: (\n\t\t\tswiftSentEvent: SwiftOrderEventWithParams<SwiftOrderSentEvent>\n\t\t) => void;\n\t\tonConfirmed?: (\n\t\t\tswiftConfirmedEvent: SwiftOrderEventWithParams<SwiftOrderConfirmedEvent>\n\t\t) => void;\n\t\tonExpired?: (\n\t\t\tswiftExpiredEvent: SwiftOrderEventWithParams<SwiftOrderErroredEvent>\n\t\t) => void;\n\t\tonErrored?: (\n\t\t\tswiftErroredEvent: SwiftOrderEventWithParams<SwiftOrderErroredEvent>\n\t\t) => void;\n\t};\n}\n\nexport type SwiftOrderObservable = Observable<SwiftOrderEvent>;\n\ninterface PrepSwiftOrderParams {\n\t/** The Drift client instance */\n\tdriftClient: DriftClient;\n\t/** The taker user account information */\n\ttakerUserAccount: {\n\t\t/** Public key of the user account */\n\t\tpubKey: PublicKey;\n\t\t/** User account ID */\n\t\tsubAccountId: number;\n\t};\n\t/** Current blockchain slot number */\n\tcurrentSlot: number;\n\t/** Whether this is a delegate order */\n\tisDelegate: boolean;\n\t/** Order parameters including main order and optional stop loss/take profit */\n\torderParams: {\n\t\t/** Main order parameters */\n\t\tmain: OptionalOrderParams;\n\t\t/** Optional stop loss order parameters */\n\t\tstopLoss?: OptionalTriggerOrderParams;\n\t\t/** Optional take profit order parameters */\n\t\ttakeProfit?: OptionalTriggerOrderParams;\n\t\t/** Optional max leverage for the position */\n\t\tpositionMaxLeverage?: number;\n\t};\n\t/** Buffer slots to account for signing time (default: 2 slots ~1 second). If a user is required to manually sign the message, this should be a higher number. */\n\tslotBuffer?: number;\n\t/**\n\t * Optional builder code parameters for revenue sharing.\n\t * If provided, the builder will receive a portion of the trading fees.\n\t *\n\t * Prerequisites:\n\t * - User must have initialized a RevenueShareEscrow account\n\t * - Builder must be in the user's approved_builders list\n\t * - builderFeeTenthBps must not exceed the builder's max_fee_tenth_bps\n\t */\n\tbuilderParams?: {\n\t\t/**\n\t\t * Index of the builder in the user's approved_builders list.\n\t\t * This is the position (0-indexed) of the builder in the RevenueShareEscrow.approved_builders array.\n\t\t */\n\t\tbuilderIdx: number;\n\t\t/**\n\t\t * Fee to charge for this order, in tenths of basis points.\n\t\t * Must be <= the builder's max_fee_tenth_bps.\n\t\t *\n\t\t * Examples:\n\t\t * - 10 = 1 bps = 0.01%\n\t\t * - 50 = 5 bps = 0.05%\n\t\t * - 100 = 10 bps = 0.1%\n\t\t */\n\t\tbuilderFeeTenthBps: number;\n\t};\n}\n\n/**\n * Prepares a swift order by encoding the order parameters into a message format\n * suitable for signing and sending to the Swift server.\n *\n * @param driftClient - The Drift client instance\n * @param takerUserAccount - The taker user account information\n * @param currentSlot - Current blockchain slot number\n * @param isDelegate - Whether this is a delegate order\n * @param orderParams - Order parameters including main order and optional stop loss/take profit\n * @param slotBuffer - Buffer slots to account for signing time (default: 35 slots ~14 seconds). Use this default value if it is not an auction order, else used an estimate number of slots to sign the message.\n *\n * @returns An object containing:\n * - `hexEncodedSwiftOrderMessage`: The encoded order message in both Uint8Array and string formats. The Uint8Array format is for a wallet to sign, while the string format is used to send to the SWIFT server.\n * - `signedMsgOrderParamsMessage`: The signed message order parameters\n * - `slotForSignedMsg`: The slot number for the signed message\n * - `signedMsgOrderUuid`: Unique identifier for the signed message order\n */\nexport const prepSwiftOrder = ({\n\tdriftClient,\n\ttakerUserAccount,\n\tcurrentSlot,\n\tisDelegate,\n\torderParams,\n\tslotBuffer = 35,\n\tbuilderParams,\n}: PrepSwiftOrderParams): {\n\thexEncodedSwiftOrderMessage: {\n\t\tuInt8Array: Uint8Array;\n\t\tstring: string;\n\t};\n\tsignedMsgOrderParamsMessage:\n\t\t| SignedMsgOrderParamsMessage\n\t\t| SignedMsgOrderParamsDelegateMessage;\n\tslotForSignedMsg: BN;\n\tsignedMsgOrderUuid: Uint8Array;\n} => {\n\tconst mainOrderParams = getOrderParams({\n\t\t...orderParams.main,\n\t\tauctionDuration: orderParams.main.auctionDuration || null, // swift server expects auctionDuration to be null if not set, won't handle 0\n\t});\n\n\t// buffer for time the user takes to sign a message and send to the swift server\n\tconst slotForSignedMsg = new BN(currentSlot + slotBuffer);\n\n\tconst signedMsgOrderUuid = generateSignedMsgUuid();\n\n\tconst baseSignedMsgOrderParamsMessage = {\n\t\tsignedMsgOrderParams: mainOrderParams,\n\t\tuuid: signedMsgOrderUuid,\n\t\tslot: slotForSignedMsg,\n\t\tstopLossOrderParams: orderParams.stopLoss\n\t\t\t? {\n\t\t\t\t\tbaseAssetAmount: orderParams.stopLoss.baseAssetAmount,\n\t\t\t\t\ttriggerPrice: orderParams.stopLoss.triggerPrice,\n\t\t\t }\n\t\t\t: null,\n\t\ttakeProfitOrderParams: orderParams.takeProfit\n\t\t\t? {\n\t\t\t\t\tbaseAssetAmount: orderParams.takeProfit.baseAssetAmount,\n\t\t\t\t\ttriggerPrice: orderParams.takeProfit.triggerPrice,\n\t\t\t }\n\t\t\t: null,\n\t\tmaxMarginRatio: orderParams.positionMaxLeverage\n\t\t\t? TRADING_UTILS.convertLeverageToMarginRatio(\n\t\t\t\t\torderParams.positionMaxLeverage\n\t\t\t )\n\t\t\t: null,\n\t\t// Include builder params if provided\n\t\tbuilderIdx: builderParams?.builderIdx ?? null,\n\t\tbuilderFeeTenthBps: builderParams?.builderFeeTenthBps ?? null,\n\t};\n\n\tconst signedMsgOrderParamsMessage:\n\t\t| SignedMsgOrderParamsMessage\n\t\t| SignedMsgOrderParamsDelegateMessage = isDelegate\n\t\t? {\n\t\t\t\t...baseSignedMsgOrderParamsMessage,\n\t\t\t\ttakerPubkey: takerUserAccount.pubKey,\n\t\t }\n\t\t: {\n\t\t\t\t...baseSignedMsgOrderParamsMessage,\n\t\t\t\tsubAccountId: takerUserAccount.subAccountId,\n\t\t };\n\n\tconst encodedOrderMessage = driftClient.encodeSignedMsgOrderParamsMessage(\n\t\tsignedMsgOrderParamsMessage,\n\t\tisDelegate\n\t);\n\tconst hexEncodedSwiftOrderMessage = Buffer.from(\n\t\tencodedOrderMessage.toString('hex')\n\t);\n\n\treturn {\n\t\thexEncodedSwiftOrderMessage: {\n\t\t\tuInt8Array: new Uint8Array(hexEncodedSwiftOrderMessage),\n\t\t\tstring: hexEncodedSwiftOrderMessage.toString(),\n\t\t},\n\t\tsignedMsgOrderParamsMessage,\n\t\tslotForSignedMsg,\n\t\tsignedMsgOrderUuid,\n\t};\n};\n\n/**\n * Error thrown when an auction slot has expired\n */\nexport class AuctionSlotExpiredError extends Error {\n\tname = 'AuctionSlotExpiredError';\n\n\t/**\n\t * Creates an instance of AuctionSlotExpiredError\n\t * @param message - Error message (default: 'Auction slot expired')\n\t */\n\tconstructor(message: string = 'Auction slot expired') {\n\t\tsuper(message);\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, AuctionSlotExpiredError);\n\t\t}\n\t}\n}\n\ninterface SignOrderMsgParams {\n\t/** Wallet instance with message signing capability */\n\twallet: {\n\t\t/** Function to sign a message */\n\t\tsignMessage: (message: Uint8Array) => Promise<Uint8Array>;\n\t};\n\t/** Hex-encoded swift order message to sign */\n\thexEncodedSwiftOrderMessage: Uint8Array;\n\t/** Time in milliseconds till the auction expires */\n\texpirationTimeMs: number;\n\t/** Callback function called when the auction expires */\n\tonExpired?: () => void;\n}\n\n/**\n * Signs a swift order message with slot expiration monitoring.\n * Continuously monitors the current slot and rejects with AuctionSlotExpiredError\n * if the auction slot expires before signing is complete.\n *\n * @param wallet - Wallet instance with message signing capability\n * @param hexEncodedSwiftOrderMessage - Hex-encoded swift order message to sign\n * @param expirationTimeMs - Time in milliseconds till the auction expires\n * @param onExpired - Callback function called when the auction expires\n *\n * @returns Promise resolving to the signed message as Uint8Array\n * @throws {AuctionSlotExpiredError} When the auction slot expires before signing completes\n */\nexport const signSwiftOrderMsg = async ({\n\twallet,\n\thexEncodedSwiftOrderMessage,\n\texpirationTimeMs,\n\tonExpired,\n}: SignOrderMsgParams): Promise<Uint8Array> => {\n\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\ttry {\n\t\t// Sign the message\n\t\tconst signedMessagePromise = wallet.signMessage(\n\t\t\thexEncodedSwiftOrderMessage\n\t\t);\n\n\t\tconst signingExpiredPromise = new Promise<never>((_resolve, reject) => {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\tonExpired?.();\n\t\t\t\treject(new AuctionSlotExpiredError());\n\t\t\t}, expirationTimeMs);\n\t\t});\n\n\t\t// Ensure that the user signs the message before the expiration time\n\t\tconst signedMessage = await Promise.race([\n\t\t\tsignedMessagePromise,\n\t\t\tsigningExpiredPromise,\n\t\t]);\n\n\t\treturn signedMessage;\n\t} finally {\n\t\tif (timeoutId) {\n\t\t\tclearTimeout(timeoutId);\n\t\t}\n\t}\n};\n\n/**\n * Parameters for sending a swift order to the Swift server\n * @interface SendSwiftOrderParams\n */\ninterface SendSwiftOrderParams {\n\t/** The Drift client instance */\n\tdriftClient: DriftClient;\n\t/** Market identifier for the order */\n\tmarketId: MarketId;\n\t/** Hex-encoded swift order message as string */\n\thexEncodedSwiftOrderMessageString: string;\n\t/** The signed message from the wallet */\n\tsignedMessage: Uint8Array;\n\t/** Unique identifier for the signed message order */\n\tsignedMsgOrderUuid: Uint8Array;\n\t/** Public key of the taker authority */\n\ttakerAuthority: PublicKey;\n\t/** Public key of the signing authority */\n\tsigningAuthority: PublicKey;\n\t/** Duration of the auction in slots (optional) */\n\tauctionDuration?: number;\n}\n\n/**\n * Sends a swift order to the Swift server and handles the response.\n * Monitors the order status and calls appropriate callback functions based on the response type.\n *\n * @param driftClient - The Drift client instance\n * @param marketId - Market identifier for the order\n * @param hexEncodedSwiftOrderMessageString - Hex-encoded swift order message as string\n * @param signedMessage - The signed message from the wallet\n * @param signedMsgOrderUuid - Unique identifier for the signed message order\n * @param takerAuthority - Public key of the taker authority\n * @param signingAuthority - Public key of the signing authority\n * @param auctionDurationSlot - Duration of the auction in slots (optional)\n * @param swiftConfirmationSlotBuffer - Slot buffer for swift server confirmation time (default: 15)\n * @param onExpired - Callback function called when the order expires\n * @param onErrored - Callback function called when the order encounters an error\n * @param onConfirmed - Callback function called when the order is confirmed\n *\n * @returns Promise that resolves when the order processing is complete\n *\n */\nexport const sendSwiftOrder = ({\n\tdriftClient,\n\tmarketId,\n\thexEncodedSwiftOrderMessageString,\n\tsignedMessage,\n\tsignedMsgOrderUuid,\n\ttakerAuthority,\n\tsigningAuthority,\n\tauctionDuration,\n}: SendSwiftOrderParams): SwiftOrderObservable => {\n\tconst signedMsgUserOrdersAccountPubkey = getSignedMsgUserAccountPublicKey(\n\t\tdriftClient.program.programId,\n\t\ttakerAuthority\n\t);\n\n\tconst swiftOrderObservable = SwiftClient.sendAndConfirmSwiftOrderWS(\n\t\tdriftClient.connection,\n\t\tdriftClient,\n\t\tmarketId.marketIndex,\n\t\tmarketId.marketType,\n\t\thexEncodedSwiftOrderMessageString,\n\t\tBuffer.from(signedMessage),\n\t\ttakerAuthority,\n\t\tsignedMsgUserOrdersAccountPubkey,\n\t\tsignedMsgOrderUuid,\n\t\t((auctionDuration ?? 0) + 15) * SLOT_TIME_ESTIMATE_MS,\n\t\tsigningAuthority\n\t);\n\n\treturn swiftOrderObservable;\n};\n\ntype PrepSignAndSendSwiftOrderParams = {\n\tdriftClient: DriftClient;\n\tsubAccountId: number;\n\tuserAccountPubKey: PublicKey;\n\tmarketIndex: number;\n\tslotBuffer: number;\n\tswiftOptions: SwiftOrderOptions;\n\torderParams: {\n\t\tmain: OptionalOrderParams;\n\t\ttakeProfit?: OptionalTriggerOrderParams;\n\t\tstopLoss?: OptionalTriggerOrderParams;\n\t\t/**\n\t\t * Adjusts the max leverage of a position.\n\t\t */\n\t\tpositionMaxLeverage?: number;\n\t};\n\t/**\n\t * Optional builder code parameters for revenue sharing.\n\t * If provided, the builder will receive a portion of the trading fees.\n\t *\n\t * Prerequisites:\n\t * - User must have initialized a RevenueShareEscrow account\n\t * - Builder must be in the user's approved_builders list\n\t * - builderFeeTenthBps must not exceed the builder's max_fee_tenth_bps\n\t *\n\t * @example\n\t * ```typescript\n\t * builderParams: {\n\t * builderIdx: 0, // First builder in approved list\n\t * builderFeeTenthBps: 50 // 5 bps = 0.05%\n\t * }\n\t * ```\n\t */\n\tbuilderParams?: {\n\t\t/**\n\t\t * Index of the builder in the user's approved_builders list.\n\t\t */\n\t\tbuilderIdx: number;\n\t\t/**\n\t\t * Fee to charge for this order, in tenths of basis points.\n\t\t * Must be <= the builder's max_fee_tenth_bps.\n\t\t */\n\t\tbuilderFeeTenthBps: number;\n\t};\n};\n\n/**\n * Handles the full flow of the swift order, from preparing to signing and sending to the Swift server.\n * Callbacks can be provided to handle the events of the Swift order.\n * Returns a promise that resolves when the Swift order has reached a terminal state (i.e. confirmed, expired, or errored).\n */\nexport const prepSignAndSendSwiftOrder = async ({\n\tdriftClient,\n\tsubAccountId,\n\tuserAccountPubKey,\n\tmarketIndex,\n\tslotBuffer,\n\tswiftOptions,\n\torderParams,\n\tbuilderParams,\n}: PrepSignAndSendSwiftOrderParams): Promise<void> => {\n\tconst currentSlot = await driftClient.connection.getSlot('confirmed');\n\n\tconst {\n\t\thexEncodedSwiftOrderMessage,\n\t\tsignedMsgOrderUuid,\n\t\tsignedMsgOrderParamsMessage,\n\t} = prepSwiftOrder({\n\t\tdriftClient,\n\t\ttakerUserAccount: {\n\t\t\tpubKey: userAccountPubKey,\n\t\t\tsubAccountId: subAccountId,\n\t\t},\n\t\tcurrentSlot,\n\t\tisDelegate: swiftOptions.isDelegate || false,\n\t\torderParams,\n\t\tslotBuffer,\n\t\tbuilderParams,\n\t});\n\n\tswiftOptions.callbacks?.onOrderParamsMessagePrepped?.(\n\t\tsignedMsgOrderParamsMessage\n\t);\n\n\tconst expirationTimeMs =\n\t\tMath.max(\n\t\t\tslotBuffer +\n\t\t\t\t(orderParams.main.auctionDuration || 0) -\n\t\t\t\tSWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS,\n\t\t\tMINIMUM_SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS\n\t\t) * SLOT_TIME_ESTIMATE_MS;\n\n\t// Ensure that the user signs the message before the expiration time\n\tconst signedMessage = await signSwiftOrderMsg({\n\t\twallet: swiftOptions.wallet,\n\t\thexEncodedSwiftOrderMessage: hexEncodedSwiftOrderMessage.uInt8Array,\n\t\texpirationTimeMs,\n\t\tonExpired: () =>\n\t\t\tswiftOptions.callbacks?.onSigningExpiry?.(signedMsgOrderParamsMessage),\n\t});\n\n\tswiftOptions.callbacks?.onSigningSuccess?.(\n\t\tsignedMessage,\n\t\tsignedMsgOrderUuid,\n\t\tsignedMsgOrderParamsMessage\n\t);\n\n\t// Initialize SwiftClient (required before using sendSwiftOrder)\n\tSwiftClient.init(swiftOptions.swiftServerUrl);\n\n\t// Create a promise-based wrapper for the sendSwiftOrder callback-based API\n\tconst swiftOrderObservable = sendSwiftOrder({\n\t\tdriftClient,\n\t\tmarketId: MarketId.createPerpMarket(marketIndex),\n\t\thexEncodedSwiftOrderMessageString: hexEncodedSwiftOrderMessage.string,\n\t\tsignedMessage,\n\t\tsignedMsgOrderUuid,\n\t\ttakerAuthority: swiftOptions.wallet.takerAuthority,\n\t\tsigningAuthority:\n\t\t\tswiftOptions.wallet.signingAuthority ??\n\t\t\tswiftOptions.wallet.takerAuthority,\n\t\tauctionDuration: orderParams.main.auctionDuration || undefined,\n\t});\n\n\tconst wrapSwiftOrderEvent = <T extends SwiftOrderEvent>(\n\t\tswiftOrderEvent: T\n\t) => {\n\t\treturn {\n\t\t\t...swiftOrderEvent,\n\t\t\tswiftOrderUuid: signedMsgOrderUuid,\n\t\t\torderParamsMessage: signedMsgOrderParamsMessage,\n\t\t};\n\t};\n\n\tlet promiseResolver: (value: void | PromiseLike<void>) => void;\n\tconst promise = new Promise<void>((resolve) => {\n\t\tpromiseResolver = resolve;\n\t});\n\n\tconst handleTerminalEvent = (subscription: Subscription) => {\n\t\tsubscription.unsubscribe();\n\t\tpromiseResolver();\n\t};\n\n\tconst subscription = swiftOrderObservable.subscribe((swiftOrderEvent) => {\n\t\tif (swiftOrderEvent.type === 'sent') {\n\t\t\tswiftOptions.callbacks?.onSent?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t}\n\t\tif (swiftOrderEvent.type === 'confirmed') {\n\t\t\tswiftOptions.callbacks?.onConfirmed?.(\n\t\t\t\twrapSwiftOrderEvent(swiftOrderEvent)\n\t\t\t);\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t\tif (swiftOrderEvent.type === 'expired') {\n\t\t\tswiftOptions.callbacks?.onExpired?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t\tif (swiftOrderEvent.type === 'errored') {\n\t\t\tswiftOptions.callbacks?.onErrored?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t});\n\n\treturn promise;\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../src/drift/base/actions/trade/openPerpOrder/openSwiftOrder/index.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tgetSignedMsgUserAccountPublicKey,\n\tSignedMsgOrderParamsDelegateMessage,\n\tSignedMsgOrderParamsMessage,\n\tSLOT_TIME_ESTIMATE_MS,\n} from '@drift-labs/sdk';\nimport {\n\tBN,\n\tDriftClient,\n\tgenerateSignedMsgUuid,\n\tgetOrderParams,\n\tOptionalOrderParams,\n\tPublicKey,\n} from '@drift-labs/sdk';\nimport { getSwiftConfirmationTimeoutMs } from '../../../../../../utils';\nimport {\n\tSwiftClient,\n\tSwiftOrderConfirmedEvent,\n\tSwiftOrderErroredEvent,\n\tSwiftOrderEvent,\n\tSwiftOrderEventWithParams,\n\tSwiftOrderSentEvent,\n} from '../../../../../../clients/swiftClient';\nimport { MarketId } from '../../../../../../types';\nimport { Observable, Subscription } from 'rxjs';\nimport { OptionalTriggerOrderParams } from '../types';\nimport { TRADING_UTILS } from '../../../../../../common-ui-utils/trading';\n\nexport const SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = 5;\nexport const MINIMUM_SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS = 5;\n\nexport interface SwiftOrderOptions {\n\twallet: {\n\t\tsignMessage: (message: Uint8Array) => Promise<Uint8Array>;\n\t\ttakerAuthority: PublicKey;\n\t\tsigningAuthority?: PublicKey;\n\t};\n\tswiftServerUrl: string;\n\tsignedMessageOrderSlotBuffer?: number;\n\tisDelegate?: boolean;\n\tcallbacks?: {\n\t\tonOrderParamsMessagePrepped?: (\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSigningExpiry?: (\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSigningSuccess?: (\n\t\t\tsignedMessage: Uint8Array,\n\t\t\t// we add the following here, because the onSigningSuccess callback is called before the order is sent to the swift server\n\t\t\torderUuid: Uint8Array,\n\t\t\torderParamsMessage:\n\t\t\t\t| SignedMsgOrderParamsMessage\n\t\t\t\t| SignedMsgOrderParamsDelegateMessage\n\t\t) => void;\n\t\tonSent?: (\n\t\t\tswiftSentEvent: SwiftOrderEventWithParams<SwiftOrderSentEvent>\n\t\t) => void;\n\t\tonConfirmed?: (\n\t\t\tswiftConfirmedEvent: SwiftOrderEventWithParams<SwiftOrderConfirmedEvent>\n\t\t) => void;\n\t\tonExpired?: (\n\t\t\tswiftExpiredEvent: SwiftOrderEventWithParams<SwiftOrderErroredEvent>\n\t\t) => void;\n\t\tonErrored?: (\n\t\t\tswiftErroredEvent: SwiftOrderEventWithParams<SwiftOrderErroredEvent>\n\t\t) => void;\n\t};\n}\n\nexport type SwiftOrderObservable = Observable<SwiftOrderEvent>;\n\ninterface PrepSwiftOrderParams {\n\t/** The Drift client instance */\n\tdriftClient: DriftClient;\n\t/** The taker user account information */\n\ttakerUserAccount: {\n\t\t/** Public key of the user account */\n\t\tpubKey: PublicKey;\n\t\t/** User account ID */\n\t\tsubAccountId: number;\n\t};\n\t/** Current blockchain slot number */\n\tcurrentSlot: number;\n\t/** Whether this is a delegate order */\n\tisDelegate: boolean;\n\t/** Order parameters including main order and optional stop loss/take profit */\n\torderParams: {\n\t\t/** Main order parameters */\n\t\tmain: OptionalOrderParams;\n\t\t/** Optional stop loss order parameters */\n\t\tstopLoss?: OptionalTriggerOrderParams;\n\t\t/** Optional take profit order parameters */\n\t\ttakeProfit?: OptionalTriggerOrderParams;\n\t\t/** Optional max leverage for the position */\n\t\tpositionMaxLeverage?: number;\n\t};\n\t/** Buffer slots to account for signing time (default: 2 slots ~1 second). If a user is required to manually sign the message, this should be a higher number. */\n\tslotBuffer?: number;\n\t/**\n\t * Optional builder code parameters for revenue sharing.\n\t * If provided, the builder will receive a portion of the trading fees.\n\t *\n\t * Prerequisites:\n\t * - User must have initialized a RevenueShareEscrow account\n\t * - Builder must be in the user's approved_builders list\n\t * - builderFeeTenthBps must not exceed the builder's max_fee_tenth_bps\n\t */\n\tbuilderParams?: {\n\t\t/**\n\t\t * Index of the builder in the user's approved_builders list.\n\t\t * This is the position (0-indexed) of the builder in the RevenueShareEscrow.approved_builders array.\n\t\t */\n\t\tbuilderIdx: number;\n\t\t/**\n\t\t * Fee to charge for this order, in tenths of basis points.\n\t\t * Must be <= the builder's max_fee_tenth_bps.\n\t\t *\n\t\t * Examples:\n\t\t * - 10 = 1 bps = 0.01%\n\t\t * - 50 = 5 bps = 0.05%\n\t\t * - 100 = 10 bps = 0.1%\n\t\t */\n\t\tbuilderFeeTenthBps: number;\n\t};\n}\n\n/**\n * Prepares a swift order by encoding the order parameters into a message format\n * suitable for signing and sending to the Swift server.\n *\n * @param driftClient - The Drift client instance\n * @param takerUserAccount - The taker user account information\n * @param currentSlot - Current blockchain slot number\n * @param isDelegate - Whether this is a delegate order\n * @param orderParams - Order parameters including main order and optional stop loss/take profit\n * @param slotBuffer - Buffer slots to account for signing time (default: 35 slots ~14 seconds). Use this default value if it is not an auction order, else used an estimate number of slots to sign the message.\n *\n * @returns An object containing:\n * - `hexEncodedSwiftOrderMessage`: The encoded order message in both Uint8Array and string formats. The Uint8Array format is for a wallet to sign, while the string format is used to send to the SWIFT server.\n * - `signedMsgOrderParamsMessage`: The signed message order parameters\n * - `slotForSignedMsg`: The slot number for the signed message\n * - `signedMsgOrderUuid`: Unique identifier for the signed message order\n */\nexport const prepSwiftOrder = ({\n\tdriftClient,\n\ttakerUserAccount,\n\tcurrentSlot,\n\tisDelegate,\n\torderParams,\n\tslotBuffer = 35,\n\tbuilderParams,\n}: PrepSwiftOrderParams): {\n\thexEncodedSwiftOrderMessage: {\n\t\tuInt8Array: Uint8Array;\n\t\tstring: string;\n\t};\n\tsignedMsgOrderParamsMessage:\n\t\t| SignedMsgOrderParamsMessage\n\t\t| SignedMsgOrderParamsDelegateMessage;\n\tslotForSignedMsg: BN;\n\tsignedMsgOrderUuid: Uint8Array;\n} => {\n\tconst mainOrderParams = getOrderParams({\n\t\t...orderParams.main,\n\t\tauctionDuration: orderParams.main.auctionDuration || null, // swift server expects auctionDuration to be null if not set, won't handle 0\n\t});\n\n\t// buffer for time the user takes to sign a message and send to the swift server\n\tconst slotForSignedMsg = new BN(currentSlot + slotBuffer);\n\n\tconst signedMsgOrderUuid = generateSignedMsgUuid();\n\n\tconst baseSignedMsgOrderParamsMessage = {\n\t\tsignedMsgOrderParams: mainOrderParams,\n\t\tuuid: signedMsgOrderUuid,\n\t\tslot: slotForSignedMsg,\n\t\tstopLossOrderParams: orderParams.stopLoss\n\t\t\t? {\n\t\t\t\t\tbaseAssetAmount: orderParams.stopLoss.baseAssetAmount,\n\t\t\t\t\ttriggerPrice: orderParams.stopLoss.triggerPrice,\n\t\t\t }\n\t\t\t: null,\n\t\ttakeProfitOrderParams: orderParams.takeProfit\n\t\t\t? {\n\t\t\t\t\tbaseAssetAmount: orderParams.takeProfit.baseAssetAmount,\n\t\t\t\t\ttriggerPrice: orderParams.takeProfit.triggerPrice,\n\t\t\t }\n\t\t\t: null,\n\t\tmaxMarginRatio: orderParams.positionMaxLeverage\n\t\t\t? TRADING_UTILS.convertLeverageToMarginRatio(\n\t\t\t\t\torderParams.positionMaxLeverage\n\t\t\t )\n\t\t\t: null,\n\t\t// Include builder params if provided\n\t\tbuilderIdx: builderParams?.builderIdx ?? null,\n\t\tbuilderFeeTenthBps: builderParams?.builderFeeTenthBps ?? null,\n\t};\n\n\tconst signedMsgOrderParamsMessage:\n\t\t| SignedMsgOrderParamsMessage\n\t\t| SignedMsgOrderParamsDelegateMessage = isDelegate\n\t\t? {\n\t\t\t\t...baseSignedMsgOrderParamsMessage,\n\t\t\t\ttakerPubkey: takerUserAccount.pubKey,\n\t\t }\n\t\t: {\n\t\t\t\t...baseSignedMsgOrderParamsMessage,\n\t\t\t\tsubAccountId: takerUserAccount.subAccountId,\n\t\t };\n\n\tconst encodedOrderMessage = driftClient.encodeSignedMsgOrderParamsMessage(\n\t\tsignedMsgOrderParamsMessage,\n\t\tisDelegate\n\t);\n\tconst hexEncodedSwiftOrderMessage = Buffer.from(\n\t\tencodedOrderMessage.toString('hex')\n\t);\n\n\treturn {\n\t\thexEncodedSwiftOrderMessage: {\n\t\t\tuInt8Array: new Uint8Array(hexEncodedSwiftOrderMessage),\n\t\t\tstring: hexEncodedSwiftOrderMessage.toString(),\n\t\t},\n\t\tsignedMsgOrderParamsMessage,\n\t\tslotForSignedMsg,\n\t\tsignedMsgOrderUuid,\n\t};\n};\n\n/**\n * Error thrown when an auction slot has expired\n */\nexport class AuctionSlotExpiredError extends Error {\n\tname = 'AuctionSlotExpiredError';\n\n\t/**\n\t * Creates an instance of AuctionSlotExpiredError\n\t * @param message - Error message (default: 'Auction slot expired')\n\t */\n\tconstructor(message: string = 'Auction slot expired') {\n\t\tsuper(message);\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, AuctionSlotExpiredError);\n\t\t}\n\t}\n}\n\ninterface SignOrderMsgParams {\n\t/** Wallet instance with message signing capability */\n\twallet: {\n\t\t/** Function to sign a message */\n\t\tsignMessage: (message: Uint8Array) => Promise<Uint8Array>;\n\t};\n\t/** Hex-encoded swift order message to sign */\n\thexEncodedSwiftOrderMessage: Uint8Array;\n\t/** Time in milliseconds till the auction expires */\n\texpirationTimeMs: number;\n\t/** Callback function called when the auction expires */\n\tonExpired?: () => void;\n}\n\n/**\n * Signs a swift order message with slot expiration monitoring.\n * Continuously monitors the current slot and rejects with AuctionSlotExpiredError\n * if the auction slot expires before signing is complete.\n *\n * @param wallet - Wallet instance with message signing capability\n * @param hexEncodedSwiftOrderMessage - Hex-encoded swift order message to sign\n * @param expirationTimeMs - Time in milliseconds till the auction expires\n * @param onExpired - Callback function called when the auction expires\n *\n * @returns Promise resolving to the signed message as Uint8Array\n * @throws {AuctionSlotExpiredError} When the auction slot expires before signing completes\n */\nexport const signSwiftOrderMsg = async ({\n\twallet,\n\thexEncodedSwiftOrderMessage,\n\texpirationTimeMs,\n\tonExpired,\n}: SignOrderMsgParams): Promise<Uint8Array> => {\n\tlet timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n\ttry {\n\t\t// Sign the message\n\t\tconst signedMessagePromise = wallet.signMessage(\n\t\t\thexEncodedSwiftOrderMessage\n\t\t);\n\n\t\tconst signingExpiredPromise = new Promise<never>((_resolve, reject) => {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\tonExpired?.();\n\t\t\t\treject(new AuctionSlotExpiredError());\n\t\t\t}, expirationTimeMs);\n\t\t});\n\n\t\t// Ensure that the user signs the message before the expiration time\n\t\tconst signedMessage = await Promise.race([\n\t\t\tsignedMessagePromise,\n\t\t\tsigningExpiredPromise,\n\t\t]);\n\n\t\treturn signedMessage;\n\t} finally {\n\t\tif (timeoutId) {\n\t\t\tclearTimeout(timeoutId);\n\t\t}\n\t}\n};\n\n/**\n * Parameters for sending a swift order to the Swift server\n * @interface SendSwiftOrderParams\n */\ninterface SendSwiftOrderParams {\n\t/** The Drift client instance */\n\tdriftClient: DriftClient;\n\t/** Market identifier for the order */\n\tmarketId: MarketId;\n\t/** Hex-encoded swift order message as string */\n\thexEncodedSwiftOrderMessageString: string;\n\t/** The signed message from the wallet */\n\tsignedMessage: Uint8Array;\n\t/** Unique identifier for the signed message order */\n\tsignedMsgOrderUuid: Uint8Array;\n\t/** Public key of the taker authority */\n\ttakerAuthority: PublicKey;\n\t/** Public key of the signing authority */\n\tsigningAuthority: PublicKey;\n\t/** Duration of the auction in slots (optional) */\n\tauctionDuration?: number;\n}\n\n/**\n * Sends a swift order to the Swift server and handles the response.\n * Monitors the order status and calls appropriate callback functions based on the response type.\n *\n * @param driftClient - The Drift client instance\n * @param marketId - Market identifier for the order\n * @param hexEncodedSwiftOrderMessageString - Hex-encoded swift order message as string\n * @param signedMessage - The signed message from the wallet\n * @param signedMsgOrderUuid - Unique identifier for the signed message order\n * @param takerAuthority - Public key of the taker authority\n * @param signingAuthority - Public key of the signing authority\n * @param auctionDurationSlot - Duration of the auction in slots (optional)\n * @param swiftConfirmationSlotBuffer - Slot buffer for swift server confirmation time (default: 15)\n * @param onExpired - Callback function called when the order expires\n * @param onErrored - Callback function called when the order encounters an error\n * @param onConfirmed - Callback function called when the order is confirmed\n *\n * @returns Promise that resolves when the order processing is complete\n *\n */\nexport const sendSwiftOrder = ({\n\tdriftClient,\n\tmarketId,\n\thexEncodedSwiftOrderMessageString,\n\tsignedMessage,\n\tsignedMsgOrderUuid,\n\ttakerAuthority,\n\tsigningAuthority,\n\tauctionDuration,\n}: SendSwiftOrderParams): SwiftOrderObservable => {\n\tconst signedMsgUserOrdersAccountPubkey = getSignedMsgUserAccountPublicKey(\n\t\tdriftClient.program.programId,\n\t\ttakerAuthority\n\t);\n\n\tconst swiftOrderObservable = SwiftClient.sendAndConfirmSwiftOrderWS(\n\t\tdriftClient.connection,\n\t\tdriftClient,\n\t\tmarketId.marketIndex,\n\t\tmarketId.marketType,\n\t\thexEncodedSwiftOrderMessageString,\n\t\tBuffer.from(signedMessage),\n\t\ttakerAuthority,\n\t\tsignedMsgUserOrdersAccountPubkey,\n\t\tsignedMsgOrderUuid,\n\t\tgetSwiftConfirmationTimeoutMs(auctionDuration ?? 0),\n\t\tsigningAuthority\n\t);\n\n\treturn swiftOrderObservable;\n};\n\ntype PrepSignAndSendSwiftOrderParams = {\n\tdriftClient: DriftClient;\n\tsubAccountId: number;\n\tuserAccountPubKey: PublicKey;\n\tmarketIndex: number;\n\tslotBuffer: number;\n\tswiftOptions: SwiftOrderOptions;\n\torderParams: {\n\t\tmain: OptionalOrderParams;\n\t\ttakeProfit?: OptionalTriggerOrderParams;\n\t\tstopLoss?: OptionalTriggerOrderParams;\n\t\t/**\n\t\t * Adjusts the max leverage of a position.\n\t\t */\n\t\tpositionMaxLeverage?: number;\n\t};\n\t/**\n\t * Optional builder code parameters for revenue sharing.\n\t * If provided, the builder will receive a portion of the trading fees.\n\t *\n\t * Prerequisites:\n\t * - User must have initialized a RevenueShareEscrow account\n\t * - Builder must be in the user's approved_builders list\n\t * - builderFeeTenthBps must not exceed the builder's max_fee_tenth_bps\n\t *\n\t * @example\n\t * ```typescript\n\t * builderParams: {\n\t * builderIdx: 0, // First builder in approved list\n\t * builderFeeTenthBps: 50 // 5 bps = 0.05%\n\t * }\n\t * ```\n\t */\n\tbuilderParams?: {\n\t\t/**\n\t\t * Index of the builder in the user's approved_builders list.\n\t\t */\n\t\tbuilderIdx: number;\n\t\t/**\n\t\t * Fee to charge for this order, in tenths of basis points.\n\t\t * Must be <= the builder's max_fee_tenth_bps.\n\t\t */\n\t\tbuilderFeeTenthBps: number;\n\t};\n};\n\n/**\n * Handles the full flow of the swift order, from preparing to signing and sending to the Swift server.\n * Callbacks can be provided to handle the events of the Swift order.\n * Returns a promise that resolves when the Swift order has reached a terminal state (i.e. confirmed, expired, or errored).\n */\nexport const prepSignAndSendSwiftOrder = async ({\n\tdriftClient,\n\tsubAccountId,\n\tuserAccountPubKey,\n\tmarketIndex,\n\tslotBuffer,\n\tswiftOptions,\n\torderParams,\n\tbuilderParams,\n}: PrepSignAndSendSwiftOrderParams): Promise<void> => {\n\tconst currentSlot = await driftClient.connection.getSlot('confirmed');\n\n\tconst {\n\t\thexEncodedSwiftOrderMessage,\n\t\tsignedMsgOrderUuid,\n\t\tsignedMsgOrderParamsMessage,\n\t} = prepSwiftOrder({\n\t\tdriftClient,\n\t\ttakerUserAccount: {\n\t\t\tpubKey: userAccountPubKey,\n\t\t\tsubAccountId: subAccountId,\n\t\t},\n\t\tcurrentSlot,\n\t\tisDelegate: swiftOptions.isDelegate || false,\n\t\torderParams,\n\t\tslotBuffer,\n\t\tbuilderParams,\n\t});\n\n\tswiftOptions.callbacks?.onOrderParamsMessagePrepped?.(\n\t\tsignedMsgOrderParamsMessage\n\t);\n\n\tconst expirationTimeMs =\n\t\tMath.max(\n\t\t\tslotBuffer +\n\t\t\t\t(orderParams.main.auctionDuration || 0) -\n\t\t\t\tSWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS,\n\t\t\tMINIMUM_SWIFT_ORDER_SIGNING_EXPIRATION_BUFFER_SLOTS\n\t\t) * SLOT_TIME_ESTIMATE_MS;\n\n\t// Ensure that the user signs the message before the expiration time\n\tconst signedMessage = await signSwiftOrderMsg({\n\t\twallet: swiftOptions.wallet,\n\t\thexEncodedSwiftOrderMessage: hexEncodedSwiftOrderMessage.uInt8Array,\n\t\texpirationTimeMs,\n\t\tonExpired: () =>\n\t\t\tswiftOptions.callbacks?.onSigningExpiry?.(signedMsgOrderParamsMessage),\n\t});\n\n\tswiftOptions.callbacks?.onSigningSuccess?.(\n\t\tsignedMessage,\n\t\tsignedMsgOrderUuid,\n\t\tsignedMsgOrderParamsMessage\n\t);\n\n\t// Initialize SwiftClient (required before using sendSwiftOrder)\n\tSwiftClient.init(swiftOptions.swiftServerUrl);\n\n\t// Create a promise-based wrapper for the sendSwiftOrder callback-based API\n\tconst swiftOrderObservable = sendSwiftOrder({\n\t\tdriftClient,\n\t\tmarketId: MarketId.createPerpMarket(marketIndex),\n\t\thexEncodedSwiftOrderMessageString: hexEncodedSwiftOrderMessage.string,\n\t\tsignedMessage,\n\t\tsignedMsgOrderUuid,\n\t\ttakerAuthority: swiftOptions.wallet.takerAuthority,\n\t\tsigningAuthority:\n\t\t\tswiftOptions.wallet.signingAuthority ??\n\t\t\tswiftOptions.wallet.takerAuthority,\n\t\tauctionDuration: orderParams.main.auctionDuration || undefined,\n\t});\n\n\tconst wrapSwiftOrderEvent = <T extends SwiftOrderEvent>(\n\t\tswiftOrderEvent: T\n\t) => {\n\t\treturn {\n\t\t\t...swiftOrderEvent,\n\t\t\tswiftOrderUuid: signedMsgOrderUuid,\n\t\t\torderParamsMessage: signedMsgOrderParamsMessage,\n\t\t};\n\t};\n\n\tlet promiseResolver: (value: void | PromiseLike<void>) => void;\n\tconst promise = new Promise<void>((resolve) => {\n\t\tpromiseResolver = resolve;\n\t});\n\n\tconst handleTerminalEvent = (subscription: Subscription) => {\n\t\tsubscription.unsubscribe();\n\t\tpromiseResolver();\n\t};\n\n\tconst subscription = swiftOrderObservable.subscribe((swiftOrderEvent) => {\n\t\tif (swiftOrderEvent.type === 'sent') {\n\t\t\tswiftOptions.callbacks?.onSent?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t}\n\t\tif (swiftOrderEvent.type === 'confirmed') {\n\t\t\tswiftOptions.callbacks?.onConfirmed?.(\n\t\t\t\twrapSwiftOrderEvent(swiftOrderEvent)\n\t\t\t);\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t\tif (swiftOrderEvent.type === 'expired') {\n\t\t\tswiftOptions.callbacks?.onExpired?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t\tif (swiftOrderEvent.type === 'errored') {\n\t\t\tswiftOptions.callbacks?.onErrored?.(wrapSwiftOrderEvent(swiftOrderEvent));\n\t\t\thandleTerminalEvent(subscription);\n\t\t}\n\t});\n\n\treturn promise;\n};\n"]}
package/lib/index.d.ts CHANGED
@@ -31,6 +31,7 @@ export * from './clients/candleClient';
31
31
  export * from './clients/marketDataFeed';
32
32
  export * from './clients/swiftClient';
33
33
  export * from './clients/tvFeed';
34
+ export * from './clients/DlobWebsocketClient';
34
35
  export * from './utils/pollingSequenceGuard';
35
36
  export * from './utils/driftEvents';
36
37
  export * from './utils/MultiplexWebSocket';
package/lib/index.js CHANGED
@@ -51,6 +51,7 @@ __exportStar(require("./clients/candleClient"), exports);
51
51
  __exportStar(require("./clients/marketDataFeed"), exports);
52
52
  __exportStar(require("./clients/swiftClient"), exports);
53
53
  __exportStar(require("./clients/tvFeed"), exports);
54
+ __exportStar(require("./clients/DlobWebsocketClient"), exports);
54
55
  __exportStar(require("./utils/pollingSequenceGuard"), exports);
55
56
  __exportStar(require("./utils/driftEvents"), exports);
56
57
  __exportStar(require("./utils/MultiplexWebSocket"), exports);
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,0CAAwB;AACxB,yDAAuC;AACvC,0CAAwB;AACxB,gDAA8B;AAC9B,oDAAkC;AAClC,sDAAoC;AACpC,yDAAuC;AACvC,uDAAqC;AACrC,gEAA8C;AAC9C,qDAAmC;AACnC,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,yDAAuC;AACvC,oDAAkC;AAClC,8CAA4B;AAC5B,wEAAsD;AACtD,yDAAuC;AACvC,oDAAkC;AAClC,wDAAsC;AACtC,qDAAmC;AACnC,gDAA8B;AAC9B,sDAAoC;AACpC,+EAA6D;AAC7D,sEAAoD;AACpD,wDAAsC;AACtC,oDAAkC;AAClC,yDAAuC;AACvC,2DAAyC;AACzC,wDAAsC;AACtC,mDAAiC;AACjC,+DAA6C;AAC7C,sDAAoC;AACpC,6DAA2C;AAC3C,mEAAiD;AACjD,0DAAwC;AACxC,+CAA6B;AAC7B,uDAAqC;AACrC,iDAA+B;AAC/B,0CAAwB;AAExB,0BAA0B;AAC1B,gHAA4E;AAEnE,sBAFF,iCAAW,CAEE;AADpB,gHAA4E;AACtD,sBADf,iCAAW,CACe;AAEjC,kGAAqE;AAC5D,sBADF,0BAAW,CACE","sourcesContent":["export * from './Config';\nexport * from './chartConstants';\nexport * from './types';\nexport * from './EnvironmentConstants';\nexport * from './utils';\nexport * from './utils/index';\nexport * from './utils/s3Buckets';\nexport * from './serializableTypes';\nexport * from './utils/candles/Candle';\nexport * from './utils/featureFlags';\nexport * from './utils/WalletConnectionState';\nexport * from './utils/rpcLatency';\nexport * from './utils/token';\nexport * from './utils/math';\nexport * from './utils/logger';\nexport * from './utils/equalityChecks';\nexport * from './common-ui-utils';\nexport * from './constants';\nexport * from './actions/actionHelpers/actionHelpers';\nexport * from './utils/SharedInterval';\nexport * from './utils/Stopwatch';\nexport * from './utils/priority-fees';\nexport * from './utils/superstake';\nexport * from './utils/fetch';\nexport * from './utils/priceImpact';\nexport * from './utils/dlob-server/DlobServerWebsocketUtils';\nexport * from './common-ui-utils/settings/settings';\nexport * from './utils/priority-fees';\nexport * from './utils/orderbook';\nexport * from './clients/candleClient';\nexport * from './clients/marketDataFeed';\nexport * from './clients/swiftClient';\nexport * from './clients/tvFeed';\nexport * from './utils/pollingSequenceGuard';\nexport * from './utils/driftEvents';\nexport * from './utils/MultiplexWebSocket';\nexport * from './utils/SlotBasedResultValidator';\nexport * from './utils/CircularBuffers';\nexport * from './utils/rxjs';\nexport * from './utils/priorityFees';\nexport * from './utils/NumLib';\nexport * from './drift';\n\n// External Program Errors\nimport JupV4Errors from './constants/autogenerated/jup-v4-error-codes.json';\nimport JupV6Errors from './constants/autogenerated/jup-v6-error-codes.json';\nexport { JupV4Errors, JupV6Errors };\n\nimport DriftErrors from './constants/autogenerated/driftErrors.json';\nexport { DriftErrors };\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,mDAAiC;AACjC,0CAAwB;AACxB,yDAAuC;AACvC,0CAAwB;AACxB,gDAA8B;AAC9B,oDAAkC;AAClC,sDAAoC;AACpC,yDAAuC;AACvC,uDAAqC;AACrC,gEAA8C;AAC9C,qDAAmC;AACnC,gDAA8B;AAC9B,+CAA6B;AAC7B,iDAA+B;AAC/B,yDAAuC;AACvC,oDAAkC;AAClC,8CAA4B;AAC5B,wEAAsD;AACtD,yDAAuC;AACvC,oDAAkC;AAClC,wDAAsC;AACtC,qDAAmC;AACnC,gDAA8B;AAC9B,sDAAoC;AACpC,+EAA6D;AAC7D,sEAAoD;AACpD,wDAAsC;AACtC,oDAAkC;AAClC,yDAAuC;AACvC,2DAAyC;AACzC,wDAAsC;AACtC,mDAAiC;AACjC,gEAA8C;AAC9C,+DAA6C;AAC7C,sDAAoC;AACpC,6DAA2C;AAC3C,mEAAiD;AACjD,0DAAwC;AACxC,+CAA6B;AAC7B,uDAAqC;AACrC,iDAA+B;AAC/B,0CAAwB;AAExB,0BAA0B;AAC1B,gHAA4E;AAEnE,sBAFF,iCAAW,CAEE;AADpB,gHAA4E;AACtD,sBADf,iCAAW,CACe;AAEjC,kGAAqE;AAC5D,sBADF,0BAAW,CACE","sourcesContent":["export * from './Config';\nexport * from './chartConstants';\nexport * from './types';\nexport * from './EnvironmentConstants';\nexport * from './utils';\nexport * from './utils/index';\nexport * from './utils/s3Buckets';\nexport * from './serializableTypes';\nexport * from './utils/candles/Candle';\nexport * from './utils/featureFlags';\nexport * from './utils/WalletConnectionState';\nexport * from './utils/rpcLatency';\nexport * from './utils/token';\nexport * from './utils/math';\nexport * from './utils/logger';\nexport * from './utils/equalityChecks';\nexport * from './common-ui-utils';\nexport * from './constants';\nexport * from './actions/actionHelpers/actionHelpers';\nexport * from './utils/SharedInterval';\nexport * from './utils/Stopwatch';\nexport * from './utils/priority-fees';\nexport * from './utils/superstake';\nexport * from './utils/fetch';\nexport * from './utils/priceImpact';\nexport * from './utils/dlob-server/DlobServerWebsocketUtils';\nexport * from './common-ui-utils/settings/settings';\nexport * from './utils/priority-fees';\nexport * from './utils/orderbook';\nexport * from './clients/candleClient';\nexport * from './clients/marketDataFeed';\nexport * from './clients/swiftClient';\nexport * from './clients/tvFeed';\nexport * from './clients/DlobWebsocketClient';\nexport * from './utils/pollingSequenceGuard';\nexport * from './utils/driftEvents';\nexport * from './utils/MultiplexWebSocket';\nexport * from './utils/SlotBasedResultValidator';\nexport * from './utils/CircularBuffers';\nexport * from './utils/rxjs';\nexport * from './utils/priorityFees';\nexport * from './utils/NumLib';\nexport * from './drift';\n\n// External Program Errors\nimport JupV4Errors from './constants/autogenerated/jup-v4-error-codes.json';\nimport JupV6Errors from './constants/autogenerated/jup-v6-error-codes.json';\nexport { JupV4Errors, JupV6Errors };\n\nimport DriftErrors from './constants/autogenerated/driftErrors.json';\nexport { DriftErrors };\n"]}
@@ -9,10 +9,11 @@ type WebSocketSubscriptionProps<T = Record<string, unknown>> = {
9
9
  unsubscribeMessage: string;
10
10
  onError: (err?: any) => void;
11
11
  onMessage: (message: WebSocketMessage<T>) => void;
12
- messageFilter: (message: WebSocketMessage<T>) => boolean;
13
- errorMessageFilter: (message: WebSocketMessage<T>) => boolean;
12
+ messageFilter?: (message: WebSocketMessage<T>) => boolean;
13
+ errorMessageFilter?: (message: WebSocketMessage<T>) => boolean;
14
14
  onClose?: () => void;
15
15
  enableHeartbeatMonitoring?: boolean;
16
+ heartbeatTimeoutMs?: number;
16
17
  };
17
18
  type WebSocketSubscriptionState<T = Record<string, unknown>> = WebSocketSubscriptionProps<T> & {
18
19
  hasSentSubscribeMessage?: boolean;
@@ -63,6 +64,7 @@ export declare class MultiplexWebSocket<T = Record<string, unknown>> implements
63
64
  private closeTimeout;
64
65
  private heartbeatTimeout;
65
66
  private heartbeatMonitoringEnabled;
67
+ private heartbeatTimeoutMs;
66
68
  private constructor();
67
69
  /**
68
70
  * Creates a new virtual websocket subscription. If an existing websocket for the given URL exists, the subscription will be added to the existing websocket.
@@ -21,7 +21,7 @@ const isomorphic_ws_1 = __importDefault(require("isomorphic-ws"));
21
21
  const DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;
22
22
  const DEFAULT_MAX_RECONNECT_WINDOW_MS = 60 * 1000;
23
23
  const DEFAULT_CONNECTION_CLOSE_DELAY_MS = 2 * 1000; // 2 seconds delay before closing connection
24
- const DEFAULT_HEARTBEAT_TIMEOUT_MS = 60 * 1000; // Consider connection dead if no heartbeat within 60 seconds
24
+ const DEFAULT_HEARTBEAT_TIMEOUT_MS = 11 * 1000; // Consider connection dead if no heartbeat within 11 seconds (a little more than twice of 5 seconds, the interval Drift servers use)
25
25
  /**
26
26
  * Manages reconnection logic for WebSocket connections with exponential backoff and rate limiting.
27
27
  *
@@ -92,11 +92,12 @@ var WebSocketConnectionState;
92
92
  * - The websocket will be refreshed (new instance) when it disconnects unexpectedly or errors, until it reaches the maximum number of reconnect attempts
93
93
  */
94
94
  class MultiplexWebSocket {
95
- constructor(wsUrl, enableHeartbeatMonitoring = false) {
95
+ constructor(wsUrl, enableHeartbeatMonitoring = false, heartbeatTimeoutMs = DEFAULT_HEARTBEAT_TIMEOUT_MS) {
96
96
  _MultiplexWebSocket_webSocket.set(this, void 0);
97
97
  this.closeTimeout = null;
98
98
  this.heartbeatTimeout = null;
99
99
  this.heartbeatMonitoringEnabled = false;
100
+ this.heartbeatTimeoutMs = DEFAULT_HEARTBEAT_TIMEOUT_MS;
100
101
  if (MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {
101
102
  throw new Error(`Attempting to create a new websocket for ${wsUrl}, but it already exists`);
102
103
  }
@@ -106,6 +107,7 @@ class MultiplexWebSocket {
106
107
  this.subscriptions = new Map();
107
108
  this.reconnectionManager = new ReconnectionManager();
108
109
  this.heartbeatMonitoringEnabled = enableHeartbeatMonitoring;
110
+ this.heartbeatTimeoutMs = heartbeatTimeoutMs;
109
111
  this.webSocket = new isomorphic_ws_1.default(wsUrl);
110
112
  MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.set(wsUrl, this);
111
113
  }
@@ -125,8 +127,8 @@ class MultiplexWebSocket {
125
127
  }
126
128
  }
127
129
  static handleNewSubForNewWsUrl(newSubscriptionProps) {
128
- var _a;
129
- const newMWS = new MultiplexWebSocket(newSubscriptionProps.wsUrl, (_a = newSubscriptionProps.enableHeartbeatMonitoring) !== null && _a !== void 0 ? _a : false);
130
+ var _a, _b;
131
+ const newMWS = new MultiplexWebSocket(newSubscriptionProps.wsUrl, (_a = newSubscriptionProps.enableHeartbeatMonitoring) !== null && _a !== void 0 ? _a : false, (_b = newSubscriptionProps.heartbeatTimeoutMs) !== null && _b !== void 0 ? _b : DEFAULT_HEARTBEAT_TIMEOUT_MS);
130
132
  newMWS.subscribe(newSubscriptionProps);
131
133
  return {
132
134
  unsubscribe: () => {
@@ -135,7 +137,7 @@ class MultiplexWebSocket {
135
137
  };
136
138
  }
137
139
  static handleNewSubForExistingWsUrl(newSubscriptionProps) {
138
- var _a;
140
+ var _a, _b;
139
141
  const { wsUrl, subscriptionId } = newSubscriptionProps;
140
142
  if (!MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {
141
143
  throw new Error(`Attempting to subscribe to ${subscriptionId} on websocket ${wsUrl}, but websocket does not exist yet`);
@@ -147,6 +149,12 @@ class MultiplexWebSocket {
147
149
  console.warn(`WebSocket for ${wsUrl} already exists with heartbeat monitoring ${existingMWS.heartbeatMonitoringEnabled ? 'enabled' : 'disabled'}, ` +
148
150
  `but new subscription requests ${requestedHeartbeat ? 'enabled' : 'disabled'}. Using existing setting.`);
149
151
  }
152
+ // Check if heartbeat timeout settings match for the same websocket URL (note that this assumes that all types of subscriptions from the same websocket URL are expected to have the same heartbeat interval)
153
+ const requestedTimeout = (_b = newSubscriptionProps.heartbeatTimeoutMs) !== null && _b !== void 0 ? _b : DEFAULT_HEARTBEAT_TIMEOUT_MS;
154
+ if (existingMWS.heartbeatTimeoutMs !== requestedTimeout) {
155
+ console.warn(`WebSocket for ${wsUrl} already exists with heartbeat timeout ${existingMWS.heartbeatTimeoutMs}ms, ` +
156
+ `but new subscription requests ${requestedTimeout}ms. Using existing setting.`);
157
+ }
150
158
  // Track new subscription for existing websocket
151
159
  existingMWS.subscribe(newSubscriptionProps);
152
160
  return {
@@ -220,6 +228,7 @@ class MultiplexWebSocket {
220
228
  if (subscriptionState) {
221
229
  subscriptionState.hasSentSubscribeMessage = true;
222
230
  }
231
+ // Create internal subscription for message handling
223
232
  const subjectSubscription = this.subject
224
233
  .pipe((0, rxjs_1.catchError)((err) => {
225
234
  console.error('Caught websocket error', err);
@@ -229,9 +238,9 @@ class MultiplexWebSocket {
229
238
  .subscribe({
230
239
  next: (message) => {
231
240
  try {
232
- if (!messageFilter(message))
241
+ if (messageFilter && !messageFilter(message))
233
242
  return;
234
- if (errorMessageFilter(message)) {
243
+ if (errorMessageFilter && errorMessageFilter(message)) {
235
244
  onError();
236
245
  return;
237
246
  }
@@ -358,9 +367,9 @@ class MultiplexWebSocket {
358
367
  }
359
368
  // Set new timeout
360
369
  this.heartbeatTimeout = setTimeout(() => {
361
- console.warn(`No heartbeat received within ${DEFAULT_HEARTBEAT_TIMEOUT_MS}ms - connection appears dead`);
370
+ console.warn(`No heartbeat received within ${this.heartbeatTimeoutMs}ms - connection appears dead`);
362
371
  this.refreshWebSocket();
363
- }, DEFAULT_HEARTBEAT_TIMEOUT_MS);
372
+ }, this.heartbeatTimeoutMs);
364
373
  }
365
374
  isHeartbeatMessage(message) {
366
375
  // Check if message is a heartbeat message from server
@@ -1 +1 @@
1
- {"version":3,"file":"MultiplexWebSocket.js","sourceRoot":"","sources":["../../src/utils/MultiplexWebSocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject, catchError, Subscription } from 'rxjs';\nimport WebSocket, { MessageEvent } from 'isomorphic-ws';\n\ntype WebSocketMessage<T = Record<string, unknown>> = T;\n\ntype WebSocketSubscriptionProps<T = Record<string, unknown>> = {\n\twsUrl: string;\n\tsubscriptionId: string;\n\tsubscribeMessage: string;\n\tunsubscribeMessage: string;\n\tonError: (err?: any) => void;\n\tonMessage: (message: WebSocketMessage<T>) => void;\n\tmessageFilter: (message: WebSocketMessage<T>) => boolean;\n\terrorMessageFilter: (message: WebSocketMessage<T>) => boolean;\n\tonClose?: () => void;\n\tenableHeartbeatMonitoring?: boolean;\n};\n\ntype WebSocketSubscriptionState<T = Record<string, unknown>> =\n\tWebSocketSubscriptionProps<T> & {\n\t\thasSentSubscribeMessage?: boolean;\n\t\tsubjectSubscription?: Subscription;\n\t};\n\ntype WebSocketUrl = string;\ntype SubscriptionId = string;\n\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;\nconst DEFAULT_MAX_RECONNECT_WINDOW_MS = 60 * 1000;\nconst DEFAULT_CONNECTION_CLOSE_DELAY_MS = 2 * 1000; // 2 seconds delay before closing connection\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 60 * 1000; // Consider connection dead if no heartbeat within 60 seconds\n\n/**\n * Manages reconnection logic for WebSocket connections with exponential backoff and rate limiting.\n *\n * Features:\n * - Tracks reconnection attempts within a time window\n * - Implements exponential backoff (1s, 2s, 4s, 8s max)\n * - Resets attempt counter after configurable time window\n * - Throws error when max attempts exceeded\n * - Provides configurable limits for attempts and time window\n *\n * @example\n * ```ts\n * const manager = new ReconnectionManager(5, 60000); // 5 attempts in 60s\n * const { shouldReconnect, delay } = manager.attemptReconnection('ws://example.com');\n * if (shouldReconnect) {\n * setTimeout(() => reconnect(), delay);\n * }\n * ```\n */\nclass ReconnectionManager {\n\tprivate reconnectAttempts: number = 0;\n\tprivate lastReconnectWindow: number = Date.now();\n\tprivate maxAttemptsCount: number;\n\tprivate maxAttemptsWindowMs: number;\n\n\tconstructor(\n\t\tmaxAttemptsCount = DEFAULT_MAX_RECONNECT_ATTEMPTS,\n\t\tmaxAttemptsWindowMs = DEFAULT_MAX_RECONNECT_WINDOW_MS\n\t) {\n\t\tthis.maxAttemptsCount = maxAttemptsCount;\n\t\tthis.maxAttemptsWindowMs = maxAttemptsWindowMs;\n\t}\n\n\tpublic attemptReconnection(wsUrl: string): {\n\t\tshouldReconnect: boolean;\n\t\tdelay: number;\n\t} {\n\t\tconst now = Date.now();\n\n\t\t// Reset reconnect attempts if more than a minute has passed\n\t\tif (now - this.lastReconnectWindow > this.maxAttemptsWindowMs) {\n\t\t\tthis.reconnectAttempts = 0;\n\t\t\tthis.lastReconnectWindow = now;\n\t\t}\n\n\t\t// Check if we've exceeded the maximum reconnect attempts\n\t\tif (this.reconnectAttempts >= this.maxAttemptsCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`WebSocket reconnection failed: Maximum reconnect attempts (${this.maxAttemptsCount}) exceeded within ${this.maxAttemptsWindowMs}ms for ${wsUrl}`\n\t\t\t);\n\t\t}\n\n\t\tthis.reconnectAttempts++;\n\n\t\t// Calculate exponential backoff delay: 1s, 2s, 4s, 8s, etc. (capped at 8s)\n\t\tconst backoffDelay = Math.min(\n\t\t\t1000 * Math.pow(2, this.reconnectAttempts - 1),\n\t\t\t8000\n\t\t);\n\n\t\treturn {\n\t\t\tshouldReconnect: true,\n\t\t\tdelay: backoffDelay,\n\t\t};\n\t}\n\n\tpublic reset(): void {\n\t\tthis.reconnectAttempts = 0;\n\t\tthis.lastReconnectWindow = Date.now();\n\t}\n}\n\nenum WebSocketConnectionState {\n\tCONNECTING,\n\tCONNECTED,\n\tDISCONNECTING,\n\tDISCONNECTED,\n}\n\ntype IMultiplexWebSocket<T = Record<string, unknown>> = {\n\twsUrl: WebSocketUrl;\n\twebSocket: WebSocket;\n\tcustomConnectionState: WebSocketConnectionState;\n\tsubject: Subject<WebSocketMessage<T>>;\n\tsubscriptions: Map<\n\t\tSubscriptionId,\n\t\tOmit<WebSocketSubscriptionProps<T>, 'wsUrl' | 'subscriptionId'>\n\t>;\n};\n\n/**\n * MultiplexWebSocket allows for multiple subscriptions to a single websocket of the same URL, improving efficiency and reducing the number of open connections.\n *\n * This implementation assumes the following:\n * - All websocket streams are treated equally - reconnection attempts are performed at the same standards\n * - All messages returned are in the `WebSocketMessage` format\n * - A single instance of the websocket manager is created for each websocket URL - this means all subscriptions to the same websocket URL will share the same websocket instance\n *\n * Internal implementation details:\n * - The websocket is closed when the number of subscriptions is 0\n * - The websocket will be refreshed (new instance) when it disconnects unexpectedly or errors, until it reaches the maximum number of reconnect attempts\n */\nexport class MultiplexWebSocket<T = Record<string, unknown>>\n\timplements IMultiplexWebSocket<T>\n{\n\t/**\n\t * A lookup of all websockets by their URL.\n\t */\n\tprivate static URL_TO_WEBSOCKETS_LOOKUP = new Map<\n\t\tWebSocketUrl,\n\t\tMultiplexWebSocket<any>\n\t>();\n\n\t/**\n\t * A lookup from websocket URL to all subscription IDs for that URL.\n\t */\n\tprivate static URL_TO_SUBSCRIPTION_IDS_LOOKUP = new Map<\n\t\tWebSocketUrl,\n\t\tSet<SubscriptionId>\n\t>();\n\n\twsUrl: WebSocketUrl;\n\t#webSocket: WebSocket;\n\tcustomConnectionState: WebSocketConnectionState;\n\tsubject: Subject<WebSocketMessage<T>>;\n\tsubscriptions: Map<\n\t\tSubscriptionId,\n\t\tOmit<WebSocketSubscriptionState<T>, 'wsUrl' | 'subscriptionId'>\n\t>;\n\tprivate reconnectionManager: ReconnectionManager;\n\tprivate closeTimeout: NodeJS.Timeout | null = null;\n\tprivate heartbeatTimeout: NodeJS.Timeout | null = null;\n\tprivate heartbeatMonitoringEnabled: boolean = false;\n\n\tprivate constructor(\n\t\twsUrl: WebSocketUrl,\n\t\tenableHeartbeatMonitoring: boolean = false\n\t) {\n\t\tif (MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to create a new websocket for ${wsUrl}, but it already exists`\n\t\t\t);\n\t\t}\n\n\t\tthis.wsUrl = wsUrl;\n\t\tthis.customConnectionState = WebSocketConnectionState.CONNECTING;\n\t\tthis.subject = new Subject<WebSocketMessage<T>>();\n\t\tthis.subscriptions = new Map<\n\t\t\tSubscriptionId,\n\t\t\tOmit<WebSocketSubscriptionProps<T>, 'wsUrl' | 'subscriptionId'>\n\t\t>();\n\n\t\tthis.reconnectionManager = new ReconnectionManager();\n\t\tthis.heartbeatMonitoringEnabled = enableHeartbeatMonitoring;\n\n\t\tthis.webSocket = new WebSocket(wsUrl);\n\n\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.set(wsUrl, this);\n\t}\n\n\t/**\n\t * Creates a new virtual websocket subscription. If an existing websocket for the given URL exists, the subscription will be added to the existing websocket.\n\t * Returns a function that can be called to unsubscribe from the subscription.\n\t */\n\tpublic static createWebSocketSubscription<T = Record<string, unknown>>(\n\t\tprops: WebSocketSubscriptionProps<T>\n\t): { unsubscribe: () => void } {\n\t\tconst { wsUrl } = props;\n\n\t\tconst doesWebSocketForWsUrlExist =\n\t\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl);\n\n\t\tif (doesWebSocketForWsUrlExist) {\n\t\t\treturn this.handleNewSubForExistingWsUrl<T>(props);\n\t\t} else {\n\t\t\t// Create new websocket for new URL or reopen previously closed websocket\n\t\t\treturn this.handleNewSubForNewWsUrl<T>(props);\n\t\t}\n\t}\n\n\tprivate static handleNewSubForNewWsUrl<T = Record<string, unknown>>(\n\t\tnewSubscriptionProps: WebSocketSubscriptionProps<T>\n\t) {\n\t\tconst newMWS = new MultiplexWebSocket<T>(\n\t\t\tnewSubscriptionProps.wsUrl,\n\t\t\tnewSubscriptionProps.enableHeartbeatMonitoring ?? false\n\t\t);\n\n\t\tnewMWS.subscribe(newSubscriptionProps);\n\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\tnewMWS.unsubscribe(newSubscriptionProps.subscriptionId);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate static handleNewSubForExistingWsUrl<T = Record<string, unknown>>(\n\t\tnewSubscriptionProps: WebSocketSubscriptionProps<T>\n\t) {\n\t\tconst { wsUrl, subscriptionId } = newSubscriptionProps;\n\n\t\tif (!MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to subscribe to ${subscriptionId} on websocket ${wsUrl}, but websocket does not exist yet`\n\t\t\t);\n\t\t}\n\n\t\tconst existingMWS = MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.get(\n\t\t\twsUrl\n\t\t) as MultiplexWebSocket<T>;\n\n\t\t// Check if heartbeat monitoring settings match\n\t\tconst requestedHeartbeat =\n\t\t\tnewSubscriptionProps.enableHeartbeatMonitoring ?? false;\n\t\tif (existingMWS.heartbeatMonitoringEnabled !== requestedHeartbeat) {\n\t\t\tconsole.warn(\n\t\t\t\t`WebSocket for ${wsUrl} already exists with heartbeat monitoring ${\n\t\t\t\t\texistingMWS.heartbeatMonitoringEnabled ? 'enabled' : 'disabled'\n\t\t\t\t}, ` +\n\t\t\t\t\t`but new subscription requests ${\n\t\t\t\t\t\trequestedHeartbeat ? 'enabled' : 'disabled'\n\t\t\t\t\t}. Using existing setting.`\n\t\t\t);\n\t\t}\n\n\t\t// Track new subscription for existing websocket\n\t\texistingMWS.subscribe(newSubscriptionProps);\n\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\texistingMWS.unsubscribe(newSubscriptionProps.subscriptionId);\n\t\t\t},\n\t\t};\n\t}\n\n\tget webSocket() {\n\t\treturn this.#webSocket;\n\t}\n\n\t/**\n\t * Setting the WebSocket instance will automatically add event handlers to the WebSocket instance.\n\t * When the WebSocket is connected, all existing subscriptions will be subscribed to.\n\t */\n\tset webSocket(webSocket: WebSocket) {\n\t\twebSocket.onopen = () => {\n\t\t\tthis.customConnectionState = WebSocketConnectionState.CONNECTED;\n\t\t\tthis.reconnectionManager.reset(); // Reset reconnection attempts on successful connection\n\n\t\t\t// Start heartbeat monitoring if enabled\n\t\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\t\tthis.startHeartbeatMonitoring();\n\t\t\t}\n\n\t\t\t// sends subscription message for each subscription for those that are added before the websocket is connected\n\t\t\tfor (const [subscriptionId] of this.subscriptions.entries()) {\n\t\t\t\tthis.subscribeToWebSocket(subscriptionId);\n\t\t\t}\n\t\t};\n\n\t\twebSocket.onmessage = (messageEvent: MessageEvent) => {\n\t\t\tconst message = JSON.parse(\n\t\t\t\tmessageEvent.data as string\n\t\t\t) as WebSocketMessage<T>;\n\n\t\t\t// Check for heartbeat message from server (only if heartbeat monitoring is enabled)\n\t\t\tif (this.heartbeatMonitoringEnabled && this.isHeartbeatMessage(message)) {\n\t\t\t\tthis.handleHeartbeat(message);\n\t\t\t\treturn; // Don't forward heartbeat messages to subscriptions\n\t\t\t}\n\n\t\t\tthis.subject.next(message);\n\t\t};\n\n\t\twebSocket.onclose = (event) => {\n\t\t\tthis.customConnectionState = WebSocketConnectionState.DISCONNECTED;\n\n\t\t\t// Stop heartbeat monitoring when connection closes (if enabled)\n\t\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\t\tthis.stopHeartbeatMonitoring();\n\t\t\t}\n\n\t\t\t// Restart websocket if it was closed unexpectedly (not by us)\n\t\t\tif (!event.wasClean && this.subscriptions.size > 0) {\n\t\t\t\tconsole.log('WebSocket closed unexpectedly, restarting...', event);\n\t\t\t\tthis.refreshWebSocket();\n\t\t\t}\n\t\t};\n\n\t\twebSocket.onerror = (error) => {\n\t\t\tconsole.error('MultiplexWebSocket Error', { error, webSocket });\n\n\t\t\t// Forward error to all subscriptions for this websocket URL\n\t\t\tconst subscriptionIds =\n\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl);\n\t\t\tif (subscriptionIds) {\n\t\t\t\tfor (const subscriptionId of subscriptionIds) {\n\t\t\t\t\tconst subscription = this.subscriptions.get(subscriptionId);\n\t\t\t\t\tif (subscription) {\n\t\t\t\t\t\tsubscription.onError(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Restart the websocket connection on error\n\t\t\tthis.refreshWebSocket();\n\t\t};\n\n\t\tthis.#webSocket = webSocket;\n\t}\n\n\tprivate subscribeToWebSocket(subscriptionId: SubscriptionId) {\n\t\tconst subscriptionState = this.subscriptions.get(subscriptionId);\n\n\t\tconst {\n\t\t\tsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t} = subscriptionState;\n\n\t\tthis.webSocket.send(subscribeMessage);\n\t\tif (subscriptionState) {\n\t\t\tsubscriptionState.hasSentSubscribeMessage = true;\n\t\t}\n\n\t\tconst subjectSubscription = this.subject\n\t\t\t.pipe(\n\t\t\t\tcatchError((err) => {\n\t\t\t\t\tconsole.error('Caught websocket error', err);\n\t\t\t\t\tonError();\n\t\t\t\t\treturn [];\n\t\t\t\t})\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: (message: WebSocketMessage<T>) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!messageFilter(message)) return;\n\n\t\t\t\t\t\tif (errorMessageFilter(message)) {\n\t\t\t\t\t\t\tonError();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tonMessage(message);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error('Error parsing websocket message', err);\n\t\t\t\t\t\tonError();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: (err) => {\n\t\t\t\t\tconsole.error('Error subscribing to websocket', err);\n\t\t\t\t\tonError();\n\t\t\t\t},\n\t\t\t\tcomplete: () => {\n\t\t\t\t\tif (onClose) {\n\t\t\t\t\t\tonClose();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\tsubscriptionState.subjectSubscription = subjectSubscription;\n\t}\n\n\tprivate subscribe(props: WebSocketSubscriptionProps<T>) {\n\t\tconst {\n\t\t\tsubscriptionId,\n\t\t\tsubscribeMessage,\n\t\t\tunsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t} = props;\n\n\t\tif (this.subscriptions.get(subscriptionId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to subscribe to ${subscriptionId} on websocket ${this.wsUrl}, but subscription already exists`\n\t\t\t);\n\t\t}\n\n\t\t// Cancel any pending delayed close since we're adding a new subscription\n\t\tthis.cancelDelayedClose();\n\n\t\tthis.subscriptions.set(subscriptionId, {\n\t\t\tsubscribeMessage,\n\t\t\tunsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t\thasSentSubscribeMessage: false,\n\t\t});\n\n\t\t// Update URL to subscription IDs lookup\n\t\tif (!MultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.has(this.wsUrl)) {\n\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.set(\n\t\t\t\tthis.wsUrl,\n\t\t\t\tnew Set()\n\t\t\t);\n\t\t}\n\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl)!.add(\n\t\t\tsubscriptionId\n\t\t);\n\n\t\tif (this.customConnectionState === WebSocketConnectionState.CONNECTED) {\n\t\t\tthis.subscribeToWebSocket(subscriptionId);\n\t\t} else if (\n\t\t\tthis.customConnectionState === WebSocketConnectionState.CONNECTING\n\t\t) {\n\t\t\t// do nothing, subscription will automatically start when websocket is connected\n\t\t} else {\n\t\t\t// handle case where websocket is disconnecting/disconnected\n\t\t\tthis.refreshWebSocket();\n\t\t}\n\t}\n\n\tprivate unsubscribe(subscriptionId: SubscriptionId) {\n\t\tconst subscriptionState = this.subscriptions.get(subscriptionId);\n\t\tif (subscriptionState) {\n\t\t\tsubscriptionState.subjectSubscription?.unsubscribe();\n\n\t\t\t// Only send unsubscribe message if websocket is connected and ready to send.\n\t\t\t//// Otherwise, when the websocket DOES connect we don't have to worry about this subscription because we are deleting it from the subscriptions map. (Which only trigger their connections once the websocket becomes connected)\n\t\t\tif (\n\t\t\t\tthis.customConnectionState === WebSocketConnectionState.CONNECTED &&\n\t\t\t\tthis.webSocket.readyState === WebSocket.OPEN\n\t\t\t) {\n\t\t\t\tthis.webSocket.send(subscriptionState.unsubscribeMessage);\n\t\t\t}\n\n\t\t\tthis.subscriptions.delete(subscriptionId);\n\n\t\t\t// Update URL to subscription IDs lookup\n\t\t\tconst subscriptionIds =\n\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl);\n\t\t\tif (subscriptionIds) {\n\t\t\t\tsubscriptionIds.delete(subscriptionId);\n\t\t\t\tif (subscriptionIds.size === 0) {\n\t\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.delete(this.wsUrl);\n\t\t\t\t\t// Schedule delayed close when last subscriber unsubscribes\n\t\t\t\t\tthis.scheduleDelayedClose();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate scheduleDelayedClose() {\n\t\t// Cancel any existing delayed close timeout\n\t\tthis.cancelDelayedClose();\n\n\t\t// Schedule new delayed close\n\t\tthis.closeTimeout = setTimeout(() => {\n\t\t\tthis.close();\n\t\t}, DEFAULT_CONNECTION_CLOSE_DELAY_MS);\n\t}\n\n\tprivate cancelDelayedClose() {\n\t\tif (this.closeTimeout) {\n\t\t\tclearTimeout(this.closeTimeout);\n\t\t\tthis.closeTimeout = null;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\t// Cancel any pending delayed close\n\t\tthis.cancelDelayedClose();\n\n\t\t// Stop heartbeat monitoring (if enabled)\n\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\tthis.stopHeartbeatMonitoring();\n\t\t}\n\n\t\tfor (const [subscriptionId] of this.subscriptions.entries()) {\n\t\t\tthis.unsubscribe(subscriptionId);\n\t\t}\n\n\t\tthis.subscriptions.clear();\n\t\tthis.webSocket.close();\n\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.delete(this.wsUrl);\n\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.delete(this.wsUrl);\n\t\tthis.reconnectionManager.reset();\n\t}\n\n\tprivate startHeartbeatMonitoring() {\n\t\t// Start the heartbeat timeout - if we don't receive a heartbeat message within the timeout, refresh connection\n\t\tthis.resetHeartbeatTimeout();\n\t}\n\n\tprivate stopHeartbeatMonitoring() {\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout);\n\t\t\tthis.heartbeatTimeout = null;\n\t\t}\n\t}\n\n\tprivate resetHeartbeatTimeout() {\n\t\t// Clear existing timeout\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout);\n\t\t}\n\n\t\t// Set new timeout\n\t\tthis.heartbeatTimeout = setTimeout(() => {\n\t\t\tconsole.warn(\n\t\t\t\t`No heartbeat received within ${DEFAULT_HEARTBEAT_TIMEOUT_MS}ms - connection appears dead`\n\t\t\t);\n\t\t\tthis.refreshWebSocket();\n\t\t}, DEFAULT_HEARTBEAT_TIMEOUT_MS);\n\t}\n\n\tprivate isHeartbeatMessage(message: WebSocketMessage<T>): boolean {\n\t\t// Check if message is a heartbeat message from server\n\t\treturn (message as any)?.channel === 'heartbeat';\n\t}\n\n\tprivate handleHeartbeat(_message: WebSocketMessage<T>) {\n\t\t// Reset the heartbeat timeout\n\t\tthis.resetHeartbeatTimeout();\n\t}\n\n\tprivate refreshWebSocket() {\n\t\t// Cancel any pending delayed close since we're refreshing\n\t\tthis.cancelDelayedClose();\n\n\t\t// Reset heartbeat monitoring during refresh (if enabled) - it will restart when the new connection opens\n\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\tthis.stopHeartbeatMonitoring();\n\t\t}\n\n\t\tconst { shouldReconnect, delay } =\n\t\t\tthis.reconnectionManager.attemptReconnection(this.wsUrl);\n\n\t\tif (!shouldReconnect) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up current websocket\n\t\tconst currentWebSocket = this.webSocket;\n\t\tif (currentWebSocket) {\n\t\t\tcurrentWebSocket.onerror = () => {};\n\t\t\tcurrentWebSocket.onclose = () => {};\n\t\t\tcurrentWebSocket.onmessage = () => {};\n\t\t\tcurrentWebSocket.onopen = () => {\n\t\t\t\t// in the event where the websocket has yet to connect, we close the connection after it is connected\n\t\t\t\tcurrentWebSocket.close();\n\t\t\t};\n\t\t\tcurrentWebSocket.close();\n\t\t}\n\n\t\t// Reset subscription states\n\t\tthis.subscriptions.forEach((subscription) => {\n\t\t\tsubscription.hasSentSubscribeMessage = false;\n\t\t});\n\n\t\t// Use exponential backoff before attempting to reconnect\n\t\tsetTimeout(() => {\n\t\t\tthis.webSocket = new WebSocket(this.wsUrl);\n\t\t}, delay);\n\t}\n}\n"]}
1
+ {"version":3,"file":"MultiplexWebSocket.js","sourceRoot":"","sources":["../../src/utils/MultiplexWebSocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { Subject, Subscription, catchError } from 'rxjs';\nimport WebSocket, { MessageEvent } from 'isomorphic-ws';\n\ntype WebSocketMessage<T = Record<string, unknown>> = T;\n\ntype WebSocketSubscriptionProps<T = Record<string, unknown>> = {\n\twsUrl: string;\n\tsubscriptionId: string;\n\tsubscribeMessage: string;\n\tunsubscribeMessage: string;\n\tonError: (err?: any) => void;\n\tonMessage: (message: WebSocketMessage<T>) => void;\n\tmessageFilter?: (message: WebSocketMessage<T>) => boolean;\n\terrorMessageFilter?: (message: WebSocketMessage<T>) => boolean;\n\tonClose?: () => void;\n\tenableHeartbeatMonitoring?: boolean;\n\theartbeatTimeoutMs?: number;\n};\n\ntype WebSocketSubscriptionState<T = Record<string, unknown>> =\n\tWebSocketSubscriptionProps<T> & {\n\t\thasSentSubscribeMessage?: boolean;\n\t\tsubjectSubscription?: Subscription;\n\t};\n\ntype WebSocketUrl = string;\ntype SubscriptionId = string;\n\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 5;\nconst DEFAULT_MAX_RECONNECT_WINDOW_MS = 60 * 1000;\nconst DEFAULT_CONNECTION_CLOSE_DELAY_MS = 2 * 1000; // 2 seconds delay before closing connection\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 11 * 1000; // Consider connection dead if no heartbeat within 11 seconds (a little more than twice of 5 seconds, the interval Drift servers use)\n\n/**\n * Manages reconnection logic for WebSocket connections with exponential backoff and rate limiting.\n *\n * Features:\n * - Tracks reconnection attempts within a time window\n * - Implements exponential backoff (1s, 2s, 4s, 8s max)\n * - Resets attempt counter after configurable time window\n * - Throws error when max attempts exceeded\n * - Provides configurable limits for attempts and time window\n *\n * @example\n * ```ts\n * const manager = new ReconnectionManager(5, 60000); // 5 attempts in 60s\n * const { shouldReconnect, delay } = manager.attemptReconnection('ws://example.com');\n * if (shouldReconnect) {\n * setTimeout(() => reconnect(), delay);\n * }\n * ```\n */\nclass ReconnectionManager {\n\tprivate reconnectAttempts: number = 0;\n\tprivate lastReconnectWindow: number = Date.now();\n\tprivate maxAttemptsCount: number;\n\tprivate maxAttemptsWindowMs: number;\n\n\tconstructor(\n\t\tmaxAttemptsCount = DEFAULT_MAX_RECONNECT_ATTEMPTS,\n\t\tmaxAttemptsWindowMs = DEFAULT_MAX_RECONNECT_WINDOW_MS\n\t) {\n\t\tthis.maxAttemptsCount = maxAttemptsCount;\n\t\tthis.maxAttemptsWindowMs = maxAttemptsWindowMs;\n\t}\n\n\tpublic attemptReconnection(wsUrl: string): {\n\t\tshouldReconnect: boolean;\n\t\tdelay: number;\n\t} {\n\t\tconst now = Date.now();\n\n\t\t// Reset reconnect attempts if more than a minute has passed\n\t\tif (now - this.lastReconnectWindow > this.maxAttemptsWindowMs) {\n\t\t\tthis.reconnectAttempts = 0;\n\t\t\tthis.lastReconnectWindow = now;\n\t\t}\n\n\t\t// Check if we've exceeded the maximum reconnect attempts\n\t\tif (this.reconnectAttempts >= this.maxAttemptsCount) {\n\t\t\tthrow new Error(\n\t\t\t\t`WebSocket reconnection failed: Maximum reconnect attempts (${this.maxAttemptsCount}) exceeded within ${this.maxAttemptsWindowMs}ms for ${wsUrl}`\n\t\t\t);\n\t\t}\n\n\t\tthis.reconnectAttempts++;\n\n\t\t// Calculate exponential backoff delay: 1s, 2s, 4s, 8s, etc. (capped at 8s)\n\t\tconst backoffDelay = Math.min(\n\t\t\t1000 * Math.pow(2, this.reconnectAttempts - 1),\n\t\t\t8000\n\t\t);\n\n\t\treturn {\n\t\t\tshouldReconnect: true,\n\t\t\tdelay: backoffDelay,\n\t\t};\n\t}\n\n\tpublic reset(): void {\n\t\tthis.reconnectAttempts = 0;\n\t\tthis.lastReconnectWindow = Date.now();\n\t}\n}\n\nenum WebSocketConnectionState {\n\tCONNECTING,\n\tCONNECTED,\n\tDISCONNECTING,\n\tDISCONNECTED,\n}\n\ntype IMultiplexWebSocket<T = Record<string, unknown>> = {\n\twsUrl: WebSocketUrl;\n\twebSocket: WebSocket;\n\tcustomConnectionState: WebSocketConnectionState;\n\tsubject: Subject<WebSocketMessage<T>>;\n\tsubscriptions: Map<\n\t\tSubscriptionId,\n\t\tOmit<WebSocketSubscriptionProps<T>, 'wsUrl' | 'subscriptionId'>\n\t>;\n};\n\n/**\n * MultiplexWebSocket allows for multiple subscriptions to a single websocket of the same URL, improving efficiency and reducing the number of open connections.\n *\n * This implementation assumes the following:\n * - All websocket streams are treated equally - reconnection attempts are performed at the same standards\n * - All messages returned are in the `WebSocketMessage` format\n * - A single instance of the websocket manager is created for each websocket URL - this means all subscriptions to the same websocket URL will share the same websocket instance\n *\n * Internal implementation details:\n * - The websocket is closed when the number of subscriptions is 0\n * - The websocket will be refreshed (new instance) when it disconnects unexpectedly or errors, until it reaches the maximum number of reconnect attempts\n */\nexport class MultiplexWebSocket<T = Record<string, unknown>>\n\timplements IMultiplexWebSocket<T>\n{\n\t/**\n\t * A lookup of all websockets by their URL.\n\t */\n\tprivate static URL_TO_WEBSOCKETS_LOOKUP = new Map<\n\t\tWebSocketUrl,\n\t\tMultiplexWebSocket<any>\n\t>();\n\n\t/**\n\t * A lookup from websocket URL to all subscription IDs for that URL.\n\t */\n\tprivate static URL_TO_SUBSCRIPTION_IDS_LOOKUP = new Map<\n\t\tWebSocketUrl,\n\t\tSet<SubscriptionId>\n\t>();\n\n\twsUrl: WebSocketUrl;\n\t#webSocket: WebSocket;\n\tcustomConnectionState: WebSocketConnectionState;\n\tsubject: Subject<WebSocketMessage<T>>;\n\tsubscriptions: Map<\n\t\tSubscriptionId,\n\t\tOmit<WebSocketSubscriptionState<T>, 'wsUrl' | 'subscriptionId'>\n\t>;\n\tprivate reconnectionManager: ReconnectionManager;\n\tprivate closeTimeout: NodeJS.Timeout | null = null;\n\tprivate heartbeatTimeout: NodeJS.Timeout | null = null;\n\tprivate heartbeatMonitoringEnabled: boolean = false;\n\tprivate heartbeatTimeoutMs: number = DEFAULT_HEARTBEAT_TIMEOUT_MS;\n\n\tprivate constructor(\n\t\twsUrl: WebSocketUrl,\n\t\tenableHeartbeatMonitoring: boolean = false,\n\t\theartbeatTimeoutMs: number = DEFAULT_HEARTBEAT_TIMEOUT_MS\n\t) {\n\t\tif (MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to create a new websocket for ${wsUrl}, but it already exists`\n\t\t\t);\n\t\t}\n\n\t\tthis.wsUrl = wsUrl;\n\t\tthis.customConnectionState = WebSocketConnectionState.CONNECTING;\n\t\tthis.subject = new Subject<WebSocketMessage<T>>();\n\t\tthis.subscriptions = new Map<\n\t\t\tSubscriptionId,\n\t\t\tOmit<WebSocketSubscriptionProps<T>, 'wsUrl' | 'subscriptionId'>\n\t\t>();\n\n\t\tthis.reconnectionManager = new ReconnectionManager();\n\t\tthis.heartbeatMonitoringEnabled = enableHeartbeatMonitoring;\n\t\tthis.heartbeatTimeoutMs = heartbeatTimeoutMs;\n\n\t\tthis.webSocket = new WebSocket(wsUrl);\n\n\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.set(wsUrl, this);\n\t}\n\n\t/**\n\t * Creates a new virtual websocket subscription. If an existing websocket for the given URL exists, the subscription will be added to the existing websocket.\n\t * Returns a function that can be called to unsubscribe from the subscription.\n\t */\n\tpublic static createWebSocketSubscription<T = Record<string, unknown>>(\n\t\tprops: WebSocketSubscriptionProps<T>\n\t): { unsubscribe: () => void } {\n\t\tconst { wsUrl } = props;\n\n\t\tconst doesWebSocketForWsUrlExist =\n\t\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl);\n\n\t\tif (doesWebSocketForWsUrlExist) {\n\t\t\treturn this.handleNewSubForExistingWsUrl<T>(props);\n\t\t} else {\n\t\t\t// Create new websocket for new URL or reopen previously closed websocket\n\t\t\treturn this.handleNewSubForNewWsUrl<T>(props);\n\t\t}\n\t}\n\n\tprivate static handleNewSubForNewWsUrl<T = Record<string, unknown>>(\n\t\tnewSubscriptionProps: WebSocketSubscriptionProps<T>\n\t) {\n\t\tconst newMWS = new MultiplexWebSocket<T>(\n\t\t\tnewSubscriptionProps.wsUrl,\n\t\t\tnewSubscriptionProps.enableHeartbeatMonitoring ?? false,\n\t\t\tnewSubscriptionProps.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS\n\t\t);\n\n\t\tnewMWS.subscribe(newSubscriptionProps);\n\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\tnewMWS.unsubscribe(newSubscriptionProps.subscriptionId);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate static handleNewSubForExistingWsUrl<T = Record<string, unknown>>(\n\t\tnewSubscriptionProps: WebSocketSubscriptionProps<T>\n\t) {\n\t\tconst { wsUrl, subscriptionId } = newSubscriptionProps;\n\n\t\tif (!MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.has(wsUrl)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to subscribe to ${subscriptionId} on websocket ${wsUrl}, but websocket does not exist yet`\n\t\t\t);\n\t\t}\n\n\t\tconst existingMWS = MultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.get(\n\t\t\twsUrl\n\t\t) as MultiplexWebSocket<T>;\n\n\t\t// Check if heartbeat monitoring settings match\n\t\tconst requestedHeartbeat =\n\t\t\tnewSubscriptionProps.enableHeartbeatMonitoring ?? false;\n\t\tif (existingMWS.heartbeatMonitoringEnabled !== requestedHeartbeat) {\n\t\t\tconsole.warn(\n\t\t\t\t`WebSocket for ${wsUrl} already exists with heartbeat monitoring ${\n\t\t\t\t\texistingMWS.heartbeatMonitoringEnabled ? 'enabled' : 'disabled'\n\t\t\t\t}, ` +\n\t\t\t\t\t`but new subscription requests ${\n\t\t\t\t\t\trequestedHeartbeat ? 'enabled' : 'disabled'\n\t\t\t\t\t}. Using existing setting.`\n\t\t\t);\n\t\t}\n\n\t\t// Check if heartbeat timeout settings match for the same websocket URL (note that this assumes that all types of subscriptions from the same websocket URL are expected to have the same heartbeat interval)\n\t\tconst requestedTimeout =\n\t\t\tnewSubscriptionProps.heartbeatTimeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;\n\t\tif (existingMWS.heartbeatTimeoutMs !== requestedTimeout) {\n\t\t\tconsole.warn(\n\t\t\t\t`WebSocket for ${wsUrl} already exists with heartbeat timeout ${existingMWS.heartbeatTimeoutMs}ms, ` +\n\t\t\t\t\t`but new subscription requests ${requestedTimeout}ms. Using existing setting.`\n\t\t\t);\n\t\t}\n\n\t\t// Track new subscription for existing websocket\n\t\texistingMWS.subscribe(newSubscriptionProps);\n\n\t\treturn {\n\t\t\tunsubscribe: () => {\n\t\t\t\texistingMWS.unsubscribe(newSubscriptionProps.subscriptionId);\n\t\t\t},\n\t\t};\n\t}\n\n\tget webSocket() {\n\t\treturn this.#webSocket;\n\t}\n\n\t/**\n\t * Setting the WebSocket instance will automatically add event handlers to the WebSocket instance.\n\t * When the WebSocket is connected, all existing subscriptions will be subscribed to.\n\t */\n\tset webSocket(webSocket: WebSocket) {\n\t\twebSocket.onopen = () => {\n\t\t\tthis.customConnectionState = WebSocketConnectionState.CONNECTED;\n\t\t\tthis.reconnectionManager.reset(); // Reset reconnection attempts on successful connection\n\n\t\t\t// Start heartbeat monitoring if enabled\n\t\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\t\tthis.startHeartbeatMonitoring();\n\t\t\t}\n\n\t\t\t// sends subscription message for each subscription for those that are added before the websocket is connected\n\t\t\tfor (const [subscriptionId] of this.subscriptions.entries()) {\n\t\t\t\tthis.subscribeToWebSocket(subscriptionId);\n\t\t\t}\n\t\t};\n\n\t\twebSocket.onmessage = (messageEvent: MessageEvent) => {\n\t\t\tconst message = JSON.parse(\n\t\t\t\tmessageEvent.data as string\n\t\t\t) as WebSocketMessage<T>;\n\n\t\t\t// Check for heartbeat message from server (only if heartbeat monitoring is enabled)\n\t\t\tif (this.heartbeatMonitoringEnabled && this.isHeartbeatMessage(message)) {\n\t\t\t\tthis.handleHeartbeat(message);\n\t\t\t\treturn; // Don't forward heartbeat messages to subscriptions\n\t\t\t}\n\n\t\t\tthis.subject.next(message);\n\t\t};\n\n\t\twebSocket.onclose = (event) => {\n\t\t\tthis.customConnectionState = WebSocketConnectionState.DISCONNECTED;\n\n\t\t\t// Stop heartbeat monitoring when connection closes (if enabled)\n\t\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\t\tthis.stopHeartbeatMonitoring();\n\t\t\t}\n\n\t\t\t// Restart websocket if it was closed unexpectedly (not by us)\n\t\t\tif (!event.wasClean && this.subscriptions.size > 0) {\n\t\t\t\tconsole.log('WebSocket closed unexpectedly, restarting...', event);\n\t\t\t\tthis.refreshWebSocket();\n\t\t\t}\n\t\t};\n\n\t\twebSocket.onerror = (error) => {\n\t\t\tconsole.error('MultiplexWebSocket Error', { error, webSocket });\n\n\t\t\t// Forward error to all subscriptions for this websocket URL\n\t\t\tconst subscriptionIds =\n\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl);\n\t\t\tif (subscriptionIds) {\n\t\t\t\tfor (const subscriptionId of subscriptionIds) {\n\t\t\t\t\tconst subscription = this.subscriptions.get(subscriptionId);\n\t\t\t\t\tif (subscription) {\n\t\t\t\t\t\tsubscription.onError(error);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Restart the websocket connection on error\n\t\t\tthis.refreshWebSocket();\n\t\t};\n\n\t\tthis.#webSocket = webSocket;\n\t}\n\n\tprivate subscribeToWebSocket(subscriptionId: SubscriptionId) {\n\t\tconst subscriptionState = this.subscriptions.get(subscriptionId);\n\n\t\tconst {\n\t\t\tsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t} = subscriptionState;\n\n\t\tthis.webSocket.send(subscribeMessage);\n\t\tif (subscriptionState) {\n\t\t\tsubscriptionState.hasSentSubscribeMessage = true;\n\t\t}\n\n\t\t// Create internal subscription for message handling\n\t\tconst subjectSubscription = this.subject\n\t\t\t.pipe(\n\t\t\t\tcatchError((err) => {\n\t\t\t\t\tconsole.error('Caught websocket error', err);\n\t\t\t\t\tonError();\n\t\t\t\t\treturn [];\n\t\t\t\t})\n\t\t\t)\n\t\t\t.subscribe({\n\t\t\t\tnext: (message: WebSocketMessage<T>) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (messageFilter && !messageFilter(message)) return;\n\n\t\t\t\t\t\tif (errorMessageFilter && errorMessageFilter(message)) {\n\t\t\t\t\t\t\tonError();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tonMessage(message);\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tconsole.error('Error parsing websocket message', err);\n\t\t\t\t\t\tonError();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: (err) => {\n\t\t\t\t\tconsole.error('Error subscribing to websocket', err);\n\t\t\t\t\tonError();\n\t\t\t\t},\n\t\t\t\tcomplete: () => {\n\t\t\t\t\tif (onClose) {\n\t\t\t\t\t\tonClose();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\n\t\tsubscriptionState.subjectSubscription = subjectSubscription;\n\t}\n\n\tprivate subscribe(props: WebSocketSubscriptionProps<T>) {\n\t\tconst {\n\t\t\tsubscriptionId,\n\t\t\tsubscribeMessage,\n\t\t\tunsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t} = props;\n\n\t\tif (this.subscriptions.get(subscriptionId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Attempting to subscribe to ${subscriptionId} on websocket ${this.wsUrl}, but subscription already exists`\n\t\t\t);\n\t\t}\n\n\t\t// Cancel any pending delayed close since we're adding a new subscription\n\t\tthis.cancelDelayedClose();\n\n\t\tthis.subscriptions.set(subscriptionId, {\n\t\t\tsubscribeMessage,\n\t\t\tunsubscribeMessage,\n\t\t\tonError,\n\t\t\tonMessage,\n\t\t\tmessageFilter,\n\t\t\terrorMessageFilter,\n\t\t\tonClose,\n\t\t\thasSentSubscribeMessage: false,\n\t\t});\n\n\t\t// Update URL to subscription IDs lookup\n\t\tif (!MultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.has(this.wsUrl)) {\n\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.set(\n\t\t\t\tthis.wsUrl,\n\t\t\t\tnew Set()\n\t\t\t);\n\t\t}\n\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl)!.add(\n\t\t\tsubscriptionId\n\t\t);\n\n\t\tif (this.customConnectionState === WebSocketConnectionState.CONNECTED) {\n\t\t\tthis.subscribeToWebSocket(subscriptionId);\n\t\t} else if (\n\t\t\tthis.customConnectionState === WebSocketConnectionState.CONNECTING\n\t\t) {\n\t\t\t// do nothing, subscription will automatically start when websocket is connected\n\t\t} else {\n\t\t\t// handle case where websocket is disconnecting/disconnected\n\t\t\tthis.refreshWebSocket();\n\t\t}\n\t}\n\n\tprivate unsubscribe(subscriptionId: SubscriptionId) {\n\t\tconst subscriptionState = this.subscriptions.get(subscriptionId);\n\t\tif (subscriptionState) {\n\t\t\tsubscriptionState.subjectSubscription?.unsubscribe();\n\n\t\t\t// Only send unsubscribe message if websocket is connected and ready to send.\n\t\t\t//// Otherwise, when the websocket DOES connect we don't have to worry about this subscription because we are deleting it from the subscriptions map. (Which only trigger their connections once the websocket becomes connected)\n\t\t\tif (\n\t\t\t\tthis.customConnectionState === WebSocketConnectionState.CONNECTED &&\n\t\t\t\tthis.webSocket.readyState === WebSocket.OPEN\n\t\t\t) {\n\t\t\t\tthis.webSocket.send(subscriptionState.unsubscribeMessage);\n\t\t\t}\n\n\t\t\tthis.subscriptions.delete(subscriptionId);\n\n\t\t\t// Update URL to subscription IDs lookup\n\t\t\tconst subscriptionIds =\n\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.get(this.wsUrl);\n\t\t\tif (subscriptionIds) {\n\t\t\t\tsubscriptionIds.delete(subscriptionId);\n\t\t\t\tif (subscriptionIds.size === 0) {\n\t\t\t\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.delete(this.wsUrl);\n\t\t\t\t\t// Schedule delayed close when last subscriber unsubscribes\n\t\t\t\t\tthis.scheduleDelayedClose();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate scheduleDelayedClose() {\n\t\t// Cancel any existing delayed close timeout\n\t\tthis.cancelDelayedClose();\n\n\t\t// Schedule new delayed close\n\t\tthis.closeTimeout = setTimeout(() => {\n\t\t\tthis.close();\n\t\t}, DEFAULT_CONNECTION_CLOSE_DELAY_MS);\n\t}\n\n\tprivate cancelDelayedClose() {\n\t\tif (this.closeTimeout) {\n\t\t\tclearTimeout(this.closeTimeout);\n\t\t\tthis.closeTimeout = null;\n\t\t}\n\t}\n\n\tprivate close() {\n\t\t// Cancel any pending delayed close\n\t\tthis.cancelDelayedClose();\n\n\t\t// Stop heartbeat monitoring (if enabled)\n\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\tthis.stopHeartbeatMonitoring();\n\t\t}\n\n\t\tfor (const [subscriptionId] of this.subscriptions.entries()) {\n\t\t\tthis.unsubscribe(subscriptionId);\n\t\t}\n\n\t\tthis.subscriptions.clear();\n\t\tthis.webSocket.close();\n\t\tMultiplexWebSocket.URL_TO_WEBSOCKETS_LOOKUP.delete(this.wsUrl);\n\t\tMultiplexWebSocket.URL_TO_SUBSCRIPTION_IDS_LOOKUP.delete(this.wsUrl);\n\t\tthis.reconnectionManager.reset();\n\t}\n\n\tprivate startHeartbeatMonitoring() {\n\t\t// Start the heartbeat timeout - if we don't receive a heartbeat message within the timeout, refresh connection\n\t\tthis.resetHeartbeatTimeout();\n\t}\n\n\tprivate stopHeartbeatMonitoring() {\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout);\n\t\t\tthis.heartbeatTimeout = null;\n\t\t}\n\t}\n\n\tprivate resetHeartbeatTimeout() {\n\t\t// Clear existing timeout\n\t\tif (this.heartbeatTimeout) {\n\t\t\tclearTimeout(this.heartbeatTimeout);\n\t\t}\n\n\t\t// Set new timeout\n\t\tthis.heartbeatTimeout = setTimeout(() => {\n\t\t\tconsole.warn(\n\t\t\t\t`No heartbeat received within ${this.heartbeatTimeoutMs}ms - connection appears dead`\n\t\t\t);\n\t\t\tthis.refreshWebSocket();\n\t\t}, this.heartbeatTimeoutMs);\n\t}\n\n\tprivate isHeartbeatMessage(message: WebSocketMessage<T>): boolean {\n\t\t// Check if message is a heartbeat message from server\n\t\treturn (message as any)?.channel === 'heartbeat';\n\t}\n\n\tprivate handleHeartbeat(_message: WebSocketMessage<T>) {\n\t\t// Reset the heartbeat timeout\n\t\tthis.resetHeartbeatTimeout();\n\t}\n\n\tprivate refreshWebSocket() {\n\t\t// Cancel any pending delayed close since we're refreshing\n\t\tthis.cancelDelayedClose();\n\n\t\t// Reset heartbeat monitoring during refresh (if enabled) - it will restart when the new connection opens\n\t\tif (this.heartbeatMonitoringEnabled) {\n\t\t\tthis.stopHeartbeatMonitoring();\n\t\t}\n\n\t\tconst { shouldReconnect, delay } =\n\t\t\tthis.reconnectionManager.attemptReconnection(this.wsUrl);\n\n\t\tif (!shouldReconnect) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean up current websocket\n\t\tconst currentWebSocket = this.webSocket;\n\t\tif (currentWebSocket) {\n\t\t\tcurrentWebSocket.onerror = () => {};\n\t\t\tcurrentWebSocket.onclose = () => {};\n\t\t\tcurrentWebSocket.onmessage = () => {};\n\t\t\tcurrentWebSocket.onopen = () => {\n\t\t\t\t// in the event where the websocket has yet to connect, we close the connection after it is connected\n\t\t\t\tcurrentWebSocket.close();\n\t\t\t};\n\t\t\tcurrentWebSocket.close();\n\t\t}\n\n\t\t// Reset subscription states\n\t\tthis.subscriptions.forEach((subscription) => {\n\t\t\tsubscription.hasSentSubscribeMessage = false;\n\t\t});\n\n\t\t// Use exponential backoff before attempting to reconnect\n\t\tsetTimeout(() => {\n\t\t\tthis.webSocket = new WebSocket(this.wsUrl);\n\t\t}, delay);\n\t}\n}\n"]}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Utility class which makes sure that all results with a slot are only accepted if the slot is higher than the previous result
3
+ * Enhanced to handle tab return scenarios and prevent "speed run" through queued messages
4
+ */
5
+ export declare class ResultSlotIncrementer {
6
+ private resultIncrements;
7
+ private tabReturnTimestamp;
8
+ private isInTabReturnMode;
9
+ private tabReturnDebounceMs;
10
+ private maxSlotJumpThreshold;
11
+ /**
12
+ * Call this when the tab returns from being inactive to enable enhanced filtering
13
+ */
14
+ handleTabReturn(): void;
15
+ /**
16
+ * Check if we should reset state due to a large slot jump (indicating queued messages)
17
+ */
18
+ private shouldResetDueToSlotJump;
19
+ /**
20
+ * Enhanced result handler that deals with tab return scenarios
21
+ */
22
+ handleResult(key: string | symbol, slot: number, messageTimestamp?: number): boolean;
23
+ /**
24
+ * Reset slot tracking for a specific key (useful when reestablishing connections)
25
+ */
26
+ resetKey(key: string | symbol): void;
27
+ /**
28
+ * Configure the tab return behavior
29
+ */
30
+ configureTabReturn(debounceMs: number, slotJumpThreshold: number): void;
31
+ }