@exponent-labs/exponent-sdk 0.9.1 → 0.9.2
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/build/client/vaults/types/kaminoObligationEntry.d.ts +21 -21
- package/build/client/vaults/types/obligationType.d.ts +1 -1
- package/build/client/vaults/types/proposalAction.d.ts +54 -54
- package/build/client/vaults/types/reserveFarmMapping.d.ts +3 -3
- package/build/client/vaults/types/strategyPosition.d.ts +1 -1
- package/build/exponentVaults/index.d.ts +1 -1
- package/build/exponentVaults/index.js +3 -2
- package/build/exponentVaults/index.js.map +1 -1
- package/build/exponentVaults/vault-instruction-types.d.ts +1 -1
- package/build/exponentVaults/vault-interaction.d.ts +58 -41
- package/build/exponentVaults/vault-interaction.js +294 -54
- package/build/exponentVaults/vault-interaction.js.map +1 -1
- package/build/exponentVaults/vault-interaction.kamino-vault.test.d.ts +1 -0
- package/build/exponentVaults/vault-interaction.kamino-vault.test.js +143 -0
- package/build/exponentVaults/vault-interaction.kamino-vault.test.js.map +1 -0
- package/build/exponentVaults/vaultTransactionBuilder.js +35 -30
- package/build/exponentVaults/vaultTransactionBuilder.js.map +1 -1
- package/build/exponentVaults/vaultTransactionBuilder.test.js +84 -1
- package/build/exponentVaults/vaultTransactionBuilder.test.js.map +1 -1
- package/package.json +34 -32
- package/src/exponentVaults/index.ts +1 -0
- package/src/exponentVaults/vault-instruction-types.ts +1 -1
- package/src/exponentVaults/vault-interaction.kamino-vault.test.ts +149 -0
- package/src/exponentVaults/vault-interaction.ts +514 -86
- package/src/exponentVaults/vaultTransactionBuilder.test.ts +93 -0
- package/src/exponentVaults/vaultTransactionBuilder.ts +47 -41
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { describe, expect, it } from "@jest/globals"
|
|
2
|
+
import BN from "bn.js"
|
|
3
|
+
import Decimal from "decimal.js"
|
|
4
|
+
import { PublicKey } from "@solana/web3.js"
|
|
5
|
+
|
|
6
|
+
import { __kaminoVaultTesting } from "./vault-interaction"
|
|
7
|
+
|
|
8
|
+
function pk(seed: number): PublicKey {
|
|
9
|
+
return new PublicKey(Uint8Array.from({ length: 32 }, () => seed))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
describe("Kamino Vault withdraw planning", () => {
|
|
13
|
+
it("computes tokens per share from available liquidity, invested liquidity, and pending fees", () => {
|
|
14
|
+
const tokensPerShare = __kaminoVaultTesting.calculateKaminoVaultTokensPerShareFromSnapshot({
|
|
15
|
+
sharesBalance: new BN(50),
|
|
16
|
+
tokenAvailable: new BN(50),
|
|
17
|
+
sharesIssued: new BN(100),
|
|
18
|
+
pendingFeesSf: new BN("11529215046068469760"), // 10.0 in Fraction fixed-point
|
|
19
|
+
reserves: [
|
|
20
|
+
{
|
|
21
|
+
reserveAddress: pk(1),
|
|
22
|
+
investedLiquidityAmount: new Decimal(60),
|
|
23
|
+
availableLiquidityToWithdraw: new Decimal(40),
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
reserveAddress: pk(2),
|
|
27
|
+
investedLiquidityAmount: new Decimal(40),
|
|
28
|
+
availableLiquidityToWithdraw: new Decimal(20),
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
expect(tokensPerShare.toFixed(6)).toBe("1.400000")
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it("uses the first active reserve when vault-side available liquidity already covers the withdraw", () => {
|
|
37
|
+
const reserveOne = pk(10)
|
|
38
|
+
const reserveTwo = pk(11)
|
|
39
|
+
const legs = __kaminoVaultTesting.planKaminoVaultWithdrawLegsFromSnapshot({
|
|
40
|
+
sharesAmount: new BN(10),
|
|
41
|
+
snapshot: {
|
|
42
|
+
sharesBalance: new BN(100),
|
|
43
|
+
tokenAvailable: new BN(20),
|
|
44
|
+
sharesIssued: new BN(100),
|
|
45
|
+
pendingFeesSf: new BN(0),
|
|
46
|
+
reserves: [
|
|
47
|
+
{
|
|
48
|
+
reserveAddress: reserveOne,
|
|
49
|
+
investedLiquidityAmount: new Decimal(40),
|
|
50
|
+
availableLiquidityToWithdraw: new Decimal(25),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
reserveAddress: reserveTwo,
|
|
54
|
+
investedLiquidityAmount: new Decimal(40),
|
|
55
|
+
availableLiquidityToWithdraw: new Decimal(30),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
},
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
expect(legs).toHaveLength(1)
|
|
62
|
+
expect(legs[0]?.reserveAddress.equals(reserveOne)).toBe(true)
|
|
63
|
+
expect(legs[0]?.sharesAmount.toString()).toBe("10")
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
it("keeps a single-reserve invested withdraw on that reserve when reserve is omitted", () => {
|
|
67
|
+
const reserve = pk(20)
|
|
68
|
+
const legs = __kaminoVaultTesting.planKaminoVaultWithdrawLegsFromSnapshot({
|
|
69
|
+
sharesAmount: new BN(50),
|
|
70
|
+
snapshot: {
|
|
71
|
+
sharesBalance: new BN(80),
|
|
72
|
+
tokenAvailable: new BN(10),
|
|
73
|
+
sharesIssued: new BN(100),
|
|
74
|
+
pendingFeesSf: new BN(0),
|
|
75
|
+
reserves: [{
|
|
76
|
+
reserveAddress: reserve,
|
|
77
|
+
investedLiquidityAmount: new Decimal(90),
|
|
78
|
+
availableLiquidityToWithdraw: new Decimal(90),
|
|
79
|
+
}],
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(legs).toHaveLength(1)
|
|
84
|
+
expect(legs[0]?.reserveAddress.equals(reserve)).toBe(true)
|
|
85
|
+
expect(legs[0]?.sharesAmount.toString()).toBe("50")
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it("orders multi-reserve withdraw legs by withdrawable liquidity when invested liquidity must be unwound", () => {
|
|
89
|
+
const reserveOne = pk(30)
|
|
90
|
+
const reserveTwo = pk(31)
|
|
91
|
+
const reserveThree = pk(32)
|
|
92
|
+
const legs = __kaminoVaultTesting.planKaminoVaultWithdrawLegsFromSnapshot({
|
|
93
|
+
sharesAmount: new BN(50),
|
|
94
|
+
snapshot: {
|
|
95
|
+
sharesBalance: new BN(80),
|
|
96
|
+
tokenAvailable: new BN(10),
|
|
97
|
+
sharesIssued: new BN(100),
|
|
98
|
+
pendingFeesSf: new BN(0),
|
|
99
|
+
reserves: [
|
|
100
|
+
{
|
|
101
|
+
reserveAddress: reserveOne,
|
|
102
|
+
investedLiquidityAmount: new Decimal(50),
|
|
103
|
+
availableLiquidityToWithdraw: new Decimal(15),
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
reserveAddress: reserveTwo,
|
|
107
|
+
investedLiquidityAmount: new Decimal(40),
|
|
108
|
+
availableLiquidityToWithdraw: new Decimal(30),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
reserveAddress: reserveThree,
|
|
112
|
+
investedLiquidityAmount: new Decimal(20),
|
|
113
|
+
availableLiquidityToWithdraw: new Decimal(5),
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
expect(legs.map((leg) => leg.reserveAddress.toBase58())).toEqual([
|
|
120
|
+
reserveTwo.toBase58(),
|
|
121
|
+
reserveOne.toBase58(),
|
|
122
|
+
reserveThree.toBase58(),
|
|
123
|
+
])
|
|
124
|
+
expect(legs.map((leg) => leg.sharesAmount.toString())).toEqual(["33", "12", "4"])
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
it("preserves an explicit reserve override", () => {
|
|
128
|
+
const reserve = pk(40)
|
|
129
|
+
const legs = __kaminoVaultTesting.planKaminoVaultWithdrawLegsFromSnapshot({
|
|
130
|
+
sharesAmount: new BN(25),
|
|
131
|
+
reserve,
|
|
132
|
+
snapshot: {
|
|
133
|
+
sharesBalance: new BN(80),
|
|
134
|
+
tokenAvailable: new BN(0),
|
|
135
|
+
sharesIssued: new BN(80),
|
|
136
|
+
pendingFeesSf: new BN(0),
|
|
137
|
+
reserves: [{
|
|
138
|
+
reserveAddress: reserve,
|
|
139
|
+
investedLiquidityAmount: new Decimal(80),
|
|
140
|
+
availableLiquidityToWithdraw: new Decimal(80),
|
|
141
|
+
}],
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
expect(legs).toHaveLength(1)
|
|
146
|
+
expect(legs[0]?.reserveAddress.equals(reserve)).toBe(true)
|
|
147
|
+
expect(legs[0]?.sharesAmount.toString()).toBe("25")
|
|
148
|
+
})
|
|
149
|
+
})
|