@kamino-finance/klend-sdk 5.11.11 → 5.11.12

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 (50) hide show
  1. package/README_KAMINO_MANAGER.md +2 -2
  2. package/dist/classes/vault.js +2 -2
  3. package/dist/client_kamino_manager.d.ts.map +1 -1
  4. package/dist/client_kamino_manager.js +76 -3
  5. package/dist/client_kamino_manager.js.map +1 -1
  6. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts +9 -6
  7. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts.map +1 -1
  8. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js +19 -13
  9. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js.map +1 -1
  10. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts +9 -1
  11. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts.map +1 -1
  12. package/dist/idl_codegen_kamino_vault/errors/custom.js +15 -1
  13. package/dist/idl_codegen_kamino_vault/errors/custom.js.map +1 -1
  14. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts +2 -0
  15. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts.map +1 -1
  16. package/dist/idl_codegen_kamino_vault/instructions/index.js +3 -1
  17. package/dist/idl_codegen_kamino_vault/instructions/index.js.map +1 -1
  18. package/dist/idl_codegen_kamino_vault/instructions/removeAllocation.d.ts +8 -0
  19. package/dist/idl_codegen_kamino_vault/instructions/removeAllocation.d.ts.map +1 -0
  20. package/dist/idl_codegen_kamino_vault/instructions/removeAllocation.js +17 -0
  21. package/dist/idl_codegen_kamino_vault/instructions/removeAllocation.js.map +1 -0
  22. package/dist/idl_codegen_kamino_vault/programId.d.ts.map +1 -1
  23. package/dist/idl_codegen_kamino_vault/programId.js +1 -1
  24. package/dist/idl_codegen_kamino_vault/programId.js.map +1 -1
  25. package/dist/lending_operations/repay_with_collateral_operations.d.ts +3 -1
  26. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  27. package/dist/lending_operations/repay_with_collateral_operations.js +13 -3
  28. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  29. package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
  30. package/dist/lending_operations/swap_collateral_operations.js +4 -0
  31. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  32. package/dist/leverage/operations.d.ts +5 -2
  33. package/dist/leverage/operations.d.ts.map +1 -1
  34. package/dist/leverage/operations.js +83 -44
  35. package/dist/leverage/operations.js.map +1 -1
  36. package/dist/leverage/types.d.ts +11 -0
  37. package/dist/leverage/types.d.ts.map +1 -1
  38. package/package.json +2 -2
  39. package/src/classes/vault.ts +2 -2
  40. package/src/client_kamino_manager.ts +110 -3
  41. package/src/idl_codegen_kamino_vault/accounts/VaultState.ts +25 -17
  42. package/src/idl_codegen_kamino_vault/errors/custom.ts +17 -0
  43. package/src/idl_codegen_kamino_vault/instructions/index.ts +2 -0
  44. package/src/idl_codegen_kamino_vault/instructions/removeAllocation.ts +26 -0
  45. package/src/idl_codegen_kamino_vault/programId.ts +1 -2
  46. package/src/idl_kamino_vault.json +38 -3
  47. package/src/lending_operations/repay_with_collateral_operations.ts +22 -6
  48. package/src/lending_operations/swap_collateral_operations.ts +12 -1
  49. package/src/leverage/operations.ts +101 -55
  50. package/src/leverage/types.ts +13 -0
@@ -16,12 +16,14 @@ import {
16
16
  Chain,
17
17
  DEFAULT_RECENT_SLOT_DURATION_MS,
18
18
  encodeTokenName,
19
+ initLookupTableIx,
19
20
  KaminoManager,
20
21
  KaminoMarket,
21
22
  KaminoVault,
22
23
  KaminoVaultConfig,
23
24
  LendingMarket,
24
25
  MAINNET_BETA_CHAIN_ID,
26
+ parseZeroPaddedUtf8,
25
27
  Reserve,
26
28
  ReserveAllocationConfig,
27
29
  ReserveWithAddress,
@@ -408,6 +410,14 @@ async function main() {
408
410
  mode === 'execute' && console.log('Management fee updated:', updateVaultConfigSig);
409
411
  });
