@hobba-io/core 0.1.0

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 (190) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +87 -0
  3. package/dist/amountUtils.d.ts +15 -0
  4. package/dist/amountUtils.d.ts.map +1 -0
  5. package/dist/amountUtils.js +59 -0
  6. package/dist/amountUtils.js.map +1 -0
  7. package/dist/constants.d.ts +148 -0
  8. package/dist/constants.d.ts.map +1 -0
  9. package/dist/constants.js +231 -0
  10. package/dist/constants.js.map +1 -0
  11. package/dist/errors.d.ts +7 -0
  12. package/dist/errors.d.ts.map +1 -0
  13. package/dist/errors.js +29 -0
  14. package/dist/errors.js.map +1 -0
  15. package/dist/executeAction.d.ts +36 -0
  16. package/dist/executeAction.d.ts.map +1 -0
  17. package/dist/executeAction.js +606 -0
  18. package/dist/executeAction.js.map +1 -0
  19. package/dist/executeDepositBorrow.d.ts +49 -0
  20. package/dist/executeDepositBorrow.d.ts.map +1 -0
  21. package/dist/executeDepositBorrow.js +444 -0
  22. package/dist/executeDepositBorrow.js.map +1 -0
  23. package/dist/idl/hobba.json +5072 -0
  24. package/dist/idl.d.ts +783 -0
  25. package/dist/idl.d.ts.map +1 -0
  26. package/dist/idl.js +7 -0
  27. package/dist/idl.js.map +1 -0
  28. package/dist/index.d.ts +17 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +22 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/juplend/accountResolvers.d.ts +106 -0
  33. package/dist/juplend/accountResolvers.d.ts.map +1 -0
  34. package/dist/juplend/accountResolvers.js +148 -0
  35. package/dist/juplend/accountResolvers.js.map +1 -0
  36. package/dist/juplend/operateRemaining.d.ts +11 -0
  37. package/dist/juplend/operateRemaining.d.ts.map +1 -0
  38. package/dist/juplend/operateRemaining.js +46 -0
  39. package/dist/juplend/operateRemaining.js.map +1 -0
  40. package/dist/juplend/positionInit.d.ts +34 -0
  41. package/dist/juplend/positionInit.d.ts.map +1 -0
  42. package/dist/juplend/positionInit.js +56 -0
  43. package/dist/juplend/positionInit.js.map +1 -0
  44. package/dist/juplend/positionParser.d.ts +8 -0
  45. package/dist/juplend/positionParser.d.ts.map +1 -0
  46. package/dist/juplend/positionParser.js +30 -0
  47. package/dist/juplend/positionParser.js.map +1 -0
  48. package/dist/juplend/sdkApi.d.ts +39 -0
  49. package/dist/juplend/sdkApi.d.ts.map +1 -0
  50. package/dist/juplend/sdkApi.js +68 -0
  51. package/dist/juplend/sdkApi.js.map +1 -0
  52. package/dist/juplend/tickMath.d.ts +19 -0
  53. package/dist/juplend/tickMath.d.ts.map +1 -0
  54. package/dist/juplend/tickMath.js +91 -0
  55. package/dist/juplend/tickMath.js.map +1 -0
  56. package/dist/juplend/tickUtils.d.ts +20 -0
  57. package/dist/juplend/tickUtils.d.ts.map +1 -0
  58. package/dist/juplend/tickUtils.js +115 -0
  59. package/dist/juplend/tickUtils.js.map +1 -0
  60. package/dist/juplend/vaultConfigParser.d.ts +25 -0
  61. package/dist/juplend/vaultConfigParser.d.ts.map +1 -0
  62. package/dist/juplend/vaultConfigParser.js +38 -0
  63. package/dist/juplend/vaultConfigParser.js.map +1 -0
  64. package/dist/kamino/accountResolvers.d.ts +110 -0
  65. package/dist/kamino/accountResolvers.d.ts.map +1 -0
  66. package/dist/kamino/accountResolvers.js +220 -0
  67. package/dist/kamino/accountResolvers.js.map +1 -0
  68. package/dist/kamino/obligationParser.d.ts +13 -0
  69. package/dist/kamino/obligationParser.d.ts.map +1 -0
  70. package/dist/kamino/obligationParser.js +92 -0
  71. package/dist/kamino/obligationParser.js.map +1 -0
  72. package/dist/kamino/refreshInstructions.d.ts +4 -0
  73. package/dist/kamino/refreshInstructions.d.ts.map +1 -0
  74. package/dist/kamino/refreshInstructions.js +32 -0
  75. package/dist/kamino/refreshInstructions.js.map +1 -0
  76. package/dist/limits.d.ts +87 -0
  77. package/dist/limits.d.ts.map +1 -0
  78. package/dist/limits.js +174 -0
  79. package/dist/limits.js.map +1 -0
  80. package/dist/marketConfig.d.ts +35 -0
  81. package/dist/marketConfig.d.ts.map +1 -0
  82. package/dist/marketConfig.js +85 -0
  83. package/dist/marketConfig.js.map +1 -0
  84. package/dist/oracle/scopePrice.d.ts +7 -0
  85. package/dist/oracle/scopePrice.d.ts.map +1 -0
  86. package/dist/oracle/scopePrice.js +31 -0
  87. package/dist/oracle/scopePrice.js.map +1 -0
  88. package/dist/pdas.d.ts +33 -0
  89. package/dist/pdas.d.ts.map +1 -0
  90. package/dist/pdas.js +116 -0
  91. package/dist/pdas.js.map +1 -0
  92. package/dist/position.d.ts +45 -0
  93. package/dist/position.d.ts.map +1 -0
  94. package/dist/position.js +68 -0
  95. package/dist/position.js.map +1 -0
  96. package/dist/positionMetrics.d.ts +108 -0
  97. package/dist/positionMetrics.d.ts.map +1 -0
  98. package/dist/positionMetrics.js +238 -0
  99. package/dist/positionMetrics.js.map +1 -0
  100. package/dist/program.d.ts +12 -0
  101. package/dist/program.d.ts.map +1 -0
  102. package/dist/program.js +24 -0
  103. package/dist/program.js.map +1 -0
  104. package/dist/quote.d.ts +90 -0
  105. package/dist/quote.d.ts.map +1 -0
  106. package/dist/quote.js +198 -0
  107. package/dist/quote.js.map +1 -0
  108. package/dist/rates/borrowRates.d.ts +44 -0
  109. package/dist/rates/borrowRates.d.ts.map +1 -0
  110. package/dist/rates/borrowRates.js +229 -0
  111. package/dist/rates/borrowRates.js.map +1 -0
  112. package/dist/rates/collateralInfo.d.ts +21 -0
  113. package/dist/rates/collateralInfo.d.ts.map +1 -0
  114. package/dist/rates/collateralInfo.js +104 -0
  115. package/dist/rates/collateralInfo.js.map +1 -0
  116. package/dist/rates/constants.d.ts +22 -0
  117. package/dist/rates/constants.d.ts.map +1 -0
  118. package/dist/rates/constants.js +70 -0
  119. package/dist/rates/constants.js.map +1 -0
  120. package/dist/rates/index.d.ts +11 -0
  121. package/dist/rates/index.d.ts.map +1 -0
  122. package/dist/rates/index.js +11 -0
  123. package/dist/rates/index.js.map +1 -0
  124. package/dist/rates/kaminoApi.d.ts +24 -0
  125. package/dist/rates/kaminoApi.d.ts.map +1 -0
  126. package/dist/rates/kaminoApi.js +98 -0
  127. package/dist/rates/kaminoApi.js.map +1 -0
  128. package/dist/rates/supplyRates.d.ts +23 -0
  129. package/dist/rates/supplyRates.d.ts.map +1 -0
  130. package/dist/rates/supplyRates.js +67 -0
  131. package/dist/rates/supplyRates.js.map +1 -0
  132. package/dist/transactionBuilder.d.ts +5 -0
  133. package/dist/transactionBuilder.d.ts.map +1 -0
  134. package/dist/transactionBuilder.js +287 -0
  135. package/dist/transactionBuilder.js.map +1 -0
  136. package/dist/txHelpers.d.ts +16 -0
  137. package/dist/txHelpers.d.ts.map +1 -0
  138. package/dist/txHelpers.js +82 -0
  139. package/dist/txHelpers.js.map +1 -0
  140. package/dist/userState.d.ts +21 -0
  141. package/dist/userState.d.ts.map +1 -0
  142. package/dist/userState.js +60 -0
  143. package/dist/userState.js.map +1 -0
  144. package/dist/vault/vaultAccounts.d.ts +82 -0
  145. package/dist/vault/vaultAccounts.d.ts.map +1 -0
  146. package/dist/vault/vaultAccounts.js +275 -0
  147. package/dist/vault/vaultAccounts.js.map +1 -0
  148. package/dist/wallet.d.ts +12 -0
  149. package/dist/wallet.d.ts.map +1 -0
  150. package/dist/wallet.js +2 -0
  151. package/dist/wallet.js.map +1 -0
  152. package/package.json +63 -0
  153. package/src/amountUtils.ts +69 -0
  154. package/src/constants.ts +263 -0
  155. package/src/errors.ts +33 -0
  156. package/src/executeAction.ts +884 -0
  157. package/src/executeDepositBorrow.ts +677 -0
  158. package/src/idl/hobba.json +5072 -0
  159. package/src/idl.ts +7 -0
  160. package/src/index.ts +21 -0
  161. package/src/juplend/accountResolvers.ts +207 -0
  162. package/src/juplend/operateRemaining.ts +81 -0
  163. package/src/juplend/positionInit.ts +86 -0
  164. package/src/juplend/positionParser.ts +41 -0
  165. package/src/juplend/sdkApi.ts +112 -0
  166. package/src/juplend/tickMath.ts +82 -0
  167. package/src/juplend/tickUtils.ts +163 -0
  168. package/src/juplend/vaultConfigParser.ts +45 -0
  169. package/src/kamino/accountResolvers.ts +299 -0
  170. package/src/kamino/obligationParser.ts +123 -0
  171. package/src/kamino/refreshInstructions.ts +45 -0
  172. package/src/limits.ts +222 -0
  173. package/src/marketConfig.ts +139 -0
  174. package/src/oracle/scopePrice.ts +31 -0
  175. package/src/pdas.ts +226 -0
  176. package/src/position.ts +131 -0
  177. package/src/positionMetrics.ts +387 -0
  178. package/src/program.ts +30 -0
  179. package/src/quote.ts +310 -0
  180. package/src/rates/borrowRates.ts +270 -0
  181. package/src/rates/collateralInfo.ts +136 -0
  182. package/src/rates/constants.ts +87 -0
  183. package/src/rates/index.ts +38 -0
  184. package/src/rates/kaminoApi.ts +134 -0
  185. package/src/rates/supplyRates.ts +102 -0
  186. package/src/transactionBuilder.ts +324 -0
  187. package/src/txHelpers.ts +107 -0
  188. package/src/userState.ts +91 -0
  189. package/src/vault/vaultAccounts.ts +365 -0
  190. package/src/wallet.ts +12 -0
