@kamino-finance/klend-sdk 5.0.4 → 5.0.6

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 (239) hide show
  1. package/dist/classes/fraction.d.ts.map +1 -1
  2. package/dist/classes/fraction.js.map +1 -1
  3. package/dist/classes/manager.d.ts +38 -4
  4. package/dist/classes/manager.d.ts.map +1 -1
  5. package/dist/classes/manager.js +112 -5
  6. package/dist/classes/manager.js.map +1 -1
  7. package/dist/classes/market.d.ts +4 -0
  8. package/dist/classes/market.d.ts.map +1 -1
  9. package/dist/classes/market.js +17 -25
  10. package/dist/classes/market.js.map +1 -1
  11. package/dist/classes/obligation.d.ts +3 -4
  12. package/dist/classes/obligation.d.ts.map +1 -1
  13. package/dist/classes/obligation.js +96 -27
  14. package/dist/classes/obligation.js.map +1 -1
  15. package/dist/classes/reserve.d.ts +2 -1
  16. package/dist/classes/reserve.d.ts.map +1 -1
  17. package/dist/classes/reserve.js +32 -29
  18. package/dist/classes/reserve.js.map +1 -1
  19. package/dist/classes/utils.d.ts +3 -0
  20. package/dist/classes/utils.d.ts.map +1 -1
  21. package/dist/classes/utils.js +30 -0
  22. package/dist/classes/utils.js.map +1 -1
  23. package/dist/classes/vault.d.ts +12 -8
  24. package/dist/classes/vault.d.ts.map +1 -1
  25. package/dist/classes/vault.js +94 -66
  26. package/dist/classes/vault.js.map +1 -1
  27. package/dist/client_kamino_manager.d.ts.map +1 -1
  28. package/dist/client_kamino_manager.js +15 -1
  29. package/dist/client_kamino_manager.js.map +1 -1
  30. package/dist/idl.json +27 -2
  31. package/dist/idl_codegen/accounts/LendingMarket.d.ts +6 -0
  32. package/dist/idl_codegen/accounts/LendingMarket.d.ts.map +1 -1
  33. package/dist/idl_codegen/accounts/LendingMarket.js +8 -1
  34. package/dist/idl_codegen/accounts/LendingMarket.js.map +1 -1
  35. package/dist/idl_codegen/accounts/Obligation.d.ts +3 -12
  36. package/dist/idl_codegen/accounts/Obligation.d.ts.map +1 -1
  37. package/dist/idl_codegen/accounts/Obligation.js +1 -4
  38. package/dist/idl_codegen/accounts/Obligation.js.map +1 -1
  39. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.d.ts +20 -0
  40. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.d.ts.map +1 -1
  41. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.js +33 -1
  42. package/dist/idl_codegen/types/UpdateLendingMarketConfigValue.js.map +1 -1
  43. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts +13 -0
  44. package/dist/idl_codegen/types/UpdateLendingMarketMode.d.ts.map +1 -1
  45. package/dist/idl_codegen/types/UpdateLendingMarketMode.js +25 -1
  46. package/dist/idl_codegen/types/UpdateLendingMarketMode.js.map +1 -1
  47. package/dist/idl_codegen/types/index.d.ts +4 -4
  48. package/dist/idl_codegen/types/index.d.ts.map +1 -1
  49. package/dist/idl_codegen/types/index.js.map +1 -1
  50. package/dist/idl_codegen_kamino_vault/accounts/Reserve.d.ts +3 -3
  51. package/dist/idl_codegen_kamino_vault/accounts/Reserve.d.ts.map +1 -1
  52. package/dist/idl_codegen_kamino_vault/accounts/Reserve.js +22 -18
  53. package/dist/idl_codegen_kamino_vault/accounts/Reserve.js.map +1 -1
  54. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts +45 -15
  55. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts.map +1 -1
  56. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js +101 -39
  57. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js.map +1 -1
  58. package/dist/idl_codegen_kamino_vault/accounts/index.d.ts +4 -4
  59. package/dist/idl_codegen_kamino_vault/accounts/index.d.ts.map +1 -1
  60. package/dist/idl_codegen_kamino_vault/accounts/index.js.map +1 -1
  61. package/dist/idl_codegen_kamino_vault/errors/anchor.d.ts.map +1 -1
  62. package/dist/idl_codegen_kamino_vault/errors/anchor.js +162 -162
  63. package/dist/idl_codegen_kamino_vault/errors/anchor.js.map +1 -1
  64. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts +144 -32
  65. package/dist/idl_codegen_kamino_vault/errors/custom.d.ts.map +1 -1
  66. package/dist/idl_codegen_kamino_vault/errors/custom.js +305 -109
  67. package/dist/idl_codegen_kamino_vault/errors/custom.js.map +1 -1
  68. package/dist/idl_codegen_kamino_vault/errors/index.d.ts +3 -3
  69. package/dist/idl_codegen_kamino_vault/errors/index.d.ts.map +1 -1
  70. package/dist/idl_codegen_kamino_vault/errors/index.js +7 -2
  71. package/dist/idl_codegen_kamino_vault/errors/index.js.map +1 -1
  72. package/dist/idl_codegen_kamino_vault/instructions/deposit.d.ts +4 -2
  73. package/dist/idl_codegen_kamino_vault/instructions/deposit.d.ts.map +1 -1
  74. package/dist/idl_codegen_kamino_vault/instructions/deposit.js +3 -1
  75. package/dist/idl_codegen_kamino_vault/instructions/deposit.js.map +1 -1
  76. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.d.ts +13 -0
  77. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.d.ts.map +1 -0
  78. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.js +47 -0
  79. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.js.map +1 -0
  80. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts +18 -10
  81. package/dist/idl_codegen_kamino_vault/instructions/index.d.ts.map +1 -1
  82. package/dist/idl_codegen_kamino_vault/instructions/index.js +9 -1
  83. package/dist/idl_codegen_kamino_vault/instructions/index.js.map +1 -1
  84. package/dist/idl_codegen_kamino_vault/instructions/initVault.d.ts +2 -1
  85. package/dist/idl_codegen_kamino_vault/instructions/initVault.d.ts.map +1 -1
  86. package/dist/idl_codegen_kamino_vault/instructions/initVault.js +1 -0
  87. package/dist/idl_codegen_kamino_vault/instructions/initVault.js.map +1 -1
  88. package/dist/idl_codegen_kamino_vault/instructions/invest.d.ts +6 -2
  89. package/dist/idl_codegen_kamino_vault/instructions/invest.d.ts.map +1 -1
  90. package/dist/idl_codegen_kamino_vault/instructions/invest.js +9 -1
  91. package/dist/idl_codegen_kamino_vault/instructions/invest.js.map +1 -1
  92. package/dist/idl_codegen_kamino_vault/instructions/updateAdmin.d.ts +7 -0
  93. package/dist/idl_codegen_kamino_vault/instructions/updateAdmin.d.ts.map +1 -0
  94. package/dist/idl_codegen_kamino_vault/instructions/updateAdmin.js +16 -0
  95. package/dist/idl_codegen_kamino_vault/instructions/updateAdmin.js.map +1 -0
  96. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.d.ts +2 -2
  97. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.d.ts.map +1 -1
  98. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.js +1 -1
  99. package/dist/idl_codegen_kamino_vault/instructions/updateReserveAllocation.js.map +1 -1
  100. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.d.ts +14 -0
  101. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.d.ts.map +1 -0
  102. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.js +52 -0
  103. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.js.map +1 -0
  104. package/dist/idl_codegen_kamino_vault/instructions/withdraw.d.ts +4 -2
  105. package/dist/idl_codegen_kamino_vault/instructions/withdraw.d.ts.map +1 -1
  106. package/dist/idl_codegen_kamino_vault/instructions/withdraw.js +8 -2
  107. package/dist/idl_codegen_kamino_vault/instructions/withdraw.js.map +1 -1
  108. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.d.ts +23 -0
  109. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.d.ts.map +1 -0
  110. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.js +51 -0
  111. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.js.map +1 -0
  112. package/dist/idl_codegen_kamino_vault/programId.d.ts +1 -1
  113. package/dist/idl_codegen_kamino_vault/programId.d.ts.map +1 -1
  114. package/dist/idl_codegen_kamino_vault/programId.js +1 -1
  115. package/dist/idl_codegen_kamino_vault/programId.js.map +1 -1
  116. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.d.ts +2 -2
  117. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.d.ts.map +1 -1
  118. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.js +4 -1
  119. package/dist/idl_codegen_kamino_vault/types/BigFractionBytes.js.map +1 -1
  120. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.d.ts +1 -1
  121. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.d.ts.map +1 -1
  122. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.js +1 -1
  123. package/dist/idl_codegen_kamino_vault/types/BorrowRateCurve.js.map +1 -1
  124. package/dist/idl_codegen_kamino_vault/types/CurvePoint.d.ts +1 -1
  125. package/dist/idl_codegen_kamino_vault/types/CurvePoint.d.ts.map +1 -1
  126. package/dist/idl_codegen_kamino_vault/types/CurvePoint.js +1 -1
  127. package/dist/idl_codegen_kamino_vault/types/CurvePoint.js.map +1 -1
  128. package/dist/idl_codegen_kamino_vault/types/LastUpdate.d.ts +2 -2
  129. package/dist/idl_codegen_kamino_vault/types/LastUpdate.d.ts.map +1 -1
  130. package/dist/idl_codegen_kamino_vault/types/LastUpdate.js +6 -1
  131. package/dist/idl_codegen_kamino_vault/types/LastUpdate.js.map +1 -1
  132. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.d.ts +2 -2
  133. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.d.ts.map +1 -1
  134. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.js +1 -1
  135. package/dist/idl_codegen_kamino_vault/types/PriceHeuristic.js.map +1 -1
  136. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.d.ts +2 -2
  137. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.d.ts.map +1 -1
  138. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.js +1 -1
  139. package/dist/idl_codegen_kamino_vault/types/PythConfiguration.js.map +1 -1
  140. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.d.ts +3 -3
  141. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.d.ts.map +1 -1
  142. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.js +5 -5
  143. package/dist/idl_codegen_kamino_vault/types/ReserveCollateral.js.map +1 -1
  144. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.d.ts +27 -24
  145. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.d.ts.map +1 -1
  146. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.js +59 -53
  147. package/dist/idl_codegen_kamino_vault/types/ReserveConfig.js.map +1 -1
  148. package/dist/idl_codegen_kamino_vault/types/ReserveFees.d.ts +2 -2
  149. package/dist/idl_codegen_kamino_vault/types/ReserveFees.d.ts.map +1 -1
  150. package/dist/idl_codegen_kamino_vault/types/ReserveFees.js +5 -1
  151. package/dist/idl_codegen_kamino_vault/types/ReserveFees.js.map +1 -1
  152. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.d.ts +11 -3
  153. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.d.ts.map +1 -1
  154. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.js +25 -17
  155. package/dist/idl_codegen_kamino_vault/types/ReserveLiquidity.js.map +1 -1
  156. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.d.ts +2 -2
  157. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.d.ts.map +1 -1
  158. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.js +3 -3
  159. package/dist/idl_codegen_kamino_vault/types/ScopeConfiguration.js.map +1 -1
  160. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.d.ts +2 -2
  161. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.d.ts.map +1 -1
  162. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.js +1 -1
  163. package/dist/idl_codegen_kamino_vault/types/SwitchboardConfiguration.js.map +1 -1
  164. package/dist/idl_codegen_kamino_vault/types/TokenInfo.d.ts +3 -3
  165. package/dist/idl_codegen_kamino_vault/types/TokenInfo.d.ts.map +1 -1
  166. package/dist/idl_codegen_kamino_vault/types/TokenInfo.js +11 -11
  167. package/dist/idl_codegen_kamino_vault/types/TokenInfo.js.map +1 -1
  168. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.d.ts +18 -8
  169. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.d.ts.map +1 -1
  170. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.js +27 -13
  171. package/dist/idl_codegen_kamino_vault/types/VaultAllocation.js.map +1 -1
  172. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.d.ts +110 -0
  173. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.d.ts.map +1 -0
  174. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.js +242 -0
  175. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.js.map +1 -0
  176. package/dist/idl_codegen_kamino_vault/types/index.d.ts +34 -30
  177. package/dist/idl_codegen_kamino_vault/types/index.d.ts.map +1 -1
  178. package/dist/idl_codegen_kamino_vault/types/index.js +26 -1
  179. package/dist/idl_codegen_kamino_vault/types/index.js.map +1 -1
  180. package/dist/utils/ObligationType.d.ts.map +1 -1
  181. package/dist/utils/ObligationType.js.map +1 -1
  182. package/dist/utils/managerTypes.d.ts.map +1 -1
  183. package/dist/utils/managerTypes.js.map +1 -1
  184. package/dist/utils/pubkey.d.ts.map +1 -1
  185. package/dist/utils/pubkey.js.map +1 -1
  186. package/dist/utils/rpc.d.ts.map +1 -1
  187. package/dist/utils/rpc.js +2 -1
  188. package/dist/utils/rpc.js.map +1 -1
  189. package/package.json +2 -1
  190. package/src/classes/fraction.ts +5 -0
  191. package/src/classes/manager.ts +136 -5
  192. package/src/classes/market.ts +19 -2
  193. package/src/classes/obligation.ts +141 -30
  194. package/src/classes/reserve.ts +70 -41
  195. package/src/classes/utils.ts +30 -0
  196. package/src/classes/vault.ts +123 -49
  197. package/src/client_kamino_manager.ts +19 -1
  198. package/src/idl_codegen/accounts/LendingMarket.ts +12 -1
  199. package/src/idl_codegen/accounts/Obligation.ts +3 -12
  200. package/src/idl_codegen/types/UpdateLendingMarketConfigValue.ts +43 -0
  201. package/src/idl_codegen/types/UpdateLendingMarketMode.ts +30 -0
  202. package/src/idl_codegen/types/index.ts +4 -0
  203. package/src/idl_codegen_kamino_vault/accounts/Reserve.ts +132 -105
  204. package/src/idl_codegen_kamino_vault/accounts/VaultState.ts +217 -124
  205. package/src/idl_codegen_kamino_vault/accounts/index.ts +4 -4
  206. package/src/idl_codegen_kamino_vault/errors/anchor.ts +335 -326
  207. package/src/idl_codegen_kamino_vault/errors/custom.ts +353 -157
  208. package/src/idl_codegen_kamino_vault/errors/index.ts +35 -22
  209. package/src/idl_codegen_kamino_vault/instructions/deposit.ts +33 -25
  210. package/src/idl_codegen_kamino_vault/instructions/giveUpPendingFees.ts +40 -0
  211. package/src/idl_codegen_kamino_vault/instructions/index.ts +27 -10
  212. package/src/idl_codegen_kamino_vault/instructions/initVault.ts +25 -20
  213. package/src/idl_codegen_kamino_vault/instructions/invest.ts +40 -25
  214. package/src/idl_codegen_kamino_vault/instructions/updateAdmin.ts +24 -0
  215. package/src/idl_codegen_kamino_vault/instructions/updateReserveAllocation.ts +24 -24
  216. package/src/idl_codegen_kamino_vault/instructions/updateVaultConfig.ts +49 -0
  217. package/src/idl_codegen_kamino_vault/instructions/withdraw.ts +45 -33
  218. package/src/idl_codegen_kamino_vault/instructions/withdrawPendingFees.ts +75 -0
  219. package/src/idl_codegen_kamino_vault/programId.ts +5 -3
  220. package/src/idl_codegen_kamino_vault/types/BigFractionBytes.ts +24 -18
  221. package/src/idl_codegen_kamino_vault/types/BorrowRateCurve.ts +21 -16
  222. package/src/idl_codegen_kamino_vault/types/CurvePoint.ts +21 -18
  223. package/src/idl_codegen_kamino_vault/types/LastUpdate.ts +32 -27
  224. package/src/idl_codegen_kamino_vault/types/PriceHeuristic.ts +25 -22
  225. package/src/idl_codegen_kamino_vault/types/PythConfiguration.ts +14 -14
  226. package/src/idl_codegen_kamino_vault/types/ReserveCollateral.ts +35 -35
  227. package/src/idl_codegen_kamino_vault/types/ReserveConfig.ts +232 -191
  228. package/src/idl_codegen_kamino_vault/types/ReserveFees.ts +27 -23
  229. package/src/idl_codegen_kamino_vault/types/ReserveLiquidity.ts +116 -98
  230. package/src/idl_codegen_kamino_vault/types/ScopeConfiguration.ts +25 -25
  231. package/src/idl_codegen_kamino_vault/types/SwitchboardConfiguration.ts +21 -18
  232. package/src/idl_codegen_kamino_vault/types/TokenInfo.ts +92 -74
  233. package/src/idl_codegen_kamino_vault/types/VaultAllocation.ts +67 -49
  234. package/src/idl_codegen_kamino_vault/types/VaultConfigField.ts +270 -0
  235. package/src/idl_codegen_kamino_vault/types/index.ts +77 -30
  236. package/src/utils/ObligationType.ts +6 -0
  237. package/src/utils/managerTypes.ts +1 -0
  238. package/src/utils/pubkey.ts +2 -0
  239. package/src/utils/rpc.ts +3 -1
