@kamino-finance/klend-sdk 5.14.3 → 5.14.5

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 (122) hide show
  1. package/dist/classes/configItems.d.ts +166 -0
  2. package/dist/classes/configItems.d.ts.map +1 -0
  3. package/dist/classes/configItems.js +202 -0
  4. package/dist/classes/configItems.js.map +1 -0
  5. package/dist/classes/manager.d.ts +4 -7
  6. package/dist/classes/manager.d.ts.map +1 -1
  7. package/dist/classes/manager.js +37 -292
  8. package/dist/classes/manager.js.map +1 -1
  9. package/dist/classes/market.d.ts.map +1 -1
  10. package/dist/classes/market.js.map +1 -1
  11. package/dist/classes/reserve.d.ts +5 -14
  12. package/dist/classes/reserve.d.ts.map +1 -1
  13. package/dist/classes/reserve.js +93 -465
  14. package/dist/classes/reserve.js.map +1 -1
  15. package/dist/classes/utils.d.ts +1 -0
  16. package/dist/classes/utils.d.ts.map +1 -1
  17. package/dist/classes/utils.js +12 -0
  18. package/dist/classes/utils.js.map +1 -1
  19. package/dist/classes/vault.d.ts.map +1 -1
  20. package/dist/classes/vault.js +28 -1
  21. package/dist/classes/vault.js.map +1 -1
  22. package/dist/classes/vault_types.d.ts +1 -0
  23. package/dist/classes/vault_types.d.ts.map +1 -1
  24. package/dist/client_kamino_manager.d.ts.map +1 -1
  25. package/dist/client_kamino_manager.js +24 -11
  26. package/dist/client_kamino_manager.js.map +1 -1
  27. package/dist/idl.json +193 -16
  28. package/dist/idl_codegen/accounts/GlobalConfig.d.ts +40 -0
  29. package/dist/idl_codegen/accounts/GlobalConfig.d.ts.map +1 -0
  30. package/dist/idl_codegen/accounts/GlobalConfig.js +116 -0
  31. package/dist/idl_codegen/accounts/GlobalConfig.js.map +1 -0
  32. package/dist/idl_codegen/accounts/LendingMarket.d.ts +24 -3
  33. package/dist/idl_codegen/accounts/LendingMarket.d.ts.map +1 -1
  34. package/dist/idl_codegen/accounts/LendingMarket.js +25 -7
  35. package/dist/idl_codegen/accounts/LendingMarket.js.map +1 -1
  36. package/dist/idl_codegen/accounts/index.d.ts +2 -0
  37. package/dist/idl_codegen/accounts/index.d.ts.map +1 -1
  38. package/dist/idl_codegen/accounts/index.js +3 -1
  39. package/dist/idl_codegen/accounts/index.js.map +1 -1
  40. package/dist/idl_codegen/errors/custom.d.ts +35 -11
  41. package/dist/idl_codegen/errors/custom.d.ts.map +1 -1
  42. package/dist/idl_codegen/errors/custom.js +64 -22
  43. package/dist/idl_codegen/errors/custom.js.map +1 -1
  44. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts +2 -1
  45. package/dist/idl_codegen/instructions/idlMissingTypes.d.ts.map +1 -1
  46. package/dist/idl_codegen/instructions/idlMissingTypes.js +2 -1
  47. package/dist/idl_codegen/instructions/idlMissingTypes.js.map +1 -1
  48. package/dist/idl_codegen/instructions/index.d.ts +6 -0
  49. package/dist/idl_codegen/instructions/index.d.ts.map +1 -1
  50. package/dist/idl_codegen/instructions/index.js +7 -1
  51. package/dist/idl_codegen/instructions/index.js.map +1 -1
  52. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts +10 -0
  53. package/dist/idl_codegen/instructions/initGlobalConfig.d.ts.map +1 -0
  54. package/dist/idl_codegen/instructions/initGlobalConfig.js +19 -0
  55. package/dist/idl_codegen/instructions/initGlobalConfig.js.map +1 -0
  56. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts +13 -0
  57. package/dist/idl_codegen/instructions/updateGlobalConfig.d.ts.map +1 -0
  58. package/dist/idl_codegen/instructions/updateGlobalConfig.js +61 -0
  59. package/dist/idl_codegen/instructions/updateGlobalConfig.js.map +1 -0
  60. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts +7 -0
  61. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.d.ts.map +1 -0
  62. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js +16 -0
  63. package/dist/idl_codegen/instructions/updateGlobalConfigAdmin.js.map +1 -0
  64. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts +5 -4
  65. package/dist/idl_codegen/instructions/updateReserveConfig.d.ts.map +1 -1
  66. package/dist/idl_codegen/instructions/updateReserveConfig.js +7 -5
  67. package/dist/idl_codegen/instructions/updateReserveConfig.js.map +1 -1
  68. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts +2 -2
  69. package/dist/idl_codegen/instructions/withdrawProtocolFee.d.ts.map +1 -1
  70. package/dist/idl_codegen/instructions/withdrawProtocolFee.js +2 -6
  71. package/dist/idl_codegen/instructions/withdrawProtocolFee.js.map +1 -1
  72. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts +32 -0
  73. package/dist/idl_codegen/types/UpdateGlobalConfigMode.d.ts.map +1 -0
  74. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js +108 -0
  75. package/dist/idl_codegen/types/UpdateGlobalConfigMode.js.map +1 -0
  76. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts +33 -7
  77. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts.map +1 -1
  78. package/dist/idl_codegen/types/UpdateLendingMarketMode.js +60 -12
  79. package/dist/idl_codegen/types/UpdateLendingMarketMode.js.map +1 -1
  80. package/dist/idl_codegen/types/index.d.ts +6 -2
  81. package/dist/idl_codegen/types/index.d.ts.map +1 -1
  82. package/dist/idl_codegen/types/index.js +3 -1
  83. package/dist/idl_codegen/types/index.js.map +1 -1
  84. package/dist/utils/instruction.d.ts.map +1 -1
  85. package/dist/utils/instruction.js.map +1 -1
  86. package/dist/utils/lookupTable.d.ts.map +1 -1
  87. package/dist/utils/lookupTable.js +1 -6
  88. package/dist/utils/lookupTable.js.map +1 -1
  89. package/dist/utils/managerTypes.js +1 -1
  90. package/dist/utils/managerTypes.js.map +1 -1
  91. package/dist/utils/seeds.d.ts +16 -0
  92. package/dist/utils/seeds.d.ts.map +1 -1
  93. package/dist/utils/seeds.js +23 -1
  94. package/dist/utils/seeds.js.map +1 -1
  95. package/package.json +1 -1
  96. package/src/classes/configItems.ts +295 -0
  97. package/src/classes/manager.ts +49 -392
  98. package/src/classes/market.ts +2 -6
  99. package/src/classes/reserve.ts +122 -786
  100. package/src/classes/utils.ts +12 -0
  101. package/src/classes/vault.ts +47 -2
  102. package/src/classes/vault_types.ts +1 -0
  103. package/src/client_kamino_manager.ts +40 -14
  104. package/src/idl.json +193 -16
  105. package/src/idl_codegen/accounts/GlobalConfig.ts +125 -0
  106. package/src/idl_codegen/accounts/LendingMarket.ts +41 -9
  107. package/src/idl_codegen/accounts/index.ts +2 -0
  108. package/src/idl_codegen/errors/custom.ts +65 -20
  109. package/src/idl_codegen/instructions/idlMissingTypes.ts +4 -2
  110. package/src/idl_codegen/instructions/index.ts +9 -0
  111. package/src/idl_codegen/instructions/initGlobalConfig.ts +30 -0
  112. package/src/idl_codegen/instructions/updateGlobalConfig.ts +47 -0
  113. package/src/idl_codegen/instructions/updateGlobalConfigAdmin.ts +24 -0
  114. package/src/idl_codegen/instructions/updateReserveConfig.ts +10 -8
  115. package/src/idl_codegen/instructions/withdrawProtocolFee.ts +4 -8
  116. package/src/idl_codegen/types/UpdateGlobalConfigMode.ts +90 -0
  117. package/src/idl_codegen/types/UpdateLendingMarketMode.ts +73 -13
  118. package/src/idl_codegen/types/index.ts +16 -2
  119. package/src/utils/instruction.ts +2 -2
  120. package/src/utils/lookupTable.ts +1 -7
  121. package/src/utils/managerTypes.ts +1 -1
  122. package/src/utils/seeds.ts +25 -0
