@neutral-trade/sdk 0.4.4 → 0.4.8

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/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as SupportedToken, B as DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, C as VaultRegistryEntry, D as UserBundleAccount, E as OracleData, F as ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, G as getDefaultBundleProgramIdByCluster, H as assertAllowlistedBundleProgramId, I as BUNDLE_PROGRAM_ID_V2_MAINNET, K as isAllowlistedBundleProgramId, L as BundleCluster, M as getSolanaTokenDecimals, N as getSolanaTokenMint, O as UserBundleTempData, P as tokens, R as BundleProgram, S as VaultRegistry, T as BundleAccount, U as createAllowlistedBundleProgram, V as DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, W as createBundleProgramById, _ as vaults, b as VaultBalanceData, d as NeutralTradeConfig, f as getBundleProgramId, g as isValidVaultAddress, h as getVaultRegistry, j as Token, k as SupportedChain, m as getVaultById, p as getVaultByAddress, t as NeutralTradeCoreContext, u as NeutralTrade, v as vaultsDevnet, w as VaultType, x as VaultCategory, y as UserBalanceResult, z as BundleProvider } from "./neutral-trade-core-BGjOiCsY.mjs";
2
- import { AnchorProvider, Wallet } from "@coral-xyz/anchor";
1
+ import { A as SupportedToken, B as DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, C as VaultRegistryEntry, D as UserBundleAccount, E as OracleData, F as ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, G as getDefaultBundleProgramIdByCluster, H as assertAllowlistedBundleProgramId, I as BUNDLE_PROGRAM_ID_V2_MAINNET, K as isAllowlistedBundleProgramId, L as BundleCluster, M as getSolanaTokenDecimals, N as getSolanaTokenMint, O as UserBundleTempData, P as tokens, R as BundleProgram, S as VaultRegistry, T as BundleAccount, U as createAllowlistedBundleProgram, V as DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, W as createBundleProgramById, _ as vaults$1, b as VaultBalanceData, d as NeutralTradeConfig, f as getBundleProgramId, g as isValidVaultAddress, h as getVaultRegistry, j as Token, k as SupportedChain, m as getVaultById, p as getVaultByAddress, t as NeutralTradeCoreContext, u as NeutralTrade, v as vaultsDevnet, w as VaultType, x as VaultCategory, y as UserBalanceResult, z as BundleProvider } from "./neutral-trade-core-BGjOiCsY.mjs";
2
+ import { AnchorProvider, Program, Wallet } from "@coral-xyz/anchor";
3
3
  import { Connection, PublicKey, TransactionInstruction } from "@solana/web3.js";
4
4
  import BN from "bn.js";
5
5
 
@@ -199,6 +199,88 @@ declare function parseAmountRawToBigInt(amountRaw: string): bigint;
199
199
  */
200
200
  declare function humanFloatToAmountRawString(human: number, decimals: number): string;
201
201
  //#endregion
