@stabbleorg/mclmm-sdk 0.1.14 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/idl/stabble_clmm.json +0 -28
  2. package/lib/__tests__/fixtures/pool-states.d.ts +84 -0
  3. package/lib/__tests__/fixtures/pool-states.d.ts.map +1 -0
  4. package/lib/__tests__/fixtures/tick-arrays.d.ts +42 -0
  5. package/lib/__tests__/fixtures/tick-arrays.d.ts.map +1 -0
  6. package/lib/__tests__/helpers/integration-mocks.d.ts +82 -0
  7. package/lib/__tests__/helpers/integration-mocks.d.ts.map +1 -0
  8. package/lib/__tests__/integration/performance.test.d.ts +12 -0
  9. package/lib/__tests__/integration/performance.test.d.ts.map +1 -0
  10. package/lib/__tests__/integration/swap-flow.test.d.ts +12 -0
  11. package/lib/__tests__/integration/swap-flow.test.d.ts.map +1 -0
  12. package/lib/__tests__/setup.d.ts +19 -0
  13. package/lib/__tests__/setup.d.ts.map +1 -0
  14. package/lib/__tests__/unit/math-utils.test.d.ts +11 -0
  15. package/lib/__tests__/unit/math-utils.test.d.ts.map +1 -0
  16. package/lib/__tests__/unit/pool-data-manager.test.d.ts +16 -0
  17. package/lib/__tests__/unit/pool-data-manager.test.d.ts.map +1 -0
  18. package/lib/__tests__/unit/price-api-client.test.d.ts +2 -0
  19. package/lib/__tests__/unit/price-api-client.test.d.ts.map +1 -0
  20. package/lib/__tests__/unit/swap-manager.test.d.ts +14 -0
  21. package/lib/__tests__/unit/swap-manager.test.d.ts.map +1 -0
  22. package/lib/__tests__/unit/swap-math-engine.test.d.ts +14 -0
  23. package/lib/__tests__/unit/swap-math-engine.test.d.ts.map +1 -0
  24. package/lib/api/config.d.ts +6 -0
  25. package/lib/api/config.d.ts.map +1 -1
  26. package/lib/client.d.ts +2 -0
  27. package/lib/client.d.ts.map +1 -1
  28. package/lib/constants.d.ts +41 -1
  29. package/lib/constants.d.ts.map +1 -1
  30. package/lib/generated/accounts/ammConfig.d.ts +1 -1
  31. package/lib/generated/accounts/ammConfig.d.ts.map +1 -1
  32. package/lib/generated/accounts/observationState.d.ts +1 -1
  33. package/lib/generated/accounts/observationState.d.ts.map +1 -1
  34. package/lib/generated/accounts/operationState.d.ts +1 -1
  35. package/lib/generated/accounts/operationState.d.ts.map +1 -1
  36. package/lib/generated/accounts/personalPositionState.d.ts +1 -1
  37. package/lib/generated/accounts/personalPositionState.d.ts.map +1 -1
  38. package/lib/generated/accounts/poolState.d.ts +1 -1
  39. package/lib/generated/accounts/poolState.d.ts.map +1 -1
  40. package/lib/generated/accounts/protocolPositionState.d.ts +1 -1
  41. package/lib/generated/accounts/protocolPositionState.d.ts.map +1 -1
  42. package/lib/generated/accounts/supportMintAssociated.d.ts +1 -1
  43. package/lib/generated/accounts/supportMintAssociated.d.ts.map +1 -1
  44. package/lib/generated/accounts/tickArrayBitmapExtension.d.ts +1 -1
  45. package/lib/generated/accounts/tickArrayBitmapExtension.d.ts.map +1 -1
  46. package/lib/generated/accounts/tickArrayState.d.ts +1 -1
  47. package/lib/generated/accounts/tickArrayState.d.ts.map +1 -1
  48. package/lib/generated/instructions/closePosition.d.ts +1 -1
  49. package/lib/generated/instructions/closePosition.d.ts.map +1 -1
  50. package/lib/generated/instructions/closeProtocolPosition.d.ts +1 -1
  51. package/lib/generated/instructions/closeProtocolPosition.d.ts.map +1 -1
  52. package/lib/generated/instructions/collectFundFee.d.ts +1 -1
  53. package/lib/generated/instructions/collectFundFee.d.ts.map +1 -1
  54. package/lib/generated/instructions/collectProtocolFee.d.ts +1 -1
  55. package/lib/generated/instructions/collectProtocolFee.d.ts.map +1 -1
  56. package/lib/generated/instructions/collectRemainingRewards.d.ts +1 -1
  57. package/lib/generated/instructions/collectRemainingRewards.d.ts.map +1 -1
  58. package/lib/generated/instructions/createAmmConfig.d.ts +1 -1
  59. package/lib/generated/instructions/createAmmConfig.d.ts.map +1 -1
  60. package/lib/generated/instructions/createOperationAccount.d.ts +1 -1
  61. package/lib/generated/instructions/createOperationAccount.d.ts.map +1 -1
  62. package/lib/generated/instructions/createPool.d.ts +1 -1
  63. package/lib/generated/instructions/createPool.d.ts.map +1 -1
  64. package/lib/generated/instructions/createSupportMintAssociated.d.ts +1 -1
  65. package/lib/generated/instructions/createSupportMintAssociated.d.ts.map +1 -1
  66. package/lib/generated/instructions/decreaseLiquidityV2.d.ts +1 -1
  67. package/lib/generated/instructions/decreaseLiquidityV2.d.ts.map +1 -1
  68. package/lib/generated/instructions/increaseLiquidityV2.d.ts +1 -1
  69. package/lib/generated/instructions/increaseLiquidityV2.d.ts.map +1 -1
  70. package/lib/generated/instructions/initializeReward.d.ts +1 -1
  71. package/lib/generated/instructions/initializeReward.d.ts.map +1 -1
  72. package/lib/generated/instructions/openPositionWithToken22Nft.d.ts +1 -1
  73. package/lib/generated/instructions/openPositionWithToken22Nft.d.ts.map +1 -1
  74. package/lib/generated/instructions/setRewardParams.d.ts +1 -1
  75. package/lib/generated/instructions/setRewardParams.d.ts.map +1 -1
  76. package/lib/generated/instructions/swapRouterBaseIn.d.ts +1 -1
  77. package/lib/generated/instructions/swapRouterBaseIn.d.ts.map +1 -1
  78. package/lib/generated/instructions/swapV2.d.ts +1 -1
  79. package/lib/generated/instructions/swapV2.d.ts.map +1 -1
  80. package/lib/generated/instructions/transferRewardOwner.d.ts +1 -1
  81. package/lib/generated/instructions/transferRewardOwner.d.ts.map +1 -1
  82. package/lib/generated/instructions/updateAmmConfig.d.ts +1 -1
  83. package/lib/generated/instructions/updateAmmConfig.d.ts.map +1 -1
  84. package/lib/generated/instructions/updateOperationAccount.d.ts +1 -1
  85. package/lib/generated/instructions/updateOperationAccount.d.ts.map +1 -1
  86. package/lib/generated/instructions/updatePoolStatus.d.ts +1 -1
  87. package/lib/generated/instructions/updatePoolStatus.d.ts.map +1 -1
  88. package/lib/generated/instructions/updateRewardInfos.d.ts +1 -1
  89. package/lib/generated/instructions/updateRewardInfos.d.ts.map +1 -1
  90. package/lib/generated/programs/ammV3.d.ts.map +1 -1
  91. package/lib/generated/shared/index.d.ts.map +1 -1
  92. package/lib/generated/types/decreaseLiquidityEvent.d.ts +0 -2
  93. package/lib/generated/types/decreaseLiquidityEvent.d.ts.map +1 -1
  94. package/lib/generated/types/index.d.ts +0 -1
  95. package/lib/generated/types/index.d.ts.map +1 -1
  96. package/lib/index.d.ts +5 -0
  97. package/lib/index.d.ts.map +1 -1
  98. package/lib/index.js +6011 -3305
  99. package/lib/index.mjs +5519 -2825
  100. package/lib/managers/index.d.ts +7 -0
  101. package/lib/managers/index.d.ts.map +1 -0
  102. package/lib/managers/pool-data-manager.d.ts +132 -0
  103. package/lib/managers/pool-data-manager.d.ts.map +1 -0
  104. package/lib/managers/price-api-client.d.ts +295 -0
  105. package/lib/managers/price-api-client.d.ts.map +1 -0
  106. package/lib/position-manager.d.ts.map +1 -1
  107. package/lib/swap.d.ts +832 -2
  108. package/lib/swap.d.ts.map +1 -1
  109. package/lib/types.d.ts +23 -4
  110. package/lib/types.d.ts.map +1 -1
  111. package/lib/utils/index.d.ts +5 -2
  112. package/lib/utils/index.d.ts.map +1 -1
  113. package/lib/utils/math.d.ts +386 -0
  114. package/lib/utils/math.d.ts.map +1 -1
  115. package/lib/utils/tickQuery.d.ts +62 -1
  116. package/lib/utils/tickQuery.d.ts.map +1 -1
  117. package/package.json +13 -5
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Manager Exports
3
+ */
4
+ export { PoolDataManager } from "./pool-data-manager";
5
+ export { PriceApiClient } from "./price-api-client";
6
+ export type { PriceApiConfig, PriceData } from "./price-api-client";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -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;AAqBjB,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,aAAa;IAElD,OAAO,CAAC,wBAAwB;IAyBhC;;;;;OAKG;IACG,yCAAyC,CAAC,MAAM,EAAE;QACtD,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE;YACT,QAAQ,EAAE,iBAAiB,CAAC;YAC5B,MAAM,EAAE,OAAO,CAAC;YAChB,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,CAAC;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,iBAAiB,EAAE,CAAC;KACjD,GAAG,OAAO,CACT,qBAAqB,CAAC;QACpB,eAAe,EAAE,OAAO,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC,CACH;IA+FD;;;;;OAKG;IACG,oCAAoC,CAAC,MAAM,EAAE;QACjD,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACzC,SAAS,EAAE;YACT,MAAM,EAAE,iBAAiB,CAAC;YAC1B,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,CAAC;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;QACxB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,OAAO,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,iBAAiB,EAAE,CAAC;KACjD,GAAG,OAAO,CACT,qBAAqB,CAAC;QACpB,eAAe,EAAE,OAAO,CAAC;QACzB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,eAAe,EAAE,OAAO,CAAC;QACzB,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC,CACH;IAsJD;;;;OAIG;IACG,mCAAmC,CAAC,MAAM,EAAE;QAChD,aAAa,EAAE,qBAAqB,CAAC;QACrC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACvC,SAAS,EAAE;YACT,MAAM,EAAE,iBAAiB,CAAC;YAC1B,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,EAAE,OAAO,CAAC;SACxB,CAAC;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IAgGtC;;;;OAIG;IACG,mCAAmC,CAAC,MAAM,EAAE;QAChD,aAAa,EAAE,qBAAqB,CAAC;QACrC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACvC,SAAS,EAAE;YACT,MAAM,EAAE,iBAAiB,CAAC;YAC1B,aAAa,EAAE,OAAO,CAAC;YACvB,aAAa,EAAE,OAAO,CAAC;SACxB,CAAC;QACF,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IA+FtC;;;;OAIG;IACG,6BAA6B,CAAC,MAAM,EAAE;QAC1C,aAAa,EAAE,qBAAqB,CAAC;QACrC,SAAS,EAAE;YACT,MAAM,EAAE,iBAAiB,CAAC;SAC3B,CAAC;KACH,GAAG,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;IA6BtC;;;;OAIG;IACG,WAAW,CACf,YAAY,EAAE,OAAO,GACpB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAuBxC;;;;;OAKG;IACH,kBAAkB,CAChB,QAAQ,EAAE,qBAAqB,EAC/B,IAAI,EAAE,SAAS,GACd,YAAY;IA6Ff;;;;OAIG;IACG,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAiEtE"}
1
+ {"version":3,"file":"position-manager.d.ts","sourceRoot":"","sources":["../src/position-manager.ts"],"names":[],"mappings":"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"}