@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
|
@@ -31,12 +31,10 @@ import {
|
|
|
31
31
|
ExponentPrices,
|
|
32
32
|
ExponentVault as ExponentVaultAccountType,
|
|
33
33
|
ExponentVault as ExponentVaultType,
|
|
34
|
-
ExponentVaultsFetcher,
|
|
35
34
|
OrderbookEntry,
|
|
36
35
|
PriceId,
|
|
37
36
|
TokenAccountEntry,
|
|
38
37
|
TokenEntry,
|
|
39
|
-
transformAnchorData,
|
|
40
38
|
} from "@exponent-labs/exponent-vaults-fetcher"
|
|
41
39
|
import { PROGRAM_ID as EXPONENT_VAULTS_PROGRAM_ID } from "@exponent-labs/exponent-vaults-idl"
|
|
42
40
|
import { ExponentVaultsPDA, SeedId, SquadsPDA } from "@exponent-labs/exponent-vaults-pda"
|
|
@@ -44,9 +42,13 @@ import { ExponentVaultsPDA, SeedId, SquadsPDA } from "@exponent-labs/exponent-va
|
|
|
44
42
|
import { fetchAllMaybeMarketThreeAccounts } from "../client/clmm/accounts/marketThree"
|
|
45
43
|
import * as exponentVaults from "../client/vaults"
|
|
46
44
|
import { Environment, LOCAL_ENV } from "../environment"
|
|
47
|
-
import { emitEventAuthority } from "../utils"
|
|
45
|
+
import { emitEventAuthority, uniqueRemainingAccounts } from "../utils"
|
|
48
46
|
import { AumCalculator } from "./aumCalculator"
|
|
47
|
+
import { deserializeExponentStrategyVaultFetcherShape, ExponentVaultsFetcher } from "./fetcher"
|
|
48
|
+
import { getKaminoFarmScopePricesAddress, decodeKaminoFarmState } from "./kamino-farms"
|
|
49
|
+
import { extractPriceIds } from "./pricePathResolver"
|
|
49
50
|
import { SquadsVaultTxnResolver } from "./squadsVaultTxnResolver"
|
|
51
|
+
import { getKaminoFarmsObligationFarm } from "./../../../kamino-lend-standard/src/constants"
|
|
50
52
|
|
|
51
53
|
type Numeric = bigint | number
|
|
52
54
|
|
|
@@ -54,6 +56,8 @@ export const SYNTHETIC_USD_MINT = new PublicKey("USD1111111111111111111111111111
|
|
|
54
56
|
export const SYNTHETIC_USD_DECIMALS = 6
|
|
55
57
|
export const SYNTHETIC_USD9_MINT = new PublicKey("USD1111111111111111111111111111111111111119")
|
|
56
58
|
export const SYNTHETIC_USD9_DECIMALS = 9
|
|
59
|
+
const LOCAL_UPDATE_PRICE_DISCRIMINATOR = Buffer.from([7])
|
|
60
|
+
const KAMINO_FARMS_PROGRAM_ID = new PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr")
|
|
57
61
|
|
|
58
62
|
export const getSyntheticMintDecimals = (mint: PublicKey): number | null => {
|
|
59
63
|
if (mint.equals(SYNTHETIC_USD_MINT)) return SYNTHETIC_USD_DECIMALS
|
|
@@ -61,6 +65,103 @@ export const getSyntheticMintDecimals = (mint: PublicKey): number | null => {
|
|
|
61
65
|
return null
|
|
62
66
|
}
|
|
63
67
|
|
|
68
|
+
function unwrapTupleLikeValue(value: unknown): unknown {
|
|
69
|
+
if (Array.isArray(value)) {
|
|
70
|
+
return value[0]
|
|
71
|
+
}
|
|
72
|
+
if (value && typeof value === "object" && "0" in value) {
|
|
73
|
+
return (value as { 0?: unknown })[0]
|
|
74
|
+
}
|
|
75
|
+
return value ?? undefined
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function addTrackedPriceIds(target: Set<number>, priceIdValue: unknown) {
|
|
79
|
+
for (const id of extractPriceIds(priceIdValue)) {
|
|
80
|
+
const numericId = Number(id)
|
|
81
|
+
if (numericId !== 0) {
|
|
82
|
+
target.add(numericId)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function collectTrackedStrategyVaultPriceIds(state: {
|
|
88
|
+
tokenEntries: Array<{ priceId: unknown }>
|
|
89
|
+
strategyPositions: Array<Record<string, unknown>>
|
|
90
|
+
}): Set<number> {
|
|
91
|
+
const allPriceIds = new Set<number>()
|
|
92
|
+
|
|
93
|
+
for (const entry of state.tokenEntries) {
|
|
94
|
+
addTrackedPriceIds(allPriceIds, entry.priceId)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const position of state.strategyPositions) {
|
|
98
|
+
if ("orderbook" in position) {
|
|
99
|
+
const orderbook = unwrapTupleLikeValue(position.orderbook) as { priceIdPt?: unknown } | undefined
|
|
100
|
+
if (orderbook?.priceIdPt) {
|
|
101
|
+
addTrackedPriceIds(allPriceIds, orderbook.priceIdPt)
|
|
102
|
+
}
|
|
103
|
+
continue
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if ("tokenAccount" in position) {
|
|
107
|
+
const tokenAccount = unwrapTupleLikeValue(position.tokenAccount) as {
|
|
108
|
+
balances?: Array<{ priceId?: unknown }>
|
|
109
|
+
} | undefined
|
|
110
|
+
for (const balance of tokenAccount?.balances ?? []) {
|
|
111
|
+
if (balance.priceId) {
|
|
112
|
+
addTrackedPriceIds(allPriceIds, balance.priceId)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if ("yieldPosition" in position) {
|
|
119
|
+
const yieldPosition = unwrapTupleLikeValue(position.yieldPosition) as { priceIdPt?: unknown } | undefined
|
|
120
|
+
if (yieldPosition?.priceIdPt) {
|
|
121
|
+
addTrackedPriceIds(allPriceIds, yieldPosition.priceIdPt)
|
|
122
|
+
}
|
|
123
|
+
continue
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if ("clmmPosition" in position) {
|
|
127
|
+
const clmmPosition = unwrapTupleLikeValue(position.clmmPosition) as {
|
|
128
|
+
priceIdPt?: unknown
|
|
129
|
+
priceIdSy?: unknown
|
|
130
|
+
} | undefined
|
|
131
|
+
if (clmmPosition?.priceIdPt) {
|
|
132
|
+
addTrackedPriceIds(allPriceIds, clmmPosition.priceIdPt)
|
|
133
|
+
}
|
|
134
|
+
if (clmmPosition?.priceIdSy) {
|
|
135
|
+
addTrackedPriceIds(allPriceIds, clmmPosition.priceIdSy)
|
|
136
|
+
}
|
|
137
|
+
continue
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if ("obligation" in position) {
|
|
141
|
+
const rawObligation = position.obligation as Record<string, unknown> | Array<unknown>
|
|
142
|
+
const inner = unwrapTupleLikeValue(rawObligation as unknown[] | { 0?: unknown })
|
|
143
|
+
const kaminoVariant =
|
|
144
|
+
inner && typeof inner === "object" && "kaminoObligation" in inner
|
|
145
|
+
? (inner as { kaminoObligation?: unknown }).kaminoObligation
|
|
146
|
+
: inner
|
|
147
|
+
const kaminoEntry = unwrapTupleLikeValue(kaminoVariant) as {
|
|
148
|
+
quotePriceId?: unknown
|
|
149
|
+
reservePriceMappings?: Array<{ reservePriceId?: unknown }>
|
|
150
|
+
} | undefined
|
|
151
|
+
if (kaminoEntry?.quotePriceId) {
|
|
152
|
+
addTrackedPriceIds(allPriceIds, kaminoEntry.quotePriceId)
|
|
153
|
+
}
|
|
154
|
+
for (const mapping of kaminoEntry?.reservePriceMappings ?? []) {
|
|
155
|
+
if (mapping.reservePriceId) {
|
|
156
|
+
addTrackedPriceIds(allPriceIds, mapping.reservePriceId)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return allPriceIds
|
|
163
|
+
}
|
|
164
|
+
|
|
64
165
|
const getMintDecimals = async (connection: Connection, mint: PublicKey): Promise<number> => {
|
|
65
166
|
const syntheticDecimals = getSyntheticMintDecimals(mint)
|
|
66
167
|
if (syntheticDecimals !== null) {
|
|
@@ -76,6 +177,15 @@ const pushPriceMintAccount = (remainingAccounts: AccountMeta[], mint: PublicKey)
|
|
|
76
177
|
remainingAccounts.push({ pubkey: mint, isSigner: false, isWritable: false })
|
|
77
178
|
}
|
|
78
179
|
|
|
180
|
+
const isLocalRpcEndpoint = (rpcEndpoint: string): boolean => {
|
|
181
|
+
try {
|
|
182
|
+
const hostname = new URL(rpcEndpoint).hostname
|
|
183
|
+
return hostname === "127.0.0.1" || hostname === "localhost"
|
|
184
|
+
} catch {
|
|
185
|
+
return rpcEndpoint.includes("127.0.0.1") || rpcEndpoint.includes("localhost")
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
79
189
|
// ============================================================================
|
|
80
190
|
// Policy Types (matching on-chain structures)
|
|
81
191
|
// ============================================================================
|
|
@@ -403,6 +513,11 @@ export interface UpdatePriceParams {
|
|
|
403
513
|
priceId: number
|
|
404
514
|
}
|
|
405
515
|
|
|
516
|
+
export interface UpdateStrategyVaultPricesOptions {
|
|
517
|
+
manager?: PublicKey
|
|
518
|
+
priceIds?: Iterable<number>
|
|
519
|
+
}
|
|
520
|
+
|
|
406
521
|
export interface QueueWithdrawalParams {
|
|
407
522
|
depositor: PublicKey
|
|
408
523
|
lpAmount: Numeric
|
|
@@ -691,6 +806,29 @@ export interface WrapperManagerUpdatePositionParams {
|
|
|
691
806
|
systemProgram?: PublicKey
|
|
692
807
|
}
|
|
693
808
|
|
|
809
|
+
export interface WrapperAddKaminoObligationPositionParams {
|
|
810
|
+
manager: PublicKey
|
|
811
|
+
obligation: PublicKey
|
|
812
|
+
lendingProgramId: PublicKey
|
|
813
|
+
quotePriceId: exponentVaults.PriceId
|
|
814
|
+
reservePriceMappings: exponentVaults.ReservePriceMapping[]
|
|
815
|
+
reserveFarmMappings?: exponentVaults.ReserveFarmMapping[]
|
|
816
|
+
minPriceStatusFlags: number
|
|
817
|
+
remainingAccounts?: AccountMeta[]
|
|
818
|
+
exponentPrices?: PublicKey
|
|
819
|
+
systemProgram?: PublicKey
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
export interface WrapperUpsertKaminoObligationReservePriceMappingsParams {
|
|
823
|
+
manager: PublicKey
|
|
824
|
+
obligation: PublicKey
|
|
825
|
+
reservePriceMappings: exponentVaults.ReservePriceMapping[]
|
|
826
|
+
reserveFarmMappings?: exponentVaults.ReserveFarmMapping[]
|
|
827
|
+
remainingAccounts?: AccountMeta[]
|
|
828
|
+
exponentPrices?: PublicKey
|
|
829
|
+
systemProgram?: PublicKey
|
|
830
|
+
}
|
|
831
|
+
|
|
694
832
|
export type WrapperAddPolicyParams = AddPolicyParams
|
|
695
833
|
|
|
696
834
|
export type WrapperRemovePolicyParams = RemovePolicyParams
|
|
@@ -722,6 +860,8 @@ export class ExponentVault {
|
|
|
722
860
|
public pda: ExponentVaultsPDA
|
|
723
861
|
public aumCalculator: AumCalculator
|
|
724
862
|
private clmmTicksMap: Map<string, PublicKey> = new Map()
|
|
863
|
+
private kaminoFarmAuxAccountsMap: Map<string, AccountMeta[]> = new Map()
|
|
864
|
+
private kaminoObligationFarmUserStates: Set<string> = new Set()
|
|
725
865
|
static squadsVaultTxnResolver = new SquadsVaultTxnResolver()
|
|
726
866
|
|
|
727
867
|
constructor(params: {
|
|
@@ -755,7 +895,10 @@ export class ExponentVault {
|
|
|
755
895
|
connection: params.connection,
|
|
756
896
|
programId: fetcher.programId,
|
|
757
897
|
})
|
|
758
|
-
await
|
|
898
|
+
await Promise.all([
|
|
899
|
+
vault.populateClmmTicksCache(params.connection),
|
|
900
|
+
vault.populateKaminoFarmAuxAccountsCache(params.connection),
|
|
901
|
+
])
|
|
759
902
|
return vault
|
|
760
903
|
}
|
|
761
904
|
|
|
@@ -776,7 +919,12 @@ export class ExponentVault {
|
|
|
776
919
|
programId: fetcher.programId,
|
|
777
920
|
}),
|
|
778
921
|
)
|
|
779
|
-
await Promise.all(
|
|
922
|
+
await Promise.all(
|
|
923
|
+
results.flatMap((vault) => [
|
|
924
|
+
vault.populateClmmTicksCache(params.connection),
|
|
925
|
+
vault.populateKaminoFarmAuxAccountsCache(params.connection),
|
|
926
|
+
]),
|
|
927
|
+
)
|
|
780
928
|
return results
|
|
781
929
|
}
|
|
782
930
|
|
|
@@ -784,6 +932,8 @@ export class ExponentVault {
|
|
|
784
932
|
const refreshed = await ExponentVault.load({ env: this.env, connection, address: this.selfAddress })
|
|
785
933
|
this.state = refreshed.state
|
|
786
934
|
this.clmmTicksMap = refreshed.clmmTicksMap
|
|
935
|
+
this.kaminoFarmAuxAccountsMap = refreshed.kaminoFarmAuxAccountsMap
|
|
936
|
+
this.kaminoObligationFarmUserStates = refreshed.kaminoObligationFarmUserStates
|
|
787
937
|
this.connection = connection
|
|
788
938
|
this.aumCalculator = new AumCalculator(this.state, this.connection, this.env)
|
|
789
939
|
return refreshed
|
|
@@ -810,6 +960,128 @@ export class ExponentVault {
|
|
|
810
960
|
}
|
|
811
961
|
}
|
|
812
962
|
|
|
963
|
+
private async populateKaminoFarmAuxAccountsCache(connection: Connection): Promise<void> {
|
|
964
|
+
this.kaminoFarmAuxAccountsMap.clear()
|
|
965
|
+
this.kaminoObligationFarmUserStates.clear()
|
|
966
|
+
|
|
967
|
+
const farmStates: PublicKey[] = []
|
|
968
|
+
const delegatedFarmUsers: Array<{ obligation: PublicKey; farmState: PublicKey; userState: PublicKey }> = []
|
|
969
|
+
for (const pos of this.state.strategyPositions) {
|
|
970
|
+
if ("kaminoFarm" in pos && pos.kaminoFarm && typeof pos.kaminoFarm === "object") {
|
|
971
|
+
const entry = (pos as { kaminoFarm: { 0: { farmState: PublicKey } } }).kaminoFarm[0]
|
|
972
|
+
if (!farmStates.some((farmState) => farmState.equals(entry.farmState))) {
|
|
973
|
+
farmStates.push(entry.farmState)
|
|
974
|
+
}
|
|
975
|
+
continue
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
if (!("obligation" in pos) || !pos.obligation || typeof pos.obligation !== "object") {
|
|
979
|
+
continue
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
const rawObligation = pos["obligation"] as Record<string, unknown> | Array<unknown>
|
|
983
|
+
const inner = Array.isArray(rawObligation)
|
|
984
|
+
? (rawObligation[0] as Record<string, unknown> | undefined)
|
|
985
|
+
: rawObligation && typeof rawObligation === "object" && "0" in rawObligation
|
|
986
|
+
? (rawObligation[0] as Record<string, unknown> | undefined)
|
|
987
|
+
: (rawObligation as Record<string, unknown> | undefined)
|
|
988
|
+
const kaminoVariant = inner && "kaminoObligation" in inner ? (inner.kaminoObligation as unknown) : inner
|
|
989
|
+
const entry = Array.isArray(kaminoVariant)
|
|
990
|
+
? (kaminoVariant[0] as
|
|
991
|
+
| {
|
|
992
|
+
obligation?: PublicKey
|
|
993
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
994
|
+
}
|
|
995
|
+
| undefined)
|
|
996
|
+
: kaminoVariant && typeof kaminoVariant === "object" && "0" in (kaminoVariant as Record<string, unknown>)
|
|
997
|
+
? ((
|
|
998
|
+
kaminoVariant as {
|
|
999
|
+
0?: {
|
|
1000
|
+
obligation?: PublicKey
|
|
1001
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
)[0] ?? undefined)
|
|
1005
|
+
: (kaminoVariant as
|
|
1006
|
+
| {
|
|
1007
|
+
obligation?: PublicKey
|
|
1008
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
1009
|
+
}
|
|
1010
|
+
| undefined)
|
|
1011
|
+
if (!(entry?.obligation instanceof PublicKey)) {
|
|
1012
|
+
continue
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
for (const mapping of entry.reserveFarmMappings ?? []) {
|
|
1016
|
+
if (!farmStates.some((farmState) => farmState.equals(mapping.farmState))) {
|
|
1017
|
+
farmStates.push(mapping.farmState)
|
|
1018
|
+
}
|
|
1019
|
+
delegatedFarmUsers.push({
|
|
1020
|
+
obligation: entry.obligation,
|
|
1021
|
+
farmState: mapping.farmState,
|
|
1022
|
+
userState: getKaminoFarmsObligationFarm(entry.obligation, mapping.farmState, KAMINO_FARMS_PROGRAM_ID),
|
|
1023
|
+
})
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
if (farmStates.length === 0) {
|
|
1028
|
+
return
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
const farmInfos = await connection.getMultipleAccountsInfo(farmStates)
|
|
1032
|
+
for (const [index, farmInfo] of farmInfos.entries()) {
|
|
1033
|
+
const farmState = farmStates[index]
|
|
1034
|
+
if (!farmState || !farmInfo?.data) {
|
|
1035
|
+
if (ExponentVault.debugAum && farmState) {
|
|
1036
|
+
console.log("[VAULT_AUM] kaminoFarmAux: missing farm info", farmState.toBase58())
|
|
1037
|
+
}
|
|
1038
|
+
continue
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
const farm = decodeKaminoFarmState(Buffer.from(farmInfo.data))
|
|
1042
|
+
const auxAccounts: AccountMeta[] = [{ pubkey: farm.globalConfig, isSigner: false, isWritable: false }]
|
|
1043
|
+
const scopePrices = getKaminoFarmScopePricesAddress(farm)
|
|
1044
|
+
if (scopePrices) {
|
|
1045
|
+
auxAccounts.push({ pubkey: scopePrices, isSigner: false, isWritable: false })
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
this.kaminoFarmAuxAccountsMap.set(farmState.toBase58(), auxAccounts)
|
|
1049
|
+
if (ExponentVault.debugAum) {
|
|
1050
|
+
console.log(
|
|
1051
|
+
"[VAULT_AUM] kaminoFarmAux:",
|
|
1052
|
+
farmState.toBase58(),
|
|
1053
|
+
auxAccounts.map((account) => account.pubkey.toBase58()).join(", "),
|
|
1054
|
+
)
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
if (delegatedFarmUsers.length === 0) {
|
|
1059
|
+
return
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
const uniqueUsers = Array.from(
|
|
1063
|
+
new Map(
|
|
1064
|
+
delegatedFarmUsers.map((entry) => [
|
|
1065
|
+
`${entry.obligation.toBase58()}:${entry.farmState.toBase58()}`,
|
|
1066
|
+
entry,
|
|
1067
|
+
]),
|
|
1068
|
+
).values(),
|
|
1069
|
+
)
|
|
1070
|
+
const userInfos = await connection.getMultipleAccountsInfo(uniqueUsers.map((entry) => entry.userState))
|
|
1071
|
+
for (const [index, userInfo] of userInfos.entries()) {
|
|
1072
|
+
if (!userInfo?.data) {
|
|
1073
|
+
continue
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
const entry = uniqueUsers[index]
|
|
1077
|
+
if (!entry) {
|
|
1078
|
+
continue
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
this.kaminoObligationFarmUserStates.add(`${entry.obligation.toBase58()}:${entry.farmState.toBase58()}`)
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
|
|
813
1085
|
/**
|
|
814
1086
|
* Derive the PDA for a vault using its 8-byte seed identifier.
|
|
815
1087
|
*/
|
|
@@ -898,13 +1170,19 @@ export class ExponentVault {
|
|
|
898
1170
|
}
|
|
899
1171
|
}
|
|
900
1172
|
} else if ("obligation" in pos && pos.obligation && typeof pos.obligation === "object") {
|
|
901
|
-
const
|
|
1173
|
+
const rawObligation = pos["obligation"] as Record<string, unknown> | Array<unknown>
|
|
1174
|
+
const inner = Array.isArray(rawObligation)
|
|
1175
|
+
? (rawObligation[0] as Record<string, unknown> | undefined)
|
|
1176
|
+
: rawObligation && typeof rawObligation === "object" && "0" in rawObligation
|
|
1177
|
+
? (rawObligation[0] as Record<string, unknown> | undefined)
|
|
1178
|
+
: (rawObligation as Record<string, unknown> | undefined)
|
|
902
1179
|
const kaminoVariant = inner && "kaminoObligation" in inner ? (inner.kaminoObligation as unknown) : inner
|
|
903
1180
|
const entry = Array.isArray(kaminoVariant)
|
|
904
1181
|
? (kaminoVariant[0] as
|
|
905
1182
|
| {
|
|
906
1183
|
obligation?: PublicKey
|
|
907
1184
|
reservePriceMappings?: Array<{ reserve: PublicKey }>
|
|
1185
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
908
1186
|
}
|
|
909
1187
|
| undefined)
|
|
910
1188
|
: kaminoVariant && typeof kaminoVariant === "object" && "0" in (kaminoVariant as Record<string, unknown>)
|
|
@@ -913,6 +1191,7 @@ export class ExponentVault {
|
|
|
913
1191
|
0?: {
|
|
914
1192
|
obligation?: PublicKey
|
|
915
1193
|
reservePriceMappings?: Array<{ reserve: PublicKey }>
|
|
1194
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
916
1195
|
}
|
|
917
1196
|
}
|
|
918
1197
|
)[0] ?? undefined)
|
|
@@ -920,6 +1199,7 @@ export class ExponentVault {
|
|
|
920
1199
|
| {
|
|
921
1200
|
obligation?: PublicKey
|
|
922
1201
|
reservePriceMappings?: Array<{ reserve: PublicKey }>
|
|
1202
|
+
reserveFarmMappings?: Array<{ farmState: PublicKey }>
|
|
923
1203
|
}
|
|
924
1204
|
| undefined)
|
|
925
1205
|
if (entry?.obligation instanceof PublicKey) {
|
|
@@ -935,11 +1215,30 @@ export class ExponentVault {
|
|
|
935
1215
|
isWritable: false,
|
|
936
1216
|
})
|
|
937
1217
|
}
|
|
1218
|
+
for (const mapping of entry.reserveFarmMappings ?? []) {
|
|
1219
|
+
metas.push({
|
|
1220
|
+
pubkey: mapping.farmState,
|
|
1221
|
+
isSigner: false,
|
|
1222
|
+
isWritable: false,
|
|
1223
|
+
})
|
|
1224
|
+
const obligationFarmUserKey = `${entry.obligation.toBase58()}:${mapping.farmState.toBase58()}`
|
|
1225
|
+
if (this.kaminoObligationFarmUserStates.has(obligationFarmUserKey)) {
|
|
1226
|
+
metas.push({
|
|
1227
|
+
pubkey: getKaminoFarmsObligationFarm(entry.obligation, mapping.farmState, KAMINO_FARMS_PROGRAM_ID),
|
|
1228
|
+
isSigner: false,
|
|
1229
|
+
isWritable: false,
|
|
1230
|
+
})
|
|
1231
|
+
}
|
|
1232
|
+
metas.push(...(this.kaminoFarmAuxAccountsMap.get(mapping.farmState.toBase58()) ?? []))
|
|
1233
|
+
}
|
|
938
1234
|
if (ExponentVault.debugAum) {
|
|
939
1235
|
console.log("[VAULT_AUM] strategyPosition: Obligation", entry.obligation.toBase58())
|
|
940
1236
|
for (const mapping of entry.reservePriceMappings ?? []) {
|
|
941
1237
|
console.log("[VAULT_AUM] strategyPosition: Kamino reserve", mapping.reserve.toBase58())
|
|
942
1238
|
}
|
|
1239
|
+
for (const mapping of entry.reserveFarmMappings ?? []) {
|
|
1240
|
+
console.log("[VAULT_AUM] strategyPosition: Kamino delegated farm", mapping.farmState.toBase58())
|
|
1241
|
+
}
|
|
943
1242
|
}
|
|
944
1243
|
}
|
|
945
1244
|
} else if ("yieldPosition" in pos && pos.yieldPosition && typeof pos.yieldPosition === "object") {
|
|
@@ -990,6 +1289,31 @@ export class ExponentVault {
|
|
|
990
1289
|
ticksKey ? ticksKey.toBase58() : "(ticks not cached)",
|
|
991
1290
|
)
|
|
992
1291
|
}
|
|
1292
|
+
} else if ("kaminoFarm" in pos && pos.kaminoFarm && typeof pos.kaminoFarm === "object") {
|
|
1293
|
+
const entry = (pos as { kaminoFarm: { 0: { farmState: PublicKey; userState: PublicKey } } }).kaminoFarm[0]
|
|
1294
|
+
metas.push({
|
|
1295
|
+
pubkey: entry.farmState,
|
|
1296
|
+
isSigner: false,
|
|
1297
|
+
isWritable: false,
|
|
1298
|
+
})
|
|
1299
|
+
metas.push({
|
|
1300
|
+
pubkey: entry.userState,
|
|
1301
|
+
isSigner: false,
|
|
1302
|
+
isWritable: false,
|
|
1303
|
+
})
|
|
1304
|
+
const auxAccounts = this.kaminoFarmAuxAccountsMap.get(entry.farmState.toBase58()) ?? []
|
|
1305
|
+
metas.push(...auxAccounts)
|
|
1306
|
+
if (ExponentVault.debugAum) {
|
|
1307
|
+
console.log(
|
|
1308
|
+
"[VAULT_AUM] strategyPosition: KaminoFarm",
|
|
1309
|
+
entry.farmState.toBase58(),
|
|
1310
|
+
entry.userState.toBase58(),
|
|
1311
|
+
)
|
|
1312
|
+
console.log(
|
|
1313
|
+
"[VAULT_AUM] strategyPosition: KaminoFarm aux",
|
|
1314
|
+
auxAccounts.map((account) => account.pubkey.toBase58()).join(", ") || "(none)",
|
|
1315
|
+
)
|
|
1316
|
+
}
|
|
993
1317
|
} else if ("loopscaleStrategy" in pos && pos.loopscaleStrategy && typeof pos.loopscaleStrategy === "object") {
|
|
994
1318
|
const entry = (pos as any).loopscaleStrategy[0]
|
|
995
1319
|
if (entry?.strategy instanceof PublicKey) {
|
|
@@ -1044,6 +1368,59 @@ export class ExponentVault {
|
|
|
1044
1368
|
return [...this.tokenEntryAccountMetas(), ...this.strategyPositionAccountMetas()]
|
|
1045
1369
|
}
|
|
1046
1370
|
|
|
1371
|
+
/**
|
|
1372
|
+
* Returns the readonly account metas required to recalculate the vault's current tracked AUM.
|
|
1373
|
+
* Extra metas can be appended for pending positions or newly introduced Kamino reserves.
|
|
1374
|
+
*/
|
|
1375
|
+
getAumRemainingAccountMetas(extraRemainingAccounts: AccountMeta[] = []): AccountMeta[] {
|
|
1376
|
+
return uniqueRemainingAccounts([...this.aumRemainingAccounts(), ...extraRemainingAccounts])
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
private ixManagePriceUpdates({
|
|
1380
|
+
manager,
|
|
1381
|
+
updates,
|
|
1382
|
+
}: {
|
|
1383
|
+
manager?: PublicKey
|
|
1384
|
+
updates: Array<{
|
|
1385
|
+
priceId: number
|
|
1386
|
+
priceType: exponentVaults.PriceType
|
|
1387
|
+
priceInterfaceAccounts?: PublicKey
|
|
1388
|
+
}>
|
|
1389
|
+
}): TransactionInstruction {
|
|
1390
|
+
if (updates.length === 0) {
|
|
1391
|
+
throw new Error("ixManagePriceUpdates requires at least one update")
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
const resolvedManager = manager ?? this.state.roles.manager[0]
|
|
1395
|
+
if (!resolvedManager) {
|
|
1396
|
+
throw new Error("Vault manager not found")
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
const [exponentPrices] = this.pda.exponentPrices()
|
|
1400
|
+
const remainingAccounts: AccountMeta[] = []
|
|
1401
|
+
const actions: exponentVaults.UpdatePriceAction[] = updates.map((update) => {
|
|
1402
|
+
if (!update.priceInterfaceAccounts) {
|
|
1403
|
+
throw new Error(`priceInterfaceAccounts required for priceId ${update.priceId}`)
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
remainingAccounts.push({ pubkey: update.priceInterfaceAccounts, isSigner: false, isWritable: false })
|
|
1407
|
+
|
|
1408
|
+
return {
|
|
1409
|
+
__kind: "UpdatePrice",
|
|
1410
|
+
priceId: BigInt(update.priceId),
|
|
1411
|
+
priceType: update.priceType,
|
|
1412
|
+
}
|
|
1413
|
+
})
|
|
1414
|
+
|
|
1415
|
+
const ix = exponentVaults.createManagePricesInstruction(
|
|
1416
|
+
{ manager: resolvedManager, exponentPrices, systemProgram: SystemProgram.programId },
|
|
1417
|
+
{ actions },
|
|
1418
|
+
this.programId,
|
|
1419
|
+
)
|
|
1420
|
+
ix.keys.push(...remainingAccounts)
|
|
1421
|
+
return ix
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1047
1424
|
ixUpdatePrice({
|
|
1048
1425
|
priceInterfaceAccounts,
|
|
1049
1426
|
pythPriceFeedId,
|
|
@@ -1062,8 +1439,12 @@ export class ExponentVault {
|
|
|
1062
1439
|
const ix = exponentVaults.createUpdatePriceInstruction(
|
|
1063
1440
|
{ exponentPrices },
|
|
1064
1441
|
{ updates: [{ priceId: BigInt(priceId), interfaceAccountsIndex: 0 }] },
|
|
1442
|
+
this.programId,
|
|
1065
1443
|
)
|
|
1066
1444
|
ix.keys.push(...updateRemainingAccounts)
|
|
1445
|
+
if (isLocalRpcEndpoint(this.connection.rpcEndpoint)) {
|
|
1446
|
+
ix.data = Buffer.concat([LOCAL_UPDATE_PRICE_DISCRIMINATOR, ix.data.subarray(1)])
|
|
1447
|
+
}
|
|
1067
1448
|
return ix
|
|
1068
1449
|
}
|
|
1069
1450
|
|
|
@@ -1084,6 +1465,7 @@ export class ExponentVault {
|
|
|
1084
1465
|
const vault = entryTokenVault ?? entry.tokenSquadsAccount
|
|
1085
1466
|
const lpDst = tokenLpDst ?? defaultTokenAccount(this.state.mintLp, depositor, tokenProgram)
|
|
1086
1467
|
const exponentPrices = this.pda.exponentPrices()[0]
|
|
1468
|
+
const tokenProgramLp = useLegacyTokenAccounts ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID
|
|
1087
1469
|
|
|
1088
1470
|
const preIxs: TransactionInstruction[] = []
|
|
1089
1471
|
|
|
@@ -1139,7 +1521,7 @@ export class ExponentVault {
|
|
|
1139
1521
|
tokenLpDst: lpDst,
|
|
1140
1522
|
mintLp: this.state.mintLp,
|
|
1141
1523
|
tokenProgram,
|
|
1142
|
-
tokenProgramLp
|
|
1524
|
+
tokenProgramLp,
|
|
1143
1525
|
eventAuthority: this.eventAuthority,
|
|
1144
1526
|
program: this.programId,
|
|
1145
1527
|
},
|
|
@@ -1444,6 +1826,66 @@ export class ExponentVault {
|
|
|
1444
1826
|
return ix
|
|
1445
1827
|
}
|
|
1446
1828
|
|
|
1829
|
+
/**
|
|
1830
|
+
* Convenience wrapper for adding a tracked Kamino obligation position.
|
|
1831
|
+
*/
|
|
1832
|
+
ixWrapperAddKaminoObligationPosition({
|
|
1833
|
+
manager,
|
|
1834
|
+
obligation,
|
|
1835
|
+
lendingProgramId,
|
|
1836
|
+
quotePriceId,
|
|
1837
|
+
reservePriceMappings,
|
|
1838
|
+
reserveFarmMappings = [],
|
|
1839
|
+
minPriceStatusFlags,
|
|
1840
|
+
remainingAccounts = [],
|
|
1841
|
+
exponentPrices = this.pda.exponentPrices()[0],
|
|
1842
|
+
systemProgram = SystemProgram.programId,
|
|
1843
|
+
}: WrapperAddKaminoObligationPositionParams): TransactionInstruction {
|
|
1844
|
+
const obligationEntry: exponentVaults.KaminoObligationEntry = {
|
|
1845
|
+
obligation,
|
|
1846
|
+
lendingProgramId,
|
|
1847
|
+
quotePriceId,
|
|
1848
|
+
reservePriceMappings,
|
|
1849
|
+
reserveFarmMappings,
|
|
1850
|
+
minPriceStatusFlags,
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
return this.ixWrapperManagerUpdatePosition({
|
|
1854
|
+
manager,
|
|
1855
|
+
exponentPrices,
|
|
1856
|
+
systemProgram,
|
|
1857
|
+
remainingAccounts: this.getAumRemainingAccountMetas(remainingAccounts),
|
|
1858
|
+
update: exponentVaults.positionUpdate("AddKaminoObligationEntry", [
|
|
1859
|
+
obligationEntry,
|
|
1860
|
+
] as [exponentVaults.KaminoObligationEntry]),
|
|
1861
|
+
})
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* Convenience wrapper for updating tracked reserve price mappings on a Kamino obligation.
|
|
1866
|
+
*/
|
|
1867
|
+
ixWrapperUpsertKaminoObligationReservePriceMappings({
|
|
1868
|
+
manager,
|
|
1869
|
+
obligation,
|
|
1870
|
+
reservePriceMappings,
|
|
1871
|
+
reserveFarmMappings = [],
|
|
1872
|
+
remainingAccounts = [],
|
|
1873
|
+
exponentPrices = this.pda.exponentPrices()[0],
|
|
1874
|
+
systemProgram = SystemProgram.programId,
|
|
1875
|
+
}: WrapperUpsertKaminoObligationReservePriceMappingsParams): TransactionInstruction {
|
|
1876
|
+
return this.ixWrapperManagerUpdatePosition({
|
|
1877
|
+
manager,
|
|
1878
|
+
exponentPrices,
|
|
1879
|
+
systemProgram,
|
|
1880
|
+
remainingAccounts: this.getAumRemainingAccountMetas(remainingAccounts),
|
|
1881
|
+
update: exponentVaults.positionUpdate("UpsertKaminoObligationReservePriceMappings", {
|
|
1882
|
+
obligation,
|
|
1883
|
+
reservePriceMappings,
|
|
1884
|
+
reserveFarmMappings,
|
|
1885
|
+
}),
|
|
1886
|
+
})
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1447
1889
|
// ==========================================================================
|
|
1448
1890
|
// Policy Management Methods
|
|
1449
1891
|
// ==========================================================================
|
|
@@ -2013,11 +2455,9 @@ export class ExponentVault {
|
|
|
2013
2455
|
throw new Error("Jito bundle simulation failed")
|
|
2014
2456
|
}
|
|
2015
2457
|
|
|
2016
|
-
const
|
|
2017
|
-
"exponentStrategyVault",
|
|
2458
|
+
const vaultStateAfterSimulations = deserializeExponentStrategyVaultFetcherShape(
|
|
2018
2459
|
Buffer.from(postVaultAccountData, "base64"),
|
|
2019
|
-
)
|
|
2020
|
-
const vaultStateAfterSimulations = transformAnchorData(decoded) as ExponentVaultType
|
|
2460
|
+
) as ExponentVaultType
|
|
2021
2461
|
const aum =
|
|
2022
2462
|
vaultStateAfterSimulations.financials.aumInBase + vaultStateAfterSimulations.financials.aumInBaseInPositions
|
|
2023
2463
|
|
|
@@ -2028,64 +2468,35 @@ export class ExponentVault {
|
|
|
2028
2468
|
}
|
|
2029
2469
|
}
|
|
2030
2470
|
|
|
2031
|
-
async ixsUpdateStrategyVaultPrices(
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2471
|
+
async ixsUpdateStrategyVaultPrices(
|
|
2472
|
+
pricesAccount: ExponentPrices,
|
|
2473
|
+
options: UpdateStrategyVaultPricesOptions = {},
|
|
2474
|
+
): Promise<TransactionInstruction[]> {
|
|
2475
|
+
const trackedPriceIds =
|
|
2476
|
+
options.priceIds ??
|
|
2477
|
+
collectTrackedStrategyVaultPriceIds({
|
|
2478
|
+
tokenEntries: this.state.tokenEntries,
|
|
2479
|
+
strategyPositions: this.state.strategyPositions,
|
|
2480
|
+
})
|
|
2040
2481
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2482
|
+
const priceIds = [...trackedPriceIds].sort((a, b) => a - b)
|
|
2483
|
+
if (priceIds.length === 0) {
|
|
2484
|
+
return []
|
|
2043
2485
|
}
|
|
2044
2486
|
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
const orderbook = position.orderbook[0]
|
|
2048
|
-
extractPriceIds(orderbook.priceIdPt).forEach((id) => allPriceIds.add(id))
|
|
2049
|
-
continue
|
|
2050
|
-
}
|
|
2051
|
-
|
|
2052
|
-
if ("tokenAccount" in position) {
|
|
2053
|
-
for (const balance of position.tokenAccount[0].balances) {
|
|
2054
|
-
extractPriceIds(balance.priceId).forEach((id) => allPriceIds.add(id))
|
|
2055
|
-
}
|
|
2056
|
-
continue
|
|
2057
|
-
}
|
|
2487
|
+
return priceIds.map((priceId) => {
|
|
2488
|
+
const priceEntry = pricesAccount.prices[priceId]
|
|
2058
2489
|
|
|
2059
|
-
if (
|
|
2060
|
-
|
|
2061
|
-
const kaminoEntry =
|
|
2062
|
-
inner && typeof inner === "object" && "kaminoObligation" in inner ? inner.kaminoObligation?.[0] : inner?.[0]
|
|
2063
|
-
if (kaminoEntry?.quotePriceId) {
|
|
2064
|
-
extractPriceIds(kaminoEntry.quotePriceId).forEach((id: number) => allPriceIds.add(id))
|
|
2065
|
-
}
|
|
2066
|
-
for (const mapping of kaminoEntry?.reservePriceMappings ?? []) {
|
|
2067
|
-
if (mapping.reservePriceId) {
|
|
2068
|
-
extractPriceIds(mapping.reservePriceId).forEach((id: number) => allPriceIds.add(id))
|
|
2069
|
-
}
|
|
2070
|
-
}
|
|
2490
|
+
if (!priceEntry) {
|
|
2491
|
+
throw new Error(`Price entry not found for priceId ${priceId}`)
|
|
2071
2492
|
}
|
|
2072
|
-
}
|
|
2073
|
-
|
|
2074
|
-
return Promise.all(
|
|
2075
|
-
[...allPriceIds].map((priceId) => {
|
|
2076
|
-
const priceEntry = pricesAccount.prices[priceId]
|
|
2077
|
-
|
|
2078
|
-
if (!priceEntry) {
|
|
2079
|
-
throw new Error(`Price entry not found for priceId ${priceId}`)
|
|
2080
|
-
}
|
|
2081
2493
|
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
)
|
|
2494
|
+
return this.ixUpdatePrice({
|
|
2495
|
+
priceId,
|
|
2496
|
+
priceInterfaceAccounts: priceEntry.priceInterfaceAccounts,
|
|
2497
|
+
remainingAccounts: priceEntry.interfaceAccounts,
|
|
2498
|
+
})
|
|
2499
|
+
})
|
|
2089
2500
|
}
|
|
2090
2501
|
|
|
2091
2502
|
// ==========================================================================
|