202
+ //#region src/utils/bundle.d.ts
203
+ /**
204
+ * Estimated unpaid bundle fees in deposit token (mgmt + performance), matching on-chain `charge_user_fees`.
205
+ */
206
+ declare function estimatePendingBundleFeeToken({
207
+ oracleData,
208
+ bundleData,
209
+ userBundle,
210
+ assetDecimals,
211
+ nowUnixSeconds
212
+ }: {
213
+ oracleData: OracleData;
214
+ bundleData: BundleAccount;
215
+ userBundle: UserBundleAccount;
216
+ assetDecimals: number;
217
+ nowUnixSeconds?: number;
218
+ }): number;
219
+ //#endregion
220
+ //#region src/utils/bundle-fee-override.d.ts
221
+ /** Mirrors `bundle-sc` `FEE_OVERRIDE_*` bit flags. */
222
+ declare const FEE_OVERRIDE: {
223
+ readonly DEPOSIT: number;
224
+ readonly WITHDRAWAL: number;
225
+ readonly PERFORMANCE: number;
226
+ readonly MANAGEMENT: number;
227
+ readonly ALL: number;
228
+ };
229
+ interface EffectiveFeeBps {
230
+ depositFeeBps: number;
231
+ withdrawalFeeBps: number;
232
+ performanceFeeBps: number;
233
+ managementFeeBps: number;
234
+ }
235
+ /** Normalized per-user fee override fields (bps + flag mask). */
236
+ interface UserFeeOverrideFields {
237
+ feeOverrideFlags: number;
238
+ customDepositFeeBps: number;
239
+ customWithdrawalFeeBps: number;
240
+ customPerformanceFeeBps: number;
241
+ customManagementFeeBps: number;
242
+ }
243
+ /** Decimal fees matching frontend `VaultConfig` (`0.01` = 1%). */
244
+ interface EffectiveVaultFeeDecimals {
245
+ dfee: number;
246
+ wfee: number;
247
+ pfee: number;
248
+ mfee: number;
249
+ }
250
+ declare function bpsToFeeDecimal(bps: number): number;
251
+ declare function feeDecimalToBps(decimal: number): number;
252
+ declare function bpsToPercentLabel(bps: number): string;
253
+ declare function hasFeeOverrideFlag(flags: number, bit: number): boolean;
254
+ declare function buildFeeOverrideMask(flags: {
255
+ deposit?: boolean;
256
+ withdrawal?: boolean;
257
+ performance?: boolean;
258
+ management?: boolean;
259
+ }): number;
260
+ declare function formatFeeOverrideFlags(flags: number): string;
261
+ declare function readUserFeeOverrideFields(account: Record<string, unknown>): UserFeeOverrideFields;
262
+ declare function vaultFeeDecimalsToBps(fees: EffectiveVaultFeeDecimals): EffectiveFeeBps;
263
+ declare function effectiveFeeBpsToDecimals(fees: EffectiveFeeBps): EffectiveVaultFeeDecimals;
264
+ /**
265
+ * Apply per-user fee override flags onto default bps (bundle or vault-config defaults).
266
+ */
267
+ declare function resolveEffectiveFeeBpsFromDefaults(defaults: EffectiveFeeBps, user: UserFeeOverrideFields): EffectiveFeeBps;
268
+ /**
269
+ * Mirror on-chain `resolve_effective_fees`. Returns fee rates in bps.
270
+ */
271
+ declare function resolveEffectiveFeeBps(bundle: BundleAccount, user: UserBundleAccount): EffectiveFeeBps;
272
+ /**
273
+ * Resolve effective fees for UI vault config defaults + optional user bundle account.
274
+ * Returns decimal fees (`0.01` = 1%).
275
+ */
276
+ declare function resolveEffectiveVaultFees(vaultDefaults: EffectiveVaultFeeDecimals, user?: UserBundleAccount | null): EffectiveVaultFeeDecimals;
277
+ declare function hasAnyFeeOverride(user?: UserBundleAccount | null): boolean;
278
+ declare function hasCustomFeeRate(effectiveFees: EffectiveVaultFeeDecimals, vaultDefaults: EffectiveVaultFeeDecimals): boolean;
279
+ declare function computeDepositFeePreview(grossAmount: number, depositFeeDecimal: number): {
280
+ feeAmount: number;
281
+ netAmount: number;
282
+ };
283
+ //#endregion
202
284
  //#region src/utils/request-withdraw-shares.d.ts
203
285
  /**
204
286
  * Shares to burn for `requestWithdrawal`, from integer token raw and on-chain totals.
@@ -281,4 +363,4 @@ declare function derivePendingAuthPDA(bundlePDA: PublicKey, programId: PublicKey
281
363
  */
282
364
  declare function getVaultDepositorAddressSync(programId: PublicKey, vault: PublicKey, authority: PublicKey): PublicKey;
283
365
  //#endregion
