@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
package/src/idl.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Authoritative Hobba IDL for all consumers (app AnchorProvider, core's own
|
|
2
|
+
// buildHobbaProgram, scripts). Regenerate with `anchor idl build` and copy into
|
|
3
|
+
// src/idl/hobba.json — app/public/hobba.json is a served duplicate kept only
|
|
4
|
+
// for external fetchers and must be refreshed from this copy.
|
|
5
|
+
import idl from "./idl/hobba.json";
|
|
6
|
+
|
|
7
|
+
export const HOBBA_IDL = idl;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Public surface of @hobba/core — shared on-chain logic consumed by both the
|
|
2
|
+
// Next app and the embeddable widget. `executeDepositBorrow` is the main flow;
|
|
3
|
+
// `executeAction` manages existing positions; `getPosition`/`getLimits` are the
|
|
4
|
+
// headless reads. Lender routing (JupLend default, Kamino for existing Kamino
|
|
5
|
+
// users) happens inside the execute/read functions.
|
|
6
|
+
export * from "./constants";
|
|
7
|
+
export * from "./pdas";
|
|
8
|
+
export * from "./amountUtils";
|
|
9
|
+
export * from "./transactionBuilder";
|
|
10
|
+
export * from "./wallet";
|
|
11
|
+
export { buildHobbaProgram } from "./program";
|
|
12
|
+
export * from "./executeDepositBorrow";
|
|
13
|
+
export * from "./executeAction";
|
|
14
|
+
export * from "./marketConfig";
|
|
15
|
+
export * from "./userState";
|
|
16
|
+
export * from "./position";
|
|
17
|
+
export * from "./positionMetrics";
|
|
18
|
+
export * from "./quote";
|
|
19
|
+
export * from "./limits";
|
|
20
|
+
export * from "./txHelpers";
|
|
21
|
+
export * from "./errors";
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram, AccountMeta } from "@solana/web3.js";
|
|
2
|
+
import { TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync } from "@solana/spl-token";
|
|
3
|
+
import {
|
|
4
|
+
JUPLEND_PROGRAM,
|
|
5
|
+
USDC_MINT,
|
|
6
|
+
ATA_PROGRAM_ID,
|
|
7
|
+
} from "../constants";
|
|
8
|
+
import { deriveProgramConfigPda } from "../pdas";
|
|
9
|
+
|
|
10
|
+
interface JuplendUserPdas {
|
|
11
|
+
userStatePda: PublicKey;
|
|
12
|
+
allowlistEntryPda: PublicKey;
|
|
13
|
+
obligationPda: PublicKey; // = position PDA for JupLend
|
|
14
|
+
userMetadataPda: PublicKey;
|
|
15
|
+
userCollateralAta: PublicKey;
|
|
16
|
+
userUsdcAta: PublicKey;
|
|
17
|
+
pdaCollateralAta: PublicKey;
|
|
18
|
+
pdaUsdcAta: PublicKey;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const [programConfigPda] = deriveProgramConfigPda();
|
|
22
|
+
|
|
23
|
+
export function getJuplendDepositAccounts(owner: PublicKey, pdas: JuplendUserPdas, collateralMint: PublicKey) {
|
|
24
|
+
return {
|
|
25
|
+
owner,
|
|
26
|
+
userState: pdas.userStatePda,
|
|
27
|
+
userSourceLiquidity: pdas.userCollateralAta,
|
|
28
|
+
pdaSourceLiquidity: pdas.pdaCollateralAta,
|
|
29
|
+
supplyTokenMint: collateralMint,
|
|
30
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
31
|
+
associatedTokenProgram: ATA_PROGRAM_ID,
|
|
32
|
+
systemProgram: SystemProgram.programId,
|
|
33
|
+
programConfig: programConfigPda,
|
|
34
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
35
|
+
collateralMint,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Returns JupLend deposit lender accounts as AccountMeta[] for remaining_accounts.
|
|
40
|
+
/// Layout: [pda_borrow_token_account, juplend_program, ...juplend_operate_accounts]
|
|
41
|
+
export function getJuplendDepositLenderAccounts(
|
|
42
|
+
pdas: JuplendUserPdas,
|
|
43
|
+
): AccountMeta[] {
|
|
44
|
+
return [
|
|
45
|
+
{ pubkey: pdas.pdaUsdcAta, isSigner: false, isWritable: true },
|
|
46
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false },
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// Named accounts for combined JupLend deposit+borrow (single operate CPI).
|
|
51
|
+
/// vaultConfig and position are named accounts on this handler (the program
|
|
52
|
+
/// splices them back into the operate list via build_operate_accounts); pass
|
|
53
|
+
/// the operate list's index-0 (vault_config) and index-5 (position) entries.
|
|
54
|
+
export function getJuplendDepositBorrowAccounts(
|
|
55
|
+
owner: PublicKey,
|
|
56
|
+
pdas: JuplendUserPdas,
|
|
57
|
+
collateralMint: PublicKey,
|
|
58
|
+
vaultConfig: PublicKey,
|
|
59
|
+
position: PublicKey,
|
|
60
|
+
) {
|
|
61
|
+
return {
|
|
62
|
+
owner,
|
|
63
|
+
userState: pdas.userStatePda,
|
|
64
|
+
collateralMint,
|
|
65
|
+
userCollateralAta: pdas.userCollateralAta,
|
|
66
|
+
pdaCollateralAta: pdas.pdaCollateralAta,
|
|
67
|
+
pdaUsdcAta: pdas.pdaUsdcAta,
|
|
68
|
+
userUsdcAta: pdas.userUsdcAta,
|
|
69
|
+
usdcMint: USDC_MINT,
|
|
70
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
71
|
+
associatedTokenProgram: ATA_PROGRAM_ID,
|
|
72
|
+
systemProgram: SystemProgram.programId,
|
|
73
|
+
programConfig: programConfigPda,
|
|
74
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
75
|
+
vaultConfig,
|
|
76
|
+
position,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Remaining accounts for combined deposit+borrow: [juplend_program, ...operate_accounts].
|
|
81
|
+
/// Skips the two duplicated ATAs from the deposit/borrow single-side layouts.
|
|
82
|
+
export function getJuplendDepositBorrowLenderAccounts(): AccountMeta[] {
|
|
83
|
+
return [{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false }];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Matches surfpool-test.ts testJuplendBorrow accounts exactly
|
|
87
|
+
export function getJuplendBorrowAccounts(
|
|
88
|
+
owner: PublicKey,
|
|
89
|
+
pdas: JuplendUserPdas,
|
|
90
|
+
collateralMint: PublicKey,
|
|
91
|
+
hasVaultShares: boolean = false,
|
|
92
|
+
vaultAccounts?: {
|
|
93
|
+
vault: PublicKey;
|
|
94
|
+
sharesMint: PublicKey;
|
|
95
|
+
sharesAta: PublicKey;
|
|
96
|
+
}
|
|
97
|
+
) {
|
|
98
|
+
const va = vaultAccounts;
|
|
99
|
+
// Canonical ATA of the placeholder shares mint (the wallet pubkey), so the
|
|
100
|
+
// program's pda_shares_ata == ATA(user_state, shares_mint) check holds when no vault is used.
|
|
101
|
+
const placeholderSharesAta = getAssociatedTokenAddressSync(owner, pdas.userStatePda, true);
|
|
102
|
+
return {
|
|
103
|
+
owner,
|
|
104
|
+
userState: pdas.userStatePda,
|
|
105
|
+
collateralMint,
|
|
106
|
+
pdaUsdcAta: pdas.pdaUsdcAta,
|
|
107
|
+
userUsdcAta: pdas.userUsdcAta,
|
|
108
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
109
|
+
systemProgram: SystemProgram.programId,
|
|
110
|
+
vault: hasVaultShares && va ? va.vault : owner,
|
|
111
|
+
sharesMint: hasVaultShares && va ? va.sharesMint : owner,
|
|
112
|
+
pdaSharesAta: hasVaultShares && va ? va.sharesAta : placeholderSharesAta,
|
|
113
|
+
sharesTokenProgram: hasVaultShares ? TOKEN_PROGRAM_ID : SystemProgram.programId,
|
|
114
|
+
usdcMint: USDC_MINT,
|
|
115
|
+
programConfig: programConfigPda,
|
|
116
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// Returns JupLend lender accounts as AccountMeta[] for remaining_accounts.
|
|
121
|
+
/// Layout: [pda_source_liquidity, juplend_program, ...juplend_operate_accounts]
|
|
122
|
+
export function getJuplendBorrowLenderAccounts(
|
|
123
|
+
pdas: JuplendUserPdas,
|
|
124
|
+
): AccountMeta[] {
|
|
125
|
+
return [
|
|
126
|
+
{ pubkey: pdas.pdaCollateralAta, isSigner: false, isWritable: true },
|
|
127
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false },
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Matches surfpool-test.ts testJuplendRepay accounts exactly
|
|
132
|
+
export function getJuplendRepayAccounts(owner: PublicKey, pdas: JuplendUserPdas, collateralMint: PublicKey) {
|
|
133
|
+
return {
|
|
134
|
+
owner,
|
|
135
|
+
userState: pdas.userStatePda,
|
|
136
|
+
userUsdcAta: pdas.userUsdcAta,
|
|
137
|
+
pdaUsdcAta: pdas.pdaUsdcAta,
|
|
138
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
139
|
+
programConfig: programConfigPda,
|
|
140
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
141
|
+
collateralMint,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Returns JupLend repay lender accounts as AccountMeta[] for remaining_accounts.
|
|
146
|
+
/// Layout: [pda_source_liquidity, juplend_program, ...juplend_operate_accounts]
|
|
147
|
+
export function getJuplendRepayLenderAccounts(
|
|
148
|
+
pdas: JuplendUserPdas,
|
|
149
|
+
): AccountMeta[] {
|
|
150
|
+
return [
|
|
151
|
+
{ pubkey: pdas.pdaCollateralAta, isSigner: false, isWritable: true },
|
|
152
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false },
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/// Returns PrepareWithdraw named accounts for JupLend users.
|
|
157
|
+
/// Matches the shared PrepareWithdraw Anchor struct.
|
|
158
|
+
export function getJuplendPrepareWithdrawAccounts(
|
|
159
|
+
owner: PublicKey,
|
|
160
|
+
pdas: JuplendUserPdas,
|
|
161
|
+
collateralMint: PublicKey,
|
|
162
|
+
vaultAccounts: {
|
|
163
|
+
vault: PublicKey;
|
|
164
|
+
sharesMint: PublicKey;
|
|
165
|
+
sharesAta: PublicKey;
|
|
166
|
+
}
|
|
167
|
+
) {
|
|
168
|
+
const va = vaultAccounts;
|
|
169
|
+
return {
|
|
170
|
+
owner,
|
|
171
|
+
userState: pdas.userStatePda,
|
|
172
|
+
collateralMint,
|
|
173
|
+
programConfig: programConfigPda,
|
|
174
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
175
|
+
pdaUsdcAta: pdas.pdaUsdcAta,
|
|
176
|
+
vault: va.vault,
|
|
177
|
+
sharesMint: va.sharesMint,
|
|
178
|
+
pdaSharesAta: va.sharesAta,
|
|
179
|
+
sharesTokenProgram: TOKEN_PROGRAM_ID,
|
|
180
|
+
usdcMint: USDC_MINT,
|
|
181
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function getJuplendWithdrawAccounts(owner: PublicKey, pdas: JuplendUserPdas, collateralMint: PublicKey) {
|
|
186
|
+
return {
|
|
187
|
+
owner,
|
|
188
|
+
userState: pdas.userStatePda,
|
|
189
|
+
pdaDestinationAta: pdas.pdaCollateralAta,
|
|
190
|
+
userDestinationAta: pdas.userCollateralAta,
|
|
191
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
192
|
+
programConfig: programConfigPda,
|
|
193
|
+
allowlistEntry: pdas.allowlistEntryPda,
|
|
194
|
+
collateralMint,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Returns JupLend withdraw lender accounts as AccountMeta[] for remaining_accounts.
|
|
199
|
+
/// Layout: [pda_borrow_token_account, juplend_program, ...juplend_operate_accounts]
|
|
200
|
+
export function getJuplendWithdrawLenderAccounts(
|
|
201
|
+
pdas: JuplendUserPdas,
|
|
202
|
+
): AccountMeta[] {
|
|
203
|
+
return [
|
|
204
|
+
{ pubkey: pdas.pdaUsdcAta, isSigner: false, isWritable: true },
|
|
205
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false },
|
|
206
|
+
];
|
|
207
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram } from "@solana/web3.js";
|
|
2
|
+
import {
|
|
3
|
+
JUPLEND_PROGRAM,
|
|
4
|
+
JUPLEND_VAULT_CONFIG,
|
|
5
|
+
JUPLEND_VAULT_STATE,
|
|
6
|
+
JUPLEND_ORACLE,
|
|
7
|
+
JUPLEND_SUPPLY_RESERVES_LIQUIDITY,
|
|
8
|
+
JUPLEND_BORROW_RESERVES_LIQUIDITY,
|
|
9
|
+
JUPLEND_VAULT_SUPPLY_POSITION,
|
|
10
|
+
JUPLEND_VAULT_BORROW_POSITION,
|
|
11
|
+
JUPLEND_SUPPLY_RATE_MODEL,
|
|
12
|
+
JUPLEND_BORROW_RATE_MODEL,
|
|
13
|
+
JUPLEND_VAULT_SUPPLY_TOKEN_ACCOUNT,
|
|
14
|
+
JUPLEND_VAULT_BORROW_TOKEN_ACCOUNT,
|
|
15
|
+
JUPLEND_LIQUIDITY,
|
|
16
|
+
JUPLEND_LIQUIDITY_PROGRAM,
|
|
17
|
+
JUPLEND_ORACLE_PROGRAM,
|
|
18
|
+
JUPLEND_ORACLE_SOURCE,
|
|
19
|
+
JUPLEND_BRANCH,
|
|
20
|
+
JUPLEND_TICK_0,
|
|
21
|
+
JUPLEND_TICK_1,
|
|
22
|
+
JUPLEND_NEW_BRANCH,
|
|
23
|
+
ATA_PROGRAM_ID,
|
|
24
|
+
CBBTC_MINT,
|
|
25
|
+
USDC_MINT,
|
|
26
|
+
} from "../constants";
|
|
27
|
+
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
|
28
|
+
|
|
29
|
+
interface OperateRemainingResult {
|
|
30
|
+
remaining: { pubkey: PublicKey; isSigner: boolean; isWritable: boolean }[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Fallback hardcoded remaining accounts for JupLend operate
|
|
34
|
+
// Used when SDK fails (e.g., on new positions)
|
|
35
|
+
export function buildFallbackOperateRemaining(
|
|
36
|
+
position: PublicKey,
|
|
37
|
+
positionTokenAccount: PublicKey,
|
|
38
|
+
currentTick: PublicKey,
|
|
39
|
+
finalTick: PublicKey,
|
|
40
|
+
currentTickId: PublicKey,
|
|
41
|
+
finalTickId: PublicKey
|
|
42
|
+
): OperateRemainingResult {
|
|
43
|
+
return {
|
|
44
|
+
remaining: [
|
|
45
|
+
{ pubkey: JUPLEND_VAULT_CONFIG, isSigner: false, isWritable: true },
|
|
46
|
+
{ pubkey: JUPLEND_VAULT_STATE, isSigner: false, isWritable: true },
|
|
47
|
+
{ pubkey: CBBTC_MINT, isSigner: false, isWritable: false },
|
|
48
|
+
{ pubkey: USDC_MINT, isSigner: false, isWritable: false },
|
|
49
|
+
{ pubkey: JUPLEND_ORACLE, isSigner: false, isWritable: false },
|
|
50
|
+
{ pubkey: position, isSigner: false, isWritable: true },
|
|
51
|
+
{ pubkey: positionTokenAccount, isSigner: false, isWritable: false },
|
|
52
|
+
{ pubkey: currentTick, isSigner: false, isWritable: true },
|
|
53
|
+
{ pubkey: finalTick, isSigner: false, isWritable: true },
|
|
54
|
+
{ pubkey: currentTickId, isSigner: false, isWritable: true },
|
|
55
|
+
{ pubkey: finalTickId, isSigner: false, isWritable: true },
|
|
56
|
+
{ pubkey: JUPLEND_NEW_BRANCH, isSigner: false, isWritable: true },
|
|
57
|
+
{ pubkey: JUPLEND_SUPPLY_RESERVES_LIQUIDITY, isSigner: false, isWritable: true },
|
|
58
|
+
{ pubkey: JUPLEND_BORROW_RESERVES_LIQUIDITY, isSigner: false, isWritable: true },
|
|
59
|
+
{ pubkey: JUPLEND_VAULT_SUPPLY_POSITION, isSigner: false, isWritable: true },
|
|
60
|
+
{ pubkey: JUPLEND_VAULT_BORROW_POSITION, isSigner: false, isWritable: true },
|
|
61
|
+
{ pubkey: JUPLEND_SUPPLY_RATE_MODEL, isSigner: false, isWritable: true },
|
|
62
|
+
{ pubkey: JUPLEND_BORROW_RATE_MODEL, isSigner: false, isWritable: true },
|
|
63
|
+
{ pubkey: JUPLEND_VAULT_SUPPLY_TOKEN_ACCOUNT, isSigner: false, isWritable: true },
|
|
64
|
+
{ pubkey: JUPLEND_VAULT_BORROW_TOKEN_ACCOUNT, isSigner: false, isWritable: true },
|
|
65
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false }, // supply claim (none)
|
|
66
|
+
{ pubkey: JUPLEND_PROGRAM, isSigner: false, isWritable: false }, // borrow claim (none)
|
|
67
|
+
{ pubkey: JUPLEND_LIQUIDITY, isSigner: false, isWritable: true },
|
|
68
|
+
{ pubkey: JUPLEND_LIQUIDITY_PROGRAM, isSigner: false, isWritable: true },
|
|
69
|
+
{ pubkey: JUPLEND_ORACLE_PROGRAM, isSigner: false, isWritable: false },
|
|
70
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
71
|
+
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
72
|
+
{ pubkey: ATA_PROGRAM_ID, isSigner: false, isWritable: false },
|
|
73
|
+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
|
|
74
|
+
// Variable remaining: oracle source, branch, tick arrays
|
|
75
|
+
{ pubkey: JUPLEND_ORACLE_SOURCE, isSigner: false, isWritable: false },
|
|
76
|
+
{ pubkey: JUPLEND_BRANCH, isSigner: false, isWritable: true },
|
|
77
|
+
{ pubkey: JUPLEND_TICK_0, isSigner: false, isWritable: true },
|
|
78
|
+
{ pubkey: JUPLEND_TICK_1, isSigner: false, isWritable: true },
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, AccountMeta } from "@solana/web3.js";
|
|
2
|
+
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
|
|
3
|
+
import {
|
|
4
|
+
JUPLEND_PROGRAM,
|
|
5
|
+
JUPLEND_VAULT_CONFIG,
|
|
6
|
+
JUPLEND_VAULT_STATE,
|
|
7
|
+
METAPLEX_PROGRAM,
|
|
8
|
+
ATA_PROGRAM_ID,
|
|
9
|
+
} from "../constants";
|
|
10
|
+
import { deriveDepositConfigPda, deriveOriginConfigPda, deriveProgramConfigPda, deriveUserOriginPda } from "../pdas";
|
|
11
|
+
const [programConfigPda] = deriveProgramConfigPda();
|
|
12
|
+
const [JUPLEND_VAULT_ADMIN] = PublicKey.findProgramAddressSync(
|
|
13
|
+
[Buffer.from("vault_admin")],
|
|
14
|
+
JUPLEND_PROGRAM
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// Matches surfpool-test.ts createJuplendPosition accounts exactly
|
|
18
|
+
export function getCreateJuplendPositionAccounts(
|
|
19
|
+
owner: PublicKey,
|
|
20
|
+
userStatePda: PublicKey,
|
|
21
|
+
positionPda: PublicKey,
|
|
22
|
+
positionMintPda: PublicKey,
|
|
23
|
+
positionTokenAccount: PublicKey,
|
|
24
|
+
positionMetadata: PublicKey,
|
|
25
|
+
allowlistEntryPda: PublicKey,
|
|
26
|
+
collateralMint: PublicKey,
|
|
27
|
+
vaultState: PublicKey = JUPLEND_VAULT_STATE
|
|
28
|
+
) {
|
|
29
|
+
return {
|
|
30
|
+
owner,
|
|
31
|
+
userStatePda, // IDL name is "user_state_pda"
|
|
32
|
+
position: positionPda,
|
|
33
|
+
positionMint: positionMintPda,
|
|
34
|
+
positionTokenAccount,
|
|
35
|
+
positionMetadata,
|
|
36
|
+
juplendVaultAdmin: JUPLEND_VAULT_ADMIN,
|
|
37
|
+
juplendVaultState: vaultState,
|
|
38
|
+
juplendProgram: JUPLEND_PROGRAM,
|
|
39
|
+
metadataProgram: METAPLEX_PROGRAM,
|
|
40
|
+
tokenProgram: TOKEN_PROGRAM_ID,
|
|
41
|
+
associatedTokenProgram: ATA_PROGRAM_ID,
|
|
42
|
+
instructionSysvar: SYSVAR_INSTRUCTIONS_PUBKEY,
|
|
43
|
+
programConfig: programConfigPda,
|
|
44
|
+
allowlistEntry: allowlistEntryPda,
|
|
45
|
+
collateralMint,
|
|
46
|
+
rent: SYSVAR_RENT_PUBKEY,
|
|
47
|
+
systemProgram: SystemProgram.programId,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Matches surfpool-test.ts initializeUser accounts exactly
|
|
52
|
+
export function getInitializeUserJuplendAccounts(
|
|
53
|
+
owner: PublicKey,
|
|
54
|
+
userStatePda: PublicKey,
|
|
55
|
+
allowlistEntryPda: PublicKey,
|
|
56
|
+
collateralMint: PublicKey,
|
|
57
|
+
origin: number = 0,
|
|
58
|
+
) {
|
|
59
|
+
return {
|
|
60
|
+
owner,
|
|
61
|
+
userState: userStatePda,
|
|
62
|
+
collateralMint,
|
|
63
|
+
systemProgram: SystemProgram.programId,
|
|
64
|
+
programConfig: programConfigPda,
|
|
65
|
+
allowlistEntry: allowlistEntryPda,
|
|
66
|
+
depositConfig: deriveDepositConfigPda(collateralMint)[0],
|
|
67
|
+
// Per-wallet origin registration; created on the wallet's first init,
|
|
68
|
+
// later inits keep the stored origin (the origin arg is then ignored).
|
|
69
|
+
userOrigin: deriveUserOriginPda(owner)[0],
|
|
70
|
+
// Seeded by the `origin` instruction arg — always pass explicitly rather
|
|
71
|
+
// than relying on Anchor's IDL auto-resolution.
|
|
72
|
+
originConfig: deriveOriginConfigPda(origin)[0],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// Returns JupLend initialize_user lender accounts as AccountMeta[] for remaining_accounts.
|
|
77
|
+
/// Layout: [position, juplend_vault_config]
|
|
78
|
+
export function getJuplendInitializeUserLenderAccounts(
|
|
79
|
+
positionPda: PublicKey,
|
|
80
|
+
vaultConfig: PublicKey = JUPLEND_VAULT_CONFIG
|
|
81
|
+
): AccountMeta[] {
|
|
82
|
+
return [
|
|
83
|
+
{ pubkey: positionPda, isSigner: false, isWritable: false },
|
|
84
|
+
{ pubkey: vaultConfig, isSigner: false, isWritable: false },
|
|
85
|
+
];
|
|
86
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import BN from "bn.js";
|
|
2
|
+
|
|
3
|
+
// JupLend position account layout (from SDK decode):
|
|
4
|
+
// 8 (discriminator) + 2 (vaultId) + 4 (nftId) + 32 (positionMint) + 1 (isSupplyOnlyPosition)
|
|
5
|
+
// offset 47: tick (i32 LE, 4 bytes)
|
|
6
|
+
// offset 51: tickId (u32 LE, 4 bytes)
|
|
7
|
+
// offset 55: supplyAmount (u64 LE, 8 bytes) — supply shares
|
|
8
|
+
// offset 63: dustDebtAmount (u64 LE, 8 bytes) — debt in micro-USDC (approx)
|
|
9
|
+
// Total: 71 bytes
|
|
10
|
+
|
|
11
|
+
export function parseJuplendPosition(data: Buffer): {
|
|
12
|
+
collateral: number; // satoshis
|
|
13
|
+
debt: number; // micro-USDC
|
|
14
|
+
tick: number;
|
|
15
|
+
supplyAmount: number; // raw supply shares
|
|
16
|
+
dustDebtAmount: number; // raw dust debt
|
|
17
|
+
} {
|
|
18
|
+
if (data.length < 71) {
|
|
19
|
+
return { collateral: 0, debt: 0, tick: 0, supplyAmount: 0, dustDebtAmount: 0 };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const tick = data.readInt32LE(47);
|
|
23
|
+
|
|
24
|
+
// Read u64 values using BN (avoids JS Number precision issues for large u64)
|
|
25
|
+
const supplyBn = new BN(data.slice(55, 63), "le");
|
|
26
|
+
const dustDebtBn = new BN(data.slice(63, 71), "le");
|
|
27
|
+
|
|
28
|
+
const supplyAmount = supplyBn.toNumber();
|
|
29
|
+
const dustDebtAmount = dustDebtBn.toNumber();
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
// Raw values for exchange rate conversion (done in hook with vault state)
|
|
33
|
+
supplyAmount,
|
|
34
|
+
dustDebtAmount,
|
|
35
|
+
// Debt: dustDebtAmount is approximately micro-USDC
|
|
36
|
+
debt: dustDebtAmount,
|
|
37
|
+
// Collateral: needs exchange rate conversion (set to 0, computed in hook)
|
|
38
|
+
collateral: 0,
|
|
39
|
+
tick,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { PublicKey, TransactionInstruction, SystemProgram } from "@solana/web3.js";
|
|
2
|
+
import { ATA_PROGRAM_ID } from "../constants";
|
|
3
|
+
|
|
4
|
+
interface SdkRemainingEntry {
|
|
5
|
+
pubkey: string;
|
|
6
|
+
writable: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface SdkOtherIx {
|
|
10
|
+
programId: string;
|
|
11
|
+
keys: { pubkey: string; isSigner: boolean; isWritable: boolean }[];
|
|
12
|
+
data: string; // base64
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface SdkOperateResponse {
|
|
16
|
+
remaining: SdkRemainingEntry[];
|
|
17
|
+
variableRemaining: SdkRemainingEntry[];
|
|
18
|
+
otherIxs: SdkOtherIx[];
|
|
19
|
+
currentTick: string;
|
|
20
|
+
finalTick: string;
|
|
21
|
+
currentTickValue: number | null;
|
|
22
|
+
finalTickValue: number | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface SdkOperateRequest {
|
|
26
|
+
vaultId: number;
|
|
27
|
+
positionId: number;
|
|
28
|
+
colAmount: string;
|
|
29
|
+
debtAmount: string;
|
|
30
|
+
signerPda: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function fetchOperateContext(
|
|
34
|
+
params: SdkOperateRequest,
|
|
35
|
+
apiBaseUrl: string = "",
|
|
36
|
+
): Promise<SdkOperateResponse> {
|
|
37
|
+
const base = apiBaseUrl.replace(/\/+$/, "");
|
|
38
|
+
const resp = await fetch(`${base}/api/juplend-operate`, {
|
|
39
|
+
method: "POST",
|
|
40
|
+
headers: { "Content-Type": "application/json" },
|
|
41
|
+
body: JSON.stringify(params),
|
|
42
|
+
});
|
|
43
|
+
if (!resp.ok) {
|
|
44
|
+
const errData = await resp.json().catch(() => ({ error: "SDK API failed" }));
|
|
45
|
+
throw new Error(errData.error || `SDK API returned ${resp.status}`);
|
|
46
|
+
}
|
|
47
|
+
return resp.json();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Deserialize SDK remaining accounts into AccountMeta[]
|
|
51
|
+
// The API returns 27 fixed entries; caller adds ATA_PROGRAM + SystemProgram, then variable remaining
|
|
52
|
+
export function deserializeRemaining(
|
|
53
|
+
sdkResp: SdkOperateResponse
|
|
54
|
+
): { pubkey: PublicKey; isSigner: boolean; isWritable: boolean }[] {
|
|
55
|
+
const fixed = sdkResp.remaining.map((a) => ({
|
|
56
|
+
pubkey: new PublicKey(a.pubkey),
|
|
57
|
+
isSigner: false,
|
|
58
|
+
isWritable: a.writable,
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
fixed.push({ pubkey: ATA_PROGRAM_ID, isSigner: false, isWritable: false });
|
|
62
|
+
fixed.push({ pubkey: SystemProgram.programId, isSigner: false, isWritable: false });
|
|
63
|
+
|
|
64
|
+
const variable = sdkResp.variableRemaining.map((a) => ({
|
|
65
|
+
pubkey: new PublicKey(a.pubkey),
|
|
66
|
+
isSigner: false,
|
|
67
|
+
isWritable: a.writable,
|
|
68
|
+
}));
|
|
69
|
+
|
|
70
|
+
return [...fixed, ...variable];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Known JupLend instruction discriminators that the deployed program supports
|
|
74
|
+
const KNOWN_JUPLEND_DISCS = new Set([
|
|
75
|
+
"160d3e8d4959b21d", // InitTick
|
|
76
|
+
"386e79a998f156b7", // InitTickIdLiquidation
|
|
77
|
+
]);
|
|
78
|
+
const JUPLEND_PROGRAM_STR = "jupr81YtYssSyPt8jbnGuiWon5f6x9TcDEFxYe3Bdzi";
|
|
79
|
+
|
|
80
|
+
// Deserialize otherIxs (initTick, initBranch, etc.) and replace signerPda with actual payer.
|
|
81
|
+
// Filters out unrecognized JupLend instructions that cause InstructionFallbackNotFound.
|
|
82
|
+
export function deserializeOtherIxs(
|
|
83
|
+
sdkResp: SdkOperateResponse,
|
|
84
|
+
signerPda: PublicKey,
|
|
85
|
+
actualPayer: PublicKey
|
|
86
|
+
): TransactionInstruction[] {
|
|
87
|
+
const signerStr = signerPda.toBase58();
|
|
88
|
+
return sdkResp.otherIxs
|
|
89
|
+
.filter((ix) => {
|
|
90
|
+
// Keep non-JupLend instructions as-is
|
|
91
|
+
if (ix.programId !== JUPLEND_PROGRAM_STR) return true;
|
|
92
|
+
// Log ALL JupLend instruction discriminators for debugging
|
|
93
|
+
const disc = Buffer.from(ix.data, "base64").subarray(0, 8).toString("hex");
|
|
94
|
+
console.log("[otherIxs] JupLend instruction disc:", disc, KNOWN_JUPLEND_DISCS.has(disc) ? "(known)" : "(UNKNOWN — filtering out)");
|
|
95
|
+
if (!KNOWN_JUPLEND_DISCS.has(disc)) return false;
|
|
96
|
+
return true;
|
|
97
|
+
})
|
|
98
|
+
.map((ix) =>
|
|
99
|
+
new TransactionInstruction({
|
|
100
|
+
programId: new PublicKey(ix.programId),
|
|
101
|
+
keys: ix.keys.map((k) => {
|
|
102
|
+
const isSigner = k.pubkey === signerStr;
|
|
103
|
+
return {
|
|
104
|
+
pubkey: isSigner ? actualPayer : new PublicKey(k.pubkey),
|
|
105
|
+
isSigner: isSigner ? true : k.isSigner,
|
|
106
|
+
isWritable: k.isWritable,
|
|
107
|
+
};
|
|
108
|
+
}),
|
|
109
|
+
data: Buffer.from(ix.data, "base64"),
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JupLend tick ↔ debt fixed-point math (ported from the JupLend SDK).
|
|
3
|
+
* Pure BN math, browser-safe; shared by /api/juplend-position and any
|
|
4
|
+
* script that needs debt-from-tick without an RPC tick fetch.
|
|
5
|
+
*/
|
|
6
|
+
import BN from "bn.js";
|
|
7
|
+
|
|
8
|
+
export const JUPLEND_MIN_TICK = -16383;
|
|
9
|
+
export const JUPLEND_MAX_TICK_VALUE = 16383;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Tick ratio as an X48 fixed-point BN (scaled by 2^48).
|
|
13
|
+
* debtRaw = ratioX48 * (colRaw + 1) >> 48 + 1
|
|
14
|
+
*/
|
|
15
|
+
export function getRatioAtTick(tick: number): BN {
|
|
16
|
+
if (tick < JUPLEND_MIN_TICK || tick > JUPLEND_MAX_TICK_VALUE) {
|
|
17
|
+
throw new Error(`Tick ${tick} out of range [${JUPLEND_MIN_TICK}, ${JUPLEND_MAX_TICK_VALUE}]`);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const FACTORS: BN[] = [
|
|
21
|
+
new BN("18446744073709551616"), // FACTOR00 = 2^64
|
|
22
|
+
new BN("18419115400608638658"),
|
|
23
|
+
new BN("18391528108445969703"),
|
|
24
|
+
new BN("18336477419114433396"),
|
|
25
|
+
new BN("18226869890870665593"),
|
|
26
|
+
new BN("18009616477100071088"),
|
|
27
|
+
new BN("17582847377087825313"),
|
|
28
|
+
new BN("16759408633341240198"),
|
|
29
|
+
new BN("15226414841393184936"),
|
|
30
|
+
new BN("12568272644527235157"),
|
|
31
|
+
new BN("8563108841104354677"),
|
|
32
|
+
new BN("3975055583337633975"),
|
|
33
|
+
new BN("856577552520149366"),
|
|
34
|
+
new BN("39775317560084773"),
|
|
35
|
+
new BN("85764505686420"),
|
|
36
|
+
new BN("398745188"),
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
function mulShift64(n0: BN, n1: BN): BN {
|
|
40
|
+
const product = n0.mul(n1);
|
|
41
|
+
return product.shrn(64);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const absTick = Math.abs(tick);
|
|
45
|
+
let factor = FACTORS[0];
|
|
46
|
+
if (absTick & 1) factor = FACTORS[1];
|
|
47
|
+
if (absTick & 2) factor = mulShift64(factor, FACTORS[2]);
|
|
48
|
+
if (absTick & 4) factor = mulShift64(factor, FACTORS[3]);
|
|
49
|
+
if (absTick & 8) factor = mulShift64(factor, FACTORS[4]);
|
|
50
|
+
if (absTick & 16) factor = mulShift64(factor, FACTORS[5]);
|
|
51
|
+
if (absTick & 32) factor = mulShift64(factor, FACTORS[6]);
|
|
52
|
+
if (absTick & 64) factor = mulShift64(factor, FACTORS[7]);
|
|
53
|
+
if (absTick & 128) factor = mulShift64(factor, FACTORS[8]);
|
|
54
|
+
if (absTick & 256) factor = mulShift64(factor, FACTORS[9]);
|
|
55
|
+
if (absTick & 512) factor = mulShift64(factor, FACTORS[10]);
|
|
56
|
+
if (absTick & 1024) factor = mulShift64(factor, FACTORS[11]);
|
|
57
|
+
if (absTick & 2048) factor = mulShift64(factor, FACTORS[12]);
|
|
58
|
+
if (absTick & 4096) factor = mulShift64(factor, FACTORS[13]);
|
|
59
|
+
if (absTick & 8192) factor = mulShift64(factor, FACTORS[14]);
|
|
60
|
+
if (absTick & 16384) factor = mulShift64(factor, FACTORS[15]);
|
|
61
|
+
|
|
62
|
+
let precision = new BN(0);
|
|
63
|
+
if (tick > 0) {
|
|
64
|
+
const maxU128 = new BN(2).pow(new BN(128)).subn(1);
|
|
65
|
+
factor = maxU128.div(factor);
|
|
66
|
+
if (!factor.mod(new BN(65536)).isZero()) {
|
|
67
|
+
precision = new BN(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return factor.shrn(16).add(precision);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Debt (in borrow shares) implied by a position's tick and collateral shares.
|
|
76
|
+
* Returns 0 at/below MIN_TICK (no debt).
|
|
77
|
+
*/
|
|
78
|
+
export function debtFromTick(colRaw: BN, tick: number): BN {
|
|
79
|
+
if (tick <= JUPLEND_MIN_TICK) return new BN(0);
|
|
80
|
+
const ratio = getRatioAtTick(tick);
|
|
81
|
+
return ratio.mul(colRaw.addn(1)).shrn(48).addn(1);
|
|
82
|
+
}
|