410
412
 
413
+ commands.command('create-lut').action(async () => {
414
+ const env = initializeClient(false, false);
415
+ const initLutIx = initLookupTableIx(env.payer.publicKey, await env.connection.getSlot());
416
+
417
+ const updateVaultConfigSig = await processTxn(env.client, env.payer, [initLutIx[0]], 'execute', 2500, []);
418
+ console.log(`LUT created: ${initLutIx[1].toString()} tx id: ${updateVaultConfigSig}`);
419
+ });
420
+
411
421
  commands
412
422
  .command('sync-vault-lut')
413
423
  .requiredOption('--vault <string>', 'The vault address to sync')
@@ -1142,9 +1152,6 @@ async function main() {
1142
1152
  address: lendingMarketAddress,
1143
1153
  state: lendingMarketState,
1144
1154
  };
1145
- if (!lendingMarketState) {
1146
- throw new Error('Lending Market not found');
1147
- }
1148
1155
 
1149
1156
  if (mode === 'multisig') {
1150
1157
  throw new Error('If using multisig mode, multisig is required');
@@ -1163,6 +1170,106 @@ async function main() {
1163
1170
  );
1164
1171
  });
1165
1172
 
1173
+ commands
1174
+ .command('update-lending-market-name')
1175
+ .requiredOption('--lending-market <string>', 'Lending Market address')
1176
+ .requiredOption('--new-name <string>', 'Lending Market address')
1177
+ .requiredOption(
1178
+ `--mode <string>`,
1179
+ 'simulate - to print txn simulation, inspect - to get txn simulation in explorer, execute - execute txn, multisig - to get bs58 txn for multisig usage'
1180
+ )
1181
+ .option(`--staging`, 'If true, will use the staging programs')
1182
+ .action(async ({ lendingMarket, newName, mode, staging }) => {
1183
+ const env = initializeClient(mode === 'multisig', staging);
1184
+ const lendingMarketAddress = new PublicKey(lendingMarket);
1185
+ const lendingMarketState = await LendingMarket.fetch(env.connection, lendingMarketAddress, env.kLendProgramId);
1186
+ if (!lendingMarketState) {
1187
+ throw new Error('Lending Market not found');
1188
+ }
1189
+ const marketWithAddress = {
1190
+ address: lendingMarketAddress,
1191
+ state: lendingMarketState,
1192
+ };
1193
+
1194
+ if (mode === 'multisig') {
1195
+ throw new Error('If using multisig mode, multisig is required');
1196
+ }
1197
+
1198
+ const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
1199
+
1200
+ const currentName = parseZeroPaddedUtf8(lendingMarketState.name);
1201
+ const newNameEncoded = encodeTokenName(newName);
1202
+
1203
+ console.log('Current name: ', currentName, ' encoded: ', lendingMarketState.name);
1204
+ console.log('New name: ', newName, ' encoded: ', newNameEncoded);
1205
+
1206
+ // @ts-ignore
1207
+ const newLendingMarket: LendingMarket = {
1208
+ ...lendingMarketState,
1209
+ name: newNameEncoded,
1210
+ };
1211
+
1212
+ const ixns = kaminoManager.updateLendingMarketIxs(marketWithAddress, newLendingMarket);
1213
+
1214
+ const _updateLendingMarketSig = await processTxn(env.client, env.payer, ixns, mode, 2500, [], 400_000);
1215
+
1216
+ mode === 'execute' &&
1217
+ console.log(
1218
+ 'Lending market name updated to -> ',
1219
+ JSON.parse(JSON.stringify(lendingMarketState.lendingMarketOwnerCached))
1220
+ );
1221
+ });
1222
+
1223
+ commands
1224
+ .command('update-reserve-config-debt-cap')
1225
+ .requiredOption('--reserve <string>', 'Lending Market address')
1226
+ .requiredOption(
1227
+ `--mode <string>`,
1228
+ 'simulate - to print txn simulation, inspect - to get txn simulation in explorer, execute - execute txn, multisig - to get bs58 txn for multisig usage'
1229
+ )
1230
+ .option(`--staging`, 'If true, will use the staging programs')
1231
+ .action(async ({ reserve, mode, staging }) => {
1232
+ const env = initializeClient(mode === 'multisig', staging);
1233
+ const reserveAddress = new PublicKey(reserve);
1234
+ const reserveState = await Reserve.fetch(env.connection, reserveAddress, env.kLendProgramId);
1235
+ if (!reserveState) {
1236
+ throw new Error('Reserve not found');
1237
+ }
1238
+
1239
+ const lendingMarketAddress = reserveState.lendingMarket;
1240
+ const lendingMarketState = await LendingMarket.fetch(env.connection, lendingMarketAddress, env.kLendProgramId);
1241
+ if (!lendingMarketState) {
1242
+ throw new Error('Lending Market not found');
1243
+ }
1244
+
1245
+ const marketWithAddress = {
1246
+ address: lendingMarketAddress,
1247
+ state: lendingMarketState,
1248
+ };
1249
+
1250
+ if (mode === 'multisig') {
1251
+ throw new Error('If using multisig mode, multisig is required');
1252
+ }
1253
+
1254
+ const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
1255
+
1256
+ const newReserveConfigFields: ReserveConfigFields = {
1257
+ ...reserveState.config,
1258
+ borrowLimit: new BN(1000),
1259
+ };
1260
+ const newReserveConfig: ReserveConfig = new ReserveConfig(newReserveConfigFields);
1261
+
1262
+ const ixns = await kaminoManager.updateReserveIxs(marketWithAddress, reserveAddress, newReserveConfig);
1263
+
1264
+ const _updateLendingMarketSig = await processTxn(env.client, env.payer, ixns, mode, 2500, [], 400_000);
1265
+
1266
+ mode === 'execute' &&
1267
+ console.log(
1268
+ 'Lending market name updated to -> ',
1269
+ JSON.parse(JSON.stringify(lendingMarketState.lendingMarketOwnerCached))
1270
+ );
1271
+ });
1272
+
1166
1273
  await commands.parseAsync();
