@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/CHANGELOG.md +16 -0
- package/build/exponentFetcher.d.ts +242 -0
- package/build/exponentFetcher.js +492 -0
- package/build/exponentFetcher.js.map +1 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +19 -0
- package/build/index.js.map +1 -0
- package/build/utils/meteora.d.ts +54 -0
- package/build/utils/meteora.js +116 -0
- package/build/utils/meteora.js.map +1 -0
- package/package.json +35 -0
- package/src/exponentFetcher.ts +895 -0
- package/src/index.ts +2 -0
- package/src/utils/meteora.ts +126 -0
- package/tsconfig.json +34 -0
package/src/index.ts
ADDED
|
@@ -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
|
+
}
|