@@ -287,6 +287,18 @@ export function orThrow(message: string): never {
287
287
  throw new Error(message);
288
288
  }
289
289
 
290
+ export function blobEquals(left: Uint8Array, right: Uint8Array): boolean {
291
+ if (left.length !== right.length) {
292
+ return false;
293
+ }
294
+ for (let i = 0; i < left.length; ++i) {
295
+ if (left[i] !== right[i]) {
296
+ return false;
297
+ }
298
+ }
299
+ return true;
300
+ }
301
+
290
302
  /**
291
303
  * Returns an integer {@link Decimal} nearest to the given one.
292
304
  *
@@ -11,7 +11,13 @@ import {
11
11
  SYSVAR_RENT_PUBKEY,
12
12
  TransactionInstruction,
13
13
  } from '@solana/web3.js';
14
- import { getAssociatedTokenAddressSync, NATIVE_MINT, TOKEN_PROGRAM_ID, unpackAccount } from '@solana/spl-token';
14
+ import {
15
+ createCloseAccountInstruction,
16
+ getAssociatedTokenAddressSync,
17
+ NATIVE_MINT,
18
+ TOKEN_PROGRAM_ID,
19
+ unpackAccount,
20
+ } from '@solana/spl-token';
15
21
  import {
16
22
  getAssociatedTokenAddress,
17
23
  getTransferWsolIxs,
@@ -1064,6 +1070,7 @@ export class KaminoVaultClient {
1064
1070
  const withdrawIxs: WithdrawIxs = {
1065
1071
  unstakeFromFarmIfNeededIxs: [],
1066
1072
  withdrawIxs: [],
1073
+ postWithdrawIxs: [],
1067
1074
  };
1068
1075
 
1069
1076
  const shareLamportsToWithdraw = collToLamportsDecimal(shareAmount, vaultState.sharesMintDecimals.toNumber());
@@ -1099,6 +1106,13 @@ export class KaminoVaultClient {
1099
1106
  withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
1100
1107
  }
1101
1108
 
1109
+ // if the vault is for SOL return the ix to unwrap the SOL
1110
+ if (vaultState.tokenMint.equals(NATIVE_MINT)) {
1111
+ const userWsolAta = getAssociatedTokenAddress(NATIVE_MINT, user);
1112
+ const unwrapIx = createCloseAccountInstruction(userWsolAta, user, user, [], TOKEN_PROGRAM_ID);
1113
+ withdrawIxs.postWithdrawIxs.push(unwrapIx);
1114
+ }
1115
+
1102
1116
  return withdrawIxs;
1103
1117
  }
1104
1118
 
@@ -2293,7 +2307,38 @@ export class KaminoVaultClient {
2293
2307
  kaminoMarkets?: KaminoMarket[]
2294
2308
  ): Promise<PubkeyHashMap<PublicKey, MarketOverview>> {
2295
2309
  const vaultReservesStateMap = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
2296
- const vaultReservesState = Array.from(vaultReservesStateMap.values());
2310
+ const vaultReservesState: KaminoReserve[] = [];
2311
+
2312
+ const missingReserves = new PublicKeySet<PublicKey>([]);
2313
+ // filter the reserves that are not part of the vault allocation strategy
2314
+ vaultState.vaultAllocationStrategy.forEach(async (allocation) => {
2315
+ if (allocation.reserve.equals(PublicKey.default)) {
2316
+ return;
2317
+ }
2318
+ const reserve = vaultReservesStateMap.get(allocation.reserve);
2319
+ if (!reserve) {
2320
+ missingReserves.add(allocation.reserve);
2321
+ return;
2322
+ }
2323
+
2324
+ vaultReservesState.push(reserve);
2325
+ });
2326
+
2327
+ // read missing reserves
2328
+ const missingReservesStates = (await Reserve.fetchMultiple(this.getConnection(), missingReserves.toArray())).filter(
2329
+ (reserve) => reserve !== null
2330
+ );
2331
+ const missingReservesAndOracles = await getTokenOracleData(this.getConnection(), missingReservesStates);
2332
+ missingReservesAndOracles.forEach(([reserve, oracle], index) => {
2333
+ const fetchedReserve = new KaminoReserve(
2334
+ reserve,
2335
+ missingReserves.toArray()[index]!,
2336
+ oracle!,
2337
+ this.getConnection(),
2338
+ this.recentSlotDurationMs
2339
+ );
2340
+ vaultReservesState.push(fetchedReserve);
2341
+ });
2297
2342
 
2298
2343
  const vaultCollateralsPerReserve: PubkeyHashMap<PublicKey, MarketOverview> = new PubkeyHashMap();
2299
2344
 
@@ -48,6 +48,7 @@ export type DepositIxs = {
48
48
  export type WithdrawIxs = {
49
49
  unstakeFromFarmIfNeededIxs: TransactionInstruction[];
50
50
  withdrawIxs: TransactionInstruction[];
51
+ postWithdrawIxs: TransactionInstruction[]; // wSOL ATA close ix
51
52
  };
52
53
 
53
54
  /** The shares an user has in a vault (staked and unstaked), in tokens */
