@pyron-finance/pyron-client 2.5.2 → 2.6.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.
@@ -1,3 +1,1160 @@
1
- import { $t as median, A as getMeanPrioritizationFeeByPercentile, B as getComputeBudgetUnits, C as aprToApy, D as PriotitizationFeeLevels, E as calculateInterestFromApy, F as compareInstructions, G as replaceV0TxBlockhash, Gt as chunkedGetRawMultipleAccountInfoOrderedWithNulls, H as isV0Tx, Ht as TransactionConfigMap, I as decodeComputeBudgetInstruction, J as uiToMicroLamports, Jt as getValueInsensitive, K as replaceV0TxInstructions, Kt as chunkedGetRawMultipleAccountInfos, L as decodeInstruction, M as getMinPrioritizationFeeByPercentile, N as getRecentPrioritizationFeesByPercentile, O as getCalculatedPrioritizationFeeByPercentile, P as addTransactionMetadata, Qt as floor, R as decompileV0Transaction, S as wrappedI80F48toBigNumber, T as calculateApyFromInterest, U as legacyTxToV0Tx, Ut as TransactionType, V as getTxSize, Vt as TransactionArenaKeyMap, W as microLamportsToUi, Wt as chunkedGetRawMultipleAccountInfoOrdered, Xt as sleep, Y as updateV0Tx, Yt as setTimeoutPromise, Zt as ceil, _ as shortenAddress, a as groupedNumberFormatterDyn, b as uiToNative, c as percentFormatterDyn, d as usdFormatter, en as NodeWallet, f as usdFormatterDyn, g as nativeToUi, h as composeRemainingAccounts, i as groupedNumberFormatter, j as getMedianPrioritizationFeeByPercentile, k as getMaxPrioritizationFeeByPercentile, l as percentFormatterMod, m as bpsToPercentile, n as clampedNumeralFormatter, nn as fetchBanksExtendedMetadata, o as numeralFormatter, p as bigNumberToWrappedI80F48, q as splitInstructionsToFitTransactions, qt as chunks, r as dynamicNumeralFormatter, rn as parseBanksMetadataOverride, s as percentFormatter, t as CustomNumberFormat, tn as bankExtendedMetadataOverrideSchema, u as tokenPriceFormatter, v as toBigNumber, w as apyToApr, x as uiToNativeBigNumber, y as toNumber, z as getAccountKeys } from "../common-IgVl6MYx.js";
1
+ // src/common/nodeWallet.ts
2
+ var NodeWallet = class {
3
+ /**
4
+ * @param payer Keypair of the associated payer
5
+ */
6
+ constructor(payer) {
7
+ this.payer = payer;
8
+ }
9
+ async signTransaction(tx) {
10
+ if ("version" in tx) {
11
+ tx.sign([this.payer]);
12
+ } else {
13
+ tx.partialSign(this.payer);
14
+ }
15
+ return tx;
16
+ }
17
+ async signAllTransactions(txs) {
18
+ return txs.map((tx) => {
19
+ if ("version" in tx) {
20
+ tx.sign([this.payer]);
21
+ return tx;
22
+ } else {
23
+ tx.partialSign(this.payer);
24
+ return tx;
25
+ }
26
+ });
27
+ }
28
+ get publicKey() {
29
+ return this.payer.publicKey;
30
+ }
31
+ };
2
32
 
