@whetstone-research/doppler-sdk 1.0.2 → 1.0.5

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.
@@ -0,0 +1,826 @@
1
+ import { Address, Rpc, GetProgramAccountsApi, GetAccountInfoApi } from '@solana/kit';
2
+
3
+ /**
4
+ * Direction of a swap operation
5
+ * - 0: token0 -> token1 (sell token0 for token1)
6
+ * - 1: token1 -> token0 (sell token1 for token0)
7
+ */
8
+ type SwapDirection = 0 | 1;
9
+ /**
10
+ * Global AMM configuration account
11
+ * PDA: ['config']
12
+ */
13
+ interface AmmConfig {
14
+ /** Admin pubkey with authority over pools */
15
+ admin: Address;
16
+ /** Whether all pool operations are paused */
17
+ paused: boolean;
18
+ /** Default numeraire mint for pricing */
19
+ numeraireMint: Address;
20
+ /** Number of programs in sentinel allowlist */
21
+ sentinelAllowlistLen: number;
22
+ /** Allowlist of sentinel programs (fixed size: 32) */
23
+ sentinelAllowlist: Address[];
24
+ /** Maximum allowed swap fee in basis points */
25
+ maxSwapFeeBps: number;
26
+ /** Maximum allowed fee split in basis points */
27
+ maxFeeSplitBps: number;
28
+ /** Maximum number of hops for routing */
29
+ maxRouteHops: number;
30
+ /** Whether protocol fees are enabled */
31
+ protocolFeeEnabled: boolean;
32
+ /** Protocol fee in basis points (share of LP fees) */
33
+ protocolFeeBps: number;
34
+ /** Account version for migrations */
35
+ version: number;
36
+ /** Reserved bytes for future use */
37
+ reserved: Uint8Array;
38
+ }
39
+ /**
40
+ * Pool account for a trading pair
41
+ * PDA: ['pool', token0_mint, token1_mint]
42
+ */
43
+ interface Pool {
44
+ /** Reference to the AmmConfig account */
45
+ config: Address;
46
+ /** Mint of token0 (lexicographically smaller) */
47
+ token0Mint: Address;
48
+ /** Mint of token1 (lexicographically larger) */
49
+ token1Mint: Address;
50
+ /** Token account holding token0 reserves */
51
+ vault0: Address;
52
+ /** Token account holding token1 reserves */
53
+ vault1: Address;
54
+ /** PDA authority for vault transfers */
55
+ authority: Address;
56
+ /** Bump seed for authority PDA */
57
+ bump: number;
58
+ /** Current reserve of token0 (excluding distributable fees) */
59
+ reserve0: bigint;
60
+ /** Current reserve of token1 (excluding distributable fees) */
61
+ reserve1: bigint;
62
+ /** Total LP shares outstanding (u128) */
63
+ totalShares: bigint;
64
+ /** Swap fee in basis points (0-10000) */
65
+ swapFeeBps: number;
66
+ /** Fee split: % of swap fee that goes to distributable (vs compounding) */
67
+ feeSplitBps: number;
68
+ /** Global fee growth per share for token0 (Q64.64) */
69
+ feeGrowthGlobal0Q64: bigint;
70
+ /** Global fee growth per share for token1 (Q64.64) */
71
+ feeGrowthGlobal1Q64: bigint;
72
+ /** Unclaimed distributable fees in token0 */
73
+ feesUnclaimed0: bigint;
74
+ /** Unclaimed distributable fees in token1 */
75
+ feesUnclaimed1: bigint;
76
+ /** Sentinel program for hooks (default = disabled) */
77
+ sentinelProgram: Address;
78
+ /** Bitflags for enabled sentinel hooks */
79
+ sentinelFlags: number;
80
+ /** Override numeraire mint for this pool */
81
+ numeraireMint: Address;
82
+ /** Which token to use for liquidity measure (0 or 1) */
83
+ liquidityMeasureSide: number;
84
+ /** Next pool in routing chain (default = none) */
85
+ routeNextPool: Address;
86
+ /** Bridge mint for routing (must be token0 or token1) */
87
+ routeBridgeMint: Address;
88
+ /** Last k value for protocol fee calculation (u128) */
89
+ kLast: bigint;
90
+ /** Protocol position for protocol fee shares */
91
+ protocolPosition: Address;
92
+ /** Reentrancy lock (0 = unlocked, 1 = locked) */
93
+ locked: number;
94
+ /** Account version for migrations */
95
+ version: number;
96
+ /** Reserved bytes for future use */
97
+ reserved: Uint8Array;
98
+ }
99
+ /**
100
+ * Position account representing LP ownership
101
+ * PDA: ['position', pool, owner, position_id]
102
+ */
103
+ interface Position {
104
+ /** The pool this position is for */
105
+ pool: Address;
106
+ /** Owner of the position */
107
+ owner: Address;
108
+ /** Unique position ID for this owner (allows multiple positions) */
109
+ positionId: bigint;
110
+ /** Number of LP shares owned (u128) */
111
+ shares: bigint;
112
+ /** Checkpoint of fee growth for token0 (Q64.64) */
113
+ feeGrowthLast0Q64: bigint;
114
+ /** Checkpoint of fee growth for token1 (Q64.64) */
115
+ feeGrowthLast1Q64: bigint;
116
+ /** Accrued uncollected fees in token0 */
117
+ feeOwed0: bigint;
118
+ /** Accrued uncollected fees in token1 */
119
+ feeOwed1: bigint;
120
+ /** Account version for migrations */
121
+ version: number;
122
+ /** Reserved bytes for future use */
123
+ reserved: Uint8Array;
124
+ }
125
+ /**
126
+ * Single TWAP observation
127
+ */
128
+ interface Observation {
129
+ /** Timestamp of this observation */
130
+ timestamp: number;
131
+ /** Cumulative price0 at this timestamp (Q64.64 accumulated, U256) */
132
+ price0Cumulative: bigint;
133
+ /** Cumulative price1 at this timestamp (Q64.64 accumulated, U256) */
134
+ price1Cumulative: bigint;
135
+ }
136
+ /**
137
+ * Oracle state for TWAP price tracking
138
+ * PDA: ['oracle', pool]
139
+ */
140
+ interface OracleState {
141
+ /** The pool this oracle tracks */
142
+ pool: Address;
143
+ /** Whether oracle has been initialized with first observation */
144
+ initialized: boolean;
145
+ /** Maximum price change ratio per slot (Q64.64, e.g., 1.1 = 10% max move) */
146
+ maxPriceChangeRatioQ64: bigint;
147
+ /** Last slot when oracle was updated */
148
+ lastSlot: bigint;
149
+ /** Truncated (clamped) price of token0 in token1 (Q64.64) */
150
+ truncPrice0Q64: bigint;
151
+ /** Truncated (clamped) price of token1 in token0 (Q64.64) */
152
+ truncPrice1Q64: bigint;
153
+ /** Deviation between spot and truncated price0 (Q64.64) */
154
+ deviation0Q64: bigint;
155
+ /** Deviation between spot and truncated price1 (Q64.64) */
156
+ deviation1Q64: bigint;
157
+ /** Cumulative truncated price0 (wrapping U256) */
158
+ price0Cumulative: bigint;
159
+ /** Cumulative truncated price1 (wrapping U256) */
160
+ price1Cumulative: bigint;
161
+ /** Last timestamp when oracle was updated */
162
+ lastTimestamp: number;
163
+ /** Last timestamp when an observation was recorded */
164
+ lastObservationTimestamp: number;
165
+ /** Minimum seconds between observations */
166
+ observationIntervalSec: number;
167
+ /** Current index in circular observation buffer */
168
+ observationIndex: number;
169
+ /** Circular buffer of TWAP observations (fixed size: 64) */
170
+ observations: Observation[];
171
+ /** Account version for migrations */
172
+ version: number;
173
+ /** Reserved bytes for future use */
174
+ reserved: Uint8Array;
175
+ }
176
+ interface InitializeConfigArgs {
177
+ admin: Address;
178
+ numeraireMint: Address;
179
+ maxSwapFeeBps: number;
180
+ maxFeeSplitBps: number;
181
+ maxRouteHops: number;
182
+ protocolFeeEnabled: boolean;
183
+ protocolFeeBps: number;
184
+ sentinelAllowlist: Address[];
185
+ }
186
+ interface InitializePoolArgs {
187
+ mintA: Address;
188
+ mintB: Address;
189
+ initialSwapFeeBps: number;
190
+ initialFeeSplitBps: number;
191
+ liquidityMeasureSide: number;
192
+ numeraireMintOverride: Address | null;
193
+ }
194
+ interface InitializeOracleArgs {
195
+ maxPriceChangeRatioQ64: bigint;
196
+ observationIntervalSec: number;
197
+ numObservations: number;
198
+ }
199
+ interface CreatePositionArgs {
200
+ positionId: bigint;
201
+ }
202
+ interface AddLiquidityArgs {
203
+ amount0Max: bigint;
204
+ amount1Max: bigint;
205
+ minSharesOut: bigint;
206
+ updateOracle: boolean;
207
+ }
208
+ interface RemoveLiquidityArgs {
209
+ sharesIn: bigint;
210
+ minAmount0Out: bigint;
211
+ minAmount1Out: bigint;
212
+ updateOracle: boolean;
213
+ }
214
+ interface SwapExactInArgs {
215
+ amountIn: bigint;
216
+ minAmountOut: bigint;
217
+ direction: SwapDirection;
218
+ updateOracle: boolean;
219
+ }
220
+ interface CollectFeesArgs {
221
+ max0: bigint;
222
+ max1: bigint;
223
+ }
224
+ interface CollectProtocolFeesArgs {
225
+ max0: bigint;
226
+ max1: bigint;
227
+ }
228
+ interface SetSentinelArgs {
229
+ sentinelProgram: Address;
230
+ sentinelFlags: number;
231
+ }
232
+ interface SetFeesArgs {
233
+ swapFeeBps: number;
234
+ feeSplitBps: number;
235
+ }
236
+ interface SetRouteArgs {
237
+ routeNextPool: Address;
238
+ routeBridgeMint: Address;
239
+ }
240
+ interface TransferAdminArgs {
241
+ newAdmin: Address;
242
+ }
243
+ interface OracleConsultArgs {
244
+ windowSeconds: number;
245
+ }
246
+ interface QuoteToNumeraireArgs {
247
+ amount: bigint;
248
+ side: number;
249
+ maxHops: number;
250
+ /** Must be false in v0.1 (spot-only) */
251
+ useTwap: boolean;
252
+ /** Must be 0 in v0.1 (spot-only) */
253
+ windowSeconds: number;
254
+ }
255
+ interface SwapQuote {
256
+ /** Expected output amount */
257
+ amountOut: bigint;
258
+ /** Total fee charged (in input token) */
259
+ feeTotal: bigint;
260
+ /** Distributable portion of fee */
261
+ feeDist: bigint;
262
+ /** Compounding portion of fee */
263
+ feeComp: bigint;
264
+ /** Price impact as a decimal (0.01 = 1%) */
265
+ priceImpact: number;
266
+ /** Execution price (output/input) */
267
+ executionPrice: number;
268
+ }
269
+ interface SwapQuoteExactOut {
270
+ /** Required input amount */
271
+ amountIn: bigint;
272
+ /** Total fee charged (in input token) */
273
+ feeTotal: bigint;
274
+ }
275
+ interface AddLiquidityQuote {
276
+ /** Shares the user will receive */
277
+ sharesOut: bigint;
278
+ /** Actual amount of token0 to deposit */
279
+ amount0: bigint;
280
+ /** Actual amount of token1 to deposit */
281
+ amount1: bigint;
282
+ /** Share of pool after deposit */
283
+ poolShare: number;
284
+ }
285
+ interface RemoveLiquidityQuote {
286
+ /** Amount of token0 to receive */
287
+ amount0: bigint;
288
+ /** Amount of token1 to receive */
289
+ amount1: bigint;
290
+ }
291
+ interface TwapResult {
292
+ /** TWAP price of token0 in token1 (Q64.64) */
293
+ price0Q64: bigint;
294
+ /** TWAP price of token1 in token0 (Q64.64) */
295
+ price1Q64: bigint;
296
+ /** TWAP price of token0 in token1 (decimal) */
297
+ price0: number;
298
+ /** TWAP price of token1 in token0 (decimal) */
299
+ price1: number;
300
+ }
301
+ interface SwapEvent {
302
+ pool: Address;
303
+ user: Address;
304
+ direction: SwapDirection;
305
+ amountIn: bigint;
306
+ amountOut: bigint;
307
+ feeTotal: bigint;
308
+ feeDist: bigint;
309
+ }
310
+ interface AddLiquidityEvent {
311
+ pool: Address;
312
+ owner: Address;
313
+ amount0: bigint;
314
+ amount1: bigint;
315
+ sharesOut: bigint;
316
+ }
317
+ interface RemoveLiquidityEvent {
318
+ pool: Address;
319
+ owner: Address;
320
+ amount0: bigint;
321
+ amount1: bigint;
322
+ sharesIn: bigint;
323
+ }
324
+ interface CollectFeesEvent {
325
+ pool: Address;
326
+ owner: Address;
327
+ amount0: bigint;
328
+ amount1: bigint;
329
+ }
330
+ interface CollectProtocolFeesEvent {
331
+ pool: Address;
332
+ amount0: bigint;
333
+ amount1: bigint;
334
+ recipient0: Address;
335
+ recipient1: Address;
336
+ }
337
+ interface PoolInitializedEvent {
338
+ pool: Address;
339
+ token0Mint: Address;
340
+ token1Mint: Address;
341
+ vault0: Address;
342
+ vault1: Address;
343
+ }
344
+ interface PositionCreatedEvent {
345
+ pool: Address;
346
+ owner: Address;
347
+ position: Address;
348
+ positionId: bigint;
349
+ }
350
+ interface PositionClosedEvent {
351
+ pool: Address;
352
+ owner: Address;
353
+ position: Address;
354
+ }
355
+ interface SentinelInvokedEvent {
356
+ pool: Address;
357
+ action: number;
358
+ allow: number;
359
+ newFeeBps: number;
360
+ newSplitBps: number;
361
+ }
362
+ interface SentinelErrorEvent {
363
+ pool: Address;
364
+ action: number;
365
+ errorCode: bigint;
366
+ }
367
+ interface SentinelUpdatedEvent {
368
+ pool: Address;
369
+ sentinelProgram: Address;
370
+ sentinelFlags: number;
371
+ admin: Address;
372
+ }
373
+ interface FeesUpdatedEvent {
374
+ pool: Address;
375
+ prevSwapFeeBps: number;
376
+ prevFeeSplitBps: number;
377
+ swapFeeBps: number;
378
+ feeSplitBps: number;
379
+ source: number;
380
+ }
381
+ interface OracleInitializedEvent {
382
+ pool: Address;
383
+ maxPriceChangeRatioQ64: bigint;
384
+ observationIntervalSec: number;
385
+ admin: Address;
386
+ }
387
+ interface OracleUpdatedEvent {
388
+ pool: Address;
389
+ slot: bigint;
390
+ truncPrice0Q64: bigint;
391
+ truncPrice1Q64: bigint;
392
+ deviation0Q64: bigint;
393
+ deviation1Q64: bigint;
394
+ }
395
+ interface RouteUpdatedEvent {
396
+ pool: Address;
397
+ routeNextPool: Address;
398
+ routeBridgeMint: Address;
399
+ admin: Address;
400
+ }
401
+ interface AdminTransferredEvent {
402
+ oldAdmin: Address;
403
+ newAdmin: Address;
404
+ }
405
+ interface PausedEvent {
406
+ }
407
+ interface UnpausedEvent {
408
+ }
409
+ interface SkimmedEvent {
410
+ pool: Address;
411
+ amount0: bigint;
412
+ amount1: bigint;
413
+ }
414
+ interface MarketCapValidationResult {
415
+ valid: boolean;
416
+ warnings: string[];
417
+ }
418
+ interface CurveParams {
419
+ /** Virtual base token reserves for the XYK curve */
420
+ curveVirtualBase: bigint;
421
+ /** Virtual quote token reserves for the XYK curve */
422
+ curveVirtualQuote: bigint;
423
+ }
424
+ interface MarketCapToCurveParamsInput {
425
+ /** Starting market cap in USD (price at launch open) */
426
+ startMarketCapUSD: number;
427
+ /** Ending market cap in USD (graduation / migration threshold) */
428
+ endMarketCapUSD: number;
429
+ /** Total base token supply including all decimals (raw u64) */
430
+ baseTotalSupply: bigint;
431
+ /**
432
+ * Base tokens allocated to the curve vault
433
+ * (baseTotalSupply - baseForDistribution - baseForLiquidity).
434
+ * Determines the initial spot price: virtual_quote / (baseForCurve + virtualBase).
435
+ */
436
+ baseForCurve: bigint;
437
+ /** Decimals of the base (launched) token */
438
+ baseDecimals: number;
439
+ /** Decimals of the quote (numeraire) token, e.g. 9 for SOL, 6 for USDC */
440
+ quoteDecimals: number;
441
+ /** USD price of one unit of the numeraire token (e.g. SOL price in USD) */
442
+ numerairePriceUSD: number;
443
+ /**
444
+ * Virtual base reserve to use as the canonical anchor. Defaults to `baseForCurve`.
445
+ * Changing this scales `curveVirtualQuote` proportionally — the resulting spot
446
+ * price is unchanged, but a larger value gives finer integer granularity at the
447
+ * cost of a proportionally larger `curveVirtualQuote`. Only override if you have
448
+ * a specific reason; the default is appropriate for most launches.
449
+ */
450
+ virtualBase?: bigint;
451
+ }
452
+ interface CurveParamsToMarketCapInput {
453
+ curveVirtualBase: bigint;
454
+ curveVirtualQuote: bigint;
455
+ /**
456
+ * Base tokens available to the curve (vault balance minus reserved allocations).
457
+ * Computed as: baseVaultBalance - baseForDistribution - baseForLiquidity.
458
+ * At launch open this equals baseForCurve.
459
+ */
460
+ baseReserve: bigint;
461
+ /** Current quote token vault balance (raw u64) */
462
+ quoteReserve: bigint;
463
+ baseTotalSupply: bigint;
464
+ baseDecimals: number;
465
+ quoteDecimals: number;
466
+ numerairePriceUSD: number;
467
+ }
468
+
469
+ type ProgramAccountsFilter = NonNullable<NonNullable<Parameters<Rpc<GetProgramAccountsApi>['getProgramAccounts']>[1]>['filters']>[number];
470
+ /**
471
+ * A minimal RPC interface for getProgramAccounts that is compatible with both
472
+ * @solana/kit@5 and @solana/kit@6.
473
+ *
474
+ * The only breaking difference between the two versions is that kit@6 uses
475
+ * `readonly` arrays for the `filters` parameter while kit@5 uses mutable arrays.
476
+ * Declaring `filters` as a mutable array here satisfies both kit versions via
477
+ * TypeScript's function parameter contravariance: a function that accepts
478
+ * `readonly` inputs (kit@6) is a subtype of one that accepts mutable inputs.
479
+ *
480
+ * Remove this file once the frontend ecosystem (e.g. @solana/client,
481
+ * @solana/react-hooks) publishes kit@6-compatible releases.
482
+ */
483
+ type GetProgramAccountsRpc = {
484
+ getProgramAccounts(program: Parameters<Rpc<GetProgramAccountsApi>['getProgramAccounts']>[0], config?: Omit<NonNullable<Parameters<Rpc<GetProgramAccountsApi>['getProgramAccounts']>[1]>, 'filters'> & {
485
+ filters?: ProgramAccountsFilter[];
486
+ }): {
487
+ send(): Promise<unknown>;
488
+ };
489
+ };
490
+
491
+ /**
492
+ * Position fetching and utility functions for the CPMM SDK
493
+ */
494
+
495
+ /**
496
+ * Configuration for fetching positions
497
+ */
498
+ interface FetchPositionsConfig {
499
+ /** Program ID (defaults to CPMM program) */
500
+ programId?: Address;
501
+ /** Commitment level */
502
+ commitment?: 'processed' | 'confirmed' | 'finalized';
503
+ }
504
+ /**
505
+ * Position with its address
506
+ */
507
+ interface PositionWithAddress {
508
+ address: Address;
509
+ account: Position;
510
+ }
511
+ /**
512
+ * Position value in underlying tokens
513
+ */
514
+ interface PositionValue {
515
+ /** Amount of token0 the position is worth */
516
+ amount0: bigint;
517
+ /** Amount of token1 the position is worth */
518
+ amount1: bigint;
519
+ /** Pending uncollected fees in token0 */
520
+ pendingFees0: bigint;
521
+ /** Pending uncollected fees in token1 */
522
+ pendingFees1: bigint;
523
+ /** Total value in token0 (amount0 + pending0) */
524
+ totalValue0: bigint;
525
+ /** Total value in token1 (amount1 + pending1) */
526
+ totalValue1: bigint;
527
+ /** Share of pool as a decimal (0-1) */
528
+ poolShare: number;
529
+ }
530
+ /**
531
+ * Fetch and decode a single position account
532
+ *
533
+ * @param rpc - Solana RPC client
534
+ * @param address - Position account address
535
+ * @param config - Optional configuration
536
+ * @returns Decoded position data or null if not found
537
+ *
538
+ * @example
539
+ * ```ts
540
+ * const position = await fetchPosition(rpc, positionAddress);
541
+ * if (position) {
542
+ * console.log(`Position shares: ${position.shares}`);
543
+ * }
544
+ * ```
545
+ */
546
+ declare function fetchPosition(rpc: Rpc<GetAccountInfoApi>, address: Address, config?: FetchPositionsConfig): Promise<Position | null>;
547
+ /**
548
+ * Fetch all positions for a specific owner
549
+ *
550
+ * @param rpc - Solana RPC client
551
+ * @param owner - Owner address
552
+ * @param pool - Optional pool address to filter by
553
+ * @param config - Optional configuration
554
+ * @returns Array of positions with their addresses
555
+ *
556
+ * @example
557
+ * ```ts
558
+ * // Get all positions for a user
559
+ * const allPositions = await fetchUserPositions(rpc, userWallet);
560
+ *
561
+ * // Get positions for a specific pool
562
+ * const poolPositions = await fetchUserPositions(rpc, userWallet, poolAddress);
563
+ * ```
564
+ */
565
+ declare function fetchUserPositions(rpc: GetProgramAccountsRpc, owner: Address, pool?: Address, config?: FetchPositionsConfig): Promise<PositionWithAddress[]>;
566
+ /**
567
+ * Fetch all positions for a specific pool
568
+ *
569
+ * @param rpc - Solana RPC client
570
+ * @param pool - Pool address
571
+ * @param config - Optional configuration
572
+ * @returns Array of positions with their addresses
573
+ */
574
+ declare function fetchPoolPositions(rpc: GetProgramAccountsRpc, pool: Address, config?: FetchPositionsConfig): Promise<PositionWithAddress[]>;
575
+ /**
576
+ * Calculate the value of a position in underlying tokens
577
+ *
578
+ * @param pool - Pool data
579
+ * @param position - Position data
580
+ * @returns Position value breakdown
581
+ *
582
+ * @example
583
+ * ```ts
584
+ * const pool = await fetchPool(rpc, poolAddress);
585
+ * const position = await fetchPosition(rpc, positionAddress);
586
+ *
587
+ * if (pool && position) {
588
+ * const value = getPositionValue(pool, position);
589
+ * console.log(`Position worth ${value.amount0} token0 + ${value.amount1} token1`);
590
+ * console.log(`Pool share: ${(value.poolShare * 100).toFixed(2)}%`);
591
+ * }
592
+ * ```
593
+ */
594
+ declare function getPositionValue(pool: Pool, position: Position): PositionValue;
595
+ /**
596
+ * Derive and fetch a position by its deterministic parameters
597
+ *
598
+ * @param rpc - Solana RPC client
599
+ * @param pool - Pool address
600
+ * @param owner - Position owner
601
+ * @param positionId - Position ID
602
+ * @param config - Optional configuration
603
+ * @returns Position with address or null if not found
604
+ */
605
+ declare function fetchPositionByParams(rpc: Rpc<GetAccountInfoApi>, pool: Address, owner: Address, positionId: bigint, config?: FetchPositionsConfig): Promise<PositionWithAddress | null>;
606
+ /**
607
+ * Get the position address for given parameters without fetching
608
+ *
609
+ * @param pool - Pool address
610
+ * @param owner - Position owner
611
+ * @param positionId - Position ID
612
+ * @param programId - Program ID (defaults to CPMM program)
613
+ * @returns Position address
614
+ */
615
+ declare function getPositionAddressFromParams(pool: Address, owner: Address, positionId: bigint, programId?: Address): Promise<Address>;
616
+ /**
617
+ * Batch fetch multiple positions
618
+ *
619
+ * @param rpc - Solana RPC client
620
+ * @param addresses - Array of position addresses to fetch
621
+ * @param config - Optional configuration
622
+ * @returns Map of address to position (missing positions are not included)
623
+ */
624
+ declare function fetchPositionsBatch(rpc: Rpc<GetAccountInfoApi>, addresses: Address[], config?: FetchPositionsConfig): Promise<Map<Address, Position>>;
625
+ /**
626
+ * Filter positions with non-zero shares
627
+ *
628
+ * @param positions - Array of positions to filter
629
+ * @returns Positions with shares > 0
630
+ */
631
+ declare function filterActivePositions(positions: PositionWithAddress[]): PositionWithAddress[];
632
+ /**
633
+ * Sort positions by share amount
634
+ *
635
+ * @param positions - Array of positions to sort
636
+ * @param descending - Sort descending (largest first) if true
637
+ * @returns Sorted array (does not mutate input)
638
+ */
639
+ declare function sortPositionsByShares(positions: PositionWithAddress[], descending?: boolean): PositionWithAddress[];
640
+
641
+ /**
642
+ * Oracle fetching and TWAP utility functions for the CPMM SDK
643
+ */
644
+
645
+ /**
646
+ * Configuration for fetching oracles
647
+ */
648
+ interface FetchOracleConfig {
649
+ /** Program ID (defaults to CPMM program) */
650
+ programId?: Address;
651
+ /** Commitment level */
652
+ commitment?: 'processed' | 'confirmed' | 'finalized';
653
+ }
654
+ /**
655
+ * Oracle with its address
656
+ */
657
+ interface OracleWithAddress {
658
+ address: Address;
659
+ account: OracleState;
660
+ }
661
+ /**
662
+ * Fetch and decode an oracle state account
663
+ *
664
+ * @param rpc - Solana RPC client
665
+ * @param address - Oracle account address
666
+ * @param config - Optional configuration
667
+ * @returns Decoded oracle state or null if not found
668
+ *
669
+ * @example
670
+ * ```ts
671
+ * const oracle = await fetchOracle(rpc, oracleAddress);
672
+ * if (oracle) {
673
+ * console.log(`Oracle initialized: ${oracle.initialized}`);
674
+ * console.log(`Last update: ${oracle.lastTimestamp}`);
675
+ * }
676
+ * ```
677
+ */
678
+ declare function fetchOracle(rpc: Rpc<GetAccountInfoApi>, address: Address, config?: FetchOracleConfig): Promise<OracleState | null>;
679
+ /**
680
+ * Get the oracle for a specific pool
681
+ *
682
+ * Derives the oracle PDA from the pool address and fetches it.
683
+ *
684
+ * @param rpc - Solana RPC client
685
+ * @param pool - Pool address
686
+ * @param config - Optional configuration
687
+ * @returns Oracle data with address, or null if not found/initialized
688
+ *
689
+ * @example
690
+ * ```ts
691
+ * const result = await getOracleForPool(rpc, poolAddress);
692
+ * if (result) {
693
+ * console.log(`Oracle at ${result.address}`);
694
+ * const twap = consultTwap(result.account, 300); // 5-minute TWAP
695
+ * console.log(`TWAP price: ${twap.price0}`);
696
+ * }
697
+ * ```
698
+ */
699
+ declare function getOracleForPool(rpc: Rpc<GetAccountInfoApi>, pool: Address, config?: FetchOracleConfig): Promise<OracleWithAddress | null>;
700
+ /**
701
+ * Get the oracle address for a pool without fetching
702
+ *
703
+ * @param pool - Pool address
704
+ * @param programId - Program ID (defaults to CPMM program)
705
+ * @returns Oracle address
706
+ */
707
+ declare function getOracleAddressFromPool(pool: Address, programId?: Address): Promise<Address>;
708
+ /**
709
+ * Calculate TWAP price from oracle observations
710
+ *
711
+ * Finds the appropriate observations in the circular buffer and computes
712
+ * the time-weighted average price over the specified window.
713
+ *
714
+ * @param oracle - Oracle state data
715
+ * @param windowSeconds - TWAP window in seconds
716
+ * @param currentTimestamp - Optional override for current time (seconds)
717
+ * @returns TWAP prices for both directions, or null if insufficient data
718
+ *
719
+ * @example
720
+ * ```ts
721
+ * const oracle = await fetchOracle(rpc, oracleAddress);
722
+ * if (oracle && oracle.initialized) {
723
+ * // Get 5-minute TWAP
724
+ * const twap = consultTwap(oracle, 300);
725
+ * if (twap) {
726
+ * console.log(`Token0 price: ${twap.price0} token1 per token0`);
727
+ * console.log(`Token1 price: ${twap.price1} token0 per token1`);
728
+ * }
729
+ * }
730
+ * ```
731
+ */
732
+ declare function consultTwap(oracle: OracleState, windowSeconds: number, currentTimestamp?: number): TwapResult | null;
733
+ /**
734
+ * Get the current spot prices from oracle
735
+ *
736
+ * Uses the truncated (manipulation-resistant) prices stored in the oracle.
737
+ *
738
+ * @param oracle - Oracle state data
739
+ * @returns Current truncated prices
740
+ */
741
+ declare function getOracleSpotPrices(oracle: OracleState): {
742
+ price0Q64: bigint;
743
+ price1Q64: bigint;
744
+ price0: number;
745
+ price1: number;
746
+ };
747
+ /**
748
+ * Get the price deviation metrics from oracle
749
+ *
750
+ * Deviation indicates how much the spot price has moved from the truncated price.
751
+ * High deviation may indicate price manipulation or rapid market movement.
752
+ *
753
+ * @param oracle - Oracle state data
754
+ * @returns Deviation values for both price directions
755
+ */
756
+ declare function getOracleDeviation(oracle: OracleState): {
757
+ deviation0Q64: bigint;
758
+ deviation1Q64: bigint;
759
+ deviation0: number;
760
+ deviation1: number;
761
+ };
762
+ /**
763
+ * Calculate the age of the oracle (time since last update)
764
+ *
765
+ * @param oracle - Oracle state data
766
+ * @param currentTimestamp - Current timestamp (defaults to Date.now() / 1000)
767
+ * @returns Age in seconds
768
+ */
769
+ declare function getOracleAge(oracle: OracleState, currentTimestamp?: number): number;
770
+ /**
771
+ * Check if oracle is stale (hasn't been updated recently)
772
+ *
773
+ * @param oracle - Oracle state data
774
+ * @param maxAgeSeconds - Maximum acceptable age in seconds
775
+ * @param currentTimestamp - Current timestamp (defaults to Date.now() / 1000)
776
+ * @returns true if oracle is stale
777
+ */
778
+ declare function isOracleStale(oracle: OracleState, maxAgeSeconds: number, currentTimestamp?: number): boolean;
779
+ /**
780
+ * Get observation buffer statistics
781
+ *
782
+ * @param oracle - Oracle state data
783
+ * @returns Information about the observation buffer
784
+ */
785
+ declare function getOracleBufferStats(oracle: OracleState): {
786
+ /** Total buffer capacity */
787
+ capacity: number;
788
+ /** Number of observations with data */
789
+ filledCount: number;
790
+ /** Current write index */
791
+ currentIndex: number;
792
+ /** Oldest observation timestamp (0 if not filled) */
793
+ oldestTimestamp: number;
794
+ /** Newest observation timestamp */
795
+ newestTimestamp: number;
796
+ /** Time span covered by observations */
797
+ timeSpanSeconds: number;
798
+ };
799
+ /**
800
+ * Batch fetch oracles for multiple pools
801
+ *
802
+ * @param rpc - Solana RPC client
803
+ * @param pools - Array of pool addresses
804
+ * @param config - Optional configuration
805
+ * @returns Map of pool address to oracle (missing oracles not included)
806
+ */
807
+ declare function fetchOraclesBatch(rpc: Rpc<GetAccountInfoApi>, pools: Address[], config?: FetchOracleConfig): Promise<Map<Address, OracleWithAddress>>;
808
+ /**
809
+ * Calculate price from pool reserves and compare with oracle
810
+ *
811
+ * Useful for detecting price discrepancies or manipulation.
812
+ *
813
+ * @param pool - Pool data
814
+ * @param oracle - Oracle data
815
+ * @returns Comparison metrics
816
+ */
817
+ declare function comparePoolAndOraclePrices(pool: Pool, oracle: OracleState): {
818
+ /** Spot price from pool reserves (token1 per token0) */
819
+ poolPrice0: number;
820
+ /** Truncated price from oracle (token1 per token0) */
821
+ oraclePrice0: number;
822
+ /** Difference as percentage (positive = pool > oracle) */
823
+ divergencePct: number;
824
+ };
825
+
826
+ export { type TwapResult as $, type AmmConfig as A, type OracleUpdatedEvent as B, type CollectFeesArgs as C, type OracleWithAddress as D, type PausedEvent as E, type FeesUpdatedEvent as F, type GetProgramAccountsRpc as G, type PoolInitializedEvent as H, type InitializeConfigArgs as I, type PositionClosedEvent as J, type PositionCreatedEvent as K, type PositionValue as L, type MarketCapValidationResult as M, type PositionWithAddress as N, type OracleState as O, type Pool as P, type QuoteToNumeraireArgs as Q, type RemoveLiquidityArgs as R, type SwapExactInArgs as S, type TransferAdminArgs as T, type RemoveLiquidityEvent as U, type RouteUpdatedEvent as V, type SentinelErrorEvent as W, type SentinelInvokedEvent as X, type SentinelUpdatedEvent as Y, type SkimmedEvent as Z, type SwapEvent as _, type Position as a, type UnpausedEvent as a0, comparePoolAndOraclePrices as a1, consultTwap as a2, fetchOracle as a3, fetchOraclesBatch as a4, fetchPoolPositions as a5, fetchPosition as a6, fetchPositionByParams as a7, fetchPositionsBatch as a8, fetchUserPositions as a9, filterActivePositions as aa, getOracleAddressFromPool as ab, getOracleAge as ac, getOracleBufferStats as ad, getOracleDeviation as ae, getOracleForPool as af, getOracleSpotPrices as ag, getPositionAddressFromParams as ah, getPositionValue as ai, isOracleStale as aj, sortPositionsByShares as ak, type AddLiquidityArgs as b, type CollectProtocolFeesArgs as c, type CreatePositionArgs as d, type InitializePoolArgs as e, type InitializeOracleArgs as f, type SetSentinelArgs as g, type SetFeesArgs as h, type SetRouteArgs as i, type OracleConsultArgs as j, type Observation as k, type SwapDirection as l, type SwapQuote as m, type SwapQuoteExactOut as n, type AddLiquidityQuote as o, type RemoveLiquidityQuote as p, type MarketCapToCurveParamsInput as q, type CurveParams as r, type CurveParamsToMarketCapInput as s, type AddLiquidityEvent as t, type AdminTransferredEvent as u, type CollectFeesEvent as v, type CollectProtocolFeesEvent as w, type FetchOracleConfig as x, type FetchPositionsConfig as y, type OracleInitializedEvent as z };