284
- export { ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, BUNDLE_PROGRAM_ID_V2_MAINNET, type BuildBundleDepositInstructionsParams, type BuildBundleRequestWithdrawInstructionParams, type BundleAccount, type BundleCluster, type BundleProgram, type BundleProvider, DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, DevnetVaultId, NeutralTrade, type NeutralTradeConfig, type NeutralTradeCoreContext, type OracleData, SEED_ORACLE, SEED_PENDING_AUTH, SEED_TEMP, SEED_USER, SupportedChain, SupportedToken, type Token, type UserBalanceResult, type UserBundleAccount, type UserBundleTempData, type VaultBalanceData, VaultCategory, VaultId, type VaultRegistry, type VaultRegistryEntry, VaultType, assertAllowlistedBundleProgramId, buildBundleDepositInstructions, buildBundleRequestWithdrawInstruction, computeRequestWithdrawalSharesFromAmountRaw, createAllowlistedBundleProgram, createBundleProgramById, createDummyWallet, deriveOraclePDA, derivePendingAuthPDA, deriveTempDataPDA, deriveUserPDA, getBundleProgramId, getDefaultBundleProgramIdByCluster, getSolanaTokenDecimals, getSolanaTokenMint, getVaultByAddress, getVaultById, getVaultDepositorAddressSync, getVaultRegistry, humanFloatToAmountRawString, isAllowlistedBundleProgramId, isValidVaultAddress, parseAmountRawToBigInt, tokens, vaults, vaultsDevnet };
366
+ export { ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, BUNDLE_PROGRAM_ID_V2_MAINNET, type BuildBundleDepositInstructionsParams, type BuildBundleRequestWithdrawInstructionParams, type BundleAccount, type BundleCluster, type BundleProgram, type BundleProvider, DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, DevnetVaultId, type EffectiveFeeBps, type EffectiveVaultFeeDecimals, FEE_OVERRIDE, NeutralTrade, type NeutralTradeConfig, type NeutralTradeCoreContext, type OracleData, SEED_ORACLE, SEED_PENDING_AUTH, SEED_TEMP, SEED_USER, SupportedChain, SupportedToken, type Token, type UserBalanceResult, type UserBundleAccount, type UserBundleTempData, type UserFeeOverrideFields, type VaultBalanceData, VaultCategory, VaultId, type VaultRegistry, type VaultRegistryEntry, VaultType, assertAllowlistedBundleProgramId, bpsToFeeDecimal, bpsToPercentLabel, buildBundleDepositInstructions, buildBundleRequestWithdrawInstruction, buildFeeOverrideMask, computeDepositFeePreview, computeRequestWithdrawalSharesFromAmountRaw, createAllowlistedBundleProgram, createBundleProgramById, createDummyWallet, deriveOraclePDA, derivePendingAuthPDA, deriveTempDataPDA, deriveUserPDA, effectiveFeeBpsToDecimals, estimatePendingBundleFeeToken, feeDecimalToBps, formatFeeOverrideFlags, getBundleProgramId, getDefaultBundleProgramIdByCluster, getSolanaTokenDecimals, getSolanaTokenMint, getVaultByAddress, getVaultById, getVaultDepositorAddressSync, getVaultRegistry, hasAnyFeeOverride, hasCustomFeeRate, hasFeeOverrideFlag, humanFloatToAmountRawString, isAllowlistedBundleProgramId, isValidVaultAddress, parseAmountRawToBigInt, readUserFeeOverrideFields, resolveEffectiveFeeBps, resolveEffectiveFeeBpsFromDefaults, resolveEffectiveVaultFees, tokens, vaultFeeDecimalsToBps, vaults$1 as vaults, vaultsDevnet };
package/dist/index.mjs CHANGED
@@ -184,6 +184,131 @@ let DevnetVaultId = /* @__PURE__ */ function(DevnetVaultId$1) {
184
184
  return DevnetVaultId$1;
185
185
  }({});
186
186
 