@@ -0,0 +1,365 @@
1
+ import { Connection, PublicKey, SystemProgram, SYSVAR_INSTRUCTIONS_PUBKEY } from "@solana/web3.js";
2
+ import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
3
+ import BN from "bn.js";
4
+ import {
5
+ KAMINO_LENDING_PROGRAM_ID,
6
+ KVAULT_PROGRAM_ID,
7
+ ALLEZ_USDC_VAULT,
8
+ ALLEZ_USDC_TOKEN_VAULT,
9
+ ALLEZ_USDC_VAULT_AUTHORITY,
10
+ ALLEZ_USDC_SHARES_MINT,
11
+ VAULT_LOOKUP_TABLE,
12
+ USDC_PRIME_VAULT,
13
+ USDC_PRIME_TOKEN_VAULT,
14
+ USDC_PRIME_VAULT_AUTHORITY,
15
+ USDC_PRIME_SHARES_MINT,
16
+ USDC_PRIME_LOOKUP_TABLE,
17
+ ROCKAWAY_RWA_VAULT,
18
+ ROCKAWAY_RWA_TOKEN_VAULT,
19
+ ROCKAWAY_RWA_VAULT_AUTHORITY,
20
+ ROCKAWAY_RWA_SHARES_MINT,
21
+ ROCKAWAY_RWA_LOOKUP_TABLE,
22
+ KVAULT_REMAINING_ACCOUNTS,
23
+ PRIME_BATCH_ACCOUNTS,
24
+ ROCKAWAY_BATCH_ACCOUNTS,
25
+ PERENA_PROGRAM_ID,
26
+ PERENA_VAULT_STATE,
27
+ PERENA_VAULT_AUTHORITY,
28
+ PERENA_POOL_CONFIG,
29
+ PERENA_VAULT_USDC_TRANSIT,
30
+ PERENA_VAULT_METADATA,
31
+ PERENA_FEE_COLLECTOR,
32
+ PERENA_MARGINFI_PROGRAM,
33
+ PERENA_MARGINFI_GROUP,
34
+ PERENA_MARGINFI_ACCOUNT,
35
+ PERENA_MARGINFI_BANK,
36
+ PERENA_MARGINFI_BANK_AUTHORITY,
37
+ PERENA_MARGINFI_BANK_LIQUIDITY_VAULT,
38
+ PERENA_MARGINFI_ORACLE,
39
+ STAR_USDC_MINT,
40
+ USDC_MINT,
41
+ VAULT_PROVIDER_KVAULT,
42
+ VAULT_PROVIDER_PERENA,
43
+ } from "../constants";
44
+ import { deriveKvaultEventAuthority, deriveMarketAuthority } from "../pdas";
45
+
46
+ const [KVAULT_EVENT_AUTHORITY] = deriveKvaultEventAuthority();
47
+
48
+ export type VaultType = "allez" | "prime" | "rockawayRWA" | "perena";
49
+
50
+ export type VaultProvider = "kvault" | "perena";
51
+
52
+ export interface VaultInfo {
53
+ vault: PublicKey;
54
+ tokenVault: PublicKey;
55
+ authority: PublicKey;
56
+ sharesMint: PublicKey;
57
+ lookupTable: PublicKey;
58
+ provider: VaultProvider;
59
+ batchAccounts: { pubkey: PublicKey; isSigner: boolean; isWritable: boolean }[];
60
+ withdrawFixed: { pubkey: PublicKey; isSigner: boolean; isWritable: boolean }[];
61
+ }
62
+
63
+ export function vaultProviderToU8(provider: VaultProvider): number {
64
+ return provider === "kvault" ? VAULT_PROVIDER_KVAULT : VAULT_PROVIDER_PERENA;
65
+ }
66
+
67
+ // Derive KVault global config PDA
68
+ const [KVAULT_GLOBAL_CONFIG] = PublicKey.findProgramAddressSync(
69
+ [Buffer.from("global_config")],
70
+ KVAULT_PROGRAM_ID
71
+ );
72
+
73
+ /**
74
+ * Build KVault deposit vault_remaining:
75
+ * [token_vault, base_vault_authority, event_authority, kamino_program, kvault_program, ...batchAccounts]
76
+ */
77
+ export function getKvaultDepositRemaining(vaultInfo: VaultInfo): AccountMeta[] {
78
+ return [
79
+ { pubkey: vaultInfo.tokenVault, isSigner: false, isWritable: true },
80
+ { pubkey: vaultInfo.authority, isSigner: false, isWritable: false },
81
+ { pubkey: KVAULT_EVENT_AUTHORITY, isSigner: false, isWritable: false },
82
+ { pubkey: KAMINO_LENDING_PROGRAM_ID, isSigner: false, isWritable: false },
83
+ { pubkey: KVAULT_PROGRAM_ID, isSigner: false, isWritable: false },
84
+ ...vaultInfo.batchAccounts,
85
+ ];
86
+ }
87
+
88
+ /**
89
+ * Build KVault withdraw vault_remaining:
90
+ * [kvault_global_config, token_vault, base_vault_authority, event_authority, kamino_program, kvault_program, ...withdrawFixed, ...batchAccounts]
91
+ */
92
+ export function getKvaultWithdrawRemaining(vaultInfo: VaultInfo, withdrawFixed: AccountMeta[]): AccountMeta[] {
93
+ return [
94
+ { pubkey: KVAULT_GLOBAL_CONFIG, isSigner: false, isWritable: false },
95
+ { pubkey: vaultInfo.tokenVault, isSigner: false, isWritable: true },
96
+ { pubkey: vaultInfo.authority, isSigner: false, isWritable: false },
97
+ { pubkey: KVAULT_EVENT_AUTHORITY, isSigner: false, isWritable: false },
98
+ { pubkey: KAMINO_LENDING_PROGRAM_ID, isSigner: false, isWritable: false },
99
+ { pubkey: KVAULT_PROGRAM_ID, isSigner: false, isWritable: false },
100
+ ...withdrawFixed,
101
+ ...vaultInfo.batchAccounts,
102
+ ];
103
+ }
104
+
105
+ export function getVaultInfo(vaultType: VaultType): VaultInfo {
106
+ if (vaultType === "allez") {
107
+ return {
108
+ vault: ALLEZ_USDC_VAULT,
109
+ tokenVault: ALLEZ_USDC_TOKEN_VAULT,
110
+ authority: ALLEZ_USDC_VAULT_AUTHORITY,
111
+ sharesMint: ALLEZ_USDC_SHARES_MINT,
112
+ lookupTable: VAULT_LOOKUP_TABLE,
113
+ provider: "kvault",
114
+ batchAccounts: KVAULT_REMAINING_ACCOUNTS,
115
+ withdrawFixed: [], // resolved dynamically via resolveWithdrawFixed
116
+ };
117
+ } else if (vaultType === "prime") {
118
+ return {
119
+ vault: USDC_PRIME_VAULT,
120
+ tokenVault: USDC_PRIME_TOKEN_VAULT,
121
+ authority: USDC_PRIME_VAULT_AUTHORITY,
122
+ sharesMint: USDC_PRIME_SHARES_MINT,
123
+ lookupTable: USDC_PRIME_LOOKUP_TABLE,
124
+ provider: "kvault",
125
+ batchAccounts: PRIME_BATCH_ACCOUNTS,
126
+ withdrawFixed: [], // resolved dynamically via resolveWithdrawFixed
127
+ };
128
+ } else if (vaultType === "rockawayRWA") {
129
+ return {
130
+ vault: ROCKAWAY_RWA_VAULT,
131
+ tokenVault: ROCKAWAY_RWA_TOKEN_VAULT,
132
+ authority: ROCKAWAY_RWA_VAULT_AUTHORITY,
133
+ sharesMint: ROCKAWAY_RWA_SHARES_MINT,
134
+ lookupTable: ROCKAWAY_RWA_LOOKUP_TABLE,
135
+ provider: "kvault",
136
+ batchAccounts: ROCKAWAY_BATCH_ACCOUNTS,
137
+ withdrawFixed: [], // resolved dynamically via resolveWithdrawFixed
138
+ };
139
+ } else {
140
+ // Perena vault
141
+ return {
142
+ vault: PERENA_VAULT_STATE,
143
+ tokenVault: PERENA_VAULT_USDC_TRANSIT, // analogous to token vault
144
+ authority: PERENA_VAULT_AUTHORITY,
145
+ sharesMint: STAR_USDC_MINT,
146
+ lookupTable: PublicKey.default, // TODO: create Perena lookup table
147
+ provider: "perena",
148
+ batchAccounts: [], // Perena uses fixed accounts via getPerenaDepositAccounts/getPerenaWithdrawAccounts
149
+ withdrawFixed: [], // Perena uses fixed accounts via getPerenaWithdrawAccounts
150
+ };
151
+ }
152
+ }
153
+
154
+ // VaultState layout constants
155
+ const ALLOC_STRATEGY_OFFSET = 312;
156
+ const ALLOC_ENTRY_SIZE = 2160;
157
+ const ALLOC_COUNT = 25;
158
+ // ctokenAllocation at: reserve(32) + ctokenVault(32) + targetWeight(8) + tokenAllocCap(8) + ctokenVaultBump(8) + configPadding(127*8) = 1104
159
+ const CTOKEN_ALLOC_OFFSET_IN_ENTRY = 32 + 32 + 8 + 8 + 8 + 127 * 8;
160
+
161
+ type AccountMeta = { pubkey: PublicKey; isSigner: boolean; isWritable: boolean };
162
+
163
+ /**
164
+ * Reads vault state on-chain, finds the allocation with the highest ctokenAllocation,
165
+ * reads that reserve to get lending_market / liquidity.supplyVault / collateral.mintPubkey,
166
+ * and returns the 11-account withdrawFixed array.
167
+ */
168
+ export async function resolveWithdrawFixed(
169
+ connection: Connection,
170
+ vaultPubkey: PublicKey
171
+ ): Promise<AccountMeta[]> {
172
+ const vaultAcct = await connection.getAccountInfo(vaultPubkey);
173
+ if (!vaultAcct) throw new Error(`Vault account not found: ${vaultPubkey.toBase58()}`);
174
+
175
+ const data = vaultAcct.data;
176
+
177
+ let bestReserve: PublicKey | null = null;
178
+ let bestCtokenVault: PublicKey | null = null;
179
+ let bestAlloc = new BN(0);
180
+
181
+ for (let i = 0; i < ALLOC_COUNT; i++) {
182
+ const entryOffset = ALLOC_STRATEGY_OFFSET + i * ALLOC_ENTRY_SIZE;
183
+ if (entryOffset + ALLOC_ENTRY_SIZE > data.length) break;
184
+
185
+ const reserve = new PublicKey(data.slice(entryOffset, entryOffset + 32));
186
+ if (reserve.equals(PublicKey.default)) continue;
187
+
188
+ const ctokenVault = new PublicKey(data.slice(entryOffset + 32, entryOffset + 64));
189
+ const ctokenAlloc = new BN(
190
+ data.slice(
191
+ entryOffset + CTOKEN_ALLOC_OFFSET_IN_ENTRY,
192
+ entryOffset + CTOKEN_ALLOC_OFFSET_IN_ENTRY + 8
193
+ ),
194
+ "le"
195
+ );
196
+
197
+ if (ctokenAlloc.gt(bestAlloc)) {
198
+ bestAlloc = ctokenAlloc;
199
+ bestReserve = reserve;
200
+ bestCtokenVault = ctokenVault;
201
+ }
202
+ }
203
+
204
+ if (!bestReserve || !bestCtokenVault) {
205
+ throw new Error(`No non-empty allocation in vault ${vaultPubkey.toBase58()}`);
206
+ }
207
+
208
+ // Decode reserve to get lending_market, liquidity.supplyVault, collateral.mintPubkey.
209
+ // Manual offset reads (instead of klend-sdk Reserve.decode) so @hobba/core and the
210
+ // widget bundle carry no klend-sdk dependency. Layout traced from the klend borsh
211
+ // struct — same base offsets as kamino/obligationParser.ts:
212
+ // 8 disc + 8 version + 16 lastUpdate = 32 → lendingMarket (32 bytes)
213
+ // ReserveLiquidity at 128: mintPubkey @128, supplyVault @160, feeVault @192
214
+ // ReserveCollateral at 2560: mintPubkey @2560
215
+ const reserveAcct = await connection.getAccountInfo(bestReserve);
216
+ if (!reserveAcct) throw new Error(`Reserve not found: ${bestReserve.toBase58()}`);
217
+
218
+ const reserveData = reserveAcct.data;
219
+ const lendingMarket = new PublicKey(reserveData.slice(32, 64));
220
+ const liquiditySupply = new PublicKey(reserveData.slice(160, 192));
221
+ const collateralMint = new PublicKey(reserveData.slice(2560, 2592));
222
+ const [lendingMarketAuthority] = deriveMarketAuthority(lendingMarket);
223
+
224
+ return [
225
+ { pubkey: vaultPubkey, isSigner: false, isWritable: true },
226
+ { pubkey: bestReserve, isSigner: false, isWritable: true },
227
+ { pubkey: bestCtokenVault, isSigner: false, isWritable: true },
228
+ { pubkey: lendingMarket, isSigner: false, isWritable: false },
229
+ { pubkey: lendingMarketAuthority, isSigner: false, isWritable: false },
230
+ { pubkey: liquiditySupply, isSigner: false, isWritable: true },
231
+ { pubkey: collateralMint, isSigner: false, isWritable: true },
232
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
233
+ { pubkey: SYSVAR_INSTRUCTIONS_PUBKEY, isSigner: false, isWritable: false },
234
+ { pubkey: KVAULT_EVENT_AUTHORITY, isSigner: false, isWritable: false },
235
+ { pubkey: KVAULT_PROGRAM_ID, isSigner: false, isWritable: false },
236
+ ];
237
+ }
238
+
239
+ export function identifyVaultType(vaultKey: PublicKey): VaultType | null {
240
+ if (vaultKey.equals(ALLEZ_USDC_VAULT)) return "allez";
241
+ if (vaultKey.equals(USDC_PRIME_VAULT)) return "prime";
242
+ if (vaultKey.equals(ROCKAWAY_RWA_VAULT)) return "rockawayRWA";
243
+ if (vaultKey.equals(PERENA_VAULT_STATE)) return "perena";
244
+ return null;
245
+ }
246
+
247
+ export function identifyVaultProvider(vaultKey: PublicKey): VaultProvider {
248
+ if (vaultKey.equals(PERENA_VAULT_STATE)) return "perena";
249
+ return "kvault";
250
+ }
251
+
252
+ /**
253
+ * Build the 16-account list for Perena deposit (mint_w_yielding_gen).
254
+ * These go into remaining_accounts when vault_provider = 1 (Perena).
255
+ * 15 instruction accounts + Perena program for CPI resolution.
256
+ * MarginFi accounts are omitted — Perena's crank will deploy capital later.
257
+ * This matches the Perena frontend behavior and avoids MarginFi ProtocolPaused errors.
258
+ */
259
+ export function getPerenaDepositAccounts(
260
+ pdaKey: PublicKey,
261
+ pdaUsdcAta: PublicKey,
262
+ pdaStarAta: PublicKey,
263
+ ): AccountMeta[] {
264
+ return [
265
+ { pubkey: pdaKey, isSigner: false, isWritable: true }, // 0: user/pda (signer set by CPI)
266
+ { pubkey: PERENA_VAULT_STATE, isSigner: false, isWritable: true }, // 1: vault_state
267
+ { pubkey: PERENA_VAULT_AUTHORITY, isSigner: false, isWritable: true }, // 2: vault_authority PDA
268
+ { pubkey: PERENA_POOL_CONFIG, isSigner: false, isWritable: false }, // 3: pool/config
269
+ { pubkey: USDC_MINT, isSigner: false, isWritable: false }, // 4: USDC mint
270
+ { pubkey: STAR_USDC_MINT, isSigner: false, isWritable: true }, // 5: star* mint
271
+ { pubkey: pdaUsdcAta, isSigner: false, isWritable: true }, // 6: user USDC account
272
+ { pubkey: pdaStarAta, isSigner: false, isWritable: true }, // 7: user star* account
273
+ { pubkey: PERENA_VAULT_USDC_TRANSIT, isSigner: false, isWritable: true }, // 8: vault USDC transit
274
+ { pubkey: PERENA_FEE_COLLECTOR, isSigner: false, isWritable: true }, // 9: team_state (fee collector)
275
+ { pubkey: PERENA_VAULT_METADATA, isSigner: false, isWritable: true }, // 10: perena vault metadata
276
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // 11: system program
277
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 12: token program
278
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 13: token program (duplicate)
279
+ { pubkey: new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), isSigner: false, isWritable: false }, // 14: ATA program
280
+ { pubkey: PERENA_PROGRAM_ID, isSigner: false, isWritable: false }, // 15: perena program (for CPI resolution)
281
+ ];
282
+ }
283
+
284
+ /**
285
+ * Build the 16-account list for Perena withdraw (burn_for_yielding_gen) WITHOUT
286
+ * MarginFi. Use this only as a fallback when MarginFi is paused — otherwise
287
+ * Perena can only pay out from its small USDC transit buffer and will fail
288
+ * with `insufficient funds` when that buffer is drained between crank runs.
289
+ *
290
+ * Prefer `getPerenaWithdrawAccountsWithMarginfi` for normal operation.
291
+ *
292
+ * 15 instruction accounts + Perena program for CPI resolution.
293
+ */
294
+ export function getPerenaWithdrawAccounts(
295
+ pdaKey: PublicKey,
296
+ pdaUsdcAta: PublicKey,
297
+ pdaStarAta: PublicKey,
298
+ ): AccountMeta[] {
299
+ return [
300
+ { pubkey: pdaKey, isSigner: false, isWritable: true }, // 0: user/pda (signer set by CPI)
301
+ { pubkey: PERENA_VAULT_STATE, isSigner: false, isWritable: true }, // 1: vault_state
302
+ { pubkey: PERENA_VAULT_AUTHORITY, isSigner: false, isWritable: true }, // 2: vault_authority PDA
303
+ { pubkey: PERENA_POOL_CONFIG, isSigner: false, isWritable: false }, // 3: pool/config
304
+ { pubkey: USDC_MINT, isSigner: false, isWritable: false }, // 4: USDC mint
305
+ { pubkey: STAR_USDC_MINT, isSigner: false, isWritable: true }, // 5: star* mint (burned)
306
+ { pubkey: pdaUsdcAta, isSigner: false, isWritable: true }, // 6: user USDC account (destination)
307
+ { pubkey: pdaStarAta, isSigner: false, isWritable: true }, // 7: user star* account (burned from)
308
+ { pubkey: PERENA_VAULT_USDC_TRANSIT, isSigner: false, isWritable: true }, // 8: vault USDC transit
309
+ { pubkey: PERENA_FEE_COLLECTOR, isSigner: false, isWritable: true }, // 9: fee collector
310
+ { pubkey: PERENA_VAULT_METADATA, isSigner: false, isWritable: true }, // 10: fee destination secondary
311
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // 11: system program
312
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 12: token program
313
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 13: token program (duplicate)
314
+ { pubkey: new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"), isSigner: false, isWritable: false }, // 14: ATA program
315
+ { pubkey: PERENA_PROGRAM_ID, isSigner: false, isWritable: false }, // 15: perena program (for CPI resolution)
316
+ ];
317
+ }
318
+
319
+ /**
320
+ * Build the 24-account list for Perena withdraw (burn_for_yielding_gen) WITH
321
+ * MarginFi. This is the **default** for our flows: when the Perena USDC transit
322
+ * buffer is insufficient to cover the requested amount, Perena uses the
323
+ * MarginFi accounts to pull deployed capital back, so withdrawals don't fail.
324
+ *
325
+ * If MarginFi is paused (Perena's internal ProtocolPaused error), fall back to
326
+ * `getPerenaWithdrawAccounts` and retry after the next crank.
327
+ *
328
+ * 15 instruction accounts + 8 MarginFi (incl. oracle) + Perena program.
329
+ * MarginFi's LendingAccountWithdraw needs 1 oracle per active balance slot in
330
+ * Perena's marginfi account; Perena holds 2 balance slots, both USDC, so we
331
+ * pass the USDC oracle (position 22) and MarginFi reads it twice.
332
+ */
333
+ export function getPerenaWithdrawAccountsWithMarginfi(
334
+ pdaKey: PublicKey,
335
+ pdaUsdcAta: PublicKey,
336
+ pdaStarAta: PublicKey,
337
+ ): AccountMeta[] {
338
+ const ATA_PROGRAM_ID = new PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
339
+ return [
340
+ { pubkey: pdaKey, isSigner: false, isWritable: true }, // 0: user/pda
341
+ { pubkey: PERENA_VAULT_STATE, isSigner: false, isWritable: true }, // 1: vault_state
342
+ { pubkey: PERENA_VAULT_AUTHORITY, isSigner: false, isWritable: true }, // 2: vault_authority
343
+ { pubkey: PERENA_POOL_CONFIG, isSigner: false, isWritable: false }, // 3: pool/config
344
+ { pubkey: USDC_MINT, isSigner: false, isWritable: false }, // 4: USDC mint
345
+ { pubkey: STAR_USDC_MINT, isSigner: false, isWritable: true }, // 5: star* mint (burned)
346
+ { pubkey: pdaUsdcAta, isSigner: false, isWritable: true }, // 6: user USDC dest
347
+ { pubkey: pdaStarAta, isSigner: false, isWritable: true }, // 7: user star* src
348
+ { pubkey: PERENA_VAULT_USDC_TRANSIT, isSigner: false, isWritable: true }, // 8: USDC transit
349
+ { pubkey: PERENA_FEE_COLLECTOR, isSigner: false, isWritable: true }, // 9: fee collector
350
+ { pubkey: PERENA_VAULT_METADATA, isSigner: false, isWritable: true }, // 10: fee secondary
351
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // 11: system program
352
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 12: token program
353
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }, // 13: token program (dup)
354
+ { pubkey: ATA_PROGRAM_ID, isSigner: false, isWritable: false }, // 14: ATA program
355
+ { pubkey: PERENA_MARGINFI_PROGRAM, isSigner: false, isWritable: false }, // 15: marginfi program
356
+ { pubkey: PERENA_MARGINFI_GROUP, isSigner: false, isWritable: true }, // 16: marginfi group
357
+ { pubkey: PERENA_MARGINFI_ACCOUNT, isSigner: false, isWritable: true }, // 17: marginfi account
358
+ { pubkey: PERENA_MARGINFI_BANK, isSigner: false, isWritable: true }, // 18: marginfi bank
359
+ { pubkey: PERENA_MARGINFI_BANK_AUTHORITY, isSigner: false, isWritable: false },// 19: marginfi bank authority
360
+ { pubkey: PERENA_MARGINFI_BANK_LIQUIDITY_VAULT, isSigner: false, isWritable: true }, // 20: marginfi bank liquidity vault
361
+ { pubkey: PERENA_MARGINFI_BANK, isSigner: false, isWritable: true }, // 21: marginfi bank (oracle-paired bank for balance slot 1)
362
+ { pubkey: PERENA_MARGINFI_ORACLE, isSigner: false, isWritable: false }, // 22: marginfi USDC oracle
363
+ { pubkey: PERENA_PROGRAM_ID, isSigner: false, isWritable: false }, // 23: perena program (CPI resolution)
364
+ ];
365
+ }
package/src/wallet.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
2
+
3
+ /**
4
+ * Minimal wallet capability the deposit/borrow flow needs: a public key plus the
5
+ * ability to sign a (legacy or versioned) transaction. Both the app's
6
+ * wallet-adapter `WalletContextState` and a raw injected provider (window.solana /
7
+ * window.solflare) structurally satisfy this, so neither consumer needs a cast.
8
+ */
9
+ export interface HobbaSigner {
10
+ publicKey: PublicKey | null;
11
+ signTransaction?: <T extends Transaction | VersionedTransaction>(tx: T) => Promise<T>;
12
+ }