@@ -31,9 +31,11 @@ import bs58 from 'bs58';
31
31
  import { OraclePrices, Scope } from '@kamino-finance/scope-sdk';
32
32
  import { Fraction } from './fraction';
33
33
  import { chunks, KaminoPrices, MintToPriceMap } from '@kamino-finance/kliquidity-sdk';
34
- import { parseTokenSymbol } from './utils';
34
+ import { parseTokenSymbol, parseZeroPaddedUtf8 } from './utils';
35
35
  import SwitchboardProgram from '@switchboard-xyz/sbv2-lite';
36
36
  import { ObligationZP } from '../idl_codegen/zero_padding';
37
+ import { ReserveStatus } from '../idl_codegen/types';
38
+ import { getProgramAccounts } from '../utils/rpc';
37
39
 
38
40
  export interface ReserveRewardInfo {
39
41
  rewardsPerSecond: Decimal; // not lamport
@@ -84,8 +86,11 @@ export class KaminoMarket {
84
86
  * Load a new market with all of its associated reserves
85
87
  * @param connection
86
88
  * @param marketAddress
89
+ * @param recentSlotDurationMs
87
90
  * @param programId
91
+ * @param withReserves
88
92
  * @param setupLocalTest
93
+ * @param withReserves
89
94
  */
90
95
  static async load(
91
96
  connection: Connection,
@@ -175,6 +180,10 @@ export class KaminoMarket {
175
180
  return lendingMarketAuthPda(this.getAddress(), this.programId)[0];
176
181
  }
177
182
 
183
+ getName(): string {
184
+ return parseZeroPaddedUtf8(this.state.name);
185
+ }
186
+
178
187
  async getObligationDepositByWallet(
179
188
  owner: PublicKey,
180
189
  mint: PublicKey,
@@ -524,7 +533,6 @@ export class KaminoMarket {
524
533
  * @param tag
525
534
  */
526
535
  async getAllObligationsForMarket(tag?: number): Promise<KaminoObligation[]> {
527
- const { getProgramAccounts } = await import('../utils/rpc');
528
536
  const filters = [
529
537
  {
530
538
  dataSize: Obligation.layout.span + 8,
@@ -1082,6 +1090,10 @@ export class KaminoMarket {
1082
1090
  const spot: MintToPriceMap = {};
1083
1091
  const twaps: MintToPriceMap = {};
1084
1092
  for (const reserve of this.reserves.values()) {
1093
+ if (reserve.state.config.status === ReserveStatus.Obsolete.discriminator) {
1094
+ // skip obsolete reserves
1095
+ continue;
1096
+ }
1085
1097
  const tokenMint = reserve.getLiquidityMint().toString();
1086
1098
  const tokenName = reserve.getTokenSymbol();
1087
1099
  const oracle = reserve.state.config.tokenInfo.scopeConfiguration.priceFeed;
@@ -1119,6 +1131,11 @@ export class KaminoMarket {
1119
1131
  const switchboardV2 = await SwitchboardProgram.loadMainnet(this.connection);
1120
1132
 
1121
1133
  for (const reserve of this.reserves.values()) {
1134
+ if (reserve.state.config.status === ReserveStatus.Obsolete.discriminator) {
1135
+ // skip obsolete reserves
1136
+ continue;
1137
+ }
1138
+
1122
1139
  const tokenMint = reserve.getLiquidityMint().toString();
1123
1140
  const tokenName = reserve.getTokenSymbol();
1124
1141
  const scopeOracle = reserve.state.config.tokenInfo.scopeConfiguration.priceFeed;
@@ -362,11 +362,14 @@ export class KaminoObligation {
362
362
  collateralExchangeRates: Map<PublicKey, Decimal>
363
363
  ): ObligationCollateral[] {
364
364
  const newDeposits: ObligationCollateral[] = [];
365
+ const depositIndex = obligationDeposits.findIndex((deposit) => deposit.depositReserve.equals(changeReserve));
366
+
367
+ // Always copy the previous deposits and modify the changeReserve one if it exists
365
368
  for (let i = 0; i < obligationDeposits.length; i++) {
366
369
  if (obligationDeposits[i].depositReserve.equals(changeReserve)) {
367
370
  const coll: ObligationCollateralFields = { ...obligationDeposits[i] };
368
371
  const exchangeRate = collateralExchangeRates.get(changeReserve)!;
369
- const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate);
372
+ const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate).toFixed(0);
370
373
  const updatedDeposit = new Decimal(obligationDeposits[i].depositedAmount.toNumber()).add(changeInCollateral);
371
374
  coll.depositedAmount = new BN(positiveOrZero(updatedDeposit).toString());
372
375
  newDeposits.push(new ObligationCollateral(coll));
@@ -375,6 +378,25 @@ export class KaminoObligation {
375
378
  }
376
379
  }
377
380
 
381
+ if (depositIndex === -1) {
382
+ // If the reserve is not in the obligation, we add it
383
+ const firstBorrowIndexAvailable = obligationDeposits.findIndex((deposit) =>
384
+ deposit.depositReserve.equals(PublicKey.default)
385
+ );
386
+
387
+ if (firstBorrowIndexAvailable === -1) {
388
+ throw new Error('No available borrows to modify');
389
+ }
390
+
391
+ const coll: ObligationCollateralFields = { ...obligationDeposits[firstBorrowIndexAvailable] };
392
+ const exchangeRate = collateralExchangeRates.get(changeReserve)!;
393
+ const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate).toFixed(0);
394
+ coll.depositedAmount = new BN(positiveOrZero(new Decimal(changeInCollateral)).toString());
395
+ coll.depositReserve = changeReserve;
396
+
397
+ newDeposits[firstBorrowIndexAvailable] = new ObligationCollateral(coll);
398
+ }
399
+
378
400
  return newDeposits;
379
401
  }
380
402
 
@@ -387,17 +409,30 @@ export class KaminoObligation {
387
409
  const newBorrows: ObligationLiquidity[] = [];
388
410
  const borrowIndex = obligationBorrows.findIndex((borrow) => borrow.borrowReserve.equals(changeReserve));
389
411
 
390
- if (borrowIndex !== -1) {
391
- const borrow: ObligationLiquidityFields = { ...obligationBorrows[borrowIndex] };
392
- const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);
393
- const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();
394
- borrow.borrowedAmountSf = newBorrowedAmountSf;
395
- newBorrows.push(new ObligationLiquidity(borrow));
396
- } else {
412
+ // Always copy the previous borrows and modify the changeReserve one if it exists
413
+ for (let i = 0; i < obligationBorrows.length; i++) {
414
+ if (obligationBorrows[i].borrowReserve.equals(changeReserve)) {
415
+ const borrow: ObligationLiquidityFields = { ...obligationBorrows[borrowIndex] };
416
+ const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);
417
+ const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();
418
+ borrow.borrowedAmountSf = newBorrowedAmountSf;
419
+
420
+ newBorrows.push(new ObligationLiquidity(borrow));
421
+ } else {
422
+ newBorrows.push(obligationBorrows[i]);
423
+ }
424
+ }
425
+
426
+ if (borrowIndex === -1) {
427
+ // If the reserve is not in the obligation, we add it
397
428
  const firstBorrowIndexAvailable = obligationBorrows.findIndex((borrow) =>
398
429
  borrow.borrowReserve.equals(PublicKey.default)
399
430
  );
400
431
 
432
+ if (firstBorrowIndexAvailable === -1) {
433
+ throw new Error('No available borrows to modify');
434
+ }
435
+
401
436
  const borrow: ObligationLiquidityFields = { ...obligationBorrows[firstBorrowIndexAvailable] };
402
437
  borrow.borrowedAmountSf = Fraction.fromDecimal(new Decimal(changeInLamports)).getValue();
403
438
  borrow.borrowReserve = changeReserve;
@@ -405,7 +440,7 @@ export class KaminoObligation {
405
440
  padding: [],
406
441
  value: [Fraction.fromDecimal(cumulativeBorrowRate).getValue(), new BN(0), new BN(0), new BN(0)],
407
442
  };
408
- newBorrows.push(new ObligationLiquidity(borrow));
443
+ newBorrows[firstBorrowIndexAvailable] = new ObligationLiquidity(borrow);
409
444
  }
410
445
 
411
446
  return newBorrows;
@@ -433,7 +468,23 @@ export class KaminoObligation {
433
468
  const { amountCollateral, amountDebt, action, mintCollateral, mintDebt, market } = params;
434
469
  let newStats = { ...this.refreshedStats };
435
470
 
436
- const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, params.slot);
471
+ const collateralReservePk = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;
472
+ const debtReservePk = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;
473
+
474
+ const additionalReserves = [];
475
+ if (collateralReservePk !== undefined) {
476
+ additionalReserves.push(collateralReservePk);
477
+ }
478
+ if (debtReservePk !== undefined) {
479
+ additionalReserves.push(debtReservePk);
480
+ }
481
+
482
+ const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(
483
+ market,
484
+ this.state,
485
+ params.slot,
486
+ additionalReserves
487
+ );
437
488
 
438
489
  const elevationGroup = params.elevationGroupOverride ?? this.state.elevationGroup;
439
490
 
@@ -444,8 +495,6 @@ export class KaminoObligation {
444
495
  // so we have to recalculate the entire position, not just an updated deposit or borrow
445
496
  // as both LTVs and borrow factors can change, affecting all calcs
446
497
 
447
- const collateralReservePk = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;
448
- const debtReservePk = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;
449
498
  const debtReserveCumulativeBorrowRate = mintDebt
450
499
  ? market.getReserveByMint(mintDebt)!.getCumulativeBorrowRate()
451
500
  : undefined;
@@ -453,6 +502,14 @@ export class KaminoObligation {
453
502
  let newObligationDeposits = this.state.deposits;
454
503
  let newObligationBorrows = this.state.borrows;
455
504
 
505
+ // Print deposits and borrows before
506
+ for (const deposit of this.state.deposits) {
507
+ console.log(`Before Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
508
+ }
509
+ for (const borrow of this.state.borrows) {
510
+ console.log(`Before Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
511
+ }
512
+
456
513
  switch (action) {
457
514
  case 'deposit': {
458
515
  if (amountCollateral === undefined || mintCollateral === undefined) {
@@ -567,6 +624,14 @@ export class KaminoObligation {
567
624
  null
568
625
  );
569
626
 
627
+ // Print deposits and borrows after
628
+ for (const deposit of newObligationDeposits) {
629
+ console.log(`After Deposit: ${deposit.depositReserve.toBase58()} - ${deposit.depositedAmount}`);
630
+ }
631
+ for (const borrow of newObligationBorrows) {
632
+ console.log(`After Borrow: ${borrow.borrowReserve.toBase58()} - ${borrow.borrowedAmountSf}`);
633
+ }
634
+
570
635
  newStats = refreshedStats;
571
636
  newDeposits = deposits;
572
637
  newBorrows = borrows;
@@ -921,12 +986,17 @@ export class KaminoObligation {
921
986
  throw new Error('Reserve not found');
922
987
  }
923
988
 
924
- const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(market, [elevationGroup])[0];
989
+ const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(
990
+ market,
991
+ [elevationGroup],
992
+ Array.from(this.deposits.keys())
993
+ )[0];
925
994
  const maxBorrowAmount = this.getBorrowPower(market, liquidityMint, slot, elevationGroup);
926
995
 
927
996
  if (elevationGroup === this.state.elevationGroup) {
928
997
  return Decimal.min(maxBorrowAmount, liquidityAvailable);
929
998
  } else {
999
+ // TODO: this is wrong, most liquidity caps are global, we should add up only the ones that are specific to this mode
930
1000
  const { amount: debtThisReserve } = this.borrows.get(reserve.address) || { amount: new Decimal(0) };
931
1001
  const liquidityAvailablePostMigration = Decimal.max(0, liquidityAvailable.minus(debtThisReserve));
932
1002
  return Decimal.min(maxBorrowAmount, liquidityAvailablePostMigration);
@@ -1212,7 +1282,8 @@ export class KaminoObligation {
1212
1282
  public static getRatesForObligation(
1213
1283
  kaminoMarket: KaminoMarket,
1214
1284
  obligation: Obligation,
1215
- slot: number
1285
+ slot: number,
1286
+ additionalReserves: PublicKey[] = []
1216
1287
  ): {
1217
1288
  collateralExchangeRates: Map<PublicKey, Decimal>;
1218
1289
  cumulativeBorrowRates: Map<PublicKey, Decimal>;
@@ -1220,12 +1291,14 @@ export class KaminoObligation {
1220
1291
  const collateralExchangeRates = KaminoObligation.getCollateralExchangeRatesForObligation(
1221
1292
  kaminoMarket,
1222
1293
  obligation,
1223
- slot
1294
+ slot,
1295
+ additionalReserves
1224
1296
  );
1225
1297
  const cumulativeBorrowRates = KaminoObligation.getCumulativeBorrowRatesForObligation(
1226
1298
  kaminoMarket,
1227
1299
  obligation,
1228
- slot
1300
+ slot,
1301
+ additionalReserves
1229
1302
  );
1230
1303
 
1231
1304
  return {
@@ -1248,20 +1321,35 @@ export class KaminoObligation {
1248
1321
  static getCollateralExchangeRatesForObligation(
1249
1322
  kaminoMarket: KaminoMarket,
1250
1323
  obligation: Obligation,
1251
- slot: number
1324
+ slot: number,
1325
+ additionalReserves: PublicKey[]
1252
1326
  ): Map<PublicKey, Decimal> {
1253
1327
  const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();
1328
+
1329
+ // Create a set of all reserves coming from deposit plus additional reserves
1330
+ const allReserves = new Set<PublicKey>();
1254
1331
  for (let i = 0; i < obligation.deposits.length; i++) {
1255
1332
  const deposit = obligation.deposits[i];
1256
- if (isNotNullPubkey(deposit.depositReserve) && !collateralExchangeRates.has(deposit.depositReserve)) {
1257
- const reserve = kaminoMarket.getReserveByAddress(deposit.depositReserve)!;
1258
- const collateralExchangeRate = reserve.getEstimatedCollateralExchangeRate(
1259
- slot,
1260
- kaminoMarket.state.referralFeeBps
1261
- );
1262
- collateralExchangeRates.set(reserve.address, collateralExchangeRate);
1333
+ if (isNotNullPubkey(deposit.depositReserve)) {
1334
+ allReserves.add(deposit.depositReserve);
1335
+ }
1336
+ }
1337
+ for (let i = 0; i < additionalReserves.length; i++) {
1338
+ if (isNotNullPubkey(additionalReserves[i])) {
1339
+ allReserves.add(additionalReserves[i]);
1263
1340
  }
1264
1341
  }
1342
+
1343
+ // Run through all reserves and get the exchange rate
1344
+ for (const reserve of allReserves) {
1345
+ const reserveInstance = kaminoMarket.getReserveByAddress(reserve)!;
1346
+ const collateralExchangeRate = reserveInstance.getEstimatedCollateralExchangeRate(
1347
+ slot,
1348
+ kaminoMarket.state.referralFeeBps
1349
+ );
1350
+ collateralExchangeRates.set(reserve, collateralExchangeRate);
1351
+ }
1352
+
1265
1353
  return collateralExchangeRates;
1266
1354
  }
1267
1355
 
@@ -1284,16 +1372,39 @@ export class KaminoObligation {
1284
1372
  }
1285
1373
  }
1286
1374
 
1287
- static getCumulativeBorrowRatesForObligation(kaminoMarket: KaminoMarket, obligation: Obligation, slot: number) {
1288
- const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();
1375
+ static getCumulativeBorrowRatesForObligation(
1376
+ kaminoMarket: KaminoMarket,
1377
+ obligation: Obligation,
1378
+ slot: number,
1379
+ additionalReserves: PublicKey[] = []
1380
+ ): Map<PublicKey, Decimal> {
1381
+ const allReserves = new Set<PublicKey>();
1289
1382
  for (let i = 0; i < obligation.borrows.length; i++) {
1290
1383
  const borrow = obligation.borrows[i];
1291
- if (isNotNullPubkey(borrow.borrowReserve) && !cumulativeBorrowRates.has(borrow.borrowReserve)) {
1292
- const reserve = kaminoMarket.getReserveByAddress(borrow.borrowReserve)!;
1293
- const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);
1294
- cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);
1384
+ if (isNotNullPubkey(borrow.borrowReserve)) {
1385
+ allReserves.add(borrow.borrowReserve);
1295
1386
  }
1296
1387
  }
1388
+
1389
+ // Add additional reserves
1390
+ for (let i = 0; i < additionalReserves.length; i++) {
1391
+ if (isNotNullPubkey(additionalReserves[i])) {
1392
+ allReserves.add(additionalReserves[i]);
1393
+ }
1394
+ }
1395
+
1396
+ const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();
1397
+
1398
+ // Run through all reserves and get the cumulative borrow rate
1399
+ for (const reserve of allReserves) {
1400
+ const reserveInstance = kaminoMarket.getReserveByAddress(reserve)!;
1401
+ const cumulativeBorrowRate = reserveInstance.getEstimatedCumulativeBorrowRate(
1402
+ slot,
1403
+ kaminoMarket.state.referralFeeBps
1404
+ );
1405
+ cumulativeBorrowRates.set(reserve, cumulativeBorrowRate);
1406
+ }
1407
+
1297
1408
  return cumulativeBorrowRates;
1298
1409
  }
1299
1410
 
@@ -23,7 +23,14 @@ import {
23
23
  import { FeeCalculation, Fees, ReserveDataType, ReserveFarmInfo, ReserveRewardYield, ReserveStatus } from './shared';
24
24
  import { Reserve, ReserveFields } from '../idl_codegen/accounts';
25
25
  import { BorrowRateCurve, CurvePointFields, ReserveConfig, UpdateConfigMode } from '../idl_codegen/types';
26
- import { calculateAPYFromAPR, getBorrowRate, lamportsToNumberDecimal, parseTokenSymbol, positiveOrZero } from './utils';
26
+ import {
27
+ calculateAPYFromAPR,
28
+ getBorrowRate,
29
+ lamportsToNumberDecimal,
30
+ parseTokenSymbol,
31
+ positiveOrZero,
32
+ sameLengthArrayEquals,
33
+ } from './utils';
27
34
  import { Fraction } from './fraction';
28
35
  import BN from 'bn.js';
29
36
  import { ActionType } from './action';
@@ -570,7 +577,7 @@ export class KaminoReserve {
570
577
  return Decimal.max(new Decimal(0), maxBorrowAmount);
571
578
  }
572
579
 
573
- calcSimulatedBorrowAPR(
580
+ calcSimulatedBorrowRate(
574
581
  amount: Decimal,
575
582
  action: ActionType,
576
583
  slot: number,
@@ -580,7 +587,20 @@ export class KaminoReserve {
580
587
  const slotAdjustmentFactor = this.slotAdjustmentFactor();
581
588
  const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
582
589
  const curve = truncateBorrowCurve(this.state.config.borrowRateCurve.points);
583
- return getBorrowRate(newUtilization, curve) * slotAdjustmentFactor + this.getFixedHostInterestRate().toNumber();
590
+ return getBorrowRate(newUtilization, curve) * slotAdjustmentFactor;
591
+ }
592
+
593
+ calcSimulatedBorrowAPR(
594
+ amount: Decimal,
595
+ action: ActionType,
596
+ slot: number,
597
+ referralFeeBps: number,
598
+ outflowAmount?: Decimal
599
+ ) {
600
+ return (
601
+ this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount) +
602
+ this.getFixedHostInterestRate().toNumber()
603
+ );
584
604
  }
585
605
 
586
606
  calcSimulatedSupplyAPR(
@@ -591,7 +611,7 @@ export class KaminoReserve {
591
611
  outflowAmount?: Decimal
592
612
  ) {
593
613
  const newUtilization = this.calcSimulatedUtilizationRatio(amount, action, slot, referralFeeBps, outflowAmount);
594
- const simulatedBorrowAPR = this.calcSimulatedBorrowAPR(amount, action, slot, referralFeeBps, outflowAmount);
614
+ const simulatedBorrowAPR = this.calcSimulatedBorrowRate(amount, action, slot, referralFeeBps, outflowAmount);
595
615
  const protocolTakeRatePct = 1 - this.state.config.protocolTakeRatePct / 100;
596
616
 
597
617
  return newUtilization * simulatedBorrowAPR * protocolTakeRatePct;
@@ -1033,7 +1053,11 @@ export class KaminoReserve {
1033
1053
  }
1034
1054
 
1035
1055
  /* This takes into account all the caps */
1036
- getLiquidityAvailableForDebtReserveGivenCaps(market: KaminoMarket, elevationGroups: number[]): Decimal[] {
1056
+ getLiquidityAvailableForDebtReserveGivenCaps(
1057
+ market: KaminoMarket,
1058
+ elevationGroups: number[],
1059
+ collateralReserves: PublicKey[] = []
1060
+ ): Decimal[] {
1037
1061
  const caps = this.getBorrowCapForReserve(market);
1038
1062
 
1039
1063
  const liquidityAvailable = this.getLiquidityAvailableAmount();
@@ -1069,7 +1093,16 @@ export class KaminoReserve {
1069
1093
  (x) => x.elevationGroup === elevationGroup
1070
1094
  );
1071
1095
  if (capsGivenEgroup.length > 0) {
1072
- remainingInsideEmodeCaps = Decimal.min(...capsGivenEgroup.map((x) => x.maxDebt.minus(x.currentValue)));
1096
+ remainingInsideEmodeCaps = Decimal.min(
1097
+ ...capsGivenEgroup.map((x) => {
1098
+ // check reserve is part of collReserves array
1099
+ if (collateralReserves.find((collateralReserve) => collateralReserve.equals(x.collateralReserve))) {
1100
+ return x.maxDebt.minus(x.currentValue);
1101
+ } else {
1102
+ return new Decimal(U64_MAX);
1103
+ }
1104
+ })
1105
+ );
1073
1106
  }
1074
1107
  return Decimal.min(
1075
1108
  positiveOrZero(liquidityAvailable),
@@ -1746,17 +1779,11 @@ export function parseForChangesReserveConfigAndGetIxs(
1746
1779
  ),
1747
1780
  });
1748
1781
  } else {
1749
- for (let i = 0; i < tokenInfo.name.length; i++) {
1750
- if (reserve.config.tokenInfo.name[i] !== tokenInfo.name[i]) {
1751
- updateReserveIxnsArgs.push({
1752
- mode: UpdateConfigMode.UpdateTokenInfoName.discriminator,
1753
- value: updateReserveConfigEncodedValue(
1754
- UpdateConfigMode.UpdateTokenInfoName.discriminator,
1755
- tokenInfo.name
1756
- ),
1757
- });
1758
- break;
1759
- }
1782
+ if (!sameLengthArrayEquals(reserve.config.tokenInfo.name, tokenInfo.name)) {
1783
+ updateReserveIxnsArgs.push({
1784
+ mode: UpdateConfigMode.UpdateTokenInfoName.discriminator,
1785
+ value: updateReserveConfigEncodedValue(UpdateConfigMode.UpdateTokenInfoName.discriminator, tokenInfo.name),
1786
+ });
1760
1787
  }
1761
1788
  if (!reserve.config.tokenInfo.heuristic.lower.eq(tokenInfo.heuristic.lower)) {
1762
1789
  updateReserveIxnsArgs.push({
@@ -1812,31 +1839,33 @@ export function parseForChangesReserveConfigAndGetIxs(
1812
1839
  ),
1813
1840
  });
1814
1841
  }
1815
- for (let i = 0; i < tokenInfo.scopeConfiguration.priceChain.length; i++) {
1816
- if (
1817
- reserve.config.tokenInfo.scopeConfiguration.priceChain[i] !== tokenInfo.scopeConfiguration.priceChain[i]
1818
- ) {
1819
- updateReserveIxnsArgs.push({
1820
- mode: UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
1821
- value: updateReserveConfigEncodedValue(
1822
- UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
1823
- tokenInfo.scopeConfiguration.priceChain
1824
- ),
1825
- });
1826
- break;
1827
- }
1842
+ if (
1843
+ !sameLengthArrayEquals(
1844
+ reserve.config.tokenInfo.scopeConfiguration.priceChain,
1845
+ tokenInfo.scopeConfiguration.priceChain
1846
+ )
1847
+ ) {
1848
+ updateReserveIxnsArgs.push({
1849
+ mode: UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
1850
+ value: updateReserveConfigEncodedValue(
1851
+ UpdateConfigMode.UpdateTokenInfoScopeChain.discriminator,
1852
+ tokenInfo.scopeConfiguration.priceChain
1853
+ ),
1854
+ });
1828
1855
  }
1829
- for (let i = 0; i < tokenInfo.scopeConfiguration.twapChain.length; i++) {
1830
- if (reserve.config.tokenInfo.scopeConfiguration.twapChain[i] !== tokenInfo.scopeConfiguration.twapChain[i]) {
1831
- updateReserveIxnsArgs.push({
1832
- mode: UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
1833
- value: updateReserveConfigEncodedValue(
1834
- UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
1835
- tokenInfo.scopeConfiguration.twapChain
1836
- ),
1837
- });
1838
- break;
1839
- }
1856
+ if (
1857
+ !sameLengthArrayEquals(
1858
+ reserve.config.tokenInfo.scopeConfiguration.twapChain,
1859
+ tokenInfo.scopeConfiguration.twapChain
1860
+ )
1861
+ ) {
1862
+ updateReserveIxnsArgs.push({
1863
+ mode: UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
1864
+ value: updateReserveConfigEncodedValue(
1865
+ UpdateConfigMode.UpdateTokenInfoScopeTwap.discriminator,
1866
+ tokenInfo.scopeConfiguration.twapChain
1867
+ ),
1868
+ });
1840
1869
  }
1841
1870
  if (
1842
1871
  !reserve.config.tokenInfo.switchboardConfiguration.priceAggregator.equals(
@@ -142,6 +142,29 @@ export const parseTokenSymbol = (tokenSymbol: number[]): string => {
142
142
  return String.fromCharCode(...tokenSymbol.filter((x) => x > 0));
143
143
  };
144
144
 
145
+ export function parseZeroPaddedUtf8(utf8Array: number[]): string {
146
+ for (let last = utf8Array.length - 1; last >= 0; last--) {
147
+ const trailing_zero = utf8Array[last];
148
+ if (trailing_zero != 0) {
149
+ const encoding = new Uint8Array(last + 1);
150
+ for (let i = 0; i <= last; i++) {
151
+ encoding[i] = utf8Array[i];
152
+ }
153
+ break;
154
+ }
155
+ }
156
+ return new TextDecoder().decode();
157
+ }
158
+
159
+ export function renderZeroPaddedUtf8(str: string, utf8ArrayLength: number): number[] {
160
+ const encoding = new TextEncoder().encode(str);
161
+ const result = new Array<number>(utf8ArrayLength);
162
+ for (let i = 0; i < result.length; i++) {
163
+ result[i] = i < encoding.length ? encoding[i] : 0;
164
+ }
165
+ return result;
166
+ }
167
+
145
168
  export function sleep(ms: number) {
146
169
  return new Promise((resolve) => setTimeout(resolve, ms));
147
170
  }
@@ -190,3 +213,10 @@ export function calculateAPRFromAPY(apy: Decimal.Value) {
190
213
  .minus(1)
191
214
  .times(SLOTS_PER_YEAR);
192
215
  }
216
+
217
+ export function sameLengthArrayEquals(left: Array<number>, right: Array<number>): boolean {
218
+ if (left.length != right.length) {
219
+ throw new Error(`Not same length: ${left.length} != ${left.length}`);
220
+ }
221
+ return left.every((value, index) => value === right[index]);
222
+ }