@exponent-labs/exponent-sdk 0.9.0 → 0.9.1

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.
Files changed (153) hide show
  1. package/build/client/vaults/index.d.ts +2 -0
  2. package/build/client/vaults/index.js +2 -0
  3. package/build/client/vaults/index.js.map +1 -1
  4. package/build/client/vaults/types/index.d.ts +2 -0
  5. package/build/client/vaults/types/index.js +2 -0
  6. package/build/client/vaults/types/index.js.map +1 -1
  7. package/build/client/vaults/types/kaminoFarmEntry.d.ts +15 -0
  8. package/build/client/vaults/types/kaminoFarmEntry.js +17 -0
  9. package/build/client/vaults/types/kaminoFarmEntry.js.map +1 -0
  10. package/build/client/vaults/types/kaminoObligationEntry.d.ts +24 -7
  11. package/build/client/vaults/types/kaminoObligationEntry.js +2 -1
  12. package/build/client/vaults/types/kaminoObligationEntry.js.map +1 -1
  13. package/build/client/vaults/types/obligationType.d.ts +1 -1
  14. package/build/client/vaults/types/positionUpdate.d.ts +9 -0
  15. package/build/client/vaults/types/positionUpdate.js +23 -0
  16. package/build/client/vaults/types/positionUpdate.js.map +1 -1
  17. package/build/client/vaults/types/proposalAction.d.ts +54 -54
  18. package/build/client/vaults/types/proposalAction.js +0 -3
  19. package/build/client/vaults/types/proposalAction.js.map +1 -1
  20. package/build/client/vaults/types/reserveFarmMapping.d.ts +19 -0
  21. package/build/client/vaults/types/reserveFarmMapping.js +18 -0
  22. package/build/client/vaults/types/reserveFarmMapping.js.map +1 -0
  23. package/build/client/vaults/types/strategyPosition.d.ts +6 -1
  24. package/build/client/vaults/types/strategyPosition.js +5 -0
  25. package/build/client/vaults/types/strategyPosition.js.map +1 -1
  26. package/build/exponentVaults/aumCalculator.d.ts +25 -4
  27. package/build/exponentVaults/aumCalculator.js +236 -15
  28. package/build/exponentVaults/aumCalculator.js.map +1 -1
  29. package/build/exponentVaults/fetcher.d.ts +52 -0
  30. package/build/exponentVaults/fetcher.js +199 -0
  31. package/build/exponentVaults/fetcher.js.map +1 -0
  32. package/build/exponentVaults/index.d.ts +10 -9
  33. package/build/exponentVaults/index.js +25 -8
  34. package/build/exponentVaults/index.js.map +1 -1
  35. package/build/exponentVaults/kamino-farms.d.ts +144 -0
  36. package/build/exponentVaults/kamino-farms.js +396 -0
  37. package/build/exponentVaults/kamino-farms.js.map +1 -0
  38. package/build/exponentVaults/loopscale/client.d.ts +240 -0
  39. package/build/exponentVaults/loopscale/client.js +590 -0
  40. package/build/exponentVaults/loopscale/client.js.map +1 -0
  41. package/build/exponentVaults/loopscale/client.test.d.ts +1 -0
  42. package/build/exponentVaults/loopscale/client.test.js +183 -0
  43. package/build/exponentVaults/loopscale/client.test.js.map +1 -0
  44. package/build/exponentVaults/loopscale/helpers.d.ts +29 -0
  45. package/build/exponentVaults/loopscale/helpers.js +119 -0
  46. package/build/exponentVaults/loopscale/helpers.js.map +1 -0
  47. package/build/exponentVaults/loopscale/index.d.ts +3 -0
  48. package/build/exponentVaults/loopscale/index.js +12 -0
  49. package/build/exponentVaults/loopscale/index.js.map +1 -0
  50. package/build/exponentVaults/loopscale/prepared-transactions.d.ts +13 -0
  51. package/build/exponentVaults/loopscale/prepared-transactions.js +271 -0
  52. package/build/exponentVaults/loopscale/prepared-transactions.js.map +1 -0
  53. package/build/exponentVaults/loopscale/prepared-transactions.test.d.ts +1 -0
  54. package/build/exponentVaults/loopscale/prepared-transactions.test.js +400 -0
  55. package/build/exponentVaults/loopscale/prepared-transactions.test.js.map +1 -0
  56. package/build/exponentVaults/loopscale/prepared-types.d.ts +62 -0
  57. package/build/exponentVaults/loopscale/prepared-types.js +3 -0
  58. package/build/exponentVaults/loopscale/prepared-types.js.map +1 -0
  59. package/build/exponentVaults/loopscale/response-plan.d.ts +69 -0
  60. package/build/exponentVaults/loopscale/response-plan.js +141 -0
  61. package/build/exponentVaults/loopscale/response-plan.js.map +1 -0
  62. package/build/exponentVaults/loopscale/response-plan.test.d.ts +1 -0
  63. package/build/exponentVaults/loopscale/response-plan.test.js +139 -0
  64. package/build/exponentVaults/loopscale/response-plan.test.js.map +1 -0
  65. package/build/exponentVaults/loopscale/send-plan.d.ts +75 -0
  66. package/build/exponentVaults/loopscale/send-plan.js +235 -0
  67. package/build/exponentVaults/loopscale/send-plan.js.map +1 -0
  68. package/build/exponentVaults/loopscale/types.d.ts +443 -0
  69. package/build/exponentVaults/loopscale/types.js +3 -0
  70. package/build/exponentVaults/loopscale/types.js.map +1 -0
  71. package/build/exponentVaults/loopscale-client.d.ts +113 -524
  72. package/build/exponentVaults/loopscale-client.js +296 -539
  73. package/build/exponentVaults/loopscale-client.js.map +1 -1
  74. package/build/exponentVaults/loopscale-client.test.d.ts +1 -0
  75. package/build/exponentVaults/loopscale-client.test.js +162 -0
  76. package/build/exponentVaults/loopscale-client.test.js.map +1 -0
  77. package/build/exponentVaults/loopscale-client.types.d.ts +425 -0
  78. package/build/exponentVaults/loopscale-client.types.js +3 -0
  79. package/build/exponentVaults/loopscale-client.types.js.map +1 -0
  80. package/build/exponentVaults/loopscale-execution.d.ts +125 -0
  81. package/build/exponentVaults/loopscale-execution.js +341 -0
  82. package/build/exponentVaults/loopscale-execution.js.map +1 -0
  83. package/build/exponentVaults/loopscale-execution.test.d.ts +1 -0
  84. package/build/exponentVaults/loopscale-execution.test.js +139 -0
  85. package/build/exponentVaults/loopscale-execution.test.js.map +1 -0
  86. package/build/exponentVaults/loopscale-vault.d.ts +115 -0
  87. package/build/exponentVaults/loopscale-vault.js +275 -0
  88. package/build/exponentVaults/loopscale-vault.js.map +1 -0
  89. package/build/exponentVaults/loopscale-vault.test.d.ts +1 -0
  90. package/build/exponentVaults/loopscale-vault.test.js +102 -0
  91. package/build/exponentVaults/loopscale-vault.test.js.map +1 -0
  92. package/build/exponentVaults/policyBuilders.d.ts +62 -0
  93. package/build/exponentVaults/policyBuilders.js +119 -2
  94. package/build/exponentVaults/policyBuilders.js.map +1 -1
  95. package/build/exponentVaults/pricePathResolver.d.ts +45 -0
  96. package/build/exponentVaults/pricePathResolver.js +198 -0
  97. package/build/exponentVaults/pricePathResolver.js.map +1 -0
  98. package/build/exponentVaults/pricePathResolver.test.d.ts +1 -0
  99. package/build/exponentVaults/pricePathResolver.test.js +369 -0
  100. package/build/exponentVaults/pricePathResolver.test.js.map +1 -0
  101. package/build/exponentVaults/syncTransaction.js +4 -1
  102. package/build/exponentVaults/syncTransaction.js.map +1 -1
  103. package/build/exponentVaults/titan-quote.js +170 -36
  104. package/build/exponentVaults/titan-quote.js.map +1 -1
  105. package/build/exponentVaults/vault-instruction-types.d.ts +363 -0
  106. package/build/exponentVaults/vault-instruction-types.js +128 -0
  107. package/build/exponentVaults/vault-instruction-types.js.map +1 -0
  108. package/build/exponentVaults/vault-interaction.d.ts +156 -313
  109. package/build/exponentVaults/vault-interaction.js +1581 -353
  110. package/build/exponentVaults/vault-interaction.js.map +1 -1
  111. package/build/exponentVaults/vault.d.ts +51 -2
  112. package/build/exponentVaults/vault.js +324 -48
  113. package/build/exponentVaults/vault.js.map +1 -1
  114. package/build/exponentVaults/vaultTransactionBuilder.d.ts +100 -134
  115. package/build/exponentVaults/vaultTransactionBuilder.js +359 -266
  116. package/build/exponentVaults/vaultTransactionBuilder.js.map +1 -1
  117. package/build/exponentVaults/vaultTransactionBuilder.test.d.ts +1 -0
  118. package/build/exponentVaults/vaultTransactionBuilder.test.js +214 -0
  119. package/build/exponentVaults/vaultTransactionBuilder.test.js.map +1 -0
  120. package/build/marketThree.d.ts +6 -2
  121. package/build/marketThree.js +10 -8
  122. package/build/marketThree.js.map +1 -1
  123. package/package.json +32 -32
  124. package/src/client/vaults/index.ts +2 -0
  125. package/src/client/vaults/types/index.ts +2 -0
  126. package/src/client/vaults/types/kaminoFarmEntry.ts +32 -0
  127. package/src/client/vaults/types/kaminoObligationEntry.ts +6 -3
  128. package/src/client/vaults/types/positionUpdate.ts +62 -0
  129. package/src/client/vaults/types/proposalAction.ts +0 -3
  130. package/src/client/vaults/types/reserveFarmMapping.ts +35 -0
  131. package/src/client/vaults/types/strategyPosition.ts +18 -1
  132. package/src/exponentVaults/aumCalculator.ts +353 -16
  133. package/src/exponentVaults/fetcher.ts +257 -0
  134. package/src/exponentVaults/index.ts +64 -40
  135. package/src/exponentVaults/kamino-farms.ts +538 -0
  136. package/src/exponentVaults/loopscale/client.ts +808 -0
  137. package/src/exponentVaults/loopscale/helpers.ts +172 -0
  138. package/src/exponentVaults/loopscale/index.ts +57 -0
  139. package/src/exponentVaults/loopscale/prepared-transactions.ts +435 -0
  140. package/src/exponentVaults/loopscale/prepared-types.ts +73 -0
  141. package/src/exponentVaults/loopscale/types.ts +466 -0
  142. package/src/exponentVaults/policyBuilders.ts +170 -0
  143. package/src/exponentVaults/pricePathResolver.test.ts +466 -0
  144. package/src/exponentVaults/pricePathResolver.ts +273 -0
  145. package/src/exponentVaults/syncTransaction.ts +6 -1
  146. package/src/exponentVaults/titan-quote.ts +231 -45
  147. package/src/exponentVaults/vault-instruction-types.ts +493 -0
  148. package/src/exponentVaults/vault-interaction.ts +2227 -636
  149. package/src/exponentVaults/vault.ts +474 -63
  150. package/src/exponentVaults/vaultTransactionBuilder.test.ts +256 -0
  151. package/src/exponentVaults/vaultTransactionBuilder.ts +555 -413
  152. package/src/marketThree.ts +14 -6
  153. package/src/exponentVaults/loopscale-client.ts +0 -1373