187
+ //#endregion
188
+ //#region src/utils/bundle-fee-override.ts
189
+ /** Mirrors `bundle-sc` `FEE_OVERRIDE_*` bit flags. */
190
+ const FEE_OVERRIDE = {
191
+ DEPOSIT: 1,
192
+ WITHDRAWAL: 2,
193
+ PERFORMANCE: 4,
194
+ MANAGEMENT: 8,
195
+ ALL: 15
196
+ };
197
+ const FEE_EPS = 1e-9;
198
+ function bpsToFeeDecimal(bps) {
199
+ return bps / 1e4;
200
+ }
201
+ function feeDecimalToBps(decimal) {
202
+ return Math.round(decimal * 1e4);
203
+ }
204
+ function bpsToPercentLabel(bps) {
205
+ return (bps / 100).toFixed(4).replace(/\.?0+$/, "");
206
+ }
207
+ function hasFeeOverrideFlag(flags, bit) {
208
+ return (flags & bit) !== 0;
209
+ }
210
+ function buildFeeOverrideMask(flags) {
211
+ let mask = 0;
212
+ if (flags.deposit) mask |= FEE_OVERRIDE.DEPOSIT;
213
+ if (flags.withdrawal) mask |= FEE_OVERRIDE.WITHDRAWAL;
214
+ if (flags.performance) mask |= FEE_OVERRIDE.PERFORMANCE;
215
+ if (flags.management) mask |= FEE_OVERRIDE.MANAGEMENT;
216
+ return mask;
217
+ }
218
+ function formatFeeOverrideFlags(flags) {
219
+ const parts = [];
220
+ if (hasFeeOverrideFlag(flags, FEE_OVERRIDE.DEPOSIT)) parts.push("deposit");
221
+ if (hasFeeOverrideFlag(flags, FEE_OVERRIDE.WITHDRAWAL)) parts.push("withdrawal");
222
+ if (hasFeeOverrideFlag(flags, FEE_OVERRIDE.PERFORMANCE)) parts.push("performance");
223
+ if (hasFeeOverrideFlag(flags, FEE_OVERRIDE.MANAGEMENT)) parts.push("management");
224
+ return parts.length > 0 ? parts.join(", ") : "none";
225
+ }
226
+ function readUserFeeOverrideFields(account) {
227
+ return {
228
+ feeOverrideFlags: toNum(account.feeOverrideFlags ?? account.fee_override_flags),
229
+ customDepositFeeBps: toNum(account.customDepositFeeBps ?? account.custom_deposit_fee_bps),
230
+ customWithdrawalFeeBps: toNum(account.customWithdrawalFeeBps ?? account.custom_withdrawal_fee_bps),
231
+ customPerformanceFeeBps: toNum(account.customPerformanceFeeBps ?? account.custom_performance_fee_bps),
232
+ customManagementFeeBps: toNum(account.customManagementFeeBps ?? account.custom_management_fee_bps)
233
+ };
234
+ }
235
+ function toNum(value) {
236
+ if (typeof value === "number") return value;
237
+ if (typeof value === "bigint") return Number(value);
238
+ if (typeof value === "object" && value !== null && "toNumber" in value) return value.toNumber();
239
+ return Number(String(value ?? 0));
240
+ }
241
+ function bundleDefaultFeeBps(bundle) {
242
+ const b = bundle;
243
+ return {
244
+ depositFeeBps: toNum(b.depositFee),
245
+ withdrawalFeeBps: toNum(b.withdrawalFee),
246
+ performanceFeeBps: toNum(b.performanceFee),
247
+ managementFeeBps: toNum(b.managementFeeBps)
248
+ };
249
+ }
250
+ function vaultFeeDecimalsToBps(fees) {
251
+ return {
252
+ depositFeeBps: feeDecimalToBps(fees.dfee),
253
+ withdrawalFeeBps: feeDecimalToBps(fees.wfee),
254
+ performanceFeeBps: feeDecimalToBps(fees.pfee),
255
+ managementFeeBps: feeDecimalToBps(fees.mfee)
256
+ };
257
+ }
258
+ function effectiveFeeBpsToDecimals(fees) {
259
+ return {
260
+ dfee: bpsToFeeDecimal(fees.depositFeeBps),
261
+ wfee: bpsToFeeDecimal(fees.withdrawalFeeBps),
262
+ pfee: bpsToFeeDecimal(fees.performanceFeeBps),
263
+ mfee: bpsToFeeDecimal(fees.managementFeeBps)
264
+ };
265
+ }
266
+ /**
267
+ * Apply per-user fee override flags onto default bps (bundle or vault-config defaults).
268
+ */
269
+ function resolveEffectiveFeeBpsFromDefaults(defaults, user) {
270
+ const flags = toNum(user.feeOverrideFlags);
271
+ if (flags === 0) return defaults;
272
+ return {
273
+ depositFeeBps: (flags & FEE_OVERRIDE.DEPOSIT) !== 0 ? toNum(user.customDepositFeeBps) : defaults.depositFeeBps,
274
+ withdrawalFeeBps: (flags & FEE_OVERRIDE.WITHDRAWAL) !== 0 ? toNum(user.customWithdrawalFeeBps) : defaults.withdrawalFeeBps,
275
+ performanceFeeBps: (flags & FEE_OVERRIDE.PERFORMANCE) !== 0 ? toNum(user.customPerformanceFeeBps) : defaults.performanceFeeBps,
276
+ managementFeeBps: (flags & FEE_OVERRIDE.MANAGEMENT) !== 0 ? toNum(user.customManagementFeeBps) : defaults.managementFeeBps
277
+ };
278
+ }
279
+ /**
280
+ * Mirror on-chain `resolve_effective_fees`. Returns fee rates in bps.
281
+ */
282
+ function resolveEffectiveFeeBps(bundle, user) {
283
+ return resolveEffectiveFeeBpsFromDefaults(bundleDefaultFeeBps(bundle), user);
284
+ }
285
+ /**
286
+ * Resolve effective fees for UI vault config defaults + optional user bundle account.
287
+ * Returns decimal fees (`0.01` = 1%).
288
+ */
289
+ function resolveEffectiveVaultFees(vaultDefaults, user) {
290
+ if (!user) return vaultDefaults;
291
+ return effectiveFeeBpsToDecimals(resolveEffectiveFeeBpsFromDefaults(vaultFeeDecimalsToBps(vaultDefaults), user));
292
+ }
293
+ function hasAnyFeeOverride(user) {
294
+ if (!user) return false;
295
+ return toNum(user.feeOverrideFlags) !== 0;
296
+ }
297
+ function hasCustomFeeRate(effectiveFees, vaultDefaults) {
298
+ return Math.abs(effectiveFees.dfee - vaultDefaults.dfee) > FEE_EPS || Math.abs(effectiveFees.wfee - vaultDefaults.wfee) > FEE_EPS || Math.abs(effectiveFees.pfee - vaultDefaults.pfee) > FEE_EPS || Math.abs(effectiveFees.mfee - vaultDefaults.mfee) > FEE_EPS;
299
+ }
300
+ function computeDepositFeePreview(grossAmount, depositFeeDecimal) {
301
+ if (grossAmount <= 0 || depositFeeDecimal <= 0) return {
302
+ feeAmount: 0,
303
+ netAmount: grossAmount
304
+ };
305
+ const feeAmount = grossAmount * depositFeeDecimal;
306
+ return {
307
+ feeAmount,
308
+ netAmount: grossAmount - feeAmount
309
+ };
310
+ }
311
+
187
312
  //#endregion