3
- export { CustomNumberFormat, NodeWallet, PriotitizationFeeLevels, TransactionArenaKeyMap, TransactionConfigMap, TransactionType, addTransactionMetadata, aprToApy, apyToApr, bankExtendedMetadataOverrideSchema, bigNumberToWrappedI80F48, bpsToPercentile, calculateApyFromInterest, calculateInterestFromApy, ceil, chunkedGetRawMultipleAccountInfoOrdered, chunkedGetRawMultipleAccountInfoOrderedWithNulls, chunkedGetRawMultipleAccountInfos, chunks, clampedNumeralFormatter, compareInstructions, composeRemainingAccounts, decodeComputeBudgetInstruction, decodeInstruction, decompileV0Transaction, dynamicNumeralFormatter, fetchBanksExtendedMetadata, floor, getAccountKeys, getCalculatedPrioritizationFeeByPercentile, getComputeBudgetUnits, getMaxPrioritizationFeeByPercentile, getMeanPrioritizationFeeByPercentile, getMedianPrioritizationFeeByPercentile, getMinPrioritizationFeeByPercentile, getRecentPrioritizationFeesByPercentile, getTxSize, getValueInsensitive, groupedNumberFormatter, groupedNumberFormatterDyn, isV0Tx, legacyTxToV0Tx, median, microLamportsToUi, nativeToUi, numeralFormatter, parseBanksMetadataOverride, percentFormatter, percentFormatterDyn, percentFormatterMod, replaceV0TxBlockhash, replaceV0TxInstructions, setTimeoutPromise, shortenAddress, sleep, splitInstructionsToFitTransactions, toBigNumber, toNumber, tokenPriceFormatter, uiToMicroLamports, uiToNative, uiToNativeBigNumber, updateV0Tx, usdFormatter, usdFormatterDyn, wrappedI80F48toBigNumber };
33
+ // src/common/math.ts
34
+ function floor(value, decimals) {
35
+ return Math.floor(value * 10 ** decimals) / 10 ** decimals;
36
+ }
37
+ function ceil(value, decimals) {
38
+ return Math.ceil(value * 10 ** decimals) / 10 ** decimals;
39
+ }
40
+ function median(values) {
41
+ if (values.length === 0) {
42
+ throw new Error("Input array is empty");
43
+ }
44
+ const sortedValues = [...values].sort((a, b) => a - b);
45
+ const half = Math.floor(sortedValues.length / 2);
46
+ return sortedValues.length % 2 ? sortedValues[half] : (sortedValues[half - 1] + sortedValues[half]) / 2;
47
+ }
48
+
49
+ // src/common/misc.ts
50
+ import { PublicKey } from "@solana/web3.js";
51
+ function getValueInsensitive(map, key) {
52
+ const lowerCaseLabel = key.toLowerCase();
53
+ for (const key2 in map) {
54
+ if (key2.toLowerCase() === lowerCaseLabel) {
55
+ return map[key2];
56
+ }
57
+ }
58
+ throw new Error(`Token metadata not found for ${key}`);
59
+ }
60
+ function sleep(ms) {
61
+ return new Promise((resolve) => setTimeout(resolve, ms));
62
+ }
63
+ function chunks(array, size) {
64
+ return Array.apply(0, new Array(Math.ceil(array.length / size))).map(
65
+ (_, index) => array.slice(index * size, (index + 1) * size)
66
+ );
67
+ }
68
+ function setTimeoutPromise(duration, message) {
69
+ return new Promise((_, reject) => setTimeout(() => reject(new Error(message)), duration));
70
+ }
71
+ async function chunkedGetRawMultipleAccountInfos(connection, pks, batchChunkSize = 1e3, maxAccountsChunkSize = 100) {
72
+ const accountInfoMap = /* @__PURE__ */ new Map();
73
+ let contextSlot = 0;
74
+ const batches = chunkArray(pks, batchChunkSize);
75
+ for (let i = 0; i < batches.length; i++) {
76
+ const batch = batches[i];
77
+ const batchRequest = chunkArray(batch, maxAccountsChunkSize).map((pubkeys) => ({
78
+ methodName: "getMultipleAccounts",
79
+ args: connection._buildArgs([pubkeys], "confirmed", "base64")
80
+ }));
81
+ let accountInfos = [];
82
+ let retries = 0;
83
+ const maxRetries = 3;
84
+ while (retries < maxRetries && accountInfos.length === 0) {
85
+ try {
86
+ accountInfos = await connection._rpcBatchRequest(batchRequest).then((batchResults) => {
87
+ contextSlot = Math.max(...batchResults.map((res) => res.result.context.slot));
88
+ const accounts = batchResults.reduce(
89
+ (acc, res) => {
90
+ acc.push(...res.result.value);
91
+ return acc;
92
+ },
93
+ []
94
+ );
95
+ return accounts;
96
+ });
97
+ } catch (_error) {
98
+ retries++;
99
+ }
100
+ }
101
+ if (accountInfos.length === 0) {
102
+ throw new Error(`Failed to fetch account infos after ${maxRetries} retries`);
103
+ }
104
+ accountInfos.forEach((item, index) => {
105
+ const publicKey = batch[index];
106
+ if (item) {
107
+ accountInfoMap.set(publicKey, {
108
+ ...item,
109
+ owner: new PublicKey(item.owner),
110
+ data: Buffer.from(item.data[0], "base64")
111
+ });
112
+ }
113
+ });
114
+ }
115
+ return [contextSlot, accountInfoMap];
116
+ }
117
+ async function chunkedGetRawMultipleAccountInfoOrderedWithNulls(connection, pks, batchChunkSize = 1e3, maxAccountsChunkSize = 100) {
118
+ const allAccountInfos = [];
119
+ const batches = chunkArray(pks, batchChunkSize);
120
+ for (let i = 0; i < batches.length; i++) {
121
+ const batch = batches[i];
122
+ const batchRequest = chunkArray(batch, maxAccountsChunkSize).map((pubkeys) => ({
123
+ methodName: "getMultipleAccounts",
124
+ args: connection._buildArgs([pubkeys], "confirmed", "base64")
125
+ }));
126
+ let accountInfos = [];
127
+ let retries = 0;
128
+ const maxRetries = 3;
129
+ while (retries < maxRetries && accountInfos.length === 0) {
130
+ try {
131
+ accountInfos = await connection._rpcBatchRequest(batchRequest).then((batchResults) => {
132
+ const accounts = batchResults.reduce(
133
+ (acc, res) => {
134
+ acc.push(...res.result.value);
135
+ return acc;
136
+ },
137
+ []
138
+ );
139
+ return accounts;
140
+ });
141
+ } catch (_error) {
142
+ retries++;
143
+ }
144
+ }
145
+ if (accountInfos.length === 0) {
146
+ throw new Error(`Failed to fetch account infos after ${maxRetries} retries`);
147
+ }
148
+ accountInfos.forEach((item) => {
149
+ if (item) {
150
+ allAccountInfos.push({
151
+ ...item,
152
+ owner: new PublicKey(item.owner),
153
+ data: Buffer.from(item.data[0], "base64")
154
+ });
155
+ } else {
156
+ allAccountInfos.push(null);
157
+ }
158
+ });
159
+ }
160
+ return allAccountInfos;
161
+ }
162
+ async function chunkedGetRawMultipleAccountInfoOrdered(connection, pks, batchChunkSize = 1e3, maxAccountsChunkSize = 100) {
163
+ const allAccountInfos = [];
164
+ const batches = chunkArray(pks, batchChunkSize);
165
+ for (let i = 0; i < batches.length; i++) {
166
+ const batch = batches[i];
167
+ const batchRequest = chunkArray(batch, maxAccountsChunkSize).map((pubkeys) => ({
168
+ methodName: "getMultipleAccounts",
169
+ args: connection._buildArgs([pubkeys], "confirmed", "base64")
170
+ }));
171
+ let accountInfos = [];
172
+ let retries = 0;
173
+ const maxRetries = 3;
174
+ while (retries < maxRetries && accountInfos.length === 0) {
175
+ try {
176
+ accountInfos = await connection._rpcBatchRequest(batchRequest).then((batchResults) => {
177
+ const accounts = batchResults.reduce(
178
+ (acc, res) => {
179
+ acc.push(...res.result.value);
180
+ return acc;
181
+ },
182
+ []
183
+ );
184
+ return accounts;
185
+ });
186
+ } catch (_error) {
187
+ retries++;
188
+ }
189
+ }
190
+ if (accountInfos.length === 0) {
191
+ throw new Error(`Failed to fetch account infos after ${maxRetries} retries`);
192
+ }
193
+ accountInfos.forEach((item) => {
194
+ if (item) {
195
+ allAccountInfos.push({
196
+ ...item,
197
+ owner: new PublicKey(item.owner),
198
+ data: Buffer.from(item.data[0], "base64")
199
+ });
200
+ }
201
+ });
202
+ }
203
+ return allAccountInfos;
204
+ }
205
+ function chunkArray(array, chunkSize) {
206
+ const chunks2 = [];
207
+ for (let i = 0; i < array.length; i += chunkSize) {
208
+ chunks2.push(array.slice(i, i + chunkSize));
209
+ }
210
+ return chunks2;
211
+ }
212
+
213
+ // src/common/modules/transactions/transaction.types.ts
214
+ import {
215
+ PublicKey as PublicKey2
216
+ } from "@solana/web3.js";
217
+ var TransactionType = /* @__PURE__ */ ((TransactionType2) => {
218
+ TransactionType2["DEPOSIT"] = "DEPOSIT";
219
+ TransactionType2["WITHDRAW"] = "WITHDRAW";
220
+ TransactionType2["REPAY"] = "REPAY";
221
+ TransactionType2["BORROW"] = "BORROW";
222
+ TransactionType2["FLASHLOAN"] = "FLASHLOAN";
223
+ TransactionType2["LOOP"] = "LOOP";
224
+ TransactionType2["REPAY_COLLAT"] = "REPAY_COLLAT";
225
+ TransactionType2["LONG"] = "LONG";
226
+ TransactionType2["SHORT"] = "SHORT";
227
+ TransactionType2["CREATE_ACCOUNT"] = "CREATE_ACCOUNT";
228
+ TransactionType2["CREATE_ATA"] = "CREATE_ATA";
229
+ TransactionType2["CLOSE_ACCOUNT"] = "CLOSE_ACCOUNT";
230
+ TransactionType2["CLOSE_POSITION"] = "CLOSE_POSITION";
231
+ TransactionType2["MOVE_POSITION_WITHDRAW"] = "MOVE_POSITION_WITHDRAW";
232
+ TransactionType2["MOVE_POSITION_DEPOSIT"] = "MOVE_POSITION_DEPOSIT";
233
+ TransactionType2["WITHDRAW_ALL"] = "WITHDRAW_ALL";
234
+ TransactionType2["TRANSFER_AUTH"] = "TRANSFER_AUTH";
235
+ TransactionType2["CRANK"] = "CRANK";
236
+ TransactionType2["DEPOSIT_STAKE"] = "DEPOSIT_STAKE";
237
+ TransactionType2["WITHDRAW_STAKE"] = "WITHDRAW_STAKE";
238
+ TransactionType2["INITIALIZE_STAKED_POOL"] = "INITIALIZE_STAKED_POOL";
239
+ TransactionType2["ADD_STAKED_BANK"] = "ADD_STAKED_BANK";
240
+ TransactionType2["MERGE_STAKE_ACCOUNTS"] = "MERGE_STAKE_ACCOUNTS";
241
+ TransactionType2["STAKE_TO_STAKE"] = "STAKE_TO_STAKE";
242
+ TransactionType2["MINT_LST_NATIVE"] = "MINT_LST_NATIVE";
243
+ TransactionType2["SWAP_TO_SOL"] = "SWAP_TO_SOL";
244
+ TransactionType2["SOL_TO_LST"] = "SOL_TO_LST";
245
+ TransactionType2["UNSTAKE_LST"] = "UNSTAKE_LST";
246
+ TransactionType2["WITHDRAW_EMISSIONS"] = "WITHDRAW_EMISSIONS";
247
+ TransactionType2["LIQUIDATE_ACCOUNT"] = "LIQUIDATE_ACCOUNT";
248
+ TransactionType2["CREATE_PERM_BANK"] = "CREATE_PERM_BANK";
249
+ TransactionType2["CREATE_GROUP"] = "CREATE_GROUP";
250
+ TransactionType2["JUPITER_SWAP"] = "JUPITER_SWAP";
251
+ return TransactionType2;
252
+ })(TransactionType || {});
253
+ var TransactionConfigMap = {
254
+ // BASE LENDING ACTIONS
255
+ ["DEPOSIT" /* DEPOSIT */]: {
256
+ label: ({ amount, token } = {}) => amount && token ? `Deposit ${amount} ${token}` : "Deposit"
257
+ },
258
+ ["WITHDRAW" /* WITHDRAW */]: {
259
+ label: ({ amount, token } = {}) => amount && token ? `Withdraw ${amount} ${token}` : "Withdraw"
260
+ },
261
+ ["REPAY" /* REPAY */]: {
262
+ label: ({ amount, token } = {}) => amount && token ? `Repay ${amount} ${token}` : "Repay"
263
+ },
264
+ ["BORROW" /* BORROW */]: {
265
+ label: ({ amount, token } = {}) => amount && token ? `Borrow ${amount} ${token}` : "Borrow"
266
+ },
267
+ // FLASHLOANS
268
+ ["FLASHLOAN" /* FLASHLOAN */]: { label: () => "Executing Flashloan" },
269
+ ["LOOP" /* LOOP */]: {
270
+ label: ({ depositAmount, depositToken, borrowAmount, borrowToken } = {}) => depositAmount && depositToken && borrowAmount && borrowToken ? `Loop ${depositAmount} ${depositToken} with ${borrowAmount} ${borrowToken}` : "Loop"
271
+ },
272
+ ["REPAY_COLLAT" /* REPAY_COLLAT */]: {
273
+ label: ({ repayAmount, repayToken, amount, token } = {}) => repayAmount && repayToken && amount && token ? `Repay ${repayAmount} ${token} with ${amount} ${repayToken}` : "Repay with collateral"
274
+ },
275
+ ["LONG" /* LONG */]: {
276
+ label: ({ depositToken, depositAmount, borrowToken } = {}) => depositToken && depositAmount && borrowToken ? `Long ${depositToken} with ${depositAmount} ${borrowToken}` : "Open long position"
277
+ },
278
+ ["SHORT" /* SHORT */]: {
279
+ label: ({ borrowToken, depositAmount, depositToken } = {}) => borrowToken && depositAmount && depositToken ? `Short ${borrowToken} with ${depositAmount} ${depositToken}` : "Open short position"
280
+ },
281
+ // SWB
282
+ ["CRANK" /* CRANK */]: { label: () => "Updating latest prices" },
283
+ ["JUPITER_SWAP" /* JUPITER_SWAP */]: {
284
+ label: ({ originAmount, originToken, destinationAmount, destinationToken } = {}) => originAmount && originToken && destinationAmount && destinationToken ? `Swap ${originAmount} ${originToken} for ${destinationAmount} ${destinationToken}` : "Swap tokens"
285
+ },
286
+ // SETUP
287
+ ["CREATE_ACCOUNT" /* CREATE_ACCOUNT */]: { label: () => "Create lendr account" },
288
+ ["CREATE_ATA" /* CREATE_ATA */]: { label: () => "Configure token account" },
289
+ // ACCOUNT MANAGEMENT
290
+ ["CLOSE_ACCOUNT" /* CLOSE_ACCOUNT */]: { label: () => "Close lendr account" },
291
+ ["CLOSE_POSITION" /* CLOSE_POSITION */]: { label: () => "Close position" },
292
+ ["MOVE_POSITION_WITHDRAW" /* MOVE_POSITION_WITHDRAW */]: {
293
+ label: ({ originAccountAddress } = {}) => `Move position from ${originAccountAddress}`
294
+ },
295
+ ["MOVE_POSITION_DEPOSIT" /* MOVE_POSITION_DEPOSIT */]: {
296
+ label: ({ destinationAccountAddress } = {}) => `Move position to ${destinationAccountAddress}`
297
+ },
298
+ ["TRANSFER_AUTH" /* TRANSFER_AUTH */]: { label: () => "Authorize account transfer" },
299
+ // NATIVE STAKE ACTIONS
300
+ ["DEPOSIT_STAKE" /* DEPOSIT_STAKE */]: {
301
+ label: ({ amount, token } = {}) => amount && token ? `Authorize stake account and deposit ${amount} ${token}` : "Authorize stake and deposit"
302
+ },
303
+ ["WITHDRAW_STAKE" /* WITHDRAW_STAKE */]: {
304
+ label: () => "Authorize stake account"
305
+ },
306
+ ["INITIALIZE_STAKED_POOL" /* INITIALIZE_STAKED_POOL */]: { label: () => "Initialize stake pool" },
307
+ ["ADD_STAKED_BANK" /* ADD_STAKED_BANK */]: { label: () => "Create staked asset bank" },
308
+ ["MERGE_STAKE_ACCOUNTS" /* MERGE_STAKE_ACCOUNTS */]: { label: () => "Merge stake accounts" },
309
+ // LST (Liquid Staking Tokens)
310
+ ["STAKE_TO_STAKE" /* STAKE_TO_STAKE */]: { label: () => "Convert stake" },
311
+ ["MINT_LST_NATIVE" /* MINT_LST_NATIVE */]: { label: () => "Mint LST" },
312
+ ["SWAP_TO_SOL" /* SWAP_TO_SOL */]: {
313
+ label: ({ swapAmount, token } = {}) => swapAmount && token ? `Swap ${swapAmount} ${token} to SOL` : "Swap to SOL"
314
+ },
315
+ ["SOL_TO_LST" /* SOL_TO_LST */]: {
316
+ label: ({ amount } = {}) => amount ? `Mint LST with ${amount} SOL` : "Mint LST with SOL"
317
+ },
318
+ ["UNSTAKE_LST" /* UNSTAKE_LST */]: { label: ({ amount } = {}) => amount ? `Unstake ${amount} LST` : "Unstake LST" },
319
+ // EMISSIONS
320
+ ["WITHDRAW_EMISSIONS" /* WITHDRAW_EMISSIONS */]: { label: () => "Withdraw emissions" },
321
+ // LIQUIDATE
322
+ ["LIQUIDATE_ACCOUNT" /* LIQUIDATE_ACCOUNT */]: { label: () => "Liquidate account" },
323
+ // BANK and GROUPS
324
+ ["CREATE_PERM_BANK" /* CREATE_PERM_BANK */]: { label: () => "Create permissionless bank" },
325
+ ["CREATE_GROUP" /* CREATE_GROUP */]: { label: () => "Create lendr group" },
326
+ ["WITHDRAW_ALL" /* WITHDRAW_ALL */]: {
327
+ label: ({ amount, token } = {}) => amount && token ? `Withdraw ${amount} ${token}` : "Withdraw all"
328
+ }
329
+ };
330
+ var TransactionArenaKeyMap = {
331
+ ["DEPOSIT" /* DEPOSIT */]: new PublicKey2("ArenaDeposit1111111111111111111111111111111"),
332
+ ["WITHDRAW" /* WITHDRAW */]: new PublicKey2("ArenaWithdraw111111111111111111111111111111"),
333
+ ["BORROW" /* BORROW */]: new PublicKey2("ArenaBorrow11111111111111111111111111111111"),
334
+ ["REPAY" /* REPAY */]: new PublicKey2("ArenaRepay111111111111111111111111111111111"),
335
+ ["REPAY_COLLAT" /* REPAY_COLLAT */]: new PublicKey2("ArenaRepayCo11at111111111111111111111111111"),
336
+ ["LONG" /* LONG */]: new PublicKey2("ArenaLong1111111111111111111111111111111111"),
337
+ ["SHORT" /* SHORT */]: new PublicKey2("ArenaShort111111111111111111111111111111111"),
338
+ ["CLOSE_POSITION" /* CLOSE_POSITION */]: new PublicKey2("ArenaC1ose111111111111111111111111111111111")
339
+ // Add more mappings if needed
340
+ };
341
+
342
+ // src/common/modules/transactions/transaction.utils.ts
343
+ import { BorshInstructionCoder } from "@coral-xyz/anchor";
344
+ import {
345
+ ComputeBudgetProgram,
346
+ LAMPORTS_PER_SOL,
347
+ TransactionMessage,
348
+ VersionedTransaction
349
+ } from "@solana/web3.js";
350
+
351
+ // src/constants/bank.ts
352
+ var PDA_BANK_LIQUIDITY_VAULT_AUTH_SEED = Buffer.from("liquidity_vault_auth");
353
+ var PDA_BANK_INSURANCE_VAULT_AUTH_SEED = Buffer.from("insurance_vault_auth");
354
+ var PDA_BANK_FEE_VAULT_AUTH_SEED = Buffer.from("fee_vault_auth");
355
+ var PDA_BANK_LIQUIDITY_VAULT_SEED = Buffer.from("liquidity_vault");
356
+ var PDA_BANK_INSURANCE_VAULT_SEED = Buffer.from("insurance_vault");
357
+ var PDA_BANK_FEE_VAULT_SEED = Buffer.from("fee_vault");
358
+
359
+ // src/constants/defaults.ts
360
+ var DEFAULT_COMMITMENT = "processed";
361
+ var DEFAULT_SEND_OPTS = {
362
+ skipPreflight: false,
363
+ preflightCommitment: DEFAULT_COMMITMENT
364
+ };
365
+ var DEFAULT_CONFIRM_OPTS = {
366
+ commitment: DEFAULT_COMMITMENT,
367
+ ...DEFAULT_SEND_OPTS
368
+ };
369
+ var MAX_TX_SIZE = 1232;
370
+
371
+ // src/constants/flags.ts
372
+ var DISABLED_FLAG = 1 << 0;
373
+ var FLASHLOAN_ENABLED_FLAG = 1 << 2;
374
+ var TRANSFER_ACCOUNT_AUTHORITY_FLAG = 1 << 3;
375
+
376
+ // src/constants/misc.ts
377
+ import { PublicKey as PublicKey3 } from "@solana/web3.js";
378
+ import BigNumber from "bignumber.js";
379
+ var HOURS_PER_YEAR = 365.25 * 24;
380
+ var MAX_U64 = BigInt("18446744073709551615").toString();
381
+ var PYTH_PRICE_CONF_INTERVALS = new BigNumber(2.12);
382
+ var SWB_PRICE_CONF_INTERVALS = new BigNumber(1.96);
383
+ var MAX_CONFIDENCE_INTERVAL_RATIO = new BigNumber(0.05);
384
+ var PYTH_PUSH_ORACLE_ID = new PublicKey3("pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT");
385
+ var GROUP_PK = new PublicKey3(process.env.LENDR_GROUP_PK ?? "4vDRNkXaeAcwJULZCQFFdNBM295sD8hSKQt3RaMwsRFc");
386
+ var PROGRAM_ID = new PublicKey3(process.env.LENDR_PROGRAM_ID ?? "89ZQeCPwkzSPJyTpktCKWNY6hBWMKuYt47R85Jo36yyh");
387
+ var DEFAULT_CLUSTER = process.env.LENDR_CLUSTER_OVERRIDE ?? "mainnet";
388
+
389
+ // src/constants/programs.ts
390
+ import { PublicKey as PublicKey4 } from "@solana/web3.js";
391
+ var JUPITER_V6_PROGRAM = new PublicKey4("JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4");
392
+ var LENDR_PROGRAM = new PublicKey4("89ZQeCPwkzSPJyTpktCKWNY6hBWMKuYt47R85Jo36yyh");
393
+ var SINGLE_POOL_PROGRAM_ID = new PublicKey4("SVSPxpvHdN29nkVg9rPapPNDddN5DipNLRUFhyjFThE");
394
+ var STAKE_PROGRAM_ID = new PublicKey4("Stake11111111111111111111111111111111111111");
395
+ var MPL_METADATA_PROGRAM_ID = new PublicKey4("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s");
396
+ var SYSTEM_PROGRAM_ID = new PublicKey4("11111111111111111111111111111111");
397
+ var SYSVAR_RENT_ID = new PublicKey4("SysvarRent111111111111111111111111111111111");
398
+ var SYSVAR_CLOCK_ID = new PublicKey4("SysvarC1ock11111111111111111111111111111111");
399
+ var SYSVAR_STAKE_HISTORY_ID = new PublicKey4("SysvarStakeHistory1111111111111111111111111");
400
+ var STAKE_CONFIG_ID = new PublicKey4("StakeConfig11111111111111111111111111111111");
401
+
402
+ // src/constants/tokens.ts
403
+ import { PublicKey as PublicKey5 } from "@solana/web3.js";
404
+ var WSOL_MINT = new PublicKey5("So11111111111111111111111111111111111111112");
405
+ var WSOL_EXTENDED_METADATA = {
406
+ symbol: "wSOL",
407
+ name: "Wrapped SOL",
408
+ address: "D7zkaUgFUDkhQHExySRxokL3Fa1GFnnuiVDTs9yMrFHY",
409
+ logoURI: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png",
410
+ additionalMetadata: [],
411
+ uri: "",
412
+ mint: WSOL_MINT.toBase58()
413
+ };
414
+ var LST_MINT = new PublicKey5("LSTxxxnJzKDFSLr4dUkPcmCf5VyryEqzPLz5j4bpxFp");
415
+ var USDC_MINT = new PublicKey5("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
416
+ var DUMMY_USDC_MINT = new PublicKey5("JAiSLhTCvAhGM4SojCYGoTPuqjw7KaCsopvRuNryzbML");
417
+
418
+ // src/common/modules/transactions/transaction.utils.ts
419
+ function isV0Tx(tx) {
420
+ return "message" in tx;
421
+ }
422
+ function getTxSize(tx) {
423
+ const isVersioned = isV0Tx(tx);
424
+ const numSigners = tx.signatures.length;
425
+ const numRequiredSignatures = isVersioned ? tx.message.header.numRequiredSignatures : 0;
426
+ const feePayerSize = isVersioned || tx.feePayer ? 0 : 32;
427
+ const signaturesSize = (numRequiredSignatures - numSigners) * 64 + 1;
428
+ try {
429
+ const baseTxSize = isVersioned ? tx.serialize().length : tx.serialize({ requireAllSignatures: false, verifySignatures: false }).length;
430
+ return baseTxSize + feePayerSize + signaturesSize;
431
+ } catch (_error) {
432
+ return 9999;
433
+ }
434
+ }
435
+ function getAccountKeys(tx, lookupTableAccounts) {
436
+ const isVersioned = isV0Tx(tx);
437
+ try {
438
+ if (isVersioned) {
439
+ const message = TransactionMessage.decompile(tx.message, { addressLookupTableAccounts: lookupTableAccounts });
440
+ return message.compileToLegacyMessage().getAccountKeys().length;
441
+ } else {
442
+ return tx.compileMessage().getAccountKeys().length;
443
+ }
444
+ } catch (_error) {
445
+ return 9999;
446
+ }
447
+ }
448
+ function decodeInstruction(idl, encoded) {
449
+ const coder = new BorshInstructionCoder(idl);
450
+ return coder.decode(encoded, "base58");
451
+ }
452
+ function decompileV0Transaction(tx, lookupTableAccounts) {
453
+ return TransactionMessage.decompile(tx.message, { addressLookupTableAccounts: lookupTableAccounts });
454
+ }
455
+ function legacyTxToV0Tx(transaction, opts) {
456
+ const feePayer = opts?.feePayer ?? transaction.feePayer;
457
+ const blockhash = opts?.blockhash ?? transaction.recentBlockhash;
458
+ const additionalIxs = opts?.additionalIxs ?? [];
459
+ const addressLookupTables = opts?.addressLookupTables ?? [];
460
+ if (!feePayer || !blockhash) {
461
+ throw new Error("Fee payer and blockhash are required");
462
+ }
463
+ const ixs = transaction.instructions;
464
+ const versionedMessage = new TransactionMessage({
465
+ instructions: [...additionalIxs, ...ixs],
466
+ payerKey: feePayer,
467
+ recentBlockhash: blockhash
468
+ });
469
+ return new VersionedTransaction(versionedMessage.compileToV0Message(addressLookupTables));
470
+ }
471
+ function updateV0Tx(transaction, opts) {
472
+ const additionalIxs = opts?.additionalIxs ?? [];
473
+ const addressLookupTables = opts?.addressLookupTables ?? [];
474
+ let instructions = [];
475
+ const message = decompileV0Transaction(transaction, addressLookupTables);
476
+ const feePayer = opts?.feePayer ?? message.payerKey;
477
+ const blockhash = opts?.blockhash ?? message.recentBlockhash;
478
+ if (additionalIxs.length > 0) {
479
+ instructions = replaceV0TxInstructions(additionalIxs, message.instructions, opts?.replaceOnly);
480
+ } else {
481
+ instructions = message.instructions;
482
+ }
483
+ const versionedMessage = new TransactionMessage({
484
+ instructions,
485
+ payerKey: feePayer,
486
+ recentBlockhash: blockhash
487
+ });
488
+ return new VersionedTransaction(versionedMessage.compileToV0Message(addressLookupTables));
489
+ }
490
+ function compareInstructions(ix1, ix2) {
491
+ const dataCompare = ix1.data.equals(ix2.data);
492
+ const programIdCompare = ix1.programId.equals(ix2.programId);
493
+ const keysCompare = ix1.keys.length === ix2.keys.length && ix1.keys.every((key, index) => {
494
+ const key2 = ix2.keys[index];
495
+ return key.pubkey.equals(key2.pubkey) && key.isSigner === key2.isSigner && key.isWritable === key2.isWritable;
496
+ });
497
+ return dataCompare && programIdCompare && keysCompare;
498
+ }
499
+ function replaceV0TxInstructions(additionalInstructions, instructions, replaceOnly) {
500
+ let updatedAdditionalIxs = additionalInstructions;
501
+ const updatedInstructions = instructions.map((ix) => {
502
+ const programId = ix.programId;
503
+ const additionalIxs = additionalInstructions.filter((a) => a.programId.equals(programId));
504
+ if (additionalIxs.length > 0) {
505
+ if (ix.programId.equals(ComputeBudgetProgram.programId)) {
506
+ const decoded = decodeComputeBudgetInstruction(ix);
507
+ const updatedCuPriceIx = additionalIxs.find(
508
+ (a) => decodeComputeBudgetInstruction(a).instructionType === "SetComputeUnitPrice"
509
+ );
510
+ const updatedCuLimitIx = additionalIxs.find(
511
+ (a) => decodeComputeBudgetInstruction(a).instructionType === "SetComputeUnitLimit"
512
+ );
513
+ if (decoded.instructionType === "SetComputeUnitPrice" && updatedCuPriceIx) {
514
+ updatedAdditionalIxs = updatedAdditionalIxs.filter((a) => !compareInstructions(a, updatedCuPriceIx));
515
+ return updatedCuPriceIx;
516
+ }
517
+ if (decoded.instructionType === "SetComputeUnitLimit" && updatedCuLimitIx) {
518
+ updatedAdditionalIxs = updatedAdditionalIxs.filter((a) => !compareInstructions(a, updatedCuLimitIx));
519
+ return updatedCuLimitIx;
520
+ }
521
+ }
522
+ }
523
+ return ix;
524
+ });
525
+ return [...replaceOnly ? [] : updatedAdditionalIxs, ...updatedInstructions];
526
+ }
527
+ function replaceV0TxBlockhash(transaction, blockhash) {
528
+ const message = transaction.message;
529
+ message.recentBlockhash = blockhash;
530
+ return new VersionedTransaction(message);
531
+ }
532
+ function addTransactionMetadata(transaction, options) {
533
+ return Object.assign(transaction, options);
534
+ }
535
+ function identifyComputeBudgetInstruction(data) {
536
+ const discriminator = data.readUInt8(0);
537
+ switch (discriminator) {
538
+ case 0:
539
+ return "RequestUnits";
540
+ case 1:
541
+ return "RequestHeapFrame";
542
+ case 2:
543
+ return "SetComputeUnitLimit";
544
+ case 3:
545
+ return "SetComputeUnitPrice";
546
+ case 4:
547
+ return "SetLoadedAccountsDataSizeLimit";
548
+ default:
549
+ throw new Error("Unknown ComputeBudget instruction discriminator.");
550
+ }
551
+ }
552
+ function decodeComputeBudgetInstruction(instruction) {
553
+ const data = Buffer.from(instruction.data || instruction);
554
+ const instructionType = identifyComputeBudgetInstruction(data);
555
+ switch (instructionType) {
556
+ case "RequestUnits": {
557
+ if (data.length !== 9) {
558
+ throw new Error("Invalid data length for RequestUnits");
559
+ }
560
+ const units = data.readUInt32LE(1);
561
+ const additionalFee = data.readUInt32LE(5);
562
+ return { instructionType, units, additionalFee };
563
+ }
564
+ case "RequestHeapFrame": {
565
+ if (data.length !== 5) {
566
+ throw new Error("Invalid data length for RequestHeapFrame");
567
+ }
568
+ const bytes = data.readUInt32LE(1);
569
+ return { instructionType, bytes };
570
+ }
571
+ case "SetComputeUnitLimit": {
572
+ if (data.length !== 5) {
573
+ throw new Error("Invalid data length for SetComputeUnitLimit");
574
+ }
575
+ const units = data.readUInt32LE(1);
576
+ return { instructionType, units };
577
+ }
578
+ case "SetComputeUnitPrice": {
579
+ if (data.length !== 9) {
580
+ throw new Error("Invalid data length for SetComputeUnitPrice");
581
+ }
582
+ const microLamports = data.readBigUInt64LE(1);
583
+ return { instructionType, microLamports: microLamports.toString() };
584
+ }
585
+ case "SetLoadedAccountsDataSizeLimit": {
586
+ if (data.length !== 5) {
587
+ throw new Error("Invalid data length for SetLoadedAccountsDataSizeLimit");
588
+ }
589
+ const accountDataSizeLimit = data.readUInt32LE(1);
590
+ return { instructionType, accountDataSizeLimit };
591
+ }
592
+ default:
593
+ throw new Error("Unknown ComputeBudget instruction type.");
594
+ }
595
+ }
596
+ var DEFAULT_COMPUTE_BUDGET_IX = 2e5;
597
+ function getComputeBudgetUnits(tx) {
598
+ let instructions = [];
599
+ if (isV0Tx(tx)) {
600
+ const addressLookupTableAccounts = tx.addressLookupTables ?? [];
601
+ const message = decompileV0Transaction(tx, addressLookupTableAccounts);
602
+ instructions = message.instructions;
603
+ } else {
604
+ instructions = tx.instructions;
605
+ }
606
+ const computeBudgetIxs = instructions.filter((ix) => ix.programId.equals(ComputeBudgetProgram.programId));
607
+ if (computeBudgetIxs.length === 0) {
608
+ return Math.min(instructions.length * DEFAULT_COMPUTE_BUDGET_IX, 14e5);
609
+ }
610
+ const decoded = computeBudgetIxs.map((ix) => decodeComputeBudgetInstruction(ix));
611
+ const limit = decoded.find((ix) => ix.instructionType === "SetComputeUnitLimit");
612
+ return limit?.units ?? instructions.length * DEFAULT_COMPUTE_BUDGET_IX;
613
+ }
614
+ var uiToMicroLamports = (ui, limitCU = 14e5) => {
615
+ const priorityFeeMicroLamports = ui * LAMPORTS_PER_SOL * 1e6;
616
+ return priorityFeeMicroLamports / limitCU;
617
+ };
618
+ var microLamportsToUi = (microLamports, limitCU = 14e5) => {
619
+ const priorityFeeMicroLamports = microLamports * limitCU;
620
+ const priorityFeeUi = priorityFeeMicroLamports / (LAMPORTS_PER_SOL * 1e6);
621
+ return Math.trunc(priorityFeeUi * LAMPORTS_PER_SOL) / LAMPORTS_PER_SOL;
622
+ };
623
+ function splitInstructionsToFitTransactions(mandatoryIxs, ixs, opts) {
624
+ const result = [];
625
+ let buffer = [];
626
+ function buildTx(mandatoryIxs2, extraIxs, opts2) {
627
+ const messageV0 = new TransactionMessage({
628
+ payerKey: opts2.payerKey,
629
+ recentBlockhash: opts2.blockhash,
630
+ instructions: [...mandatoryIxs2, ...extraIxs]
631
+ }).compileToV0Message(opts2.luts);
632
+ return new VersionedTransaction(messageV0);
633
+ }
634
+ for (const ix of ixs) {
635
+ const trial = buildTx(mandatoryIxs, [...buffer, ix], opts);
636
+ if (getTxSize(trial) <= MAX_TX_SIZE) {
637
+ buffer.push(ix);
638
+ } else {
639
+ if (buffer.length === 0) {
640
+ throw new Error("Single instruction too large to fit in a transaction");
641
+ }
642
+ const tx = buildTx(mandatoryIxs, buffer, opts);
643
+ result.push(tx);
644
+ buffer = [ix];
645
+ const solo = buildTx(mandatoryIxs, buffer, opts);
646
+ if (getTxSize(solo) > MAX_TX_SIZE) {
647
+ throw new Error("Single instruction too large to fit in a transaction");
648
+ }
649
+ }
650
+ }
651
+ if (buffer.length > 0) {
652
+ const tx = buildTx(mandatoryIxs, buffer, opts);
653
+ result.push(tx);
654
+ }
655
+ return result;
656
+ }
657
+
658
+ // src/common/priority.ts
659
+ var PriotitizationFeeLevels = /* @__PURE__ */ ((PriotitizationFeeLevels2) => {
660
+ PriotitizationFeeLevels2[PriotitizationFeeLevels2["LOW"] = 2500] = "LOW";
661
+ PriotitizationFeeLevels2[PriotitizationFeeLevels2["MEDIAN"] = 5e3] = "MEDIAN";
662
+ PriotitizationFeeLevels2[PriotitizationFeeLevels2["HIGH"] = 7500] = "HIGH";
663
+ PriotitizationFeeLevels2[PriotitizationFeeLevels2["MAX"] = 1e4] = "MAX";
664
+ return PriotitizationFeeLevels2;
665
+ })(PriotitizationFeeLevels || {});
666
+ var getCalculatedPrioritizationFeeByPercentile = async (connection, config, slotsToReturn) => {
667
+ const fees = await getRecentPrioritizationFeesByPercentile(connection, config, slotsToReturn);
668
+ const { min, max, sum } = fees.reduce(
669
+ (acc, fee) => ({
670
+ min: fee.prioritizationFee < acc.min.prioritizationFee ? fee : acc.min,
671
+ max: fee.prioritizationFee > acc.max.prioritizationFee ? fee : acc.max,
672
+ sum: acc.sum + fee.prioritizationFee
673
+ }),
674
+ { min: fees[0], max: fees[0], sum: 0 }
675
+ );
676
+ const mean = Math.ceil(sum / fees.length);
677
+ const sortedFees = [...fees].sort((a, b) => a.prioritizationFee - b.prioritizationFee);
678
+ const midIndex = Math.floor(fees.length / 2);
679
+ const median2 = fees.length % 2 === 0 ? Math.ceil((sortedFees[midIndex - 1].prioritizationFee + sortedFees[midIndex].prioritizationFee) / 2) : sortedFees[midIndex].prioritizationFee;
680
+ return {
681
+ min,
682
+ max,
683
+ mean,
684
+ median: median2
685
+ };
686
+ };
687
+ var getMinPrioritizationFeeByPercentile = async (connection, config, slotsToReturn) => {
688
+ const recentPrioritizationFees = await getRecentPrioritizationFeesByPercentile(connection, config, slotsToReturn);
689
+ const minPriorityFee = recentPrioritizationFees.reduce((min, current) => {
690
+ return current.prioritizationFee < min.prioritizationFee ? current : min;
691
+ });
692
+ return minPriorityFee.prioritizationFee;
693
+ };
694
+ var getMaxPrioritizationFeeByPercentile = async (connection, config, slotsToReturn) => {
695
+ const recentPrioritizationFees = await getRecentPrioritizationFeesByPercentile(connection, config, slotsToReturn);
696
+ const maxPriorityFee = recentPrioritizationFees.reduce((max, current) => {
697
+ return current.prioritizationFee > max.prioritizationFee ? current : max;
698
+ });
699
+ return maxPriorityFee.prioritizationFee;
700
+ };
701
+ var getMeanPrioritizationFeeByPercentile = async (connection, config, slotsToReturn) => {
702
+ const recentPrioritizationFees = await getRecentPrioritizationFeesByPercentile(connection, config, slotsToReturn);
703
+ const mean = Math.ceil(
704
+ recentPrioritizationFees.reduce((acc, fee) => acc + fee.prioritizationFee, 0) / recentPrioritizationFees.length
705
+ );
706
+ return mean;
707
+ };
708
+ var getMedianPrioritizationFeeByPercentile = async (connection, config, slotsToReturn) => {
709
+ const recentPrioritizationFees = await getRecentPrioritizationFeesByPercentile(connection, config, slotsToReturn);
710
+ recentPrioritizationFees.sort((a, b) => a.prioritizationFee - b.prioritizationFee);
711
+ const half = Math.floor(recentPrioritizationFees.length / 2);
712
+ if (recentPrioritizationFees.length % 2) {
713
+ return recentPrioritizationFees[half].prioritizationFee;
714
+ }
715
+ return Math.ceil(
716
+ (recentPrioritizationFees[half - 1].prioritizationFee + recentPrioritizationFees[half].prioritizationFee) / 2
717
+ );
718
+ };
719
+ var getRecentPrioritizationFeesFromRpc = async (config, rpcRequest) => {
720
+ const accounts = config?.lockedWritableAccounts?.map((key) => key.toBase58());
721
+ const args = accounts?.length ? [accounts] : [[]];
722
+ config.percentile && args.push({ percentile: config.percentile });
723
+ const response = await rpcRequest("getRecentPrioritizationFees", args);
724
+ return response;
725
+ };
726
+ var getRecentPrioritizationFeesByPercentile = async (connection, config, slotsToReturn) => {
727
+ const { fallback = true, lockedWritableAccounts = [] } = config || {};
728
+ const validSlotsToReturn = slotsToReturn && Number.isInteger(slotsToReturn) ? slotsToReturn : -1;
729
+ const promises = [];
730
+ let tritonRpcResponse;
731
+ let fallbackRpcResponse;
732
+ const rpcRequest = connection._rpcRequest;
733
+ promises.push(
734
+ getRecentPrioritizationFeesFromRpc(config, rpcRequest).then((result) => {
735
+ tritonRpcResponse = result;
736
+ })
737
+ );
738
+ if (fallback) {
739
+ promises.push(
740
+ getRecentPrioritizationFeesFromRpc({ lockedWritableAccounts }, rpcRequest).then((result) => {
741
+ fallbackRpcResponse = result;
742
+ })
743
+ );
744
+ }
745
+ await Promise.all(promises);
746
+ const tritonGRPFResponse = tritonRpcResponse;
747
+ const fallbackGRPFResponse = fallbackRpcResponse;
748
+ let recentPrioritizationFees = [];
749
+ if (tritonGRPFResponse?.result) {
750
+ recentPrioritizationFees = tritonGRPFResponse.result;
751
+ }
752
+ if (fallbackGRPFResponse?.result && !tritonGRPFResponse?.result) {
753
+ recentPrioritizationFees = fallbackGRPFResponse.result;
754
+ }
755
+ if (fallback && fallbackGRPFResponse.error) {
756
+ return fallbackGRPFResponse.error;
757
+ }
758
+ if (tritonGRPFResponse?.error) {
759
+ return tritonGRPFResponse.error;
760
+ }
761
+ recentPrioritizationFees.sort((a, b) => a.slot - b.slot);
762
+ if (validSlotsToReturn > 0) return recentPrioritizationFees.slice(0, validSlotsToReturn);
763
+ return recentPrioritizationFees;
764
+ };
765
+
766
+ // src/common/utils/accounting.utils.ts
767
+ var apyToApr = (apy, compoundingFrequency = HOURS_PER_YEAR) => ((1 + apy) ** (1 / compoundingFrequency) - 1) * compoundingFrequency;
768
+ var aprToApy = (apr, compoundingFrequency = HOURS_PER_YEAR, apyCap = 3) => Math.min((1 + apr / compoundingFrequency) ** compoundingFrequency - 1, apyCap);
769
+ function calculateInterestFromApy(principal, durationInYears, apy) {
770
+ return principal * apy * durationInYears;
771
+ }
772
+ function calculateApyFromInterest(principal, durationInYears, interest) {
773
+ return interest / (principal * durationInYears);
774
+ }
775
+
776
+ // src/common/utils/conversion.utils.ts
777
+ import BigNumber2 from "bignumber.js";
778
+ import BN from "bn.js";
779
+ import { Decimal } from "decimal.js";
780
+ var I80F48_FRACTIONAL_BYTES = 6;
781
+ var I80F48_TOTAL_BYTES = 16;
782
+ var I80F48_DIVISOR = new Decimal(2).pow(8 * I80F48_FRACTIONAL_BYTES);
783
+ function wrappedI80F48toBigNumber(wrapped) {
784
+ const bytesLE = wrapped.value;
785
+ if (bytesLE.length !== I80F48_TOTAL_BYTES) {
786
+ throw new Error(`Expected a ${I80F48_TOTAL_BYTES}-byte buffer`);
787
+ }
788
+ let bytesBE = bytesLE.slice();
789
+ bytesBE.reverse();
790
+ let signChar = "";
791
+ const msb = bytesBE[0];
792
+ if (msb & 128) {
793
+ signChar = "-";
794
+ bytesBE = bytesBE.map((v) => ~v & 255);
795
+ }
796
+ const hex = `${signChar}0x${bytesBE.map((v) => v.toString(16).padStart(2, "0")).join("")}`;
797
+ const decoded = new Decimal(hex).dividedBy(I80F48_DIVISOR);
798
+ return new BigNumber2(decoded.toString());
799
+ }
800
+ function bigNumberToWrappedI80F48(value) {
801
+ let decimalValue = new Decimal(value.toString());
802
+ const isNegative = decimalValue.isNegative();
803
+ decimalValue = decimalValue.times(I80F48_DIVISOR);
804
+ let wrappedValue = new BN(decimalValue.round().toFixed()).toArray();
805
+ if (wrappedValue.length < I80F48_TOTAL_BYTES) {
806
+ const padding = Array(I80F48_TOTAL_BYTES - wrappedValue.length).fill(0);
807
+ wrappedValue.unshift(...padding);
808
+ }
809
+ if (isNegative) {
810
+ wrappedValue[wrappedValue.length - 1] |= 128;
811
+ wrappedValue = wrappedValue.map((v) => ~v & 255);
812
+ }
813
+ wrappedValue.reverse();
814
+ return { value: wrappedValue };
815
+ }
816
+ function toNumber(amount) {
817
+ let amt;
818
+ if (typeof amount === "number") {
819
+ amt = amount;
820
+ } else if (typeof amount === "string") {
821
+ amt = Number(amount);
822
+ } else {
823
+ amt = amount.toNumber();
824
+ }
825
+ return amt;
826
+ }
827
+ function toBigNumber(amount) {
828
+ let amt;
829
+ if (amount instanceof BigNumber2) {
830
+ amt = amount;
831
+ } else {
832
+ amt = new BigNumber2(amount.toString());
833
+ }
834
+ return amt;
835
+ }
836
+ function uiToNative(amount, decimals) {
837
+ const amt = toBigNumber(amount);
838
+ return new BN(amt.times(10 ** decimals).toFixed(0, BigNumber2.ROUND_FLOOR));
839
+ }
840
+ function uiToNativeBigNumber(amount, decimals) {
841
+ const amt = toBigNumber(amount);
842
+ return amt.times(10 ** decimals);
843
+ }
844
+ function nativeToUi(amount, decimals) {
845
+ const amt = toBigNumber(amount);
846
+ return amt.div(10 ** decimals).toNumber();
847
+ }
848
+ function shortenAddress(pubkey, chars = 4) {
849
+ const pubkeyStr = pubkey.toString();
850
+ return `${pubkeyStr.slice(0, chars)}...${pubkeyStr.slice(-chars)}`;
851
+ }
852
+ function bpsToPercentile(bps) {
853
+ return bps / 1e4;
854
+ }
855
+ var composeRemainingAccounts = (banksAndOracles) => {
856
+ banksAndOracles.sort((a, b) => {
857
+ const A = a[0].toBytes();
858
+ const B = b[0].toBytes();
859
+ for (let i = 0; i < 32; i++) {
860
+ if (A[i] !== B[i]) {
861
+ return B[i] - A[i];
862
+ }
863
+ }
864
+ return 0;
865
+ });
866
+ return banksAndOracles.flat();
867
+ };
868
+
869
+ // src/common/utils/formatters.utils.ts
870
+ import numeral from "numeral";
871
+ var CustomNumberFormat = class extends Intl.NumberFormat {
872
+ format(value) {
873
+ if (value === 0) {
874
+ return "-";
875
+ } else {
876
+ return super.format(value);
877
+ }
878
+ }
879
+ };
880
+ var groupedNumberFormatter = new CustomNumberFormat("en-US", {
881
+ useGrouping: true,
882
+ minimumFractionDigits: 0,
883
+ maximumFractionDigits: 2
884
+ });
885
+ var numeralFormatter = (value) => {
886
+ if (value < 0.01) {
887
+ return "0";
888
+ } else {
889
+ return numeral(value).format("0.00a");
890
+ }
891
+ };
892
+ var dynamicNumeralFormatter = (value, options = {}) => {
893
+ const {
894
+ minDisplay = 1e-5,
895
+ // Default minDisplay for backward compatibility
896
+ maxDisplay = 1e4,
897
+ // Default maxDisplay for backward compatibility
898
+ tokenPrice,
899
+ logging = false,
900
+ ignoreMinDisplay = false,
901
+ // New flag to control ignoring minDisplay
902
+ forceDecimals
903
+ } = options;
904
+ if (value === 0 || Number.isNaN(value)) return "0";
905
+ const absValue = Math.abs(value);
906
+ if (logging) {
907
+ console.log({
908
+ value,
909
+ minDisplay,
910
+ maxDisplay,
911
+ tokenPrice,
912
+ ignoreMinDisplay,
913
+ absValue
914
+ });
915
+ }
916
+ if (!ignoreMinDisplay && absValue < minDisplay) {
917
+ return `<${minDisplay}`;
918
+ }
919
+ if (absValue > maxDisplay) {
920
+ return numeral(value).format(forceDecimals ? "0,0.00a" : "0,0.[00]a");
921
+ }
922
+ if (!ignoreMinDisplay && Math.abs(value) >= 0.01) {
923
+ return numeral(value).format(forceDecimals && Math.abs(value) > 0.99 ? "0,0.00a" : "0,0.[0000]a");
924
+ }
925
+ if (ignoreMinDisplay) {
926
+ const decimalPart = absValue - Math.floor(absValue);
927
+ const decimalPlaces = decimalPart > 0 ? 3 : 0;
928
+ if (absValue >= 1) {
929
+ return value.toFixed(decimalPlaces).replace(/\.?0+$/, "");
930
+ } else {
931
+ const exponent = Math.floor(Math.log10(absValue));
932
+ const significantDecimals = Math.max(3, 2 - exponent);
933
+ return value.toFixed(significantDecimals).replace(/\.?0+$/, "");
934
+ }
935
+ }
936
+ if (Math.abs(value) >= minDisplay) {
937
+ const decimalPlaces = Math.max(0, Math.ceil(-Math.log10(minDisplay)));
938
+ return numeral(value).format(`0,0.[${"0".repeat(decimalPlaces)}]`);
939
+ }
940
+ if (tokenPrice) {
941
+ const smallestUnit = minDisplay / tokenPrice;
942
+ const significantDecimals = Math.max(3, Math.ceil(-Math.log10(smallestUnit)));
943
+ return value.toFixed(significantDecimals).replace(/\.?0+$/, "");
944
+ }
945
+ return "0";
946
+ };
947
+ var groupedNumberFormatterDyn = new Intl.NumberFormat("en-US", {
948
+ useGrouping: true,
949
+ minimumFractionDigits: 0,
950
+ maximumFractionDigits: 2
951
+ });
952
+ var usdFormatter = new Intl.NumberFormat("en-US", {
953
+ style: "currency",
954
+ currency: "USD",
955
+ minimumFractionDigits: 2,
956
+ maximumFractionDigits: 2,
957
+ signDisplay: "auto"
958
+ });
959
+ var usdFormatterDyn = new Intl.NumberFormat("en-US", {
960
+ style: "currency",
961
+ currency: "USD",
962
+ minimumFractionDigits: 0,
963
+ maximumFractionDigits: 2,
964
+ signDisplay: "auto"
965
+ });
966
+ var percentFormatter = new Intl.NumberFormat("en-US", {
967
+ style: "percent",
968
+ minimumFractionDigits: 2,
969
+ maximumFractionDigits: 2
970
+ });
971
+ var percentFormatterDyn = new Intl.NumberFormat("en-US", {
972
+ style: "percent",
973
+ minimumFractionDigits: 0,
974
+ maximumFractionDigits: 2
975
+ });
976
+ var percentFormatterMod = (value, opts = { minFractionDigits: 2, maxFractionDigits: 2 }) => {
977
+ const percentFormatter2 = new Intl.NumberFormat("en-US", {
978
+ style: "percent",
979
+ minimumFractionDigits: opts.minFractionDigits,
980
+ maximumFractionDigits: opts.maxFractionDigits
981
+ });
982
+ if (value === 0) {
983
+ return "0%";
984
+ } else {
985
+ return percentFormatter2.format(value);
986
+ }
987
+ };
988
+ var clampedNumeralFormatter = (value) => {
989
+ if (value === 0) {
990
+ return "0";
991
+ } else if (value < 0.01) {
992
+ return "< 0.01";
993
+ } else {
994
+ return numeral(value).format("0.00a");
995
+ }
996
+ };
997
+ var tokenPriceFormatter = (price, style = "currency") => {
998
+ if (price === 0) {
999
+ return 0;
1000
+ }
1001
+ const reformatNum = Number(price.toFixed(20));
1002
+ if (price === 0) {
1003
+ return 0;
1004
+ }
1005
+ if (reformatNum < 1e-8) {
1006
+ return price.toExponential(2);
1007
+ }
1008
+ const { minFractionDigits, maxFractionDigits } = reformatNum > 1 ? { minFractionDigits: 2, maxFractionDigits: 2 } : reformatNum > 1e-6 ? { minFractionDigits: 2, maxFractionDigits: 7 } : { minFractionDigits: 7, maxFractionDigits: 10 };
1009
+ const formatter = new Intl.NumberFormat("en-US", {
1010
+ style,
1011
+ currency: "USD",
1012
+ minimumFractionDigits: minFractionDigits,
1013
+ maximumFractionDigits: maxFractionDigits,
1014
+ signDisplay: "auto"
1015
+ });
1016
+ return formatter.format(price);
1017
+ };
1018
+
1019
+ // src/common/bank-metadata.ts
1020
+ import { z } from "zod";
1021
+ var bankExtendedMetadataOverrideSchema = z.object({
1022
+ name: z.string().optional(),
1023
+ symbol: z.string().optional(),
1024
+ logoURI: z.string().url().optional(),
1025
+ // TODO)) [later] remove these if not used anywhere
1026
+ address: z.string().optional(),
1027
+ mint: z.string().optional(),
1028
+ // TODO)) added in new IDL version
1029
+ validatorVoteAccount: z.string().optional()
1030
+ });
1031
+ var parseBanksMetadataOverride = (data) => {
1032
+ return z.record(z.string(), bankExtendedMetadataOverrideSchema).parse(data);
1033
+ };
1034
+ var fetchBanksExtendedMetadata = async ({
1035
+ mintsWithOwner,
1036
+ metadataService,
1037
+ logger,
1038
+ overrideBanksMetadata
1039
+ }) => {
1040
+ const metas = await metadataService.forMints(mintsWithOwner.map(({ mint }) => mint));
1041
+ const results = await Promise.all(
1042
+ mintsWithOwner.map(async ({ mint }) => {
1043
+ const mintAddress = mint.toBase58();
1044
+ const tokenMeta = metas[mintAddress];
1045
+ if (!tokenMeta) {
1046
+ logger.warn({ mintStr: mintAddress }, "fetched metadata was null");
1047
+ if (!overrideBanksMetadata) {
1048
+ return null;
1049
+ }
1050
+ const overrideMetadata2 = Object.values(overrideBanksMetadata).find((m) => m?.mint === mintAddress);
1051
+ if (!overrideMetadata2) {
1052
+ return null;
1053
+ }
1054
+ const { name: name2, symbol: symbol2, logoURI } = overrideMetadata2;
1055
+ if (name2 && symbol2) {
1056
+ return {
1057
+ mint: mintAddress,
1058
+ name: name2,
1059
+ symbol: symbol2,
1060
+ logoURI,
1061
+ uri: "",
1062
+ additionalMetadata: []
1063
+ };
1064
+ }
1065
+ logger.warn(
1066
+ {
1067
+ overrideMetadata: overrideMetadata2,
1068
+ mint: mintAddress
1069
+ },
1070
+ "override metadata exists but is missing required fields: name, symbol, mint"
1071
+ );
1072
+ return null;
1073
+ }
1074
+ const { name, symbol, image, uri } = tokenMeta;
1075
+ const overrideMetadata = overrideBanksMetadata?.[symbol];
1076
+ return {
1077
+ mint: mintAddress,
1078
+ name: overrideMetadata?.name ?? name,
1079
+ symbol: overrideMetadata?.symbol ?? symbol,
1080
+ logoURI: overrideMetadata?.logoURI ?? image,
1081
+ uri: uri ?? "",
1082
+ additionalMetadata: []
1083
+ };
1084
+ })
1085
+ );
1086
+ const metadataMap = /* @__PURE__ */ new Map();
1087
+ for (const result of results) {
1088
+ if (!result) continue;
1089
+ metadataMap.set(result.mint, result);
1090
+ }
1091
+ return metadataMap;
1092
+ };
1093
+ export {
1094
+ CustomNumberFormat,
1095
+ NodeWallet,
1096
+ PriotitizationFeeLevels,
1097
+ TransactionArenaKeyMap,
1098
+ TransactionConfigMap,
1099
+ TransactionType,
1100
+ addTransactionMetadata,
1101
+ aprToApy,
1102
+ apyToApr,
1103
+ bankExtendedMetadataOverrideSchema,
1104
+ bigNumberToWrappedI80F48,
1105
+ bpsToPercentile,
1106
+ calculateApyFromInterest,
1107
+ calculateInterestFromApy,
1108
+ ceil,
1109
+ chunkedGetRawMultipleAccountInfoOrdered,
1110
+ chunkedGetRawMultipleAccountInfoOrderedWithNulls,
1111
+ chunkedGetRawMultipleAccountInfos,
1112
+ chunks,
1113
+ clampedNumeralFormatter,
1114
+ compareInstructions,
1115
+ composeRemainingAccounts,
1116
+ decodeComputeBudgetInstruction,
1117
+ decodeInstruction,
1118
+ decompileV0Transaction,
1119
+ dynamicNumeralFormatter,
1120
+ fetchBanksExtendedMetadata,
1121
+ floor,
1122
+ getAccountKeys,
1123
+ getCalculatedPrioritizationFeeByPercentile,
1124
+ getComputeBudgetUnits,
1125
+ getMaxPrioritizationFeeByPercentile,
1126
+ getMeanPrioritizationFeeByPercentile,
1127
+ getMedianPrioritizationFeeByPercentile,
1128
+ getMinPrioritizationFeeByPercentile,
1129
+ getRecentPrioritizationFeesByPercentile,
1130
+ getTxSize,
1131
+ getValueInsensitive,
1132
+ groupedNumberFormatter,
1133
+ groupedNumberFormatterDyn,
1134
+ isV0Tx,
1135
+ legacyTxToV0Tx,
1136
+ median,
1137
+ microLamportsToUi,
1138
+ nativeToUi,
1139
+ numeralFormatter,
1140
+ parseBanksMetadataOverride,
1141
+ percentFormatter,
1142
+ percentFormatterDyn,
1143
+ percentFormatterMod,
1144
+ replaceV0TxBlockhash,
1145
+ replaceV0TxInstructions,
1146
+ setTimeoutPromise,
1147
+ shortenAddress,
1148
+ sleep,
1149
+ splitInstructionsToFitTransactions,
1150
+ toBigNumber,
1151
+ toNumber,
1152
+ tokenPriceFormatter,
1153
+ uiToMicroLamports,
1154
+ uiToNative,
1155
+ uiToNativeBigNumber,
1156
+ updateV0Tx,
1157
+ usdFormatter,
1158
+ usdFormatterDyn,
1159
+ wrappedI80F48toBigNumber
1160
+ };