@stabbleorg/mclmm-sdk 0.1.14 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/__tests__/fixtures/pool-states.d.ts +84 -0
- package/lib/__tests__/fixtures/pool-states.d.ts.map +1 -0
- package/lib/__tests__/fixtures/tick-arrays.d.ts +42 -0
- package/lib/__tests__/fixtures/tick-arrays.d.ts.map +1 -0
- package/lib/__tests__/helpers/integration-mocks.d.ts +82 -0
- package/lib/__tests__/helpers/integration-mocks.d.ts.map +1 -0
- package/lib/__tests__/integration/performance.test.d.ts +12 -0
- package/lib/__tests__/integration/performance.test.d.ts.map +1 -0
- package/lib/__tests__/integration/swap-flow.test.d.ts +12 -0
- package/lib/__tests__/integration/swap-flow.test.d.ts.map +1 -0
- package/lib/__tests__/setup.d.ts +19 -0
- package/lib/__tests__/setup.d.ts.map +1 -0
- package/lib/__tests__/unit/math-utils.test.d.ts +11 -0
- package/lib/__tests__/unit/math-utils.test.d.ts.map +1 -0
- package/lib/__tests__/unit/pool-data-manager.test.d.ts +16 -0
- package/lib/__tests__/unit/pool-data-manager.test.d.ts.map +1 -0
- package/lib/__tests__/unit/price-api-client.test.d.ts +2 -0
- package/lib/__tests__/unit/price-api-client.test.d.ts.map +1 -0
- package/lib/__tests__/unit/swap-manager.test.d.ts +14 -0
- package/lib/__tests__/unit/swap-manager.test.d.ts.map +1 -0
- package/lib/__tests__/unit/swap-math-engine.test.d.ts +14 -0
- package/lib/__tests__/unit/swap-math-engine.test.d.ts.map +1 -0
- package/lib/api/config.d.ts +6 -0
- package/lib/api/config.d.ts.map +1 -1
- package/lib/client.d.ts +2 -0
- package/lib/client.d.ts.map +1 -1
- package/lib/constants.d.ts +41 -1
- package/lib/constants.d.ts.map +1 -1
- package/lib/generated/accounts/ammConfig.d.ts +1 -1
- package/lib/generated/accounts/ammConfig.d.ts.map +1 -1
- package/lib/generated/accounts/observationState.d.ts +1 -1
- package/lib/generated/accounts/observationState.d.ts.map +1 -1
- package/lib/generated/accounts/operationState.d.ts +1 -1
- package/lib/generated/accounts/operationState.d.ts.map +1 -1
- package/lib/generated/accounts/personalPositionState.d.ts +1 -1
- package/lib/generated/accounts/personalPositionState.d.ts.map +1 -1
- package/lib/generated/accounts/poolState.d.ts +1 -1
- package/lib/generated/accounts/poolState.d.ts.map +1 -1
- package/lib/generated/accounts/protocolPositionState.d.ts +1 -1
- package/lib/generated/accounts/protocolPositionState.d.ts.map +1 -1
- package/lib/generated/accounts/supportMintAssociated.d.ts +1 -1
- package/lib/generated/accounts/supportMintAssociated.d.ts.map +1 -1
- package/lib/generated/accounts/tickArrayBitmapExtension.d.ts +1 -1
- package/lib/generated/accounts/tickArrayBitmapExtension.d.ts.map +1 -1
- package/lib/generated/accounts/tickArrayState.d.ts +1 -1
- package/lib/generated/accounts/tickArrayState.d.ts.map +1 -1
- package/lib/generated/instructions/closePosition.d.ts +1 -1
- package/lib/generated/instructions/closePosition.d.ts.map +1 -1
- package/lib/generated/instructions/closeProtocolPosition.d.ts +1 -1
- package/lib/generated/instructions/closeProtocolPosition.d.ts.map +1 -1
- package/lib/generated/instructions/collectFundFee.d.ts +1 -1
- package/lib/generated/instructions/collectFundFee.d.ts.map +1 -1
- package/lib/generated/instructions/collectProtocolFee.d.ts +1 -1
- package/lib/generated/instructions/collectProtocolFee.d.ts.map +1 -1
- package/lib/generated/instructions/collectRemainingRewards.d.ts +1 -1
- package/lib/generated/instructions/collectRemainingRewards.d.ts.map +1 -1
- package/lib/generated/instructions/createAmmConfig.d.ts +1 -1
- package/lib/generated/instructions/createAmmConfig.d.ts.map +1 -1
- package/lib/generated/instructions/createOperationAccount.d.ts +1 -1
- package/lib/generated/instructions/createOperationAccount.d.ts.map +1 -1
- package/lib/generated/instructions/createPool.d.ts +1 -1
- package/lib/generated/instructions/createPool.d.ts.map +1 -1
- package/lib/generated/instructions/createSupportMintAssociated.d.ts +1 -1
- package/lib/generated/instructions/createSupportMintAssociated.d.ts.map +1 -1
- package/lib/generated/instructions/decreaseLiquidityV2.d.ts +1 -1
- package/lib/generated/instructions/decreaseLiquidityV2.d.ts.map +1 -1
- package/lib/generated/instructions/increaseLiquidityV2.d.ts +1 -1
- package/lib/generated/instructions/increaseLiquidityV2.d.ts.map +1 -1
- package/lib/generated/instructions/initializeReward.d.ts +1 -1
- package/lib/generated/instructions/initializeReward.d.ts.map +1 -1
- package/lib/generated/instructions/openPositionWithToken22Nft.d.ts +1 -1
- package/lib/generated/instructions/openPositionWithToken22Nft.d.ts.map +1 -1
- package/lib/generated/instructions/setRewardParams.d.ts +1 -1
- package/lib/generated/instructions/setRewardParams.d.ts.map +1 -1
- package/lib/generated/instructions/swapRouterBaseIn.d.ts +1 -1
- package/lib/generated/instructions/swapRouterBaseIn.d.ts.map +1 -1
- package/lib/generated/instructions/swapV2.d.ts +1 -1
- package/lib/generated/instructions/swapV2.d.ts.map +1 -1
- package/lib/generated/instructions/transferRewardOwner.d.ts +1 -1
- package/lib/generated/instructions/transferRewardOwner.d.ts.map +1 -1
- package/lib/generated/instructions/updateAmmConfig.d.ts +1 -1
- package/lib/generated/instructions/updateAmmConfig.d.ts.map +1 -1
- package/lib/generated/instructions/updateOperationAccount.d.ts +1 -1
- package/lib/generated/instructions/updateOperationAccount.d.ts.map +1 -1
- package/lib/generated/instructions/updatePoolStatus.d.ts +1 -1
- package/lib/generated/instructions/updatePoolStatus.d.ts.map +1 -1
- package/lib/generated/instructions/updateRewardInfos.d.ts +1 -1
- package/lib/generated/instructions/updateRewardInfos.d.ts.map +1 -1
- package/lib/generated/programs/ammV3.d.ts.map +1 -1
- package/lib/generated/shared/index.d.ts.map +1 -1
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +4530 -1821
- package/lib/index.mjs +4523 -1820
- package/lib/managers/index.d.ts +7 -0
- package/lib/managers/index.d.ts.map +1 -0
- package/lib/managers/pool-data-manager.d.ts +132 -0
- package/lib/managers/pool-data-manager.d.ts.map +1 -0
- package/lib/managers/price-api-client.d.ts +295 -0
- package/lib/managers/price-api-client.d.ts.map +1 -0
- package/lib/position-manager.d.ts.map +1 -1
- package/lib/swap.d.ts +832 -2
- package/lib/swap.d.ts.map +1 -1
- package/lib/types.d.ts +29 -11
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/index.d.ts +5 -2
- package/lib/utils/index.d.ts.map +1 -1
- package/lib/utils/math.d.ts +389 -1
- package/lib/utils/math.d.ts.map +1 -1
- package/lib/utils/tickQuery.d.ts +62 -1
- package/lib/utils/tickQuery.d.ts.map +1 -1
- package/package.json +13 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/managers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool Data Manager
|
|
3
|
+
*
|
|
4
|
+
* Handles fetching and caching pool state and AMM configuration data.
|
|
5
|
+
* Provides a lightweight TTL-based cache to reduce redundant RPC calls.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - True LRU eviction based on access order
|
|
9
|
+
* - TTL-based freshness with configurable cache duration
|
|
10
|
+
* - In-flight request deduplication to prevent concurrent duplicate RPCs
|
|
11
|
+
* - Negative caching of errors with jitter to prevent hammering on failures
|
|
12
|
+
* - Stale-while-revalidate support for better UX
|
|
13
|
+
* - AbortSignal support for canceling requests
|
|
14
|
+
* - Configurable immutability strategy:
|
|
15
|
+
* - "freeze" (default): Zero-cost, works with BigInt/BN, prevents mutations
|
|
16
|
+
* - "clone": Uses structuredClone (requires Node 18+ or polyfill for BigInt/Map/Set)
|
|
17
|
+
* - "none": No protection (use only if you control all callers)
|
|
18
|
+
* - Comprehensive metrics for observability
|
|
19
|
+
*/
|
|
20
|
+
import { type Address } from "@solana/kit";
|
|
21
|
+
import { type PoolState, type AmmConfig } from "../generated";
|
|
22
|
+
import type { ClmmSdkConfig } from "../types";
|
|
23
|
+
import type { ClmmApiConfig } from "../api";
|
|
24
|
+
type Immutability = "freeze" | "clone" | "none";
|
|
25
|
+
interface FetchOptions {
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
allowStale?: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class PoolDataManager {
|
|
30
|
+
private readonly config;
|
|
31
|
+
private poolCache;
|
|
32
|
+
private ammConfigCache;
|
|
33
|
+
private readonly cacheTTL;
|
|
34
|
+
private readonly maxEntries;
|
|
35
|
+
private readonly immutability;
|
|
36
|
+
private readonly errorCacheTTL;
|
|
37
|
+
private readonly randomFn;
|
|
38
|
+
private readonly apiClient?;
|
|
39
|
+
private inFlightPools;
|
|
40
|
+
private inFlightConfigs;
|
|
41
|
+
private poolErrors;
|
|
42
|
+
private ammConfigErrors;
|
|
43
|
+
private metrics;
|
|
44
|
+
constructor(config: ClmmSdkConfig, options?: {
|
|
45
|
+
cacheTTL?: number;
|
|
46
|
+
maxEntries?: number;
|
|
47
|
+
immutability?: Immutability;
|
|
48
|
+
errorCacheTTL?: number;
|
|
49
|
+
randomFn?: () => number;
|
|
50
|
+
apiConfig?: ClmmApiConfig;
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* Protect data from mutation based on immutability strategy
|
|
54
|
+
*/
|
|
55
|
+
private protect;
|
|
56
|
+
/**
|
|
57
|
+
* Expose data to caller (already protected at storage time)
|
|
58
|
+
*/
|
|
59
|
+
private expose;
|
|
60
|
+
/**
|
|
61
|
+
* Get pool state with caching
|
|
62
|
+
*/
|
|
63
|
+
getPoolState(poolAddress: Address, options?: FetchOptions): Promise<PoolState>;
|
|
64
|
+
/**
|
|
65
|
+
* Internal method to refresh pool state from RPC
|
|
66
|
+
*/
|
|
67
|
+
private refreshPoolState;
|
|
68
|
+
/**
|
|
69
|
+
* Get AMM config with caching
|
|
70
|
+
*/
|
|
71
|
+
getAmmConfig(ammConfigAddress: Address, options?: FetchOptions): Promise<AmmConfig>;
|
|
72
|
+
/**
|
|
73
|
+
* Internal method to refresh AMM config from RPC
|
|
74
|
+
*/
|
|
75
|
+
private refreshAmmConfig;
|
|
76
|
+
/**
|
|
77
|
+
* Promote entry to most recently used (true LRU behavior)
|
|
78
|
+
* Map insertion order = access order when we delete + re-add
|
|
79
|
+
*/
|
|
80
|
+
private promote;
|
|
81
|
+
/**
|
|
82
|
+
* True LRU eviction: remove least-recently-used entries (first in Map)
|
|
83
|
+
* until size is within maxEntries. Uses while-loop to handle concurrent bursts.
|
|
84
|
+
*/
|
|
85
|
+
private evictIfNeeded;
|
|
86
|
+
/**
|
|
87
|
+
* Sweep expired entries from all caches
|
|
88
|
+
* Call this periodically if you want to proactively free memory
|
|
89
|
+
*/
|
|
90
|
+
sweepExpired(): void;
|
|
91
|
+
/**
|
|
92
|
+
* Clear all caches
|
|
93
|
+
*/
|
|
94
|
+
clearCache(): void;
|
|
95
|
+
/**
|
|
96
|
+
* Clear cache for specific pool
|
|
97
|
+
*/
|
|
98
|
+
clearPoolCache(poolAddress: Address): void;
|
|
99
|
+
/**
|
|
100
|
+
* Clear cache for specific AMM config
|
|
101
|
+
*/
|
|
102
|
+
clearAmmConfigCache(ammConfigAddress: Address): void;
|
|
103
|
+
/**
|
|
104
|
+
* Reset all metrics to zero
|
|
105
|
+
*/
|
|
106
|
+
resetMetrics(): void;
|
|
107
|
+
/**
|
|
108
|
+
* Get cache metrics for observability
|
|
109
|
+
*/
|
|
110
|
+
getMetrics(): {
|
|
111
|
+
pool: {
|
|
112
|
+
hits: number;
|
|
113
|
+
misses: number;
|
|
114
|
+
errors: number;
|
|
115
|
+
hitRate: number;
|
|
116
|
+
cacheSize: number;
|
|
117
|
+
inFlight: number;
|
|
118
|
+
errorCacheSize: number;
|
|
119
|
+
};
|
|
120
|
+
config: {
|
|
121
|
+
hits: number;
|
|
122
|
+
misses: number;
|
|
123
|
+
errors: number;
|
|
124
|
+
hitRate: number;
|
|
125
|
+
cacheSize: number;
|
|
126
|
+
inFlight: number;
|
|
127
|
+
errorCacheSize: number;
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
export {};
|
|
132
|
+
//# sourceMappingURL=pool-data-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool-data-manager.d.ts","sourceRoot":"","sources":["../../src/managers/pool-data-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EAEf,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAE5C,KAAK,YAAY,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAYhD,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,eAAe;IA6BxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IA5BzB,OAAO,CAAC,SAAS,CAA6C;IAC9D,OAAO,CAAC,cAAc,CAA6C;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAC5C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAgB;IAG3C,OAAO,CAAC,aAAa,CAA0C;IAC/D,OAAO,CAAC,eAAe,CAA0C;IAGjE,OAAO,CAAC,UAAU,CAAuC;IACzD,OAAO,CAAC,eAAe,CAAuC;IAG9D,OAAO,CAAC,OAAO,CAOb;gBAGiB,MAAM,EAAE,aAAa,EACtC,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,YAAY,CAAC;QAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,aAAa,CAAC;KAC3B;IA0BH;;OAEG;IACH,OAAO,CAAC,OAAO;IAWf;;OAEG;IACH,OAAO,CAAC,MAAM;IAKd;;OAEG;IACG,YAAY,CAChB,WAAW,EAAE,OAAO,EACpB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,SAAS,CAAC;IAyCrB;;OAEG;YACW,gBAAgB;IAiD9B;;OAEG;IACG,YAAY,CAChB,gBAAgB,EAAE,OAAO,EACzB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,SAAS,CAAC;IAyCrB;;OAEG;YACW,gBAAgB;IA6E9B;;;OAGG;IACH,OAAO,CAAC,OAAO;IAMf;;;OAGG;IACH,OAAO,CAAC,aAAa;IAOrB;;;OAGG;IACH,YAAY,IAAI,IAAI;IAgBpB;;OAEG;IACH,UAAU,IAAI,IAAI;IAOlB;;OAEG;IACH,cAAc,CAAC,WAAW,EAAE,OAAO,GAAG,IAAI;IAK1C;;OAEG;IACH,mBAAmB,CAAC,gBAAgB,EAAE,OAAO,GAAG,IAAI;IAKpD;;OAEG;IACH,YAAY,IAAI,IAAI;IASpB;;OAEG;IACH,UAAU;;;;;;;;;;;;;;;;;;;;CA8BX"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import type { Address } from "@solana/kit";
|
|
2
|
+
import Decimal from "decimal.js";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for the Price API client
|
|
5
|
+
*/
|
|
6
|
+
export interface PriceApiConfig {
|
|
7
|
+
/** Base URL for the price API (defaults to production: API_ENDPOINTS.mainnet) */
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
/** Request timeout in milliseconds (default: 5000ms) */
|
|
10
|
+
timeout?: number;
|
|
11
|
+
/** Logger for debugging and monitoring */
|
|
12
|
+
logger?: {
|
|
13
|
+
debug?: (message: string, ...args: any[]) => void;
|
|
14
|
+
info?: (message: string, ...args: any[]) => void;
|
|
15
|
+
warn?: (message: string, ...args: any[]) => void;
|
|
16
|
+
error?: (message: string, ...args: any[]) => void;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Price data for a single pool/token
|
|
21
|
+
*/
|
|
22
|
+
export interface PriceData {
|
|
23
|
+
/** Token/Pool address */
|
|
24
|
+
address: Address;
|
|
25
|
+
/** Current price as a decimal */
|
|
26
|
+
price: Decimal;
|
|
27
|
+
/** Timestamp of the price update (milliseconds since epoch) */
|
|
28
|
+
timestamp: number;
|
|
29
|
+
/** Optional: 24h volume */
|
|
30
|
+
volume24h?: number;
|
|
31
|
+
/** Optional: 24h price change percentage */
|
|
32
|
+
priceChange24h?: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Detailed result for individual price fetches
|
|
36
|
+
* Useful for debugging partial failures and correlating input→output
|
|
37
|
+
*/
|
|
38
|
+
export type PriceResult = {
|
|
39
|
+
address: Address;
|
|
40
|
+
ok: true;
|
|
41
|
+
data: PriceData;
|
|
42
|
+
} | {
|
|
43
|
+
address: Address;
|
|
44
|
+
ok: false;
|
|
45
|
+
error: Error;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* PriceApiClient - REST API client for fetching pool/token prices
|
|
49
|
+
*
|
|
50
|
+
* Why this exists: Provides a clean abstraction over the team's price REST API.
|
|
51
|
+
* Handles batching (up to 4 addresses per request), error handling, retries,
|
|
52
|
+
* and data transformation from raw API responses to typed PriceData objects.
|
|
53
|
+
*
|
|
54
|
+
* Why REST: Team's infrastructure preference to avoid exposing RPC URIs and
|
|
55
|
+
* handle rate limiting centrally through a managed API endpoint.
|
|
56
|
+
*
|
|
57
|
+
* Key features:
|
|
58
|
+
* - Batch fetching (up to 4 addresses per request as per API limit)
|
|
59
|
+
* - Automatic error handling and logging
|
|
60
|
+
* - Decimal.js for precision in price calculations
|
|
61
|
+
* - Configurable timeout for different network conditions
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* import { API_ENDPOINTS } from '../constants';
|
|
66
|
+
*
|
|
67
|
+
* // Uses production API by default
|
|
68
|
+
* const client = new PriceApiClient();
|
|
69
|
+
*
|
|
70
|
+
* // Or configure explicitly for dev
|
|
71
|
+
* const devClient = new PriceApiClient({
|
|
72
|
+
* baseUrl: API_ENDPOINTS.devnet,
|
|
73
|
+
* timeout: 5000
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* const prices = await client.getPrices([poolAddress1, poolAddress2]);
|
|
77
|
+
* console.log(`Pool 1 price: ${prices[0].price}`);
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare class PriceApiClient {
|
|
81
|
+
private readonly client;
|
|
82
|
+
private readonly logger?;
|
|
83
|
+
/**
|
|
84
|
+
* Maximum number of addresses that can be queried in a single request
|
|
85
|
+
* Per team spec: "You can query up to 4 prices at once"
|
|
86
|
+
*/
|
|
87
|
+
private static readonly MAX_ADDRESSES_PER_REQUEST;
|
|
88
|
+
/**
|
|
89
|
+
* Maximum time in milliseconds that a price timestamp can be stale
|
|
90
|
+
* before logging a warning (default: 5 minutes)
|
|
91
|
+
*/
|
|
92
|
+
private static readonly STALE_THRESHOLD_MS;
|
|
93
|
+
/**
|
|
94
|
+
* Default number of retry attempts for failed requests
|
|
95
|
+
*/
|
|
96
|
+
private static readonly DEFAULT_RETRY_ATTEMPTS;
|
|
97
|
+
/**
|
|
98
|
+
* Maximum concurrent chunk requests to avoid rate limit spikes
|
|
99
|
+
*/
|
|
100
|
+
private static readonly MAX_CONCURRENT_CHUNKS;
|
|
101
|
+
constructor(config?: PriceApiConfig);
|
|
102
|
+
private log;
|
|
103
|
+
/**
|
|
104
|
+
* Creates a concurrency limiter to prevent rate limit spikes
|
|
105
|
+
*
|
|
106
|
+
* Why this approach: Simple, correct, and avoids the pitfalls of tracking
|
|
107
|
+
* Promise arrays. Each task waits in a queue if the limit is reached,
|
|
108
|
+
* and the queue is drained as tasks complete.
|
|
109
|
+
*
|
|
110
|
+
* @param limit - Maximum concurrent executions
|
|
111
|
+
* @returns Limiter function that wraps async functions
|
|
112
|
+
*/
|
|
113
|
+
private createLimiter;
|
|
114
|
+
/**
|
|
115
|
+
* Executes a function with retry logic for transient failures
|
|
116
|
+
*
|
|
117
|
+
* Why retry: Network hiccups, temporary rate limits, and server issues
|
|
118
|
+
* are common in production. Smart retries with backoff significantly
|
|
119
|
+
* improve reliability without papering over real problems.
|
|
120
|
+
*
|
|
121
|
+
* Retry conditions:
|
|
122
|
+
* - 429 (rate limit) - respects Retry-After header (both seconds and HTTP-date)
|
|
123
|
+
* - 5xx (server errors) - temporary server issues
|
|
124
|
+
* - ECONNABORTED (timeout) - network latency spikes
|
|
125
|
+
* - ECONNRESET/ENETUNREACH - transient network issues
|
|
126
|
+
*
|
|
127
|
+
* @param fn - Function to execute with retry
|
|
128
|
+
* @param attempts - Number of attempts (default: 3)
|
|
129
|
+
* @param signal - Optional AbortSignal to cancel retries
|
|
130
|
+
* @returns Result of the function
|
|
131
|
+
* @throws Last error if all attempts fail, or immediately if aborted
|
|
132
|
+
*/
|
|
133
|
+
private withRetry;
|
|
134
|
+
/**
|
|
135
|
+
* Fetches prices for one or more addresses (pools/tokens)
|
|
136
|
+
*
|
|
137
|
+
* Why batching: The API supports up to 4 addresses per request. Batching
|
|
138
|
+
* reduces network overhead and latency compared to individual requests.
|
|
139
|
+
*
|
|
140
|
+
* Why we chunk: If user passes more than 4 addresses, we automatically split
|
|
141
|
+
* into multiple requests and combine results. This provides a better DX than
|
|
142
|
+
* forcing users to manage batching themselves.
|
|
143
|
+
*
|
|
144
|
+
* Error handling: Individual chunk failures don't fail the entire batch.
|
|
145
|
+
* We return all successful results and only throw if ALL chunks fail.
|
|
146
|
+
* Use getPricesDetailed() for more granular per-address error information.
|
|
147
|
+
*
|
|
148
|
+
* Order guarantee: Returns successful results in chunk order (not input order).
|
|
149
|
+
* Duplicates are automatically removed. Use getPricesDetailed() if you need
|
|
150
|
+
* exact input→output correspondence.
|
|
151
|
+
*
|
|
152
|
+
* @param addresses - Array of pool/token addresses to fetch prices for
|
|
153
|
+
* @param opts - Optional configuration
|
|
154
|
+
* @param opts.signal - AbortSignal to cancel the request
|
|
155
|
+
* @returns Array of price data for successful fetches (unordered)
|
|
156
|
+
* @throws Error if all chunks fail or network is unreachable
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* // Single address
|
|
161
|
+
* const [priceData] = await client.getPrices([poolAddress]);
|
|
162
|
+
*
|
|
163
|
+
* // Multiple addresses (auto-batched with concurrency control)
|
|
164
|
+
* const prices = await client.getPrices([addr1, addr2, addr3, addr4, addr5]);
|
|
165
|
+
* // This makes 2 requests: [addr1-4] and [addr5], with max 2 concurrent
|
|
166
|
+
*
|
|
167
|
+
* // With cancellation
|
|
168
|
+
* const controller = new AbortController();
|
|
169
|
+
* const prices = await client.getPrices([...], { signal: controller.signal });
|
|
170
|
+
* // Later: controller.abort();
|
|
171
|
+
* ```
|
|
172
|
+
*/
|
|
173
|
+
getPrices(addresses: Address[], opts?: {
|
|
174
|
+
signal?: AbortSignal;
|
|
175
|
+
}): Promise<PriceData[]>;
|
|
176
|
+
/**
|
|
177
|
+
* Fetches price for a single address (convenience method)
|
|
178
|
+
*
|
|
179
|
+
* @param address - Pool/token address
|
|
180
|
+
* @param opts - Optional configuration
|
|
181
|
+
* @param opts.signal - AbortSignal to cancel the request
|
|
182
|
+
* @returns Price data or null if not found
|
|
183
|
+
*/
|
|
184
|
+
getPrice(address: Address, opts?: {
|
|
185
|
+
signal?: AbortSignal;
|
|
186
|
+
}): Promise<PriceData | null>;
|
|
187
|
+
/**
|
|
188
|
+
* Fetches prices with detailed per-address results
|
|
189
|
+
*
|
|
190
|
+
* Why this exists: getPrices() returns only successful results, which makes
|
|
191
|
+
* it hard to correlate input addresses with output or detect which specific
|
|
192
|
+
* addresses failed. This method returns a result for every input address,
|
|
193
|
+
* indicating success or failure.
|
|
194
|
+
*
|
|
195
|
+
* Order guarantee: Returns results in the same order as input addresses.
|
|
196
|
+
* Duplicates in input will produce duplicate results.
|
|
197
|
+
*
|
|
198
|
+
* Useful for:
|
|
199
|
+
* - Debugging which specific addresses are failing
|
|
200
|
+
* - Building UIs that need to show per-address status
|
|
201
|
+
* - Logging/metrics that need complete input→output mapping
|
|
202
|
+
*
|
|
203
|
+
* @param addresses - Array of pool/token addresses to fetch prices for
|
|
204
|
+
* @param opts - Optional configuration
|
|
205
|
+
* @param opts.signal - AbortSignal to cancel the request
|
|
206
|
+
* @returns Array of results (success or failure) for each address, in input order
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```typescript
|
|
210
|
+
* const results = await client.getPricesDetailed([addr1, addr2, addr3]);
|
|
211
|
+
* for (const result of results) {
|
|
212
|
+
* if (result.ok) {
|
|
213
|
+
* console.log(`${result.address}: $${result.data.price}`);
|
|
214
|
+
* } else {
|
|
215
|
+
* console.error(`${result.address} failed:`, result.error.message);
|
|
216
|
+
* }
|
|
217
|
+
* }
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
getPricesDetailed(addresses: Address[], opts?: {
|
|
221
|
+
signal?: AbortSignal;
|
|
222
|
+
}): Promise<PriceResult[]>;
|
|
223
|
+
/**
|
|
224
|
+
* Fetches prices for a single chunk (≤4 addresses)
|
|
225
|
+
*
|
|
226
|
+
* Why separate method: Encapsulates the API call logic and response parsing.
|
|
227
|
+
* Makes testing easier and allows for chunk-specific error handling.
|
|
228
|
+
*
|
|
229
|
+
* Query format: /prices?addresses=addr1&addresses=addr2&addresses=addr3
|
|
230
|
+
* This follows standard REST query parameter conventions for arrays.
|
|
231
|
+
*
|
|
232
|
+
* Includes retry logic for transient failures (rate limits, timeouts, 5xx errors)
|
|
233
|
+
*
|
|
234
|
+
* @param addresses - Chunk of addresses to fetch (max 4)
|
|
235
|
+
* @param signal - Optional AbortSignal to cancel the request
|
|
236
|
+
*/
|
|
237
|
+
private fetchPricesForChunk;
|
|
238
|
+
/**
|
|
239
|
+
* Parses API response into typed PriceData objects
|
|
240
|
+
*
|
|
241
|
+
* Why careful parsing: API responses can vary in format, have missing fields,
|
|
242
|
+
* or contain invalid data. We validate and transform defensively to prevent
|
|
243
|
+
* runtime errors downstream.
|
|
244
|
+
*
|
|
245
|
+
* Why Decimal.js: Prices must be precise. JavaScript's number type loses
|
|
246
|
+
* precision for large or very small values. Decimal.js preserves exactness.
|
|
247
|
+
*
|
|
248
|
+
* Timestamp handling: Missing or stale timestamps are logged as warnings.
|
|
249
|
+
* Data with missing timestamps uses current time but is flagged. Very stale
|
|
250
|
+
* data (>5min old by default) is logged but still included - callers can
|
|
251
|
+
* filter based on timestamp if needed.
|
|
252
|
+
*
|
|
253
|
+
* @param response - Raw API response
|
|
254
|
+
* @param requestedAddresses - Addresses we requested (for logging missing data)
|
|
255
|
+
* @returns Array of validated and typed price data
|
|
256
|
+
*/
|
|
257
|
+
private parsePriceResponse;
|
|
258
|
+
/**
|
|
259
|
+
* Splits addresses into chunks of MAX_ADDRESSES_PER_REQUEST
|
|
260
|
+
*
|
|
261
|
+
* Why chunking: API limit is 4 addresses per request. We handle this
|
|
262
|
+
* transparently so users don't need to worry about batch sizes.
|
|
263
|
+
*/
|
|
264
|
+
private chunkAddresses;
|
|
265
|
+
/**
|
|
266
|
+
* Handles API errors and converts to meaningful Error objects
|
|
267
|
+
*
|
|
268
|
+
* Why detailed error handling: Helps developers debug issues quickly.
|
|
269
|
+
* Network errors, timeouts, 404s, and 5xx errors all have different
|
|
270
|
+
* root causes and require different fixes.
|
|
271
|
+
*/
|
|
272
|
+
private handleApiError;
|
|
273
|
+
/**
|
|
274
|
+
* Health check - verifies the API is reachable
|
|
275
|
+
*
|
|
276
|
+
* Useful for initialization and debugging connectivity issues.
|
|
277
|
+
*
|
|
278
|
+
* Why configurable: Using a fixed address (like SOL) can fail for reasons
|
|
279
|
+
* unrelated to API health (e.g., that specific token not indexed yet).
|
|
280
|
+
* Allowing a custom probe address gives more flexibility.
|
|
281
|
+
*
|
|
282
|
+
* Note: If your API has a dedicated /health endpoint, prefer using that
|
|
283
|
+
* instead of this price-based health check.
|
|
284
|
+
*
|
|
285
|
+
* @param opts - Optional configuration for health check
|
|
286
|
+
* @param opts.address - Address to probe (defaults to SOL mainnet)
|
|
287
|
+
* @param opts.signal - AbortSignal to cancel the request
|
|
288
|
+
* @returns True if API is reachable and responding
|
|
289
|
+
*/
|
|
290
|
+
healthCheck(opts?: {
|
|
291
|
+
address?: Address;
|
|
292
|
+
signal?: AbortSignal;
|
|
293
|
+
}): Promise<boolean>;
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=price-api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"price-api-client.d.ts","sourceRoot":"","sources":["../../src/managers/price-api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"position-manager.d.ts","sourceRoot":"","sources":["../src/position-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,OAAO,EAEZ,KAAK,iBAAiB,EAKvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAOL,qBAAqB,EACrB,SAAS,EACV,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EACV,aAAa,EACb,qBAAqB,EACrB,YAAY,EACb,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"position-manager.d.ts","sourceRoot":"","sources":["../src/position-manager.ts"],"names":[],"mappings":"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"}
|