1167
1274
  }
1168
1275
 
@@ -24,6 +24,7 @@ export interface VaultStateFields {
24
24
  prevAumSf: BN
25
25
  pendingFeesSf: BN
26
26
  vaultAllocationStrategy: Array<types.VaultAllocationFields>
27
+ padding1: Array<BN>
27
28
  minDepositAmount: BN
28
29
  minWithdrawAmount: BN
29
30
  minInvestAmount: BN
@@ -37,9 +38,9 @@ export interface VaultStateFields {
37
38
  vaultLookupTable: PublicKey
38
39
  vaultFarm: PublicKey
39
40
  creationTimestamp: BN
40
- padding1: BN
41
+ padding2: BN
41
42
  allocationAdmin: PublicKey
42
- padding2: Array<BN>
43
+ padding3: Array<BN>
43
44
  }
44
45
 
45
46
  export interface VaultStateJSON {
@@ -62,6 +63,7 @@ export interface VaultStateJSON {
62
63
  prevAumSf: string
63
64
  pendingFeesSf: string
64
65
  vaultAllocationStrategy: Array<types.VaultAllocationJSON>
66
+ padding1: Array<string>
65
67
  minDepositAmount: string
66
68
  minWithdrawAmount: string
67
69
  minInvestAmount: string
@@ -75,9 +77,9 @@ export interface VaultStateJSON {
75
77
  vaultLookupTable: string
76
78
  vaultFarm: string
77
79
  creationTimestamp: string
78
- padding1: string
80
+ padding2: string
79
81
  allocationAdmin: string
80
- padding2: Array<string>
82
+ padding3: Array<string>
81
83
  }
82
84
 
83
85
  export class VaultState {
@@ -100,6 +102,7 @@ export class VaultState {
100
102
  readonly prevAumSf: BN
101
103
  readonly pendingFeesSf: BN
102
104
  readonly vaultAllocationStrategy: Array<types.VaultAllocation>
105
+ readonly padding1: Array<BN>
103
106
  readonly minDepositAmount: BN
104
107
  readonly minWithdrawAmount: BN
105
108
  readonly minInvestAmount: BN
@@ -113,9 +116,9 @@ export class VaultState {
113
116
  readonly vaultLookupTable: PublicKey
114
117
  readonly vaultFarm: PublicKey
115
118
  readonly creationTimestamp: BN
116
- readonly padding1: BN
119
+ readonly padding2: BN
117
120
  readonly allocationAdmin: PublicKey
118
- readonly padding2: Array<BN>
121
+ readonly padding3: Array<BN>
119
122
 
120
123
  static readonly discriminator = Buffer.from([
121
124
  228, 196, 82, 165, 98, 210, 235, 152,
@@ -140,7 +143,8 @@ export class VaultState {
140
143
  borsh.u64("lastFeeChargeTimestamp"),
141
144
  borsh.u128("prevAumSf"),
142
145
  borsh.u128("pendingFeesSf"),
143
- borsh.array(types.VaultAllocation.layout(), 10, "vaultAllocationStrategy"),
146
+ borsh.array(types.VaultAllocation.layout(), 25, "vaultAllocationStrategy"),
147
+ borsh.array(borsh.u128(), 256, "padding1"),
144
148
  borsh.u64("minDepositAmount"),
145
149
  borsh.u64("minWithdrawAmount"),
146
150
  borsh.u64("minInvestAmount"),
@@ -154,9 +158,9 @@ export class VaultState {
154
158
  borsh.publicKey("vaultLookupTable"),
155
159
  borsh.publicKey("vaultFarm"),
156
160
  borsh.u64("creationTimestamp"),
157
- borsh.u64("padding1"),
161
+ borsh.u64("padding2"),
158
162
  borsh.publicKey("allocationAdmin"),
159
- borsh.array(borsh.u128(), 242, "padding2"),
163
+ borsh.array(borsh.u128(), 242, "padding3"),
160
164
  ])
161
165
 
162
166
  constructor(fields: VaultStateFields) {
@@ -181,6 +185,7 @@ export class VaultState {
181
185
  this.vaultAllocationStrategy = fields.vaultAllocationStrategy.map(
182
186
  (item) => new types.VaultAllocation({ ...item })
183
187
  )
188
+ this.padding1 = fields.padding1
184
189
  this.minDepositAmount = fields.minDepositAmount
185
190
  this.minWithdrawAmount = fields.minWithdrawAmount
186
191
  this.minInvestAmount = fields.minInvestAmount
@@ -194,9 +199,9 @@ export class VaultState {
194
199
  this.vaultLookupTable = fields.vaultLookupTable
195
200
  this.vaultFarm = fields.vaultFarm
196
201
  this.creationTimestamp = fields.creationTimestamp
197
- this.padding1 = fields.padding1
198
- this.allocationAdmin = fields.allocationAdmin
199
202
  this.padding2 = fields.padding2
203
+ this.allocationAdmin = fields.allocationAdmin
204
+ this.padding3 = fields.padding3
200
205
  }
201
206
 
202
207
  static async fetch(
@@ -266,6 +271,7 @@ export class VaultState {
266
271
  item: any /* eslint-disable-line @typescript-eslint/no-explicit-any */
267
272
  ) => types.VaultAllocation.fromDecoded(item)
268
273
  ),
274
+ padding1: dec.padding1,
269
275
  minDepositAmount: dec.minDepositAmount,
270
276
  minWithdrawAmount: dec.minWithdrawAmount,
271
277
  minInvestAmount: dec.minInvestAmount,
@@ -279,9 +285,9 @@ export class VaultState {
279
285
  vaultLookupTable: dec.vaultLookupTable,
280
286
  vaultFarm: dec.vaultFarm,
281
287
  creationTimestamp: dec.creationTimestamp,
282
- padding1: dec.padding1,
283
- allocationAdmin: dec.allocationAdmin,
284
288
  padding2: dec.padding2,
289
+ allocationAdmin: dec.allocationAdmin,
290
+ padding3: dec.padding3,
285
291
  })
286
292
  }
287
293
 
@@ -308,6 +314,7 @@ export class VaultState {
308
314
  vaultAllocationStrategy: this.vaultAllocationStrategy.map((item) =>
309
315
  item.toJSON()
310
316
  ),
317
+ padding1: this.padding1.map((item) => item.toString()),
311
318
  minDepositAmount: this.minDepositAmount.toString(),
312
319
  minWithdrawAmount: this.minWithdrawAmount.toString(),
313
320
  minInvestAmount: this.minInvestAmount.toString(),
@@ -321,9 +328,9 @@ export class VaultState {
321
328
  vaultLookupTable: this.vaultLookupTable.toString(),
322
329
  vaultFarm: this.vaultFarm.toString(),
323
330
  creationTimestamp: this.creationTimestamp.toString(),
324
- padding1: this.padding1.toString(),
331
+ padding2: this.padding2.toString(),
325
332
  allocationAdmin: this.allocationAdmin.toString(),
326
- padding2: this.padding2.map((item) => item.toString()),
333
+ padding3: this.padding3.map((item) => item.toString()),
327
334
  }
328
335
  }
329
336
 
@@ -350,6 +357,7 @@ export class VaultState {
350
357
  vaultAllocationStrategy: obj.vaultAllocationStrategy.map((item) =>
351
358
  types.VaultAllocation.fromJSON(item)
352
359
  ),
360
+ padding1: obj.padding1.map((item) => new BN(item)),
353
361
  minDepositAmount: new BN(obj.minDepositAmount),
354
362
  minWithdrawAmount: new BN(obj.minWithdrawAmount),
355
363
  minInvestAmount: new BN(obj.minInvestAmount),
@@ -363,9 +371,9 @@ export class VaultState {
363
371
  vaultLookupTable: new PublicKey(obj.vaultLookupTable),
364
372
  vaultFarm: new PublicKey(obj.vaultFarm),
365
373
  creationTimestamp: new BN(obj.creationTimestamp),
366
- padding1: new BN(obj.padding1),
374
+ padding2: new BN(obj.padding2),
367
375
  allocationAdmin: new PublicKey(obj.allocationAdmin),
368
- padding2: obj.padding2.map((item) => new BN(item)),
376
+ padding3: obj.padding3.map((item) => new BN(item)),
369
377
  })
370
378
  }
371
379
  }
@@ -46,6 +46,7 @@ export type CustomError =
46
46
  | MinWithdrawAmountTooBig
47
47
  | InvestTooSoon
48
48
  | WrongAdminOrAllocationAdmin
49
+ | ReserveHasNonZeroAllocationOrCTokens
49
50
 
50
51
  export class DepositAmountsZero extends Error {
51
52
  static readonly code = 7000
@@ -564,6 +565,20 @@ export class WrongAdminOrAllocationAdmin extends Error {
564
565
  }
565
566
  }
566
567
 
568
+ export class ReserveHasNonZeroAllocationOrCTokens extends Error {
569
+ static readonly code = 7047
570
+ readonly code = 7047
571
+ readonly name = "ReserveHasNonZeroAllocationOrCTokens"
572
+ readonly msg =
573
+ "Reserve has non-zero allocation or ctokens so cannot be removed"
574
+
575
+ constructor(readonly logs?: string[]) {
576
+ super(
577
+ "7047: Reserve has non-zero allocation or ctokens so cannot be removed"
578
+ )
579
+ }
580
+ }
581
+
567
582
  export function fromCode(code: number, logs?: string[]): CustomError | null {
568
583
  switch (code) {
569
584
  case 7000:
@@ -660,6 +675,8 @@ export function fromCode(code: number, logs?: string[]): CustomError | null {
660
675
  return new InvestTooSoon(logs)
661
676
  case 7046:
662
677
  return new WrongAdminOrAllocationAdmin(logs)
678
+ case 7047:
679
+ return new ReserveHasNonZeroAllocationOrCTokens(logs)
663
680
  }
664
681
 
665
682
  return null
@@ -40,3 +40,5 @@ export type {
40
40
  WithdrawFromAvailableArgs,
41
41
  WithdrawFromAvailableAccounts,
42
42
  } from "./withdrawFromAvailable"
43
+ export { removeAllocation } from "./removeAllocation"
44
+ export type { RemoveAllocationAccounts } from "./removeAllocation"
@@ -0,0 +1,26 @@
1
+ import { TransactionInstruction, PublicKey, AccountMeta } from "@solana/web3.js" // eslint-disable-line @typescript-eslint/no-unused-vars
2
+ import BN from "bn.js" // eslint-disable-line @typescript-eslint/no-unused-vars
3
+ import * as borsh from "@coral-xyz/borsh" // eslint-disable-line @typescript-eslint/no-unused-vars
4
+ import * as types from "../types" // eslint-disable-line @typescript-eslint/no-unused-vars
5
+ import { PROGRAM_ID } from "../programId"
6
+
7
+ export interface RemoveAllocationAccounts {
8
+ vaultAdminAuthority: PublicKey
9
+ vaultState: PublicKey
10
+ reserve: PublicKey
11
+ }
12
+
13
+ export function removeAllocation(
14
+ accounts: RemoveAllocationAccounts,
15
+ programId: PublicKey = PROGRAM_ID
16
+ ) {
17
+ const keys: Array<AccountMeta> = [
18
+ { pubkey: accounts.vaultAdminAuthority, isSigner: true, isWritable: true },
19
+ { pubkey: accounts.vaultState, isSigner: false, isWritable: true },
20
+ { pubkey: accounts.reserve, isSigner: false, isWritable: false },
21
+ ]
22
+ const identifier = Buffer.from([32, 220, 211, 141, 209, 231, 73, 76])
23
+ const data = identifier
24
+ const ix = new TransactionInstruction({ keys, programId, data })
25
+ return ix
26
+ }
@@ -2,13 +2,12 @@ import { PublicKey } from "@solana/web3.js"
2
2
 
3
3
  // Program ID passed with the cli --program-id flag when running the code generator. Do not edit, it will get overwritten.
4
4
  export const KVAULTS_PROGRAM_ID_CLI = new PublicKey(
5
- "kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr"
5
+ "KvauGMspG5k6rtzrqqn7WNn3oZdyKqLKwK2XWQ8FLjd"
6
6
  )
7
7
 
8
8
  // This constant will not get overwritten on subsequent code generations and it's safe to modify it's value.
9
9
  export let KVAULTS_PROGRAM_ID: PublicKey = KVAULTS_PROGRAM_ID_CLI
10
10
  export let PROGRAM_ID: PublicKey = KVAULTS_PROGRAM_ID_CLI
11
-
12
11
  export const setKVaultsProgramId = (programId: PublicKey) => {
13
12
  KVAULTS_PROGRAM_ID = programId;
14
13
  PROGRAM_ID = programId;
@@ -730,6 +730,27 @@
730
730
  "type": "u64"
731
731
  }
732
732
  ]
733
+ },
734
+ {
735
+ "name": "removeAllocation",
736
+ "accounts": [
737
+ {
738
+ "name": "vaultAdminAuthority",
739
+ "isMut": true,
740
+ "isSigner": true
741
+ },
742
+ {
743
+ "name": "vaultState",
744
+ "isMut": true,
745
+ "isSigner": false
746
+ },
747
+ {
748
+ "name": "reserve",
749
+ "isMut": false,
750
+ "isSigner": false
751
+ }
752
+ ],
753
+ "args": []
733
754
  }
734
755
  ],
735
756
  "accounts": [
@@ -936,7 +957,16 @@
936
957
  {
937
958
  "defined": "VaultAllocation"
938
959
  },
939
- 10
960
+ 25
961
+ ]
962
+ }
963
+ },
964
+ {
965
+ "name": "padding1",
966
+ "type": {
967
+ "array": [
968
+ "u128",
969
+ 256
940
970
  ]
941
971
  }
942
972
  },
@@ -998,7 +1028,7 @@
998
1028
  "type": "u64"
999
1029
  },
1000
1030
  {
1001
- "name": "padding1",
1031
+ "name": "padding2",
1002
1032
  "type": "u64"
1003
1033
  },
1004
1034
  {
@@ -1006,7 +1036,7 @@
1006
1036
  "type": "publicKey"
1007
1037
  },
1008
1038
  {
1009
- "name": "padding2",
1039
+ "name": "padding3",
1010
1040
  "type": {
1011
1041
  "array": [
1012
1042
  "u128",
@@ -2187,6 +2217,11 @@
2187
2217
  "code": 7046,
2188
2218
  "name": "WrongAdminOrAllocationAdmin",
2189
2219
  "msg": "Wrong admin or allocation admin"
2220
+ },
2221
+ {
2222
+ "code": 7047,
2223
+ "name": "ReserveHasNonZeroAllocationOrCTokens",
2224
+ "msg": "Reserve has non-zero allocation or ctokens so cannot be removed"
2190
2225
  }
2191
2226
  ]
2192
2227
  }
@@ -7,6 +7,8 @@ import {
7
7
  SwapIxsProvider,
8
8
  SwapQuoteProvider,
9
9
  getScopeRefreshIx,
10
+ LeverageIxnsOutput,
11
+ FlashLoanInfo,
10
12
  } from '../leverage';
11
13
  import {
12
14
  createAtasIdempotent,
@@ -23,6 +25,7 @@ import { calcMaxWithdrawCollateral, calcRepayAmountWithSlippage } from './repay_
23
25
  export type RepayWithCollIxsResponse<QuoteResponse> = {
24
26
  ixs: TransactionInstruction[];
25
27
  lookupTables: AddressLookupTableAccount[];
28
+ flashLoanInfo: FlashLoanInfo;
26
29
  swapInputs: SwapInputs;
27
30
  initialInputs: RepayWithCollInitialInputs<QuoteResponse>;
28
31
  };
@@ -77,6 +80,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
77
80
  useV2Ixs,
78
81
  }: RepayWithCollSwapInputsProps<QuoteResponse>): Promise<{
79
82
  swapInputs: SwapInputs;
83
+ flashLoanInfo: FlashLoanInfo;
80
84
  initialInputs: RepayWithCollInitialInputs<QuoteResponse>;
81
85
  }> {
82
86
  const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
@@ -124,7 +128,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
124
128
  const inputAmountLamports = Decimal.min(withdrawableCollLamports, maxCollNeededFromOracle);
125
129
 
126
130
  // Build the repay & withdraw collateral tx to get the number of accounts
127
- const klendIxs = await buildRepayWithCollateralIxs(
131
+ const klendIxs: LeverageIxnsOutput = await buildRepayWithCollateralIxs(
128
132
  kaminoMarket,
129
133
  debtReserve,
130
134
  collReserve,
@@ -143,7 +147,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
143
147
  inputAmountLamports,
144
148
  useV2Ixs
145
149
  );
146
- const uniqueKlendAccounts = uniqueAccounts(klendIxs);
150
+ const uniqueKlendAccounts = uniqueAccounts(klendIxs.instructions);
147
151
 
148
152
  const swapQuoteInputs: SwapInputs = {
149
153
  inputAmountLamports,
@@ -169,6 +173,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
169
173
  outputMint: debtTokenMint,
170
174
  amountDebtAtaBalance: new Decimal(0), // only used for kTokens
171
175
  },
176
+ flashLoanInfo: klendIxs.flashLoanInfo,
172
177
  initialInputs: {
173
178
  debtRepayAmountLamports: repayAmountLamports,
174
179
  flashRepayAmountLamports,
@@ -251,7 +256,7 @@ export async function getRepayWithCollIxs<QuoteResponse>({
251
256
  );
252
257
 
253
258
  const swapResponse = await swapper(swapInputs, initialInputs.klendAccounts, swapQuote);
254
- const ixs = await buildRepayWithCollateralIxs(
259
+ const ixs: LeverageIxnsOutput = await buildRepayWithCollateralIxs(
255
260
  kaminoMarket,
256
261
  debtReserve,
257
262
  collReserve,
@@ -268,9 +273,10 @@ export async function getRepayWithCollIxs<QuoteResponse>({
268
273
  );
269
274
 
270
275
  return {
271
- ixs,
276
+ ixs: ixs.instructions,
272
277
  lookupTables: swapResponse.lookupTables,
273
278
  swapInputs,
279
+ flashLoanInfo: ixs.flashLoanInfo,
274
280
  initialInputs,
275
281
  };
276
282
  }
@@ -289,7 +295,7 @@ async function buildRepayWithCollateralIxs(
289
295
  debtRepayAmountLamports: Decimal,
290
296
  collWithdrawLamports: Decimal,
291
297
  useV2Ixs: boolean
292
- ): Promise<TransactionInstruction[]> {
298
+ ): Promise<LeverageIxnsOutput> {
293
299
  // 1. Create atas & budget txns
294
300
  const budgetIxns = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxns(1_400_000);
295
301
 
@@ -367,7 +373,7 @@ async function buildRepayWithCollateralIxs(
367
373
  const { preActionIxs, swapIxs } = swapQuoteIxs;
368
374
  const swapInstructions = removeBudgetAndAtaIxns(swapIxs, []);
369
375
 
370
- return [
376
+ const ixns = [
371
377
  ...scopeRefreshIxn,
372
378
  ...budgetIxns,
373
379
  ...atasAndIxs.map((x) => x.createAtaIx),
@@ -377,6 +383,16 @@ async function buildRepayWithCollateralIxs(
377
383
  ...swapInstructions,
378
384
  flashRepayIxn,
379
385
  ];
386
+
387
+ const res: LeverageIxnsOutput = {
388
+ flashLoanInfo: {
389
+ flashBorrowReserve: debtReserve.address,
390
+ flashLoanFee: debtReserve.getFlashLoanFee(),
391
+ },
392
+ instructions: ixns,
393
+ };
394
+
395
+ return res;
380
396
  }
381
397
 
382
398
  export const getMaxWithdrawLtvCheck = (obligation: KaminoObligation) => {
@@ -6,7 +6,13 @@ import {
6
6
  KaminoObligation,
7
7
  KaminoReserve,
8
8
  } from '../classes';
9
- import { getFlashLoanInstructions, getScopeRefreshIx, SwapIxsProvider, SwapQuoteProvider } from '../leverage';
9
+ import {
10
+ FlashLoanInfo,
11
+ getFlashLoanInstructions,
12
+ getScopeRefreshIx,
13
+ SwapIxsProvider,
14
+ SwapQuoteProvider,
15
+ } from '../leverage';
10
16
  import {
11
17
  createAtasIdempotent,
12
18
  DEFAULT_MAX_COMPUTE_UNITS,
@@ -251,6 +257,7 @@ type SwapCollKlendIxns = {
251
257
  withdrawSourceCollIxns: TransactionInstruction[];
252
258
  targetCollFlashRepayIxn: TransactionInstruction;
253
259
  cleanupIxns: TransactionInstruction[];
260
+ flashLoanInfo: FlashLoanInfo;
254
261
  simulationDetails: {
255
262
  targetCollFlashBorrowedAmount: Decimal;
256
263
  };
@@ -295,6 +302,10 @@ async function getKlendIxns(
295
302
 
296
303
  return {
297
304
  setupIxns,
305
+ flashLoanInfo: {
306
+ flashBorrowReserve: context.targetCollReserve.address,
307
+ flashLoanFee: context.targetCollReserve.getFlashLoanFee(),
308
+ },
298
309
  targetCollFlashBorrowIxn,
299
310
  depositTargetCollIxns: depositTargetCollIxns.ixns,
300
311
  withdrawSourceCollIxns,