@exponent-labs/exponent-sdk 0.9.0 → 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/index.d.ts +2 -0
- package/build/client/vaults/index.js +2 -0
- package/build/client/vaults/index.js.map +1 -1
- package/build/client/vaults/types/index.d.ts +2 -0
- package/build/client/vaults/types/index.js +2 -0
- package/build/client/vaults/types/index.js.map +1 -1
- package/build/client/vaults/types/kaminoFarmEntry.d.ts +15 -0
- package/build/client/vaults/types/kaminoFarmEntry.js +17 -0
- package/build/client/vaults/types/kaminoFarmEntry.js.map +1 -0
- package/build/client/vaults/types/kaminoObligationEntry.d.ts +21 -4
- package/build/client/vaults/types/kaminoObligationEntry.js +2 -1
- package/build/client/vaults/types/kaminoObligationEntry.js.map +1 -1
- package/build/client/vaults/types/positionUpdate.d.ts +9 -0
- package/build/client/vaults/types/positionUpdate.js +23 -0
- package/build/client/vaults/types/positionUpdate.js.map +1 -1
- package/build/client/vaults/types/proposalAction.js +0 -3
- package/build/client/vaults/types/proposalAction.js.map +1 -1
- package/build/client/vaults/types/reserveFarmMapping.d.ts +19 -0
- package/build/client/vaults/types/reserveFarmMapping.js +18 -0
- package/build/client/vaults/types/reserveFarmMapping.js.map +1 -0
- package/build/client/vaults/types/strategyPosition.d.ts +5 -0
- package/build/client/vaults/types/strategyPosition.js +5 -0
- package/build/client/vaults/types/strategyPosition.js.map +1 -1
- package/build/exponentVaults/aumCalculator.d.ts +25 -4
- package/build/exponentVaults/aumCalculator.js +236 -15
- package/build/exponentVaults/aumCalculator.js.map +1 -1
- package/build/exponentVaults/fetcher.d.ts +52 -0
- package/build/exponentVaults/fetcher.js +199 -0
- package/build/exponentVaults/fetcher.js.map +1 -0
- package/build/exponentVaults/index.d.ts +10 -9
- package/build/exponentVaults/index.js +26 -8
- package/build/exponentVaults/index.js.map +1 -1
- package/build/exponentVaults/kamino-farms.d.ts +144 -0
- package/build/exponentVaults/kamino-farms.js +396 -0
- package/build/exponentVaults/kamino-farms.js.map +1 -0
- package/build/exponentVaults/loopscale/client.d.ts +240 -0
- package/build/exponentVaults/loopscale/client.js +590 -0
- package/build/exponentVaults/loopscale/client.js.map +1 -0
- package/build/exponentVaults/loopscale/client.test.d.ts +1 -0
- package/build/exponentVaults/loopscale/client.test.js +183 -0
- package/build/exponentVaults/loopscale/client.test.js.map +1 -0
- package/build/exponentVaults/loopscale/helpers.d.ts +29 -0
- package/build/exponentVaults/loopscale/helpers.js +119 -0
- package/build/exponentVaults/loopscale/helpers.js.map +1 -0
- package/build/exponentVaults/loopscale/index.d.ts +3 -0
- package/build/exponentVaults/loopscale/index.js +12 -0
- package/build/exponentVaults/loopscale/index.js.map +1 -0
- package/build/exponentVaults/loopscale/prepared-transactions.d.ts +13 -0
- package/build/exponentVaults/loopscale/prepared-transactions.js +271 -0
- package/build/exponentVaults/loopscale/prepared-transactions.js.map +1 -0
- package/build/exponentVaults/loopscale/prepared-transactions.test.d.ts +1 -0
- package/build/exponentVaults/loopscale/prepared-transactions.test.js +400 -0
- package/build/exponentVaults/loopscale/prepared-transactions.test.js.map +1 -0
- package/build/exponentVaults/loopscale/prepared-types.d.ts +62 -0
- package/build/exponentVaults/loopscale/prepared-types.js +3 -0
- package/build/exponentVaults/loopscale/prepared-types.js.map +1 -0
- package/build/exponentVaults/loopscale/response-plan.d.ts +69 -0
- package/build/exponentVaults/loopscale/response-plan.js +141 -0
- package/build/exponentVaults/loopscale/response-plan.js.map +1 -0
- package/build/exponentVaults/loopscale/response-plan.test.d.ts +1 -0
- package/build/exponentVaults/loopscale/response-plan.test.js +139 -0
- package/build/exponentVaults/loopscale/response-plan.test.js.map +1 -0
- package/build/exponentVaults/loopscale/send-plan.d.ts +75 -0
- package/build/exponentVaults/loopscale/send-plan.js +235 -0
- package/build/exponentVaults/loopscale/send-plan.js.map +1 -0
- package/build/exponentVaults/loopscale/types.d.ts +443 -0
- package/build/exponentVaults/loopscale/types.js +3 -0
- package/build/exponentVaults/loopscale/types.js.map +1 -0
- package/build/exponentVaults/loopscale-client.d.ts +113 -524
- package/build/exponentVaults/loopscale-client.js +296 -539
- package/build/exponentVaults/loopscale-client.js.map +1 -1
- package/build/exponentVaults/loopscale-client.test.d.ts +1 -0
- package/build/exponentVaults/loopscale-client.test.js +162 -0
- package/build/exponentVaults/loopscale-client.test.js.map +1 -0
- package/build/exponentVaults/loopscale-client.types.d.ts +425 -0
- package/build/exponentVaults/loopscale-client.types.js +3 -0
- package/build/exponentVaults/loopscale-client.types.js.map +1 -0
- package/build/exponentVaults/loopscale-execution.d.ts +125 -0
- package/build/exponentVaults/loopscale-execution.js +341 -0
- package/build/exponentVaults/loopscale-execution.js.map +1 -0
- package/build/exponentVaults/loopscale-execution.test.d.ts +1 -0
- package/build/exponentVaults/loopscale-execution.test.js +139 -0
- package/build/exponentVaults/loopscale-execution.test.js.map +1 -0
- package/build/exponentVaults/loopscale-vault.d.ts +115 -0
- package/build/exponentVaults/loopscale-vault.js +275 -0
- package/build/exponentVaults/loopscale-vault.js.map +1 -0
- package/build/exponentVaults/loopscale-vault.test.d.ts +1 -0
- package/build/exponentVaults/loopscale-vault.test.js +102 -0
- package/build/exponentVaults/loopscale-vault.test.js.map +1 -0
- package/build/exponentVaults/policyBuilders.d.ts +62 -0
- package/build/exponentVaults/policyBuilders.js +119 -2
- package/build/exponentVaults/policyBuilders.js.map +1 -1
- package/build/exponentVaults/pricePathResolver.d.ts +45 -0
- package/build/exponentVaults/pricePathResolver.js +198 -0
- package/build/exponentVaults/pricePathResolver.js.map +1 -0
- package/build/exponentVaults/pricePathResolver.test.d.ts +1 -0
- package/build/exponentVaults/pricePathResolver.test.js +369 -0
- package/build/exponentVaults/pricePathResolver.test.js.map +1 -0
- package/build/exponentVaults/syncTransaction.js +4 -1
- package/build/exponentVaults/syncTransaction.js.map +1 -1
- package/build/exponentVaults/titan-quote.js +170 -36
- package/build/exponentVaults/titan-quote.js.map +1 -1
- package/build/exponentVaults/vault-instruction-types.d.ts +363 -0
- package/build/exponentVaults/vault-instruction-types.js +128 -0
- package/build/exponentVaults/vault-instruction-types.js.map +1 -0
- package/build/exponentVaults/vault-interaction.d.ts +203 -343
- package/build/exponentVaults/vault-interaction.js +1894 -426
- 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/vault.d.ts +51 -2
- package/build/exponentVaults/vault.js +324 -48
- package/build/exponentVaults/vault.js.map +1 -1
- package/build/exponentVaults/vaultTransactionBuilder.d.ts +100 -134
- package/build/exponentVaults/vaultTransactionBuilder.js +383 -285
- package/build/exponentVaults/vaultTransactionBuilder.js.map +1 -1
- package/build/exponentVaults/vaultTransactionBuilder.test.d.ts +1 -0
- package/build/exponentVaults/vaultTransactionBuilder.test.js +297 -0
- package/build/exponentVaults/vaultTransactionBuilder.test.js.map +1 -0
- package/build/marketThree.d.ts +6 -2
- package/build/marketThree.js +10 -8
- package/build/marketThree.js.map +1 -1
- package/package.json +34 -32
- package/src/client/vaults/index.ts +2 -0
- package/src/client/vaults/types/index.ts +2 -0
- package/src/client/vaults/types/kaminoFarmEntry.ts +32 -0
- package/src/client/vaults/types/kaminoObligationEntry.ts +6 -3
- package/src/client/vaults/types/positionUpdate.ts +62 -0
- package/src/client/vaults/types/proposalAction.ts +0 -3
- package/src/client/vaults/types/reserveFarmMapping.ts +35 -0
- package/src/client/vaults/types/strategyPosition.ts +18 -1
- package/src/exponentVaults/aumCalculator.ts +353 -16
- package/src/exponentVaults/fetcher.ts +257 -0
- package/src/exponentVaults/index.ts +65 -40
- package/src/exponentVaults/kamino-farms.ts +538 -0
- package/src/exponentVaults/loopscale/client.ts +808 -0
- package/src/exponentVaults/loopscale/helpers.ts +172 -0
- package/src/exponentVaults/loopscale/index.ts +57 -0
- package/src/exponentVaults/loopscale/prepared-transactions.ts +435 -0
- package/src/exponentVaults/loopscale/prepared-types.ts +73 -0
- package/src/exponentVaults/loopscale/types.ts +466 -0
- package/src/exponentVaults/policyBuilders.ts +170 -0
- package/src/exponentVaults/pricePathResolver.test.ts +466 -0
- package/src/exponentVaults/pricePathResolver.ts +273 -0
- package/src/exponentVaults/syncTransaction.ts +6 -1
- package/src/exponentVaults/titan-quote.ts +231 -45
- package/src/exponentVaults/vault-instruction-types.ts +493 -0
- package/src/exponentVaults/vault-interaction.kamino-vault.test.ts +149 -0
- package/src/exponentVaults/vault-interaction.ts +2818 -799
- package/src/exponentVaults/vault.ts +474 -63
- package/src/exponentVaults/vaultTransactionBuilder.test.ts +349 -0
- package/src/exponentVaults/vaultTransactionBuilder.ts +581 -433
- package/src/marketThree.ts +14 -6
- package/src/exponentVaults/loopscale-client.ts +0 -1373
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { PublicKey, TransactionInstruction } from "@solana/web3.js"
|
|
2
|
+
import { SwapDirection } from "../client/clmm"
|
|
3
|
+
import { KAMINO_RESERVES, KaminoMarket } from "./kamino-markets"
|
|
4
|
+
import BN from "bn.js"
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Vault Instruction Types
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
type KaminoReserves = typeof KAMINO_RESERVES
|
|
11
|
+
|
|
12
|
+
/** Actions that can be performed through the vault instruction builder. */
|
|
13
|
+
export enum VaultAction {
|
|
14
|
+
INIT_USER_METADATA = "INIT_USER_METADATA",
|
|
15
|
+
INIT_OBLIGATION = "INIT_OBLIGATION",
|
|
16
|
+
DEPOSIT = "DEPOSIT",
|
|
17
|
+
WITHDRAW = "WITHDRAW",
|
|
18
|
+
BORROW = "BORROW",
|
|
19
|
+
REPAY = "REPAY",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** A market-level instruction (no specific reserve needed). */
|
|
23
|
+
export type MarketInstruction = {
|
|
24
|
+
action: VaultAction.INIT_USER_METADATA | VaultAction.INIT_OBLIGATION
|
|
25
|
+
market: KaminoMarket
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** A reserve-level instruction with an amount. */
|
|
29
|
+
export type ReserveInstruction = {
|
|
30
|
+
action: VaultAction.DEPOSIT | VaultAction.WITHDRAW | VaultAction.BORROW | VaultAction.REPAY
|
|
31
|
+
market: KaminoMarket
|
|
32
|
+
asset: string
|
|
33
|
+
amount: BN
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Kamino Vault Instruction Types
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
/** Actions that can be performed on a direct Kamino Vault position. */
|
|
41
|
+
export enum KaminoVaultAction {
|
|
42
|
+
DEPOSIT = "KAMINO_VAULT_DEPOSIT",
|
|
43
|
+
WITHDRAW = "KAMINO_VAULT_WITHDRAW",
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type KaminoVaultInstructionBase = {
|
|
47
|
+
action: KaminoVaultAction
|
|
48
|
+
vault: PublicKey
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Deposit the vault-owned token account into a Kamino Vault and mint shares. */
|
|
52
|
+
export type KaminoVaultDepositInstruction = KaminoVaultInstructionBase & {
|
|
53
|
+
action: KaminoVaultAction.DEPOSIT
|
|
54
|
+
amount: BN
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Withdraw Kamino Vault shares back into the vault-owned token account. */
|
|
58
|
+
export type KaminoVaultWithdrawInstruction = KaminoVaultInstructionBase & {
|
|
59
|
+
action: KaminoVaultAction.WITHDRAW
|
|
60
|
+
sharesAmount: BN
|
|
61
|
+
/** Optional reserve override. Omit it to let the SDK plan the withdraw across the vault's active reserves. */
|
|
62
|
+
reserve?: PublicKey
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type KaminoVaultInstruction =
|
|
66
|
+
| KaminoVaultDepositInstruction
|
|
67
|
+
| KaminoVaultWithdrawInstruction
|
|
68
|
+
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Kamino Farm Instruction Types
|
|
71
|
+
// ============================================================================
|
|
72
|
+
|
|
73
|
+
/** Actions that can be performed on a direct Kamino Farm position. */
|
|
74
|
+
export enum KaminoFarmAction {
|
|
75
|
+
INITIALIZE_USER = "KAMINO_FARM_INITIALIZE_USER",
|
|
76
|
+
STAKE = "KAMINO_FARM_STAKE",
|
|
77
|
+
UNSTAKE = "KAMINO_FARM_UNSTAKE",
|
|
78
|
+
WITHDRAW_UNSTAKED_DEPOSITS = "KAMINO_FARM_WITHDRAW_UNSTAKED_DEPOSITS",
|
|
79
|
+
HARVEST_REWARD = "KAMINO_FARM_HARVEST_REWARD",
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
type KaminoFarmInstructionBase = {
|
|
83
|
+
action: KaminoFarmAction
|
|
84
|
+
farmState: PublicKey
|
|
85
|
+
/**
|
|
86
|
+
* Optional delegatee used to derive the Farm `user_state`.
|
|
87
|
+
* Defaults to the managed vault owner when omitted.
|
|
88
|
+
*/
|
|
89
|
+
delegatee?: PublicKey
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Initialize the Farm `user_state` PDA for the vault owner or delegatee. */
|
|
93
|
+
export type KaminoFarmInitializeUserInstruction = KaminoFarmInstructionBase & {
|
|
94
|
+
action: KaminoFarmAction.INITIALIZE_USER
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Stake tokens from the vault-owned ATA into the Farm. */
|
|
98
|
+
export type KaminoFarmStakeInstruction = KaminoFarmInstructionBase & {
|
|
99
|
+
action: KaminoFarmAction.STAKE
|
|
100
|
+
amount: BN | "ALL"
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Unstake a scaled share amount from the Farm. */
|
|
104
|
+
export type KaminoFarmUnstakeInstruction = KaminoFarmInstructionBase & {
|
|
105
|
+
action: KaminoFarmAction.UNSTAKE
|
|
106
|
+
stakeSharesScaled: BN
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Withdraw matured unstaked deposits back into the vault-owned ATA. */
|
|
110
|
+
export type KaminoFarmWithdrawUnstakedDepositsInstruction = KaminoFarmInstructionBase & {
|
|
111
|
+
action: KaminoFarmAction.WITHDRAW_UNSTAKED_DEPOSITS
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Harvest a single Farm reward into a vault-owned reward ATA. */
|
|
115
|
+
export type KaminoFarmHarvestRewardInstruction = KaminoFarmInstructionBase & {
|
|
116
|
+
action: KaminoFarmAction.HARVEST_REWARD
|
|
117
|
+
rewardIndex: number
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type KaminoFarmInstruction =
|
|
121
|
+
| KaminoFarmInitializeUserInstruction
|
|
122
|
+
| KaminoFarmStakeInstruction
|
|
123
|
+
| KaminoFarmUnstakeInstruction
|
|
124
|
+
| KaminoFarmWithdrawUnstakedDepositsInstruction
|
|
125
|
+
| KaminoFarmHarvestRewardInstruction
|
|
126
|
+
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Orderbook Instruction Types
|
|
129
|
+
// ============================================================================
|
|
130
|
+
|
|
131
|
+
/** Orderbook trade direction */
|
|
132
|
+
export enum OrderbookTradeDirection {
|
|
133
|
+
BUY_PT = "BUY_PT",
|
|
134
|
+
SELL_PT = "SELL_PT",
|
|
135
|
+
BUY_YT = "BUY_YT",
|
|
136
|
+
SELL_YT = "SELL_YT",
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Offer options for limit orders (currently only FillOrKill supported) */
|
|
140
|
+
export type OrderbookOfferOption = "FillOrKill"
|
|
141
|
+
|
|
142
|
+
/** Actions that can be performed on the Exponent Orderbook */
|
|
143
|
+
export enum OrderbookAction {
|
|
144
|
+
POST_OFFER = "POST_OFFER",
|
|
145
|
+
MARKET_OFFER = "MARKET_OFFER",
|
|
146
|
+
REMOVE_OFFER = "REMOVE_OFFER",
|
|
147
|
+
WITHDRAW_FUNDS = "WITHDRAW_FUNDS",
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export type OrderbookInstructionMode = "wrapper" | "raw"
|
|
151
|
+
|
|
152
|
+
/** Base instruction type for all orderbook operations */
|
|
153
|
+
interface OrderbookInstructionBase {
|
|
154
|
+
action: OrderbookAction
|
|
155
|
+
orderbook: PublicKey
|
|
156
|
+
mode?: OrderbookInstructionMode
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** Post a limit order on the orderbook */
|
|
160
|
+
export interface OrderbookPostOfferInstruction extends OrderbookInstructionBase {
|
|
161
|
+
action: OrderbookAction.POST_OFFER
|
|
162
|
+
direction: OrderbookTradeDirection
|
|
163
|
+
priceApy: number
|
|
164
|
+
amount: bigint
|
|
165
|
+
offerOption?: OrderbookOfferOption
|
|
166
|
+
expirySeconds?: number
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Execute a market order on the orderbook */
|
|
170
|
+
export interface OrderbookMarketOfferInstruction extends OrderbookInstructionBase {
|
|
171
|
+
action: OrderbookAction.MARKET_OFFER
|
|
172
|
+
direction: OrderbookTradeDirection
|
|
173
|
+
maxPriceApy: number
|
|
174
|
+
amount: bigint
|
|
175
|
+
minAmountOut: bigint
|
|
176
|
+
virtualOffer?: boolean
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Cancel an existing limit order */
|
|
180
|
+
export interface OrderbookRemoveOfferInstruction extends OrderbookInstructionBase {
|
|
181
|
+
action: OrderbookAction.REMOVE_OFFER
|
|
182
|
+
offerIdx: number
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Withdraw funds from user escrow */
|
|
186
|
+
export interface OrderbookWithdrawFundsInstruction extends OrderbookInstructionBase {
|
|
187
|
+
action: OrderbookAction.WITHDRAW_FUNDS
|
|
188
|
+
ptAmount?: bigint | null
|
|
189
|
+
ytAmount?: bigint | null
|
|
190
|
+
syAmount?: bigint | null
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** A single orderbook instruction */
|
|
194
|
+
export type OrderbookInstruction =
|
|
195
|
+
| OrderbookPostOfferInstruction
|
|
196
|
+
| OrderbookMarketOfferInstruction
|
|
197
|
+
| OrderbookRemoveOfferInstruction
|
|
198
|
+
| OrderbookWithdrawFundsInstruction
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Core Instruction Types (Strip/Merge)
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
204
|
+
/** Actions that can be performed on Exponent Core */
|
|
205
|
+
export enum CoreAction {
|
|
206
|
+
STRIP = "STRIP",
|
|
207
|
+
MERGE = "MERGE",
|
|
208
|
+
WITHDRAW_YT = "WITHDRAW_YT",
|
|
209
|
+
DEPOSIT_YT = "DEPOSIT_YT",
|
|
210
|
+
INITIALIZE_YIELD_POSITION = "INITIALIZE_YIELD_POSITION",
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Base instruction type for all core operations */
|
|
214
|
+
interface CoreInstructionBase {
|
|
215
|
+
action: CoreAction
|
|
216
|
+
vault: PublicKey
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** Strip LST into PT + YT */
|
|
220
|
+
export interface CoreStripInstruction extends CoreInstructionBase {
|
|
221
|
+
action: CoreAction.STRIP
|
|
222
|
+
/** Amount of base token (LST) to strip */
|
|
223
|
+
amountBase: bigint
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Merge PT + YT into LST */
|
|
227
|
+
export interface CoreMergeInstruction extends CoreInstructionBase {
|
|
228
|
+
action: CoreAction.MERGE
|
|
229
|
+
/** Amount of PT/YT to merge (must have equal amounts of both) */
|
|
230
|
+
amountPy: bigint
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** Withdraw YT from the tracked yield position back into the YT token account */
|
|
234
|
+
export interface CoreWithdrawYtInstruction extends CoreInstructionBase {
|
|
235
|
+
action: CoreAction.WITHDRAW_YT
|
|
236
|
+
amountYt: bigint
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** Deposit YT from the YT token account back into the tracked yield position */
|
|
240
|
+
export interface CoreDepositYtInstruction extends CoreInstructionBase {
|
|
241
|
+
action: CoreAction.DEPOSIT_YT
|
|
242
|
+
amountYt: bigint
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** Initialize yield position for a vault (owner = Squads vault) */
|
|
246
|
+
export interface CoreInitializeYieldPositionInstruction extends CoreInstructionBase {
|
|
247
|
+
action: CoreAction.INITIALIZE_YIELD_POSITION
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** A single core instruction */
|
|
251
|
+
export type CoreInstruction =
|
|
252
|
+
| CoreStripInstruction
|
|
253
|
+
| CoreMergeInstruction
|
|
254
|
+
| CoreWithdrawYtInstruction
|
|
255
|
+
| CoreDepositYtInstruction
|
|
256
|
+
| CoreInitializeYieldPositionInstruction
|
|
257
|
+
|
|
258
|
+
// ============================================================================
|
|
259
|
+
// Standard Program Instruction Types (mint_sy / redeem_sy)
|
|
260
|
+
// ============================================================================
|
|
261
|
+
|
|
262
|
+
export enum SyAction {
|
|
263
|
+
MINT = "MINT_SY",
|
|
264
|
+
REDEEM = "REDEEM_SY",
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
interface SyInstructionBase {
|
|
268
|
+
action: SyAction
|
|
269
|
+
vault: PublicKey
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
export interface SyMintInstruction extends SyInstructionBase {
|
|
273
|
+
action: SyAction.MINT
|
|
274
|
+
amountBase: bigint
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export interface SyRedeemInstruction extends SyInstructionBase {
|
|
278
|
+
action: SyAction.REDEEM
|
|
279
|
+
amountSy: bigint
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export type SyInstruction = SyMintInstruction | SyRedeemInstruction
|
|
283
|
+
|
|
284
|
+
// ============================================================================
|
|
285
|
+
// Titan Instruction Types
|
|
286
|
+
// ============================================================================
|
|
287
|
+
|
|
288
|
+
export enum TitanAction {
|
|
289
|
+
SWAP = "SWAP",
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** A pre-built Titan swap instruction to wrap in a sync transaction. */
|
|
293
|
+
export interface TitanSwapInstruction {
|
|
294
|
+
action: TitanAction.SWAP
|
|
295
|
+
/** The raw Titan SwapRouteV2 TransactionInstruction (from Titan's router API) */
|
|
296
|
+
instruction: TransactionInstruction
|
|
297
|
+
/** ALT addresses returned by Titan's router for this route. */
|
|
298
|
+
addressLookupTableAddresses?: PublicKey[]
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ============================================================================
|
|
302
|
+
// Loopscale Instruction Types
|
|
303
|
+
// ============================================================================
|
|
304
|
+
|
|
305
|
+
/** Actions for Loopscale interactions (loans = borrower side, strategies = lender side). */
|
|
306
|
+
export enum LoopscaleAction {
|
|
307
|
+
CREATE_LOAN = "LOOPSCALE_CREATE_LOAN",
|
|
308
|
+
DEPOSIT_COLLATERAL = "LOOPSCALE_DEPOSIT_COLLATERAL",
|
|
309
|
+
BORROW_PRINCIPAL = "LOOPSCALE_BORROW_PRINCIPAL",
|
|
310
|
+
REPAY_PRINCIPAL = "LOOPSCALE_REPAY_PRINCIPAL",
|
|
311
|
+
WITHDRAW_COLLATERAL = "LOOPSCALE_WITHDRAW_COLLATERAL",
|
|
312
|
+
CLOSE_LOAN = "LOOPSCALE_CLOSE_LOAN",
|
|
313
|
+
UPDATE_WEIGHT_MATRIX = "LOOPSCALE_UPDATE_WEIGHT_MATRIX",
|
|
314
|
+
CREATE_STRATEGY = "LOOPSCALE_CREATE_STRATEGY",
|
|
315
|
+
DEPOSIT_STRATEGY = "LOOPSCALE_DEPOSIT_STRATEGY",
|
|
316
|
+
WITHDRAW_STRATEGY = "LOOPSCALE_WITHDRAW_STRATEGY",
|
|
317
|
+
CLOSE_STRATEGY = "LOOPSCALE_CLOSE_STRATEGY",
|
|
318
|
+
UPDATE_STRATEGY = "LOOPSCALE_UPDATE_STRATEGY",
|
|
319
|
+
LOCK_LOAN = "LOOPSCALE_LOCK_LOAN",
|
|
320
|
+
UNLOCK_LOAN = "LOOPSCALE_UNLOCK_LOAN",
|
|
321
|
+
REFINANCE_LEDGER = "LOOPSCALE_REFINANCE_LEDGER",
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** A pre-built Loopscale instruction (loan or strategy) to wrap in a sync transaction. */
|
|
325
|
+
export interface LoopscaleInstruction {
|
|
326
|
+
action: LoopscaleAction
|
|
327
|
+
/** The raw Loopscale TransactionInstruction (from Loopscale API or local builder) */
|
|
328
|
+
instruction: TransactionInstruction
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// ============================================================================
|
|
332
|
+
// CLMM Instruction Types
|
|
333
|
+
// ============================================================================
|
|
334
|
+
|
|
335
|
+
/** Actions that can be performed on the Exponent CLMM (Concentrated Liquidity Market Maker). */
|
|
336
|
+
export enum ClmmAction {
|
|
337
|
+
/** Create a new LP position with a specified tick range. Generates keypair internally. */
|
|
338
|
+
DEPOSIT_LIQUIDITY = "CLMM_DEPOSIT_LIQUIDITY",
|
|
339
|
+
/** Add more liquidity to an existing LP position. */
|
|
340
|
+
ADD_LIQUIDITY = "CLMM_ADD_LIQUIDITY",
|
|
341
|
+
/** Remove liquidity from an LP position and receive PT + SY. */
|
|
342
|
+
WITHDRAW_LIQUIDITY = "CLMM_WITHDRAW_LIQUIDITY",
|
|
343
|
+
/** Low-level PT/SY swap. Prefer buyPt/sellPt for directional trades. */
|
|
344
|
+
TRADE_PT = "CLMM_TRADE_PT",
|
|
345
|
+
/** Buy PT with SY on the CLMM. */
|
|
346
|
+
BUY_PT = "CLMM_BUY_PT",
|
|
347
|
+
/** Sell PT for SY on the CLMM. */
|
|
348
|
+
SELL_PT = "CLMM_SELL_PT",
|
|
349
|
+
/** Buy YT with SY on the CLMM. */
|
|
350
|
+
BUY_YT = "CLMM_BUY_YT",
|
|
351
|
+
/** Sell YT for SY on the CLMM. */
|
|
352
|
+
SELL_YT = "CLMM_SELL_YT",
|
|
353
|
+
/** Claim farm emissions from an LP position. */
|
|
354
|
+
CLAIM_FARM_EMISSION = "CLMM_CLAIM_FARM_EMISSION",
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** Base type for all CLMM instructions. */
|
|
358
|
+
interface ClmmInstructionBase {
|
|
359
|
+
action: ClmmAction
|
|
360
|
+
/** The CLMM MarketThree account address. */
|
|
361
|
+
market: PublicKey
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Create a new LP position on the CLMM. The lpPosition keypair is generated internally for good UX. */
|
|
365
|
+
export interface ClmmDepositLiquidityInstruction extends ClmmInstructionBase {
|
|
366
|
+
action: ClmmAction.DEPOSIT_LIQUIDITY
|
|
367
|
+
/** Maximum amount of PT to deposit. */
|
|
368
|
+
ptInIntent: bigint
|
|
369
|
+
/** Maximum amount of SY to deposit. */
|
|
370
|
+
syInIntent: bigint
|
|
371
|
+
/** Lower tick boundary (APY value). */
|
|
372
|
+
lowerTickKey: number
|
|
373
|
+
/** Upper tick boundary (APY value). */
|
|
374
|
+
upperTickKey: number
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/** Add liquidity to an existing LP position. */
|
|
378
|
+
export interface ClmmAddLiquidityInstruction extends ClmmInstructionBase {
|
|
379
|
+
action: ClmmAction.ADD_LIQUIDITY
|
|
380
|
+
/** The existing LpPosition account public key. */
|
|
381
|
+
lpPosition: PublicKey
|
|
382
|
+
/** Maximum amount of PT to add. */
|
|
383
|
+
ptInIntent: bigint
|
|
384
|
+
/** Maximum amount of SY to add. */
|
|
385
|
+
syInIntent: bigint
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/** Withdraw liquidity from an LP position. */
|
|
389
|
+
export interface ClmmWithdrawLiquidityInstruction extends ClmmInstructionBase {
|
|
390
|
+
action: ClmmAction.WITHDRAW_LIQUIDITY
|
|
391
|
+
/** The LpPosition account to withdraw from. */
|
|
392
|
+
lpPosition: PublicKey
|
|
393
|
+
/** Amount of liquidity (LP units) to remove. */
|
|
394
|
+
lpIn: bigint
|
|
395
|
+
/** Minimum PT to receive (slippage protection). */
|
|
396
|
+
minPtOut: bigint
|
|
397
|
+
/** Minimum SY to receive (slippage protection). */
|
|
398
|
+
minSyOut: bigint
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** Low-level PT/SY swap on the CLMM. Prefer buyPt/sellPt for directional trades. */
|
|
402
|
+
export interface ClmmTradePtInstruction extends ClmmInstructionBase {
|
|
403
|
+
action: ClmmAction.TRADE_PT
|
|
404
|
+
/** Amount of the input token. */
|
|
405
|
+
traderAmount: bigint
|
|
406
|
+
/** Minimum output amount (slippage protection). */
|
|
407
|
+
outConstraint: bigint
|
|
408
|
+
/** Swap direction: SyToPt or PtToSy. */
|
|
409
|
+
swapDirection: SwapDirection
|
|
410
|
+
/** Optional price limit (ln implied APY). */
|
|
411
|
+
lnImpliedApyLimit?: number
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** Buy PT with SY on the CLMM. */
|
|
415
|
+
export interface ClmmBuyPtInstruction extends ClmmInstructionBase {
|
|
416
|
+
action: ClmmAction.BUY_PT
|
|
417
|
+
/** Amount of SY to spend. */
|
|
418
|
+
amountSy: bigint
|
|
419
|
+
/** Minimum PT to receive (slippage protection). */
|
|
420
|
+
outConstraint: bigint
|
|
421
|
+
/** Optional price limit (ln implied APY). */
|
|
422
|
+
lnImpliedApyLimit?: number
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** Sell PT for SY on the CLMM. */
|
|
426
|
+
export interface ClmmSellPtInstruction extends ClmmInstructionBase {
|
|
427
|
+
action: ClmmAction.SELL_PT
|
|
428
|
+
/** Amount of PT to sell. */
|
|
429
|
+
amountPt: bigint
|
|
430
|
+
/** Minimum SY to receive (slippage protection). */
|
|
431
|
+
outConstraint: bigint
|
|
432
|
+
/** Optional price limit (ln implied APY). */
|
|
433
|
+
lnImpliedApyLimit?: number
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** Buy YT with SY on the CLMM. */
|
|
437
|
+
export interface ClmmBuyYtInstruction extends ClmmInstructionBase {
|
|
438
|
+
action: ClmmAction.BUY_YT
|
|
439
|
+
/** Minimum amount of YT to receive. */
|
|
440
|
+
ytOut: bigint
|
|
441
|
+
/** Maximum amount of SY to spend. */
|
|
442
|
+
maxSyIn: bigint
|
|
443
|
+
/** Optional price limit (ln implied APY). */
|
|
444
|
+
lnImpliedApyLimit?: number
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Sell YT for SY on the CLMM. */
|
|
448
|
+
export interface ClmmSellYtInstruction extends ClmmInstructionBase {
|
|
449
|
+
action: ClmmAction.SELL_YT
|
|
450
|
+
/** Amount of YT to sell. */
|
|
451
|
+
ytIn: bigint
|
|
452
|
+
/** Minimum SY to receive (slippage protection). */
|
|
453
|
+
minSyOut: bigint
|
|
454
|
+
/** Optional price limit (ln implied APY). */
|
|
455
|
+
lnImpliedApyLimit?: number
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/** Claim farm emissions from an LP position. */
|
|
459
|
+
export interface ClmmClaimFarmEmissionInstruction extends ClmmInstructionBase {
|
|
460
|
+
action: ClmmAction.CLAIM_FARM_EMISSION
|
|
461
|
+
/** The LpPosition account to claim from. */
|
|
462
|
+
lpPosition: PublicKey
|
|
463
|
+
/** Index of the farm to claim from. */
|
|
464
|
+
farmIndex: number
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** A single CLMM instruction. */
|
|
468
|
+
export type ClmmInstruction =
|
|
469
|
+
| ClmmDepositLiquidityInstruction
|
|
470
|
+
| ClmmAddLiquidityInstruction
|
|
471
|
+
| ClmmWithdrawLiquidityInstruction
|
|
472
|
+
| ClmmTradePtInstruction
|
|
473
|
+
| ClmmBuyPtInstruction
|
|
474
|
+
| ClmmSellPtInstruction
|
|
475
|
+
| ClmmBuyYtInstruction
|
|
476
|
+
| ClmmSellYtInstruction
|
|
477
|
+
| ClmmClaimFarmEmissionInstruction
|
|
478
|
+
|
|
479
|
+
/** A single vault instruction — pass an array of these to `createVaultSyncTransaction`. */
|
|
480
|
+
export type VaultInstruction =
|
|
481
|
+
| MarketInstruction
|
|
482
|
+
| ReserveInstruction
|
|
483
|
+
| KaminoVaultInstruction
|
|
484
|
+
| KaminoFarmInstruction
|
|
485
|
+
| OrderbookInstruction
|
|
486
|
+
| CoreInstruction
|
|
487
|
+
| SyInstruction
|
|
488
|
+
| TitanSwapInstruction
|
|
489
|
+
| ClmmInstruction
|
|
490
|
+
| LoopscaleInstruction
|
|
491
|
+
|
|
492
|
+
// Re-export KaminoReserves for use in action builders
|
|
493
|
+
export type { KaminoReserves }
|
|
@@ -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
|
+
})
|