@@ -0,0 +1,256 @@
1
+ import { describe, expect, it, jest, beforeEach } from "@jest/globals"
2
+ import {
3
+ AddressLookupTableAccount,
4
+ ComputeBudgetProgram,
5
+ Keypair,
6
+ PublicKey,
7
+ TransactionInstruction,
8
+ VersionedTransaction,
9
+ } from "@solana/web3.js"
10
+
11
+ import { VaultTransactionBuilder, type VaultTransactionBuilderConfig } from "./vaultTransactionBuilder"
12
+ import type { LoopscalePreparedTransaction } from "./loopscale"
13
+
14
+ jest.mock("./loopscale", () => ({
15
+ LoopscaleClient: jest.fn(),
16
+ }))
17
+
18
+ jest.mock("./vault-interaction", () => ({
19
+ buildSetupStatePriceRefreshInstructions: jest.fn(),
20
+ createVaultSyncTransaction: jest.fn(),
21
+ createStrategySetupContext: jest.fn(),
22
+ }))
23
+
24
+ const { LoopscaleClient: mockLoopscaleClient } = jest.requireMock("./loopscale") as {
25
+ LoopscaleClient: jest.Mock
26
+ }
27
+ const {
28
+ buildSetupStatePriceRefreshInstructions: mockBuildSetupStatePriceRefreshInstructions,
29
+ createVaultSyncTransaction: mockCreateVaultSyncTransaction,
30
+ createStrategySetupContext: mockCreateStrategySetupContext,
31
+ } = jest.requireMock("./vault-interaction") as {
32
+ buildSetupStatePriceRefreshInstructions: jest.Mock
33
+ createVaultSyncTransaction: jest.Mock
34
+ createStrategySetupContext: jest.Mock
35
+ }
36
+
37
+ type LoopscaleResponseOptions = Parameters<VaultTransactionBuilder["addLoopscaleResponse"]>[1]
38
+ const validLoopscaleOptions: LoopscaleResponseOptions = { label: "loopscale-step" }
39
+ // @ts-expect-error Loopscale builder steps only accept label metadata.
40
+ const invalidLoopscaleOptions: LoopscaleResponseOptions = { priorityFee: 123 }
41
+ void invalidLoopscaleOptions
42
+
43
+ function pk(seed: number): PublicKey {
44
+ return new PublicKey(Uint8Array.from({ length: 32 }, () => seed))
45
+ }
46
+
47
+ function ix(programId: PublicKey, dataSeed: number): TransactionInstruction {
48
+ return new TransactionInstruction({
49
+ programId,
50
+ keys: [],
51
+ data: Buffer.from([dataSeed]),
52
+ })
53
+ }
54
+
55
+ function createVault(overrides: Partial<VaultTransactionBuilderConfig> = {}): VaultTransactionBuilderConfig {
56
+ return {
57
+ vault: {
58
+ selfAddress: pk(10),
59
+ programId: pk(11),
60
+ state: {
61
+ addressLookupTable: pk(12),
62
+ squadsVault: pk(21),
63
+ },
64
+ } as any,
65
+ connection: {
66
+ getAddressLookupTable: jest.fn(async () => ({ value: null })),
67
+ getLatestBlockhash: jest.fn(async () => ({
68
+ blockhash: PublicKey.default.toBase58(),
69
+ lastValidBlockHeight: 123,
70
+ })),
71
+ sendTransaction: jest.fn(async () => "sig-123"),
72
+ confirmTransaction: jest.fn(async () => ({ value: { err: null } })),
73
+ getSlot: jest.fn(),
74
+ } as any,
75
+ signer: pk(20),
76
+ computeUnitLimit: 987_654,
77
+ heapFrameBytes: 256 * 1024,
78
+ ...overrides,
79
+ }
80
+ }
81
+
82
+ describe("VaultTransactionBuilder Loopscale integration", () => {
83
+ beforeEach(() => {
84
+ mockLoopscaleClient.mockClear()
85
+ const mockPrepareVaultTransactions = jest.fn()
86
+ const mockCoSign = jest.fn()
87
+ mockLoopscaleClient.mockImplementation((config) => ({
88
+ config,
89
+ prepareVaultTransactions: mockPrepareVaultTransactions,
90
+ coSign: mockCoSign,
91
+ }))
92
+ ;(mockLoopscaleClient as any).mockPrepareVaultTransactions = mockPrepareVaultTransactions
93
+ ;(mockLoopscaleClient as any).mockCoSign = mockCoSign
94
+ mockBuildSetupStatePriceRefreshInstructions.mockReset()
95
+ mockCreateVaultSyncTransaction.mockReset()
96
+ mockCreateStrategySetupContext.mockReset()
97
+ mockCreateStrategySetupContext.mockReturnValue({ kind: "shared-setup-context" })
98
+ })
99
+
100
+ it("narrows Loopscale step options to label-only metadata", () => {
101
+ expect(validLoopscaleOptions).toEqual({ label: "loopscale-step" })
102
+ })
103
+
104
+ it("uses builder defaults and injects price refresh only into local Loopscale-derived vault transactions", async () => {
105
+ const config = createVault()
106
+ const refreshIx = ix(config.vault.programId, 200)
107
+ const vaultSetupIx = ix(config.vault.programId, 1)
108
+ const localVaultIx = ix(config.vault.programId, 2)
109
+ const plainSetupIx = ix(pk(30), 3)
110
+ const coSignedIx = ix(pk(31), 4)
111
+ const rawAlt = pk(32)
112
+
113
+ const preparedTransactions: LoopscalePreparedTransaction[] = [
114
+ {
115
+ setupInstructions: [vaultSetupIx],
116
+ instructions: [localVaultIx],
117
+ signers: [],
118
+ addressLookupTableAddresses: [rawAlt],
119
+ requiresLoopscaleCoSign: false,
120
+ },
121
+ {
122
+ setupInstructions: [plainSetupIx],
123
+ instructions: [coSignedIx],
124
+ signers: [],
125
+ addressLookupTableAddresses: [rawAlt],
126
+ requiresLoopscaleCoSign: true,
127
+ },
128
+ ]
129
+
130
+ const mockPrepareVaultTransactions = (mockLoopscaleClient as any).mockPrepareVaultTransactions as jest.Mock
131
+ mockPrepareVaultTransactions.mockImplementation(async () => preparedTransactions)
132
+ mockBuildSetupStatePriceRefreshInstructions.mockImplementation(async () => [refreshIx])
133
+
134
+ const result = await VaultTransactionBuilder
135
+ .create(config)
136
+ .addLoopscaleResponse({ message: "", signatures: [] } as any, { label: "loop" })
137
+ .build()
138
+
139
+ expect(mockLoopscaleClient).toHaveBeenCalledTimes(1)
140
+ expect(mockLoopscaleClient).toHaveBeenCalledWith({
141
+ connection: config.connection,
142
+ userWallet: config.vault.state.squadsVault,
143
+ baseUrl: undefined,
144
+ debug: undefined,
145
+ })
146
+
147
+ expect(result.labels).toEqual(["loop-1-setup", "loop-1", "loop-2-setup", "loop-2"])
148
+
149
+ const firstSetup = result.transactionSets[0]!
150
+ expect(firstSetup.instructions).toEqual([
151
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 987_654 }),
152
+ refreshIx,
153
+ vaultSetupIx,
154
+ ])
155
+ expect(firstSetup.addressLookupTableAddresses).toEqual([config.vault.state.addressLookupTable])
156
+ expect(firstSetup.coSignWithLoopscale).toBe(false)
157
+
158
+ const firstMain = result.transactionSets[1]!
159
+ expect(firstMain.instructions).toEqual([refreshIx, localVaultIx])
160
+ expect(firstMain.addressLookupTableAddresses).toEqual([rawAlt, config.vault.state.addressLookupTable])
161
+ expect(firstMain.coSignWithLoopscale).toBe(false)
162
+
163
+ const secondSetup = result.transactionSets[2]!
164
+ expect(secondSetup.instructions).toEqual([
165
+ ComputeBudgetProgram.setComputeUnitLimit({ units: 987_654 }),
166
+ plainSetupIx,
167
+ ])
168
+ expect(secondSetup.addressLookupTableAddresses).toEqual([config.vault.state.addressLookupTable])
169
+ expect(secondSetup.coSignWithLoopscale).toBe(false)
170
+
171
+ const secondMain = result.transactionSets[3]!
172
+ expect(secondMain.instructions).toEqual([coSignedIx])
173
+ expect(secondMain.addressLookupTableAddresses).toEqual([rawAlt])
174
+ expect(secondMain.coSignWithLoopscale).toBe(true)
175
+ })
176
+
177
+ it("only co-signs flagged transactions and forwards loopscale client config to build and send paths", async () => {
178
+ const payer = Keypair.generate()
179
+ const persistentAlt = pk(50)
180
+ const config = createVault({
181
+ vault: {
182
+ selfAddress: pk(10),
183
+ programId: pk(11),
184
+ state: {
185
+ addressLookupTable: persistentAlt,
186
+ squadsVault: pk(51),
187
+ },
188
+ } as any,
189
+ loopscale: {
190
+ baseUrl: "https://loopscale.test",
191
+ debug: true,
192
+ },
193
+ })
194
+
195
+ const localIx = ix(pk(40), 1)
196
+ const coSignedIx = ix(pk(41), 2)
197
+ const persistentAltAccount = new AddressLookupTableAccount({
198
+ key: persistentAlt,
199
+ state: {
200
+ deactivationSlot: 0n,
201
+ lastExtendedSlot: 0,
202
+ lastExtendedSlotStartIndex: 0,
203
+ authority: payer.publicKey,
204
+ addresses: [config.signer, localIx.programId, coSignedIx.programId],
205
+ },
206
+ })
207
+ ;(config.connection.getAddressLookupTable as jest.Mock).mockImplementation(async (address: PublicKey) => ({
208
+ value: address.equals(persistentAlt) ? persistentAltAccount : null,
209
+ }))
210
+
211
+ const mockPrepareVaultTransactions = (mockLoopscaleClient as any).mockPrepareVaultTransactions as jest.Mock
212
+ const mockCoSign = (mockLoopscaleClient as any).mockCoSign as jest.Mock
213
+ mockPrepareVaultTransactions.mockImplementation(async () => [
214
+ {
215
+ setupInstructions: [],
216
+ instructions: [localIx],
217
+ signers: [],
218
+ addressLookupTableAddresses: [],
219
+ requiresLoopscaleCoSign: false,
220
+ },
221
+ {
222
+ setupInstructions: [],
223
+ instructions: [coSignedIx],
224
+ signers: [],
225
+ addressLookupTableAddresses: [],
226
+ requiresLoopscaleCoSign: true,
227
+ },
228
+ ] satisfies LoopscalePreparedTransaction[])
229
+ mockBuildSetupStatePriceRefreshInstructions.mockImplementation(async () => [])
230
+ mockCoSign.mockImplementation(async (transaction: VersionedTransaction) => transaction)
231
+
232
+ const result = await VaultTransactionBuilder
233
+ .create(config)
234
+ .addLoopscaleResponse({ message: "", signatures: [] } as any, { label: "loop" })
235
+ .build()
236
+
237
+ const sendResult = await result.send({ signers: [payer] })
238
+
239
+ expect(mockLoopscaleClient).toHaveBeenNthCalledWith(1, {
240
+ connection: config.connection,
241
+ userWallet: config.vault.state.squadsVault,
242
+ baseUrl: "https://loopscale.test",
243
+ debug: true,
244
+ })
245
+ expect(mockLoopscaleClient).toHaveBeenNthCalledWith(2, {
246
+ connection: config.connection,
247
+ userWallet: config.vault.state.squadsVault,
248
+ baseUrl: "https://loopscale.test",
249
+ debug: true,
250
+ })
251
+ expect(mockCoSign).toHaveBeenCalledTimes(1)
252
+ expect((config.connection.sendTransaction as jest.Mock)).toHaveBeenCalledTimes(2)
253
+ expect(sendResult.signatures).toEqual(["sig-123", "sig-123"])
254
+ expect(sendResult.ephemeralAlt).toBeNull()
255
+ })
256
+ })