@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.
- package/LICENSE +15 -0
- package/README.md +87 -0
- package/dist/amountUtils.d.ts +15 -0
- package/dist/amountUtils.d.ts.map +1 -0
- package/dist/amountUtils.js +59 -0
- package/dist/amountUtils.js.map +1 -0
- package/dist/constants.d.ts +148 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +231 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/executeAction.d.ts +36 -0
- package/dist/executeAction.d.ts.map +1 -0
- package/dist/executeAction.js +606 -0
- package/dist/executeAction.js.map +1 -0
- package/dist/executeDepositBorrow.d.ts +49 -0
- package/dist/executeDepositBorrow.d.ts.map +1 -0
- package/dist/executeDepositBorrow.js +444 -0
- package/dist/executeDepositBorrow.js.map +1 -0
- package/dist/idl/hobba.json +5072 -0
- package/dist/idl.d.ts +783 -0
- package/dist/idl.d.ts.map +1 -0
- package/dist/idl.js +7 -0
- package/dist/idl.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/juplend/accountResolvers.d.ts +106 -0
- package/dist/juplend/accountResolvers.d.ts.map +1 -0
- package/dist/juplend/accountResolvers.js +148 -0
- package/dist/juplend/accountResolvers.js.map +1 -0
- package/dist/juplend/operateRemaining.d.ts +11 -0
- package/dist/juplend/operateRemaining.d.ts.map +1 -0
- package/dist/juplend/operateRemaining.js +46 -0
- package/dist/juplend/operateRemaining.js.map +1 -0
- package/dist/juplend/positionInit.d.ts +34 -0
- package/dist/juplend/positionInit.d.ts.map +1 -0
- package/dist/juplend/positionInit.js +56 -0
- package/dist/juplend/positionInit.js.map +1 -0
- package/dist/juplend/positionParser.d.ts +8 -0
- package/dist/juplend/positionParser.d.ts.map +1 -0
- package/dist/juplend/positionParser.js +30 -0
- package/dist/juplend/positionParser.js.map +1 -0
- package/dist/juplend/sdkApi.d.ts +39 -0
- package/dist/juplend/sdkApi.d.ts.map +1 -0
- package/dist/juplend/sdkApi.js +68 -0
- package/dist/juplend/sdkApi.js.map +1 -0
- package/dist/juplend/tickMath.d.ts +19 -0
- package/dist/juplend/tickMath.d.ts.map +1 -0
- package/dist/juplend/tickMath.js +91 -0
- package/dist/juplend/tickMath.js.map +1 -0
- package/dist/juplend/tickUtils.d.ts +20 -0
- package/dist/juplend/tickUtils.d.ts.map +1 -0
- package/dist/juplend/tickUtils.js +115 -0
- package/dist/juplend/tickUtils.js.map +1 -0
- package/dist/juplend/vaultConfigParser.d.ts +25 -0
- package/dist/juplend/vaultConfigParser.d.ts.map +1 -0
- package/dist/juplend/vaultConfigParser.js +38 -0
- package/dist/juplend/vaultConfigParser.js.map +1 -0
- package/dist/kamino/accountResolvers.d.ts +110 -0
- package/dist/kamino/accountResolvers.d.ts.map +1 -0
- package/dist/kamino/accountResolvers.js +220 -0
- package/dist/kamino/accountResolvers.js.map +1 -0
- package/dist/kamino/obligationParser.d.ts +13 -0
- package/dist/kamino/obligationParser.d.ts.map +1 -0
- package/dist/kamino/obligationParser.js +92 -0
- package/dist/kamino/obligationParser.js.map +1 -0
- package/dist/kamino/refreshInstructions.d.ts +4 -0
- package/dist/kamino/refreshInstructions.d.ts.map +1 -0
- package/dist/kamino/refreshInstructions.js +32 -0
- package/dist/kamino/refreshInstructions.js.map +1 -0
- package/dist/limits.d.ts +87 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +174 -0
- package/dist/limits.js.map +1 -0
- package/dist/marketConfig.d.ts +35 -0
- package/dist/marketConfig.d.ts.map +1 -0
- package/dist/marketConfig.js +85 -0
- package/dist/marketConfig.js.map +1 -0
- package/dist/oracle/scopePrice.d.ts +7 -0
- package/dist/oracle/scopePrice.d.ts.map +1 -0
- package/dist/oracle/scopePrice.js +31 -0
- package/dist/oracle/scopePrice.js.map +1 -0
- package/dist/pdas.d.ts +33 -0
- package/dist/pdas.d.ts.map +1 -0
- package/dist/pdas.js +116 -0
- package/dist/pdas.js.map +1 -0
- package/dist/position.d.ts +45 -0
- package/dist/position.d.ts.map +1 -0
- package/dist/position.js +68 -0
- package/dist/position.js.map +1 -0
- package/dist/positionMetrics.d.ts +108 -0
- package/dist/positionMetrics.d.ts.map +1 -0
- package/dist/positionMetrics.js +238 -0
- package/dist/positionMetrics.js.map +1 -0
- package/dist/program.d.ts +12 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +24 -0
- package/dist/program.js.map +1 -0
- package/dist/quote.d.ts +90 -0
- package/dist/quote.d.ts.map +1 -0
- package/dist/quote.js +198 -0
- package/dist/quote.js.map +1 -0
- package/dist/rates/borrowRates.d.ts +44 -0
- package/dist/rates/borrowRates.d.ts.map +1 -0
- package/dist/rates/borrowRates.js +229 -0
- package/dist/rates/borrowRates.js.map +1 -0
- package/dist/rates/collateralInfo.d.ts +21 -0
- package/dist/rates/collateralInfo.d.ts.map +1 -0
- package/dist/rates/collateralInfo.js +104 -0
- package/dist/rates/collateralInfo.js.map +1 -0
- package/dist/rates/constants.d.ts +22 -0
- package/dist/rates/constants.d.ts.map +1 -0
- package/dist/rates/constants.js +70 -0
- package/dist/rates/constants.js.map +1 -0
- package/dist/rates/index.d.ts +11 -0
- package/dist/rates/index.d.ts.map +1 -0
- package/dist/rates/index.js +11 -0
- package/dist/rates/index.js.map +1 -0
- package/dist/rates/kaminoApi.d.ts +24 -0
- package/dist/rates/kaminoApi.d.ts.map +1 -0
- package/dist/rates/kaminoApi.js +98 -0
- package/dist/rates/kaminoApi.js.map +1 -0
- package/dist/rates/supplyRates.d.ts +23 -0
- package/dist/rates/supplyRates.d.ts.map +1 -0
- package/dist/rates/supplyRates.js +67 -0
- package/dist/rates/supplyRates.js.map +1 -0
- package/dist/transactionBuilder.d.ts +5 -0
- package/dist/transactionBuilder.d.ts.map +1 -0
- package/dist/transactionBuilder.js +287 -0
- package/dist/transactionBuilder.js.map +1 -0
- package/dist/txHelpers.d.ts +16 -0
- package/dist/txHelpers.d.ts.map +1 -0
- package/dist/txHelpers.js +82 -0
- package/dist/txHelpers.js.map +1 -0
- package/dist/userState.d.ts +21 -0
- package/dist/userState.d.ts.map +1 -0
- package/dist/userState.js +60 -0
- package/dist/userState.js.map +1 -0
- package/dist/vault/vaultAccounts.d.ts +82 -0
- package/dist/vault/vaultAccounts.d.ts.map +1 -0
- package/dist/vault/vaultAccounts.js +275 -0
- package/dist/vault/vaultAccounts.js.map +1 -0
- package/dist/wallet.d.ts +12 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +2 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +63 -0
- package/src/amountUtils.ts +69 -0
- package/src/constants.ts +263 -0
- package/src/errors.ts +33 -0
- package/src/executeAction.ts +884 -0
- package/src/executeDepositBorrow.ts +677 -0
- package/src/idl/hobba.json +5072 -0
- package/src/idl.ts +7 -0
- package/src/index.ts +21 -0
- package/src/juplend/accountResolvers.ts +207 -0
- package/src/juplend/operateRemaining.ts +81 -0
- package/src/juplend/positionInit.ts +86 -0
- package/src/juplend/positionParser.ts +41 -0
- package/src/juplend/sdkApi.ts +112 -0
- package/src/juplend/tickMath.ts +82 -0
- package/src/juplend/tickUtils.ts +163 -0
- package/src/juplend/vaultConfigParser.ts +45 -0
- package/src/kamino/accountResolvers.ts +299 -0
- package/src/kamino/obligationParser.ts +123 -0
- package/src/kamino/refreshInstructions.ts +45 -0
- package/src/limits.ts +222 -0
- package/src/marketConfig.ts +139 -0
- package/src/oracle/scopePrice.ts +31 -0
- package/src/pdas.ts +226 -0
- package/src/position.ts +131 -0
- package/src/positionMetrics.ts +387 -0
- package/src/program.ts +30 -0
- package/src/quote.ts +310 -0
- package/src/rates/borrowRates.ts +270 -0
- package/src/rates/collateralInfo.ts +136 -0
- package/src/rates/constants.ts +87 -0
- package/src/rates/index.ts +38 -0
- package/src/rates/kaminoApi.ts +134 -0
- package/src/rates/supplyRates.ts +102 -0
- package/src/transactionBuilder.ts +324 -0
- package/src/txHelpers.ts +107 -0
- package/src/userState.ts +91 -0
- package/src/vault/vaultAccounts.ts +365 -0
- 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
|
+
}
|