@@ -8,15 +8,20 @@ import {
8
8
  Signer,
9
9
  Transaction,
10
10
  TransactionInstruction,
11
+ TransactionMessage,
11
12
  TransactionSignature,
12
13
  VersionedTransaction,
13
14
  } from '@solana/web3.js';
14
15
  import {
15
16
  AssetReserveConfigCli,
16
17
  Chain,
18
+ createLookupTableIx,
17
19
  DEFAULT_RECENT_SLOT_DURATION_MS,
18
20
  encodeTokenName,
21
+ extendLookupTableIxs,
22
+ getLookupTableAccounts,
19
23
  getMedianSlotDurationInMsFromLastEpochs,
24
+ globalConfigPda,
20
25
  initLookupTableIx,
21
26
  KaminoManager,
22
27
  KaminoMarket,
@@ -27,6 +32,7 @@ import {
27
32
  MAINNET_BETA_CHAIN_ID,
28
33
  parseZeroPaddedUtf8,
29
34
  printHoldings,
35
+ PROGRAM_ID,
30
36
  Reserve,
31
37
  ReserveAllocationConfig,
32
38
  ReserveWithAddress,
@@ -153,7 +159,10 @@ async function main() {
153
159
 
154
160
  const _createReserveSig = await processTxn(env.client, env.payer, txnIxs[0], mode, 2500, [reserve]);
155
161
 
156
- const _updateReserveSig = await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000);
162
+ const [lut, createLutIxs] = await createUpdateReserveConfigLutIxs(env, marketAddress, reserve.publicKey);
163
+ await processTxn(env.client, env.payer, createLutIxs, mode, 2500, []);
164
+
165
+ const _updateSig = await processTxn(env.client, env.payer, txnIxs[1], mode, 2500, [], 400_000, 1000, [lut]);
157
166
 
158
167
  mode === 'execute' &&
159
168
  console.log(
@@ -895,7 +904,7 @@ async function main() {
895
904
  const withdrawSig = await processTxn(
896
905
  env.client,
897
906
  env.payer,
898
- [...withdrawIxs.unstakeFromFarmIfNeededIxs, ...withdrawIxs.withdrawIxs],
907
+ [...withdrawIxs.unstakeFromFarmIfNeededIxs, ...withdrawIxs.withdrawIxs, ...withdrawIxs.postWithdrawIxs],
899
908
  mode,
900
909
  2500,
901
910
  [],
@@ -1156,6 +1165,10 @@ async function main() {
1156
1165
  printHoldings(holdings);
1157
1166
  console.log(`Tokens per share for vault ${vaultAddress.toBase58()}: ${tokensPerShare}`);
1158
1167
  console.log('vaultOverview', vaultOverview);
1168
+
1169
+ for (const [reserveAddress, reserveOverview] of vaultOverview.reservesOverview) {
1170
+ console.log(`reserve ${reserveAddress.toBase58()} supplyAPY ${reserveOverview.supplyAPY}`);
1171
+ }
1159
1172
  });
1160
1173
 
1161
1174
  commands.command('get-oracle-mappings').action(async () => {
@@ -1608,7 +1621,8 @@ async function processTxn(
1608
1621
  priorityFeeMultiplier: number = 2500,
1609
1622
  extraSigners: Signer[],
1610
1623
  computeUnits: number = 200_000,
1611
- priorityFeeLamports: number = 1000
1624
+ priorityFeeLamports: number = 1000,
1625
+ luts: PublicKey[] = []
1612
1626
  ): Promise<TransactionSignature> {
1613
1627
  if (mode !== 'inspect' && mode !== 'simulate' && mode !== 'execute' && mode !== 'multisig') {
1614
1628
  throw new Error('Invalid mode: ' + mode + '. Must be one of: inspect/simulate/execute/multisig');
@@ -1628,25 +1642,27 @@ async function processTxn(
1628
1642
  } else {
1629
1643
  const microLamport = priorityFeeLamports * 10 ** 6; // 1000 lamports
1630
1644
  const microLamportsPrioritizationFee = microLamport / computeUnits;
1631
-
1632
- const tx = new Transaction();
1633
1645
  const { blockhash } = await web3Client.connection.getLatestBlockhash();
1646
+
1634
1647
  if (priorityFeeMultiplier) {
1635
1648
  const priorityFeeIxn = createAddExtraComputeUnitFeeTransaction(
1636
1649
  computeUnits,
1637
1650
  microLamportsPrioritizationFee * priorityFeeMultiplier
1638
1651
  );
1639
- tx.add(...priorityFeeIxn);
1652
+ ixs.push(...priorityFeeIxn);
1640
1653
  }
1641
- tx.recentBlockhash = blockhash;
1642
- tx.feePayer = admin.publicKey;
1643
- tx.add(...ixs);
1654
+
1655
+ const tx = new TransactionMessage({
1656
+ payerKey: admin.publicKey,
1657
+ recentBlockhash: blockhash,
1658
+ instructions: ixs,
1659
+ }).compileToV0Message(await getLookupTableAccounts(web3Client.connection, luts));
1644
1660
 
1645
1661
  if (mode === 'execute') {
1646
1662
  return await signSendAndConfirmRawTransactionWithRetry({
1647
1663
  mainConnection: web3Client.sendConnection,
1648
1664
  extraConnections: [],
1649
- tx: new VersionedTransaction(tx.compileMessage()),
1665
+ tx: new VersionedTransaction(tx),
1650
1666
  signers: [admin, ...extraSigners],
1651
1667
  commitment: 'confirmed',
1652
1668
  sendTransactionOptions: {
@@ -1655,9 +1671,7 @@ async function processTxn(
1655
1671
  },
1656
1672
  });
1657
1673
  } else if (mode === 'simulate') {
1658
- const simulation = await web3Client.sendConnection.simulateTransaction(
1659
- new VersionedTransaction(tx.compileMessage())
1660
- );
1674
+ const simulation = await web3Client.sendConnection.simulateTransaction(new VersionedTransaction(tx));
1661
1675
  if (simulation.value.logs && simulation.value.logs.length > 0) {
1662
1676
  console.log('Simulation: \n' + simulation.value.logs);
1663
1677
  } else {
@@ -1667,7 +1681,7 @@ async function processTxn(
1667
1681
  console.log(
1668
1682
  'Tx in B64',
1669
1683
  `https://explorer.solana.com/tx/inspector?message=${encodeURIComponent(
1670
- tx.serializeMessage().toString('base64')
1684
+ Buffer.from(tx.serialize()).toString('base64')
1671
1685
  )}`
1672
1686
  );
1673
1687
  }
@@ -1865,3 +1879,15 @@ function parseReserveConfigToFile(reserveConfig: ReserveConfig) {
1865
1879
  reserved2: Array(9).fill(0),
1866
1880
  };
1867
1881
  }
1882
+
1883
+ async function createUpdateReserveConfigLutIxs(
1884
+ env: Env,
1885
+ lendingMarketAddress: PublicKey,
1886
+ reserveAddress: PublicKey
1887
+ ): Promise<[PublicKey, TransactionInstruction[]]> {
1888
+ const [globalConfigAddress] = globalConfigPda(PROGRAM_ID);
1889
+ const contents = [globalConfigAddress, lendingMarketAddress, reserveAddress];
1890
+ const [createIx, lut] = await createLookupTableIx(env.connection, env.payer.publicKey);
1891
+ const extendIxs = extendLookupTableIxs(env.payer.publicKey, lut, contents);
1892
+ return [lut, [createIx, ...extendIxs]];
1893
+ }
package/src/idl.json CHANGED
@@ -230,10 +230,15 @@
230
230
  "name": "updateReserveConfig",
231
231
  "accounts": [
232
232
  {
233
- "name": "lendingMarketOwner",
233
+ "name": "signer",
234
234
  "isMut": false,
235
235
  "isSigner": true
236
236
  },
237
+ {
238
+ "name": "globalConfig",
239
+ "isMut": false,
240
+ "isSigner": false
241
+ },
237
242
  {
238
243
  "name": "lendingMarket",
239
244
  "isMut": false,
@@ -248,14 +253,16 @@
248
253
  "args": [
249
254
  {
250
255
  "name": "mode",
251
- "type": "u64"
256
+ "type": {
257
+ "defined": "UpdateConfigMode"
258
+ }
252
259
  },
253
260
  {
254
261
  "name": "value",
255
262
  "type": "bytes"
256
263
  },
257
264
  {
258
- "name": "skipValidation",
265
+ "name": "skipConfigIntegrityValidation",
259
266
  "type": "bool"
260
267
  }
261
268
  ]
@@ -305,9 +312,9 @@
305
312
  "name": "withdrawProtocolFee",
306
313
  "accounts": [
307
314
  {
308
- "name": "lendingMarketOwner",
315
+ "name": "globalConfig",
309
316
  "isMut": false,
310
- "isSigner": true
317
+ "isSigner": false
311
318
  },
312
319
  {
313
320
  "name": "lendingMarket",
@@ -335,7 +342,7 @@
335
342
  "isSigner": false
336
343
  },
337
344
  {
338
- "name": "lendingMarketOwnerAta",
345
+ "name": "feeCollectorAta",
339
346
  "isMut": true,
340
347
  "isSigner": false
341
348
  },
@@ -2932,14 +2939,93 @@
2932
2939
  }
2933
2940
  ]
2934
2941
  },
2942
+ {
2943
+ "name": "initGlobalConfig",
2944
+ "accounts": [
2945
+ {
2946
+ "name": "payer",
2947
+ "isMut": true,
2948
+ "isSigner": true
2949
+ },
2950
+ {
2951
+ "name": "globalConfig",
2952
+ "isMut": true,
2953
+ "isSigner": false
2954
+ },
2955
+ {
2956
+ "name": "programData",
2957
+ "isMut": false,
2958
+ "isSigner": false
2959
+ },
2960
+ {
2961
+ "name": "systemProgram",
2962
+ "isMut": false,
2963
+ "isSigner": false
2964
+ },
2965
+ {
2966
+ "name": "rent",
2967
+ "isMut": false,
2968
+ "isSigner": false
2969
+ }
2970
+ ],
2971
+ "args": []
2972
+ },
2973
+ {
2974
+ "name": "updateGlobalConfig",
2975
+ "accounts": [
2976
+ {
2977
+ "name": "globalAdmin",
2978
+ "isMut": false,
2979
+ "isSigner": true
2980
+ },
2981
+ {
2982
+ "name": "globalConfig",
2983
+ "isMut": true,
2984
+ "isSigner": false
2985
+ }
2986
+ ],
2987
+ "args": [
2988
+ {
2989
+ "name": "mode",
2990
+ "type": {
2991
+ "defined": "UpdateGlobalConfigMode"
2992
+ }
2993
+ },
2994
+ {
2995
+ "name": "value",
2996
+ "type": "bytes"
2997
+ }
2998
+ ]
2999
+ },
3000
+ {
3001
+ "name": "updateGlobalConfigAdmin",
3002
+ "accounts": [
3003
+ {
3004
+ "name": "pendingAdmin",
3005
+ "isMut": false,
3006
+ "isSigner": true
3007
+ },
3008
+ {
3009
+ "name": "globalConfig",
3010
+ "isMut": true,
3011
+ "isSigner": false
3012
+ }
3013
+ ],
3014
+ "args": []
3015
+ },
2935
3016
  {
2936
3017
  "name": "idlMissingTypes",
2937
3018
  "accounts": [
2938
3019
  {
2939
- "name": "lendingMarketOwner",
3020
+ "name": "signer",
2940
3021
  "isMut": false,
2941
3022
  "isSigner": true
2942
3023
  },
3024
+ {
3025
+ "name": "globalConfig",
3026
+ "isMut": false,
3027
+ "isSigner": false
3028
+ },
2943
3029
  {
2944
3030
  "name": "lendingMarket",
2945
3031
  "isMut": false,
@@ -3134,6 +3220,47 @@
3134
3220
  ]
3135
3221
  }
3136
3222
  },
3223
+ {
3224
+ "name": "GlobalConfig",
3225
+ "type": {
3226
+ "kind": "struct",
3227
+ "fields": [
3228
+ {
3229
+ "name": "globalAdmin",
3230
+ "docs": [
3231
+ "Global admin of the program"
3232
+ ],
3233
+ "type": "publicKey"
3234
+ },
3235
+ {
3236
+ "name": "pendingAdmin",
3237
+ "docs": [
3238
+ "Pending admin must sign a specific transaction to become the global admin"
3239
+ ],
3240
+ "type": "publicKey"
3241
+ },
3242
+ {
3243
+ "name": "feeCollector",
3244
+ "docs": [
3245
+ "Fee collector is the only allowed owner of token accounts receiving protocol fees"
3246
+ ],
3247
+ "type": "publicKey"
3248
+ },
3249
+ {
3250
+ "name": "padding",
3251
+ "docs": [
3252
+ "Padding to make the struct size 1024 bytes"
3253
+ ],
3254
+ "type": {
3255
+ "array": [
3256
+ "u8",
3257
+ 928
3258
+ ]
3259
+ }
3260
+ }
3261
+ ]
3262
+ }
3263
+ },
3137
3264
  {
3138
3265
  "name": "LendingMarket",
3139
3266
  "type": {
@@ -3353,18 +3480,33 @@
3353
3480
  "type": "u64"
3354
3481
  },
3355
3482
  {
3356
- "name": "obligationOrdersEnabled",
3483
+ "name": "obligationOrderExecutionEnabled",
3357
3484
  "docs": [
3358
3485
  "Whether the obligation orders should be evaluated during liquidations."
3359
3486
  ],
3360
3487
  "type": "u8"
3361
3488
  },
3489
+ {
3490
+ "name": "immutable",
3491
+ "docs": [
3492
+ "Whether the lending market is set as immutable."
3493
+ ],
3494
+ "type": "u8"
3495
+ },
3496
+ {
3497
+ "name": "obligationOrderCreationEnabled",
3498
+ "docs": [
3499
+ "Whether new obligation orders can be created.",
3500
+ "Note: updating or cancelling existing orders is *not* affected by this flag."
3501
+ ],
3502
+ "type": "u8"
3503
+ },
3362
3504
  {
3363
3505
  "name": "padding2",
3364
3506
  "type": {
3365
3507
  "array": [
3366
3508
  "u8",
3367
- 7
3509
+ 5
3368
3510
  ]
3369
3511
  }
3370
3512
  },
@@ -4186,7 +4328,27 @@
4186
4328
  "name": "UpdateInitialDepositAmount"
4187
4329
  },
4188
4330
  {
4189
- "name": "UpdateObligationOrdersEnabled"
4331
+ "name": "UpdateObligationOrderExecutionEnabled"
4332
+ },
4333
+ {
4334
+ "name": "UpdateImmutableFlag"
4335
+ },
4336
+ {
4337
+ "name": "UpdateObligationOrderCreationEnabled"
4338
+ }
4339
+ ]
4340
+ }
4341
+ },
4342
+ {
4343
+ "name": "UpdateGlobalConfigMode",
4344
+ "type": {
4345
+ "kind": "enum",
4346
+ "variants": [
4347
+ {
4348
+ "name": "PendingAdmin"
4349
+ },
4350
+ {
4351
+ "name": "FeeCollector"
4190
4352
  }
4191
4353
  ]
4192
4354
  }
@@ -5865,7 +6027,7 @@
5865
6027
  },
5866
6028
  {
5867
6029
  "code": 6093,
5868
- "name": "WorseLTVBlocked",
6030
+ "name": "WorseLtvBlocked",
5869
6031
  "msg": "Cannot get the obligation in a worse position"
5870
6032
  },
5871
6033
  {
@@ -5900,8 +6062,8 @@
5900
6062
  },
5901
6063
  {
5902
6064
  "code": 6100,
5903
- "name": "LiquidationLowestLTVPriority",
5904
- "msg": "Liquidation must prioritize the collateral with the lowest LTV"
6065
+ "name": "LiquidationLowestLiquidationLtvPriority",
6066
+ "msg": "Liquidation must prioritize the collateral with the lowest liquidation LTV"
5905
6067
  },
5906
6068
  {
5907
6069
  "code": 6101,
@@ -5990,12 +6152,12 @@
5990
6152
  },
5991
6153
  {
5992
6154
  "code": 6118,
5993
- "name": "MinLtvAssetsPriority",
5994
- "msg": "The operation must prioritize the collateral with the lowest LTV"
6155
+ "name": "LowestLtvAssetsPriority",
6156
+ "msg": "Withdrawing must prioritize the collateral with the lowest reserve max-LTV"
5995
6157
  },
5996
6158
  {
5997
6159
  "code": 6119,
5998
- "name": "WorseLTVThanUnhealthyLTV",
6160
+ "name": "WorseLtvThanUnhealthyLtv",
5999
6161
  "msg": "Cannot get the obligation liquidatable"
6000
6162
  },
6001
6163
  {
@@ -6032,6 +6194,21 @@
6032
6194
  "code": 6126,
6033
6195
  "name": "OperationNotPermittedWithCurrentObligationOrders",
6034
6196
  "msg": "Single debt, single collateral obligation orders have to be cancelled before changing the deposit/borrow count"
6197
+ },
6198
+ {
6199
+ "code": 6127,
6200
+ "name": "OperationNotPermittedMarketImmutable",
6201
+ "msg": "Cannot update lending market because it is set as immutable"
6202
+ },
6203
+ {
6204
+ "code": 6128,
6205
+ "name": "OrderCreationDisabled",
6206
+ "msg": "Creation of new orders is disabled"
6207
+ },
6208
+ {
6209
+ "code": 6129,
6210
+ "name": "NoUpgradeAuthority",
6211
+ "msg": "Cannot initialize global config because there is no upgrade authority to the program"
6035
6212
  }
6036
6213
  ]
6037
6214
  }
@@ -0,0 +1,125 @@
1
+ import { PublicKey, Connection } from "@solana/web3.js"
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 GlobalConfigFields {
8
+ /** Global admin of the program */
9
+ globalAdmin: PublicKey
10
+ /** Pending admin must sign a specific transaction to become the global admin */
11
+ pendingAdmin: PublicKey
12
+ /** Fee collector is the only allowed owner of token accounts receiving protocol fees */
13
+ feeCollector: PublicKey
14
+ /** Padding to make the struct size 1024 bytes */
15
+ padding: Array<number>
16
+ }
17
+
18
+ export interface GlobalConfigJSON {
19
+ /** Global admin of the program */
20
+ globalAdmin: string
21
+ /** Pending admin must sign a specific transaction to become the global admin */
22
+ pendingAdmin: string
23
+ /** Fee collector is the only allowed owner of token accounts receiving protocol fees */
24
+ feeCollector: string
25
+ /** Padding to make the struct size 1024 bytes */
26
+ padding: Array<number>
27
+ }
28
+
29
+ export class GlobalConfig {
30
+ /** Global admin of the program */
31
+ readonly globalAdmin: PublicKey
32
+ /** Pending admin must sign a specific transaction to become the global admin */
33
+ readonly pendingAdmin: PublicKey
34
+ /** Fee collector is the only allowed owner of token accounts receiving protocol fees */
35
+ readonly feeCollector: PublicKey
36
+ /** Padding to make the struct size 1024 bytes */
37
+ readonly padding: Array<number>
38
+
39
+ static readonly discriminator = Buffer.from([
40
+ 149, 8, 156, 202, 160, 252, 176, 217,
41
+ ])
42
+
43
+ static readonly layout = borsh.struct([
44
+ borsh.publicKey("globalAdmin"),
45
+ borsh.publicKey("pendingAdmin"),
46
+ borsh.publicKey("feeCollector"),
47
+ borsh.array(borsh.u8(), 928, "padding"),
48
+ ])
49
+
50
+ constructor(fields: GlobalConfigFields) {
51
+ this.globalAdmin = fields.globalAdmin
52
+ this.pendingAdmin = fields.pendingAdmin
53
+ this.feeCollector = fields.feeCollector
54
+ this.padding = fields.padding
55
+ }
56
+
57
+ static async fetch(
58
+ c: Connection,
59
+ address: PublicKey,
60
+ programId: PublicKey = PROGRAM_ID
61
+ ): Promise<GlobalConfig | null> {
62
+ const info = await c.getAccountInfo(address)
63
+
64
+ if (info === null) {
65
+ return null
66
+ }
67
+ if (!info.owner.equals(programId)) {
68
+ throw new Error("account doesn't belong to this program")
69
+ }
70
+
71
+ return this.decode(info.data)
72
+ }
73
+
74
+ static async fetchMultiple(
75
+ c: Connection,
76
+ addresses: PublicKey[],
77
+ programId: PublicKey = PROGRAM_ID
78
+ ): Promise<Array<GlobalConfig | null>> {
79
+ const infos = await c.getMultipleAccountsInfo(addresses)
80
+
81
+ return infos.map((info) => {
82
+ if (info === null) {
83
+ return null
84
+ }
85
+ if (!info.owner.equals(programId)) {
86
+ throw new Error("account doesn't belong to this program")
87
+ }
88
+
89
+ return this.decode(info.data)
90
+ })
91
+ }
92
+
93
+ static decode(data: Buffer): GlobalConfig {
94
+ if (!data.slice(0, 8).equals(GlobalConfig.discriminator)) {
95
+ throw new Error("invalid account discriminator")
96
+ }
97
+
98
+ const dec = GlobalConfig.layout.decode(data.slice(8))
99
+
100
+ return new GlobalConfig({
101
+ globalAdmin: dec.globalAdmin,
102
+ pendingAdmin: dec.pendingAdmin,
103
+ feeCollector: dec.feeCollector,
104
+ padding: dec.padding,
105
+ })
106
+ }
107
+
108
+ toJSON(): GlobalConfigJSON {
109
+ return {
110
+ globalAdmin: this.globalAdmin.toString(),
111
+ pendingAdmin: this.pendingAdmin.toString(),
112
+ feeCollector: this.feeCollector.toString(),
113
+ padding: this.padding,
114
+ }
115
+ }
116
+
117
+ static fromJSON(obj: GlobalConfigJSON): GlobalConfig {
118
+ return new GlobalConfig({
119
+ globalAdmin: new PublicKey(obj.globalAdmin),
120
+ pendingAdmin: new PublicKey(obj.pendingAdmin),
121
+ feeCollector: new PublicKey(obj.feeCollector),
122
+ padding: obj.padding,
123
+ })
124
+ }
125
+ }