188
313
  //#region src/utils/bundle.ts
189
314
  const SECONDS_PER_YEAR = 365n * 24n * 60n * 60n;
@@ -202,8 +327,9 @@ function estimatePendingBundleFeeToken({ oracleData, bundleData, userBundle, ass
202
327
  const extra = bundleData;
203
328
  const assetPrec = extra.assetPrecision != null ? BigInt(extra.assetPrecision.toString()) : BigInt(10 ** assetDecimals);
204
329
  const sharePrice = totalShares > 0n ? totalAssets * assetPrec / totalShares : assetPrec;
205
- const managementFeeBps = BigInt(Number(extra.managementFeeBps ?? 0));
206
- const performanceFeeBps = BigInt(Number(extra.performanceFee ?? 0));
330
+ const effectiveFees = resolveEffectiveFeeBps(bundleData, userBundle);
331
+ const managementFeeBps = BigInt(effectiveFees.managementFeeBps);
332
+ const performanceFeeBps = BigInt(effectiveFees.performanceFeeBps);
207
333
  const lastMgmtTs = bnToBigInt(userBundle.lastManagementFeeTimestamp);
208
334
  const nowTs = BigInt(nowUnixSeconds);
209
335
  let managementFeeShares = 0n;
@@ -406,4 +532,4 @@ var NeutralTrade = class NeutralTrade {
406
532
  };
407
533
 
408
534
  //#endregion
409
- export { ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, BUNDLE_PROGRAM_ID_V2_MAINNET, DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, DevnetVaultId, NeutralTrade, SEED_ORACLE, SEED_PENDING_AUTH, SEED_TEMP, SEED_USER, SupportedChain, SupportedToken, VaultCategory, VaultId, VaultType, assertAllowlistedBundleProgramId, buildBundleDepositInstructions, buildBundleRequestWithdrawInstruction, computeRequestWithdrawalSharesFromAmountRaw, createAllowlistedBundleProgram, createBundleProgramById, createDummyWallet, deriveOraclePDA, derivePendingAuthPDA, deriveTempDataPDA, deriveUserPDA, getBundleProgramId, getDefaultBundleProgramIdByCluster, getSolanaTokenDecimals, getSolanaTokenMint, getVaultByAddress, getVaultById, getVaultDepositorAddressSync, getVaultRegistry, humanFloatToAmountRawString, isAllowlistedBundleProgramId, isValidVaultAddress, parseAmountRawToBigInt, tokens, vaults, vaultsDevnet };
535
+ export { ALLOWLISTED_BUNDLE_PROGRAM_IDS_BY_CLUSTER, BUNDLE_PROGRAM_ID_V2_MAINNET, DEFAULT_BUNDLE_PROGRAM_ID_DEVNET, DEFAULT_BUNDLE_PROGRAM_ID_MAINNET, DevnetVaultId, FEE_OVERRIDE, NeutralTrade, SEED_ORACLE, SEED_PENDING_AUTH, SEED_TEMP, SEED_USER, SupportedChain, SupportedToken, VaultCategory, VaultId, VaultType, assertAllowlistedBundleProgramId, bpsToFeeDecimal, bpsToPercentLabel, buildBundleDepositInstructions, buildBundleRequestWithdrawInstruction, buildFeeOverrideMask, computeDepositFeePreview, computeRequestWithdrawalSharesFromAmountRaw, createAllowlistedBundleProgram, createBundleProgramById, createDummyWallet, deriveOraclePDA, derivePendingAuthPDA, deriveTempDataPDA, deriveUserPDA, effectiveFeeBpsToDecimals, estimatePendingBundleFeeToken, feeDecimalToBps, formatFeeOverrideFlags, getBundleProgramId, getDefaultBundleProgramIdByCluster, getSolanaTokenDecimals, getSolanaTokenMint, getVaultByAddress, getVaultById, getVaultDepositorAddressSync, getVaultRegistry, hasAnyFeeOverride, hasCustomFeeRate, hasFeeOverrideFlag, humanFloatToAmountRawString, isAllowlistedBundleProgramId, isValidVaultAddress, parseAmountRawToBigInt, readUserFeeOverrideFields, resolveEffectiveFeeBps, resolveEffectiveFeeBpsFromDefaults, resolveEffectiveVaultFees, tokens, vaultFeeDecimalsToBps, vaults, vaultsDevnet };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@neutral-trade/sdk",
3
3
  "type": "module",
4
- "version": "0.4.4",
4
+ "version": "0.4.8",
5
5
  "description": "SDK for Neutral Trade vaults",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/neutral-trade/sdk#readme",