@zcomb/programs-sdk 1.11.0 → 1.11.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/dist/amm/utils.js CHANGED
@@ -1,181 +1 @@
1
- "use strict";
2
- /*
3
- * Utility functions for the AMM program.
4
- * PDA derivation, state parsing, price calculations, and account fetching.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.derivePoolPDA = derivePoolPDA;
8
- exports.deriveReservePDA = deriveReservePDA;
9
- exports.deriveFeeVaultPDA = deriveFeeVaultPDA;
10
- exports.parsePoolState = parsePoolState;
11
- exports.fetchPoolAccount = fetchPoolAccount;
12
- exports.calculateSpotPrice = calculateSpotPrice;
13
- exports.computeSwapOutput = computeSwapOutput;
14
- exports.computeSwapInput = computeSwapInput;
15
- exports.calculatePriceImpact = calculatePriceImpact;
16
- exports.createSwapQuote = createSwapQuote;
17
- exports.calculateTwap = calculateTwap;
18
- exports.isOracleInWarmup = isOracleInWarmup;
19
- const anchor_1 = require("@coral-xyz/anchor");
20
- const web3_js_1 = require("@solana/web3.js");
21
- const constants_1 = require("./constants");
22
- const types_1 = require("./types");
23
- /* PDA Derivation */
24
- function derivePoolPDA(admin, mintA, mintB, programId = constants_1.PROGRAM_ID) {
25
- return web3_js_1.PublicKey.findProgramAddressSync([constants_1.POOL_SEED, admin.toBuffer(), mintA.toBuffer(), mintB.toBuffer()], programId);
26
- }
27
- function deriveReservePDA(pool, mint, programId = constants_1.PROGRAM_ID) {
28
- return web3_js_1.PublicKey.findProgramAddressSync([constants_1.RESERVE_SEED, pool.toBuffer(), mint.toBuffer()], programId);
29
- }
30
- function deriveFeeVaultPDA(pool, programId = constants_1.PROGRAM_ID) {
31
- return web3_js_1.PublicKey.findProgramAddressSync([constants_1.FEE_VAULT_SEED, pool.toBuffer()], programId);
32
- }
33
- /* Parsers */
34
- function parsePoolState(state) {
35
- if ("trading" in state)
36
- return types_1.PoolState.Trading;
37
- if ("finalized" in state)
38
- return types_1.PoolState.Finalized;
39
- throw new Error("Unknown pool state");
40
- }
41
- /* Fetch */
42
- async function fetchPoolAccount(program, poolPda) {
43
- return program.account.poolAccount.fetch(poolPda);
44
- }
45
- /* Math Utilities */
46
- const PRICE_SCALE_BN = new anchor_1.BN(constants_1.PRICE_SCALE.toString());
47
- function calculateSpotPrice(reserveA, reserveB, decimalsA, decimalsB) {
48
- if (reserveB.isZero())
49
- return new anchor_1.BN(0);
50
- const decimalDiff = decimalsB - decimalsA;
51
- if (decimalDiff >= 0) {
52
- const multiplier = new anchor_1.BN(10).pow(new anchor_1.BN(decimalDiff));
53
- return reserveA.mul(multiplier).mul(PRICE_SCALE_BN).div(reserveB);
54
- }
55
- else {
56
- const divisor = new anchor_1.BN(10).pow(new anchor_1.BN(-decimalDiff));
57
- return reserveA.mul(PRICE_SCALE_BN).div(reserveB).div(divisor);
58
- }
59
- }
60
- /**
61
- * Compute swap output using constant product formula.
62
- * Fee is ALWAYS collected in token A:
63
- * - A -> B: fee on input (before swap)
64
- * - B -> A: fee on output (after swap)
65
- */
66
- function computeSwapOutput(inputAmount, reserveIn, reserveOut, feeBps, swapAToB) {
67
- const input = typeof inputAmount === "number" ? new anchor_1.BN(inputAmount) : inputAmount;
68
- if (reserveIn.isZero() || reserveOut.isZero()) {
69
- return { outputAmount: new anchor_1.BN(0), feeAmount: new anchor_1.BN(0) };
70
- }
71
- if (swapAToB) {
72
- // A -> B: fee on input (token A)
73
- const feeAmount = input.mul(new anchor_1.BN(feeBps)).div(new anchor_1.BN(10000));
74
- const inputAfterFee = input.sub(feeAmount);
75
- // Constant product: output = reserveOut * inputAfterFee / (reserveIn + inputAfterFee)
76
- const numerator = reserveOut.mul(inputAfterFee);
77
- const denominator = reserveIn.add(inputAfterFee);
78
- const outputAmount = numerator.div(denominator);
79
- return { outputAmount, feeAmount };
80
- }
81
- else {
82
- // B -> A: fee on output (token A)
83
- // First compute gross output without fee
84
- const numerator = reserveOut.mul(input);
85
- const denominator = reserveIn.add(input);
86
- const grossOutput = numerator.div(denominator);
87
- // Then deduct fee from output
88
- const feeAmount = grossOutput.mul(new anchor_1.BN(feeBps)).div(new anchor_1.BN(10000));
89
- const outputAmount = grossOutput.sub(feeAmount);
90
- return { outputAmount, feeAmount };
91
- }
92
- }
93
- /**
94
- * Compute swap input needed to get a specific output.
95
- * Fee is ALWAYS collected in token A:
96
- * - A -> B: fee on input
97
- * - B -> A: fee on output
98
- */
99
- function computeSwapInput(outputAmount, reserveIn, reserveOut, feeBps, swapAToB) {
100
- const output = typeof outputAmount === "number" ? new anchor_1.BN(outputAmount) : outputAmount;
101
- if (reserveIn.isZero() || reserveOut.isZero() || output.gte(reserveOut)) {
102
- return { inputAmount: new anchor_1.BN(0), feeAmount: new anchor_1.BN(0) };
103
- }
104
- if (swapAToB) {
105
- // A -> B: fee on input
106
- // We need: output = (reserveOut * inputAfterFee) / (reserveIn + inputAfterFee)
107
- // Solve for inputAfterFee: inputAfterFee = (reserveIn * output) / (reserveOut - output)
108
- const numerator = reserveIn.mul(output);
109
- const denominator = reserveOut.sub(output);
110
- const inputAfterFee = numerator.div(denominator).add(new anchor_1.BN(1)); // Round up
111
- // inputAmount = inputAfterFee * 10000 / (10000 - feeBps)
112
- const inputAmount = inputAfterFee.mul(new anchor_1.BN(10000)).div(new anchor_1.BN(10000 - feeBps)).add(new anchor_1.BN(1));
113
- const feeAmount = inputAmount.sub(inputAfterFee);
114
- return { inputAmount, feeAmount };
115
- }
116
- else {
117
- // B -> A: fee on output
118
- // User wants `output` after fee, so grossOutput = output * 10000 / (10000 - feeBps)
119
- const grossOutput = output.mul(new anchor_1.BN(10000)).div(new anchor_1.BN(10000 - feeBps)).add(new anchor_1.BN(1));
120
- const feeAmount = grossOutput.sub(output);
121
- // Now compute input needed for grossOutput
122
- // grossOutput = (reserveOut * input) / (reserveIn + input)
123
- // input = (reserveIn * grossOutput) / (reserveOut - grossOutput)
124
- const numerator = reserveIn.mul(grossOutput);
125
- const denominator = reserveOut.sub(grossOutput);
126
- if (denominator.lte(new anchor_1.BN(0))) {
127
- return { inputAmount: new anchor_1.BN(0), feeAmount: new anchor_1.BN(0) };
128
- }
129
- const inputAmount = numerator.div(denominator).add(new anchor_1.BN(1)); // Round up
130
- return { inputAmount, feeAmount };
131
- }
132
- }
133
- function calculatePriceImpact(inputAmount, outputAmount, reserveIn, reserveOut, decimalsIn, decimalsOut) {
134
- if (reserveIn.isZero() || reserveOut.isZero() || inputAmount.isZero()) {
135
- return 0;
136
- }
137
- const spotPrice = calculateSpotPrice(reserveIn, reserveOut, decimalsIn, decimalsOut);
138
- const executionPrice = calculateSpotPrice(inputAmount, outputAmount, decimalsIn, decimalsOut);
139
- if (spotPrice.isZero())
140
- return 0;
141
- const impact = executionPrice.sub(spotPrice).mul(new anchor_1.BN(10000)).div(spotPrice);
142
- return Math.abs(impact.toNumber()) / 100;
143
- }
144
- function createSwapQuote(inputAmount, reserveIn, reserveOut, feeBps, decimalsIn, decimalsOut, swapAToB, slippagePercent = 0.5) {
145
- const input = typeof inputAmount === "number" ? new anchor_1.BN(inputAmount) : inputAmount;
146
- const { outputAmount, feeAmount } = computeSwapOutput(input, reserveIn, reserveOut, feeBps, swapAToB);
147
- const slippageBps = Math.floor(slippagePercent * 100);
148
- const minOutputAmount = outputAmount.mul(new anchor_1.BN(10000 - slippageBps)).div(new anchor_1.BN(10000));
149
- const spotPriceBefore = calculateSpotPrice(reserveIn, reserveOut, decimalsIn, decimalsOut);
150
- const newReserveIn = reserveIn.add(input);
151
- const newReserveOut = reserveOut.sub(outputAmount);
152
- const spotPriceAfter = calculateSpotPrice(newReserveIn, newReserveOut, decimalsIn, decimalsOut);
153
- const priceImpact = calculatePriceImpact(input, outputAmount, reserveIn, reserveOut, decimalsIn, decimalsOut);
154
- return {
155
- inputAmount: input,
156
- outputAmount,
157
- minOutputAmount,
158
- feeAmount,
159
- priceImpact,
160
- spotPriceBefore,
161
- spotPriceAfter,
162
- };
163
- }
164
- /* TWAP Utilities */
165
- function calculateTwap(oracle) {
166
- const warmupEnd = oracle.createdAtUnixTime.add(new anchor_1.BN(oracle.warmupDuration));
167
- if (oracle.lastUpdateUnixTime.lte(warmupEnd)) {
168
- return oracle.startingObservation;
169
- }
170
- const elapsed = oracle.lastUpdateUnixTime.sub(warmupEnd);
171
- if (elapsed.isZero() || oracle.cumulativeObservations.isZero()) {
172
- return null;
173
- }
174
- return oracle.cumulativeObservations.div(elapsed);
175
- }
176
- function isOracleInWarmup(oracle, currentTime) {
177
- const now = currentTime ?? new anchor_1.BN(Math.floor(Date.now() / 1000));
178
- const warmupEnd = oracle.createdAtUnixTime.add(new anchor_1.BN(oracle.warmupDuration));
179
- return now.lt(warmupEnd);
180
- }
181
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYW1tL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7O0FBU0gsc0NBVUM7QUFFRCw0Q0FTQztBQUVELDhDQVFDO0FBSUQsd0NBSUM7QUFJRCw0Q0FLQztBQU1ELGdEQWlCQztBQVFELDhDQXFDQztBQVFELDRDQThDQztBQUVELG9EQW1CQztBQUVELDBDQWlDQztBQUlELHNDQWNDO0FBRUQsNENBSUM7QUFqUUQsOENBQWdEO0FBQ2hELDZDQUE0QztBQUM1QywyQ0FBK0Y7QUFDL0YsbUNBQTZFO0FBRTdFLG9CQUFvQjtBQUVwQixTQUFnQixhQUFhLENBQzNCLEtBQWdCLEVBQ2hCLEtBQWdCLEVBQ2hCLEtBQWdCLEVBQ2hCLFlBQXVCLHNCQUFVO0lBRWpDLE9BQU8sbUJBQVMsQ0FBQyxzQkFBc0IsQ0FDckMsQ0FBQyxxQkFBUyxFQUFFLEtBQUssQ0FBQyxRQUFRLEVBQUUsRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLEVBQ2pFLFNBQVMsQ0FDVixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQWdCLGdCQUFnQixDQUM5QixJQUFlLEVBQ2YsSUFBZSxFQUNmLFlBQXVCLHNCQUFVO0lBRWpDLE9BQU8sbUJBQVMsQ0FBQyxzQkFBc0IsQ0FDckMsQ0FBQyx3QkFBWSxFQUFFLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDaEQsU0FBUyxDQUNWLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBZ0IsaUJBQWlCLENBQy9CLElBQWUsRUFDZixZQUF1QixzQkFBVTtJQUVqQyxPQUFPLG1CQUFTLENBQUMsc0JBQXNCLENBQ3JDLENBQUMsMEJBQWMsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsRUFDakMsU0FBUyxDQUNWLENBQUM7QUFDSixDQUFDO0FBRUQsYUFB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QUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2pFLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxXQUFFLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7SUFDOUUsT0FBTyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQzNCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogVXRpbGl0eSBmdW5jdGlvbnMgZm9yIHRoZSBBTU0gcHJvZ3JhbS5cbiAqIFBEQSBkZXJpdmF0aW9uLCBzdGF0ZSBwYXJzaW5nLCBwcmljZSBjYWxjdWxhdGlvbnMsIGFuZCBhY2NvdW50IGZldGNoaW5nLlxuICovXG5cbmltcG9ydCB7IFByb2dyYW0sIEJOIH0gZnJvbSBcIkBjb3JhbC14eXovYW5jaG9yXCI7XG5pbXBvcnQgeyBQdWJsaWNLZXkgfSBmcm9tIFwiQHNvbGFuYS93ZWIzLmpzXCI7XG5pbXBvcnQgeyBQT09MX1NFRUQsIFJFU0VSVkVfU0VFRCwgRkVFX1ZBVUxUX1NFRUQsIFBST0dSQU1fSUQsIFBSSUNFX1NDQUxFIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBBbW0sIFBvb2xTdGF0ZSwgUG9vbEFjY291bnQsIFR3YXBPcmFjbGUsIFN3YXBRdW90ZSB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbi8qIFBEQSBEZXJpdmF0aW9uICovXG5cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVQb29sUERBKFxuICBhZG1pbjogUHVibGljS2V5LFxuICBtaW50QTogUHVibGljS2V5LFxuICBtaW50QjogUHVibGljS2V5LFxuICBwcm9ncmFtSWQ6IFB1YmxpY0tleSA9IFBST0dSQU1fSURcbik6IFtQdWJsaWNLZXksIG51bWJlcl0ge1xuICByZXR1cm4gUHVibGljS2V5LmZpbmRQcm9ncmFtQWRkcmVzc1N5bmMoXG4gICAgW1BPT0xfU0VFRCwgYWRtaW4udG9CdWZmZXIoKSwgbWludEEudG9CdWZmZXIoKSwgbWludEIudG9CdWZmZXIoKV0sXG4gICAgcHJvZ3JhbUlkXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXJpdmVSZXNlcnZlUERBKFxuICBwb29sOiBQdWJsaWNLZXksXG4gIG1pbnQ6IFB1YmxpY0tleSxcbiAgcHJvZ3JhbUlkOiBQdWJsaWNLZXkgPSBQUk9HUkFNX0lEXG4pOiBbUHVibGljS2V5LCBudW1iZXJdIHtcbiAgcmV0dXJuIFB1YmxpY0tleS5maW5kUHJvZ3JhbUFkZHJlc3NTeW5jKFxuICAgIFtSRVNFUlZFX1NFRUQsIHBvb2wudG9CdWZmZXIoKSwgbWludC50b0J1ZmZlcigpXSxcbiAgICBwcm9ncmFtSWRcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRlcml2ZUZlZVZhdWx0UERBKFxuICBwb29sOiBQdWJsaWNLZXksXG4gIHByb2dyYW1JZDogUHVibGljS2V5ID0gUFJPR1JBTV9JRFxuKTogW1B1YmxpY0tleSwgbnVtYmVyXSB7XG4gIHJldHVybiBQdWJsaWNLZXkuZmluZFByb2dyYW1BZGRyZXNzU3luYyhcbiAgICBbRkVFX1ZBVUxUX1NFRUQsIHBvb2wudG9CdWZmZXIoKV0sXG4gICAgcHJvZ3JhbUlkXG4gICk7XG59XG5cbi8qIFBhcnNlcnMgKi9cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlUG9vbFN0YXRlKHN0YXRlOiBhbnkpOiBQb29sU3RhdGUge1xuICBpZiAoXCJ0cmFkaW5nXCIgaW4gc3RhdGUpIHJldHVybiBQb29sU3RhdGUuVHJhZGluZztcbiAgaWYgKFwiZmluYWxpemVkXCIgaW4gc3RhdGUpIHJldHVybiBQb29sU3RhdGUuRmluYWxpemVkO1xuICB0aHJvdyBuZXcgRXJyb3IoXCJVbmtub3duIHBvb2wgc3RhdGVcIik7XG59XG5cbi8qIEZldGNoICovXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFBvb2xBY2NvdW50KFxuICBwcm9ncmFtOiBQcm9ncmFtPEFtbT4sXG4gIHBvb2xQZGE6IFB1YmxpY0tleVxuKTogUHJvbWlzZTxQb29sQWNjb3VudD4ge1xuICByZXR1cm4gcHJvZ3JhbS5hY2NvdW50LnBvb2xBY2NvdW50LmZldGNoKHBvb2xQZGEpO1xufVxuXG4vKiBNYXRoIFV0aWxpdGllcyAqL1xuXG5jb25zdCBQUklDRV9TQ0FMRV9CTiA9IG5ldyBCTihQUklDRV9TQ0FMRS50b1N0cmluZygpKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVNwb3RQcmljZShcbiAgcmVzZXJ2ZUE6IEJOLFxuICByZXNlcnZlQjogQk4sXG4gIGRlY2ltYWxzQTogbnVtYmVyLFxuICBkZWNpbWFsc0I6IG51bWJlcixcbik6IEJOIHtcbiAgaWYgKHJlc2VydmVCLmlzWmVybygpKSByZXR1cm4gbmV3IEJOKDApO1xuXG4gIGNvbnN0IGRlY2ltYWxEaWZmID0gZGVjaW1hbHNCIC0gZGVjaW1hbHNBO1xuXG4gIGlmIChkZWNpbWFsRGlmZiA+PSAwKSB7XG4gICAgY29uc3QgbXVsdGlwbGllciA9IG5ldyBCTigxMCkucG93KG5ldyBCTihkZWNpbWFsRGlmZikpO1xuICAgIHJldHVybiByZXNlcnZlQS5tdWwobXVsdGlwbGllcikubXVsKFBSSUNFX1NDQUxFX0JOKS5kaXYocmVzZXJ2ZUIpO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGRpdmlzb3IgPSBuZXcgQk4oMTApLnBvdyhuZXcgQk4oLWRlY2ltYWxEaWZmKSk7XG4gICAgcmV0dXJuIHJlc2VydmVBLm11bChQUklDRV9TQ0FMRV9CTikuZGl2KHJlc2VydmVCKS5kaXYoZGl2aXNvcik7XG4gIH1cbn1cblxuLyoqXG4gKiBDb21wdXRlIHN3YXAgb3V0cHV0IHVzaW5nIGNvbnN0YW50IHByb2R1Y3QgZm9ybXVsYS5cbiAqIEZlZSBpcyBBTFdBWVMgY29sbGVjdGVkIGluIHRva2VuIEE6XG4gKiAtIEEgLT4gQjogZmVlIG9uIGlucHV0IChiZWZvcmUgc3dhcClcbiAqIC0gQiAtPiBBOiBmZWUgb24gb3V0cHV0IChhZnRlciBzd2FwKVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZVN3YXBPdXRwdXQoXG4gIGlucHV0QW1vdW50OiBCTiB8IG51bWJlcixcbiAgcmVzZXJ2ZUluOiBCTixcbiAgcmVzZXJ2ZU91dDogQk4sXG4gIGZlZUJwczogbnVtYmVyLFxuICBzd2FwQVRvQjogYm9vbGVhblxuKTogeyBvdXRwdXRBbW91bnQ6IEJOOyBmZWVBbW91bnQ6IEJOIH0ge1xuICBjb25zdCBpbnB1dCA9IHR5cGVvZiBpbnB1dEFtb3VudCA9PT0gXCJudW1iZXJcIiA/IG5ldyBCTihpbnB1dEFtb3VudCkgOiBpbnB1dEFtb3VudDtcblxuICBpZiAocmVzZXJ2ZUluLmlzWmVybygpIHx8IHJlc2VydmVPdXQuaXNaZXJvKCkpIHtcbiAgICByZXR1cm4geyBvdXRwdXRBbW91bnQ6IG5ldyBCTigwKSwgZmVlQW1vdW50OiBuZXcgQk4oMCkgfTtcbiAgfVxuXG4gIGlmIChzd2FwQVRvQikge1xuICAgIC8vIEEgLT4gQjogZmVlIG9uIGlucHV0ICh0b2tlbiBBKVxuICAgIGNvbnN0IGZlZUFtb3VudCA9IGlucHV0Lm11bChuZXcgQk4oZmVlQnBzKSkuZGl2KG5ldyBCTigxMDAwMCkpO1xuICAgIGNvbnN0IGlucHV0QWZ0ZXJGZWUgPSBpbnB1dC5zdWIoZmVlQW1vdW50KTtcblxuICAgIC8vIENvbnN0YW50IHByb2R1Y3Q6IG91dHB1dCA9IHJlc2VydmVPdXQgKiBpbnB1dEFmdGVyRmVlIC8gKHJlc2VydmVJbiArIGlucHV0QWZ0ZXJGZWUpXG4gICAgY29uc3QgbnVtZXJhdG9yID0gcmVzZXJ2ZU91dC5tdWwoaW5wdXRBZnRlckZlZSk7XG4gICAgY29uc3QgZGVub21pbmF0b3IgPSByZXNlcnZlSW4uYWRkKGlucHV0QWZ0ZXJGZWUpO1xuICAgIGNvbnN0IG91dHB1dEFtb3VudCA9IG51bWVyYXRvci5kaXYoZGVub21pbmF0b3IpO1xuXG4gICAgcmV0dXJuIHsgb3V0cHV0QW1vdW50LCBmZWVBbW91bnQgfTtcbiAgfSBlbHNlIHtcbiAgICAvLyBCIC0+IEE6IGZlZSBvbiBvdXRwdXQgKHRva2VuIEEpXG4gICAgLy8gRmlyc3QgY29tcHV0ZSBncm9zcyBvdXRwdXQgd2l0aG91dCBmZWVcbiAgICBjb25zdCBudW1lcmF0b3IgPSByZXNlcnZlT3V0Lm11bChpbnB1dCk7XG4gICAgY29uc3QgZGVub21pbmF0b3IgPSByZXNlcnZlSW4uYWRkKGlucHV0KTtcbiAgICBjb25zdCBncm9zc091dHB1dCA9IG51bWVyYXRvci5kaXYoZGVub21pbmF0b3IpO1xuXG4gICAgLy8gVGhlbiBkZWR1Y3QgZmVlIGZyb20gb3V0cHV0XG4gICAgY29uc3QgZmVlQW1vdW50ID0gZ3Jvc3NPdXRwdXQubXVsKG5ldyBCTihmZWVCcHMpKS5kaXYobmV3IEJOKDEwMDAwKSk7XG4gICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gZ3Jvc3NPdXRwdXQuc3ViKGZlZUFtb3VudCk7XG5cbiAgICByZXR1cm4geyBvdXRwdXRBbW91bnQsIGZlZUFtb3VudCB9O1xuICB9XG59XG5cbi8qKlxuICogQ29tcHV0ZSBzd2FwIGlucHV0IG5lZWRlZCB0byBnZXQgYSBzcGVjaWZpYyBvdXRwdXQuXG4gKiBGZWUgaXMgQUxXQVlTIGNvbGxlY3RlZCBpbiB0b2tlbiBBOlxuICogLSBBIC0+IEI6IGZlZSBvbiBpbnB1dFxuICogLSBCIC0+IEE6IGZlZSBvbiBvdXRwdXRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVTd2FwSW5wdXQoXG4gIG91dHB1dEFtb3VudDogQk4gfCBudW1iZXIsXG4gIHJlc2VydmVJbjogQk4sXG4gIHJlc2VydmVPdXQ6IEJOLFxuICBmZWVCcHM6IG51bWJlcixcbiAgc3dhcEFUb0I6IGJvb2xlYW5cbik6IHsgaW5wdXRBbW91bnQ6IEJOOyBmZWVBbW91bnQ6IEJOIH0ge1xuICBjb25zdCBvdXRwdXQgPSB0eXBlb2Ygb3V0cHV0QW1vdW50ID09PSBcIm51bWJlclwiID8gbmV3IEJOKG91dHB1dEFtb3VudCkgOiBvdXRwdXRBbW91bnQ7XG5cbiAgaWYgKHJlc2VydmVJbi5pc1plcm8oKSB8fCByZXNlcnZlT3V0LmlzWmVybygpIHx8IG91dHB1dC5ndGUocmVzZXJ2ZU91dCkpIHtcbiAgICByZXR1cm4geyBpbnB1dEFtb3VudDogbmV3IEJOKDApLCBmZWVBbW91bnQ6IG5ldyBCTigwKSB9O1xuICB9XG5cbiAgaWYgKHN3YXBBVG9CKSB7XG4gICAgLy8gQSAtPiBCOiBmZWUgb24gaW5wdXRcbiAgICAvLyBXZSBuZWVkOiBvdXRwdXQgPSAocmVzZXJ2ZU91dCAqIGlucHV0QWZ0ZXJGZWUpIC8gKHJlc2VydmVJbiArIGlucHV0QWZ0ZXJGZWUpXG4gICAgLy8gU29sdmUgZm9yIGlucHV0QWZ0ZXJGZWU6IGlucHV0QWZ0ZXJGZWUgPSAocmVzZXJ2ZUluICogb3V0cHV0KSAvIChyZXNlcnZlT3V0IC0gb3V0cHV0KVxuICAgIGNvbnN0IG51bWVyYXRvciA9IHJlc2VydmVJbi5tdWwob3V0cHV0KTtcbiAgICBjb25zdCBkZW5vbWluYXRvciA9IHJlc2VydmVPdXQuc3ViKG91dHB1dCk7XG4gICAgY29uc3QgaW5wdXRBZnRlckZlZSA9IG51bWVyYXRvci5kaXYoZGVub21pbmF0b3IpLmFkZChuZXcgQk4oMSkpOyAvLyBSb3VuZCB1cFxuXG4gICAgLy8gaW5wdXRBbW91bnQgPSBpbnB1dEFmdGVyRmVlICogMTAwMDAgLyAoMTAwMDAgLSBmZWVCcHMpXG4gICAgY29uc3QgaW5wdXRBbW91bnQgPSBpbnB1dEFmdGVyRmVlLm11bChuZXcgQk4oMTAwMDApKS5kaXYobmV3IEJOKDEwMDAwIC0gZmVlQnBzKSkuYWRkKG5ldyBCTigxKSk7XG4gICAgY29uc3QgZmVlQW1vdW50ID0gaW5wdXRBbW91bnQuc3ViKGlucHV0QWZ0ZXJGZWUpO1xuXG4gICAgcmV0dXJuIHsgaW5wdXRBbW91bnQsIGZlZUFtb3VudCB9O1xuICB9IGVsc2Uge1xuICAgIC8vIEIgLT4gQTogZmVlIG9uIG91dHB1dFxuICAgIC8vIFVzZXIgd2FudHMgYG91dHB1dGAgYWZ0ZXIgZmVlLCBzbyBncm9zc091dHB1dCA9IG91dHB1dCAqIDEwMDAwIC8gKDEwMDAwIC0gZmVlQnBzKVxuICAgIGNvbnN0IGdyb3NzT3V0cHV0ID0gb3V0cHV0Lm11bChuZXcgQk4oMTAwMDApKS5kaXYobmV3IEJOKDEwMDAwIC0gZmVlQnBzKSkuYWRkKG5ldyBCTigxKSk7XG4gICAgY29uc3QgZmVlQW1vdW50ID0gZ3Jvc3NPdXRwdXQuc3ViKG91dHB1dCk7XG5cbiAgICAvLyBOb3cgY29tcHV0ZSBpbnB1dCBuZWVkZWQgZm9yIGdyb3NzT3V0cHV0XG4gICAgLy8gZ3Jvc3NPdXRwdXQgPSAocmVzZXJ2ZU91dCAqIGlucHV0KSAvIChyZXNlcnZlSW4gKyBpbnB1dClcbiAgICAvLyBpbnB1dCA9IChyZXNlcnZlSW4gKiBncm9zc091dHB1dCkgLyAocmVzZXJ2ZU91dCAtIGdyb3NzT3V0cHV0KVxuICAgIGNvbnN0IG51bWVyYXRvciA9IHJlc2VydmVJbi5tdWwoZ3Jvc3NPdXRwdXQpO1xuICAgIGNvbnN0IGRlbm9taW5hdG9yID0gcmVzZXJ2ZU91dC5zdWIoZ3Jvc3NPdXRwdXQpO1xuXG4gICAgaWYgKGRlbm9taW5hdG9yLmx0ZShuZXcgQk4oMCkpKSB7XG4gICAgICByZXR1cm4geyBpbnB1dEFtb3VudDogbmV3IEJOKDApLCBmZWVBbW91bnQ6IG5ldyBCTigwKSB9O1xuICAgIH1cblxuICAgIGNvbnN0IGlucHV0QW1vdW50ID0gbnVtZXJhdG9yLmRpdihkZW5vbWluYXRvcikuYWRkKG5ldyBCTigxKSk7IC8vIFJvdW5kIHVwXG5cbiAgICByZXR1cm4geyBpbnB1dEFtb3VudCwgZmVlQW1vdW50IH07XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVByaWNlSW1wYWN0KFxuICBpbnB1dEFtb3VudDogQk4sXG4gIG91dHB1dEFtb3VudDogQk4sXG4gIHJlc2VydmVJbjogQk4sXG4gIHJlc2VydmVPdXQ6IEJOLFxuICBkZWNpbWFsc0luOiBudW1iZXIsXG4gIGRlY2ltYWxzT3V0OiBudW1iZXIsXG4pOiBudW1iZXIge1xuICBpZiAocmVzZXJ2ZUluLmlzWmVybygpIHx8IHJlc2VydmVPdXQuaXNaZXJvKCkgfHwgaW5wdXRBbW91bnQuaXNaZXJvKCkpIHtcbiAgICByZXR1cm4gMDtcbiAgfVxuXG4gIGNvbnN0IHNwb3RQcmljZSA9IGNhbGN1bGF0ZVNwb3RQcmljZShyZXNlcnZlSW4sIHJlc2VydmVPdXQsIGRlY2ltYWxzSW4sIGRlY2ltYWxzT3V0KTtcbiAgY29uc3QgZXhlY3V0aW9uUHJpY2UgPSBjYWxjdWxhdGVTcG90UHJpY2UoaW5wdXRBbW91bnQsIG91dHB1dEFtb3VudCwgZGVjaW1hbHNJbiwgZGVjaW1hbHNPdXQpO1xuXG4gIGlmIChzcG90UHJpY2UuaXNaZXJvKCkpIHJldHVybiAwO1xuXG4gIGNvbnN0IGltcGFjdCA9IGV4ZWN1dGlvblByaWNlLnN1YihzcG90UHJpY2UpLm11bChuZXcgQk4oMTAwMDApKS5kaXYoc3BvdFByaWNlKTtcbiAgcmV0dXJuIE1hdGguYWJzKGltcGFjdC50b051bWJlcigpKSAvIDEwMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVN3YXBRdW90ZShcbiAgaW5wdXRBbW91bnQ6IEJOIHwgbnVtYmVyLFxuICByZXNlcnZlSW46IEJOLFxuICByZXNlcnZlT3V0OiBCTixcbiAgZmVlQnBzOiBudW1iZXIsXG4gIGRlY2ltYWxzSW46IG51bWJlcixcbiAgZGVjaW1hbHNPdXQ6IG51bWJlcixcbiAgc3dhcEFUb0I6IGJvb2xlYW4sXG4gIHNsaXBwYWdlUGVyY2VudDogbnVtYmVyID0gMC41LFxuKTogU3dhcFF1b3RlIHtcbiAgY29uc3QgaW5wdXQgPSB0eXBlb2YgaW5wdXRBbW91bnQgPT09IFwibnVtYmVyXCIgPyBuZXcgQk4oaW5wdXRBbW91bnQpIDogaW5wdXRBbW91bnQ7XG5cbiAgY29uc3QgeyBvdXRwdXRBbW91bnQsIGZlZUFtb3VudCB9ID0gY29tcHV0ZVN3YXBPdXRwdXQoaW5wdXQsIHJlc2VydmVJbiwgcmVzZXJ2ZU91dCwgZmVlQnBzLCBzd2FwQVRvQik7XG5cbiAgY29uc3Qgc2xpcHBhZ2VCcHMgPSBNYXRoLmZsb29yKHNsaXBwYWdlUGVyY2VudCAqIDEwMCk7XG4gIGNvbnN0IG1pbk91dHB1dEFtb3VudCA9IG91dHB1dEFtb3VudC5tdWwobmV3IEJOKDEwMDAwIC0gc2xpcHBhZ2VCcHMpKS5kaXYobmV3IEJOKDEwMDAwKSk7XG5cbiAgY29uc3Qgc3BvdFByaWNlQmVmb3JlID0gY2FsY3VsYXRlU3BvdFByaWNlKHJlc2VydmVJbiwgcmVzZXJ2ZU91dCwgZGVjaW1hbHNJbiwgZGVjaW1hbHNPdXQpO1xuICBjb25zdCBuZXdSZXNlcnZlSW4gPSByZXNlcnZlSW4uYWRkKGlucHV0KTtcbiAgY29uc3QgbmV3UmVzZXJ2ZU91dCA9IHJlc2VydmVPdXQuc3ViKG91dHB1dEFtb3VudCk7XG4gIGNvbnN0IHNwb3RQcmljZUFmdGVyID0gY2FsY3VsYXRlU3BvdFByaWNlKG5ld1Jlc2VydmVJbiwgbmV3UmVzZXJ2ZU91dCwgZGVjaW1hbHNJbiwgZGVjaW1hbHNPdXQpO1xuXG4gIGNvbnN0IHByaWNlSW1wYWN0ID0gY2FsY3VsYXRlUHJpY2VJbXBhY3QoaW5wdXQsIG91dHB1dEFtb3VudCwgcmVzZXJ2ZUluLCByZXNlcnZlT3V0LCBkZWNpbWFsc0luLCBkZWNpbWFsc091dCk7XG5cbiAgcmV0dXJuIHtcbiAgICBpbnB1dEFtb3VudDogaW5wdXQsXG4gICAgb3V0cHV0QW1vdW50LFxuICAgIG1pbk91dHB1dEFtb3VudCxcbiAgICBmZWVBbW91bnQsXG4gICAgcHJpY2VJbXBhY3QsXG4gICAgc3BvdFByaWNlQmVmb3JlLFxuICAgIHNwb3RQcmljZUFmdGVyLFxuICB9O1xufVxuXG4vKiBUV0FQIFV0aWxpdGllcyAqL1xuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlVHdhcChvcmFjbGU6IFR3YXBPcmFjbGUpOiBCTiB8IG51bGwge1xuICBjb25zdCB3YXJtdXBFbmQgPSBvcmFjbGUuY3JlYXRlZEF0VW5peFRpbWUuYWRkKG5ldyBCTihvcmFjbGUud2FybXVwRHVyYXRpb24pKTtcblxuICBpZiAob3JhY2xlLmxhc3RVcGRhdGVVbml4VGltZS5sdGUod2FybXVwRW5kKSkge1xuICAgIHJldHVybiBvcmFjbGUuc3RhcnRpbmdPYnNlcnZhdGlvbjtcbiAgfVxuXG4gIGNvbnN0IGVsYXBzZWQgPSBvcmFjbGUubGFzdFVwZGF0ZVVuaXhUaW1lLnN1Yih3YXJtdXBFbmQpO1xuXG4gIGlmIChlbGFwc2VkLmlzWmVybygpIHx8IG9yYWNsZS5jdW11bGF0aXZlT2JzZXJ2YXRpb25zLmlzWmVybygpKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gb3JhY2xlLmN1bXVsYXRpdmVPYnNlcnZhdGlvbnMuZGl2KGVsYXBzZWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNPcmFjbGVJbldhcm11cChvcmFjbGU6IFR3YXBPcmFjbGUsIGN1cnJlbnRUaW1lPzogQk4pOiBib29sZWFuIHtcbiAgY29uc3Qgbm93ID0gY3VycmVudFRpbWUgPz8gbmV3IEJOKE1hdGguZmxvb3IoRGF0ZS5ub3coKSAvIDEwMDApKTtcbiAgY29uc3Qgd2FybXVwRW5kID0gb3JhY2xlLmNyZWF0ZWRBdFVuaXhUaW1lLmFkZChuZXcgQk4ob3JhY2xlLndhcm11cER1cmF0aW9uKSk7XG4gIHJldHVybiBub3cubHQod2FybXVwRW5kKTtcbn1cbiJdfQ==
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.derivePoolPDA=derivePoolPDA,exports.deriveReservePDA=deriveReservePDA,exports.deriveFeeVaultPDA=deriveFeeVaultPDA,exports.parsePoolState=parsePoolState,exports.fetchPoolAccount=fetchPoolAccount,exports.calculateSpotPrice=calculateSpotPrice,exports.computeSwapOutput=computeSwapOutput,exports.computeSwapInput=computeSwapInput,exports.calculatePriceImpact=calculatePriceImpact,exports.createSwapQuote=createSwapQuote,exports.calculateTwap=calculateTwap,exports.isOracleInWarmup=isOracleInWarmup;const anchor_1=require("@coral-xyz/anchor"),web3_js_1=require("@solana/web3.js"),constants_1=require("./constants"),types_1=require("./types");function derivePoolPDA(e,t,n,o=constants_1.PROGRAM_ID){return web3_js_1.PublicKey.findProgramAddressSync([constants_1.POOL_SEED,e.toBuffer(),t.toBuffer(),n.toBuffer()],o)}function deriveReservePDA(e,t,n=constants_1.PROGRAM_ID){return web3_js_1.PublicKey.findProgramAddressSync([constants_1.RESERVE_SEED,e.toBuffer(),t.toBuffer()],n)}function deriveFeeVaultPDA(e,t=constants_1.PROGRAM_ID){return web3_js_1.PublicKey.findProgramAddressSync([constants_1.FEE_VAULT_SEED,e.toBuffer()],t)}function parsePoolState(e){if("trading"in e)return types_1.PoolState.Trading;if("finalized"in e)return types_1.PoolState.Finalized;throw new Error("Unknown pool state")}async function fetchPoolAccount(e,t){return e.account.poolAccount.fetch(t)}const PRICE_SCALE_BN=new anchor_1.BN(constants_1.PRICE_SCALE.toString());function calculateSpotPrice(e,t,n,o){if(t.isZero())return new anchor_1.BN(0);const r=o-n;if(r>=0){const n=new anchor_1.BN(10).pow(new anchor_1.BN(r));return e.mul(n).mul(PRICE_SCALE_BN).div(t)}{const n=new anchor_1.BN(10).pow(new anchor_1.BN(-r));return e.mul(PRICE_SCALE_BN).div(t).div(n)}}function computeSwapOutput(e,t,n,o,r){const u="number"==typeof e?new anchor_1.BN(e):e;if(t.isZero()||n.isZero())return{outputAmount:new anchor_1.BN(0),feeAmount:new anchor_1.BN(0)};if(r){const e=u.mul(new anchor_1.BN(o)).div(new anchor_1.BN(1e4)),r=u.sub(e),c=n.mul(r),a=t.add(r);return{outputAmount:c.div(a),feeAmount:e}}{const e=n.mul(u),r=t.add(u),c=e.div(r),a=c.mul(new anchor_1.BN(o)).div(new anchor_1.BN(1e4));return{outputAmount:c.sub(a),feeAmount:a}}}function computeSwapInput(e,t,n,o,r){const u="number"==typeof e?new anchor_1.BN(e):e;if(t.isZero()||n.isZero()||u.gte(n))return{inputAmount:new anchor_1.BN(0),feeAmount:new anchor_1.BN(0)};if(r){const e=t.mul(u),r=n.sub(u),c=e.div(r).add(new anchor_1.BN(1)),a=c.mul(new anchor_1.BN(1e4)).div(new anchor_1.BN(1e4-o)).add(new anchor_1.BN(1)),i=a.sub(c);return{inputAmount:a,feeAmount:i}}{const e=u.mul(new anchor_1.BN(1e4)).div(new anchor_1.BN(1e4-o)).add(new anchor_1.BN(1)),r=e.sub(u),c=t.mul(e),a=n.sub(e);if(a.lte(new anchor_1.BN(0)))return{inputAmount:new anchor_1.BN(0),feeAmount:new anchor_1.BN(0)};return{inputAmount:c.div(a).add(new anchor_1.BN(1)),feeAmount:r}}}function calculatePriceImpact(e,t,n,o,r,u){if(n.isZero()||o.isZero()||e.isZero())return 0;const c=calculateSpotPrice(n,o,r,u),a=calculateSpotPrice(e,t,r,u);if(c.isZero())return 0;const i=a.sub(c).mul(new anchor_1.BN(1e4)).div(c);return Math.abs(i.toNumber())/100}function createSwapQuote(e,t,n,o,r,u,c,a=.5){const i="number"==typeof e?new anchor_1.BN(e):e,{outputAmount:s,feeAmount:p}=computeSwapOutput(i,t,n,o,c),l=Math.floor(100*a),_=s.mul(new anchor_1.BN(1e4-l)).div(new anchor_1.BN(1e4)),m=calculateSpotPrice(t,n,r,u),f=calculateSpotPrice(t.add(i),n.sub(s),r,u);return{inputAmount:i,outputAmount:s,minOutputAmount:_,feeAmount:p,priceImpact:calculatePriceImpact(i,s,t,n,r,u),spotPriceBefore:m,spotPriceAfter:f}}function calculateTwap(e){const t=e.createdAtUnixTime.add(new anchor_1.BN(e.warmupDuration));if(e.lastUpdateUnixTime.lte(t))return e.startingObservation;const n=e.lastUpdateUnixTime.sub(t);return n.isZero()||e.cumulativeObservations.isZero()?null:e.cumulativeObservations.div(n)}function isOracleInWarmup(e,t){const n=t??new anchor_1.BN(Math.floor(Date.now()/1e3)),o=e.createdAtUnixTime.add(new anchor_1.BN(e.warmupDuration));return n.lt(o)}