@exponent-labs/exponent-fetcher 0.0.3

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/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ // TODO - rename to "sol"
2
+ export * from "./exponentFetcher"
@@ -0,0 +1,126 @@
1
+ import { CurveType, VaultState } from "@exponent-labs/meteora-idl"
2
+ import { BN } from "@coral-xyz/anchor"
3
+ import sqrt from "bn-sqrt"
4
+
5
+ /**
6
+ * Calculates the unlocked (withdrawable) amount of tokens in a Meteora vault.
7
+ *
8
+ * @param onChainTime - Current blockchain timestamp in seconds
9
+ * @param vaultState - The state of the Meteora vault
10
+ * @returns A BN representing the unlocked amount that can be withdrawn from the vault
11
+ *
12
+ */
13
+ export function calculateUnlockedAmount(onChainTime: number, vaultState: VaultState) {
14
+ const {
15
+ lockedProfitTracker: { lastReport, lockedProfitDegradation, lastUpdatedLockedProfit },
16
+ totalAmount: vaultTotalAmount,
17
+ } = vaultState
18
+ const lockedProfitDegradationDenominator = new BN(1_000_000_000_000)
19
+
20
+ const duration = new BN(onChainTime).sub(lastReport)
21
+
22
+ const lockedFundRatio = duration.mul(lockedProfitDegradation)
23
+ if (lockedFundRatio.gt(lockedProfitDegradationDenominator)) {
24
+ return vaultTotalAmount
25
+ }
26
+
27
+ const lockedProfit = lastUpdatedLockedProfit
28
+ .mul(lockedProfitDegradationDenominator.sub(lockedFundRatio))
29
+ .div(lockedProfitDegradationDenominator)
30
+
31
+ return vaultTotalAmount.sub(lockedProfit)
32
+ }
33
+
34
+ /**
35
+ * Calculates the amount of tokens corresponding to a share of the vault.
36
+ *
37
+ * @param share - Share amount of LP tokens
38
+ * @param totalSupply - Total supply of LP tokens
39
+ * @param vaultState - Current state of the vault
40
+ * @param onChainTime - Current blockchain timestamp in seconds
41
+ * @returns The amount of underlying tokens represented by the shares
42
+ *
43
+ */
44
+ export function getAmountByShare(share: BN, totalSupply: BN, vaultState: VaultState, onChainTime: number): BN {
45
+ const withdrawableAmount = calculateUnlockedAmount(onChainTime, vaultState)
46
+
47
+ return totalSupply.isZero() ? new BN(0) : share.mul(withdrawableAmount).div(totalSupply)
48
+ }
49
+
50
+ /**
51
+ * Computes the StableSwap invariant (D) based on the Curve Finance formula.
52
+ *
53
+ * This function implements the iterative algorithm to find the value D such that:
54
+ * Ann * S + D * P / (A * N^n) = D^(n+1) / (n^n * prod(x_i))
55
+ *
56
+ * Where:
57
+ * - Ann is amplification coefficient * n^n
58
+ * - S is the sum of all coin amounts
59
+ * - P is the product of all coin amounts
60
+ * - n is the number of coins (2 in this case)
61
+ *
62
+ * @param ampFactor - Amplification coefficient (A)
63
+ * @param amountA - Amount of token A in the pool
64
+ * @param amountB - Amount of token B in the pool
65
+ * @returns The computed invariant D
66
+ *
67
+ */
68
+ export const computeStableSwapInvariant = (ampFactor: BN, amountA: BN, amountB: BN): BN => {
69
+ const N_COINS = new BN(2)
70
+ const ZERO = new BN(0)
71
+ const ONE = new BN(1)
72
+ const MAX_ITERS = 20
73
+
74
+ const Ann = ampFactor.mul(N_COINS) // A*n^n
75
+ const S = amountA.add(amountB) // sum(x_i), a.k.a S
76
+ if (S === ZERO) {
77
+ return ZERO
78
+ }
79
+
80
+ let dPrev = ZERO
81
+ let d = S
82
+
83
+ for (let i = 0; d.sub(dPrev).abs().gt(ONE) && i < MAX_ITERS; i++) {
84
+ dPrev = d
85
+ let dP = d
86
+ dP = dP.mul(d).div(amountA.mul(N_COINS))
87
+ dP = dP.mul(d).div(amountB.mul(N_COINS))
88
+
89
+ const dNumerator = d.mul(Ann.mul(S).add(dP.mul(N_COINS)))
90
+ const dDenominator = d.mul(Ann.sub(ONE)).add(dP.mul(N_COINS.add(ONE)))
91
+ d = dNumerator.div(dDenominator)
92
+ }
93
+
94
+ return d
95
+ }
96
+
97
+ /**
98
+ * Computes the invariant D value for a token pair based on curve type.
99
+ *
100
+ * @param curve - Type of curve (ConstantProduct or Stable with parameters)
101
+ * @param tokenAmountA - Amount of token A
102
+ * @param tokenAmountB - Amount of token B
103
+ * @returns The calculated invariant D value
104
+ *
105
+ * Corresponds to `compute_d` function in Rust implementation.
106
+ *
107
+ */
108
+ export function computeD(curve: CurveType, tokenAmountA: BN, tokenAmountB: BN): BN {
109
+ if ("cosntantProduct" in curve) {
110
+ return sqrt(tokenAmountA.mul(tokenAmountB))
111
+ } else if ("stable" in curve) {
112
+ const PRECISION = new BN(1_000_000)
113
+ const { amp, tokenMultiplier, depeg } = curve.stable
114
+
115
+ const upscaledTokenA = tokenMultiplier.tokenAMultiplier.mul(tokenAmountA)
116
+ const upscaledTokenB = tokenMultiplier.tokenBMultiplier.mul(tokenAmountB)
117
+
118
+ let invariantD = computeStableSwapInvariant(amp, upscaledTokenA, upscaledTokenB)
119
+
120
+ if (!depeg.depegType["none"]) {
121
+ return invariantD.div(PRECISION)
122
+ }
123
+
124
+ return invariantD
125
+ }
126
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": "src",
4
+ "sourceMap": true,
5
+ "incremental": true /* Save .tsbuildinfo files to allow for incremental compilation of projects. */,
6
+ "composite": true /* Enable constraints that allow a TypeScript project to be used with project references. */,
7
+ "target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
8
+ "module": "CommonJS" /* Specify what module code is generated. */,
9
+ "declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
10
+ "outDir": "./build" /* Specify an output folder for all emitted files. */,
11
+ "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
12
+ "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
13
+ "skipLibCheck": true /* Skip type checking all .d.ts files. */
14
+ },
15
+ "include": ["src"],
16
+ "exclude": ["build"],
17
+ "references": [
18
+ { "path": "../exponent-idl" },
19
+ { "path": "../exponent-ix" },
20
+ { "path": "../exponent-pda" },
21
+ { "path": "../precise-number" },
22
+ { "path": "../rust-decimal" },
23
+ { "path": "../marginfi-sy-idl" },
24
+ { "path": "../json-api-client" },
25
+ { "path": "../kamino-reserve-deserializer" },
26
+ { "path": "../exponent-types" },
27
+ { "path": "../jito-restaking-sy-idl" },
28
+ { "path": "../generic-sy-idl" },
29
+ { "path": "../generic-sy-pda" },
30
+ { "path": "../perena-sy-idl" },
31
+ { "path": "../fragmetric-idl" },
32
+ { "path": "../meteora-idl" }
33
+ ]
34
+ }