@augustdigital/sdk 9.12.0 → 9.13.1

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.
@@ -3,4 +3,4 @@
3
3
  * Generated during publish from package.json version
4
4
  * This file is gitignored and created at publish time
5
5
  */
6
- export declare const SDK_VERSION = "9.12.0";
6
+ export declare const SDK_VERSION = "9.13.1";
@@ -6,5 +6,5 @@ exports.SDK_VERSION = void 0;
6
6
  * Generated during publish from package.json version
7
7
  * This file is gitignored and created at publish time
8
8
  */
9
- exports.SDK_VERSION = '9.12.0';
9
+ exports.SDK_VERSION = '9.13.1';
10
10
  //# sourceMappingURL=version.js.map
@@ -860,9 +860,21 @@ export declare function getVaultUserLifetimePnl({ vault, wallet, options, }: {
860
860
  * Calculate PnL for a vault (vault-level, not user-specific).
861
861
  * Returns the vault's overall profit and loss across all users.
862
862
  *
863
+ * Sums, over the vault's whole history, each day's change in assets per share
864
+ * times that day's total shares, then prices the result at the receipt
865
+ * token's current USD price. The daily history comes from
866
+ * `GET /tokenized_vault/{vault}/historical-timeseries`, the replacement for the
867
+ * deprecated `load_snapshots` flag on the vault read.
868
+ *
869
+ * Network: one backend vault read, one timeseries read and one price read.
870
+ *
863
871
  * @param vault - Vault contract address
864
872
  * @param options - RPC configuration and service options
865
- * @returns Vault PnL in USD and notional value
873
+ * @returns Vault PnL in the deposit asset (`totalPnl`) and in USD (`pnlUsd`).
874
+ * Both are zero for a vault with no recorded history. `pnlUsd` is also zero
875
+ * when the receipt token price cannot be fetched.
876
+ * @throws Error when `vault` is missing, is a Stellar vault, is not an
877
+ * address, or the vault or its history cannot be read.
866
878
  */
867
879
  export declare function getVaultPnl({ vault, options, }: {
868
880
  vault: IAddress;
@@ -3445,9 +3445,21 @@ async function getVaultUserLifetimePnl({ vault, wallet, options, }) {
3445
3445
  * Calculate PnL for a vault (vault-level, not user-specific).
3446
3446
  * Returns the vault's overall profit and loss across all users.
3447
3447
  *
3448
+ * Sums, over the vault's whole history, each day's change in assets per share
3449
+ * times that day's total shares, then prices the result at the receipt
3450
+ * token's current USD price. The daily history comes from
3451
+ * `GET /tokenized_vault/{vault}/historical-timeseries`, the replacement for the
3452
+ * deprecated `load_snapshots` flag on the vault read.
3453
+ *
3454
+ * Network: one backend vault read, one timeseries read and one price read.
3455
+ *
3448
3456
  * @param vault - Vault contract address
3449
3457
  * @param options - RPC configuration and service options
3450
- * @returns Vault PnL in USD and notional value
3458
+ * @returns Vault PnL in the deposit asset (`totalPnl`) and in USD (`pnlUsd`).
3459
+ * Both are zero for a vault with no recorded history. `pnlUsd` is also zero
3460
+ * when the receipt token price cannot be fetched.
3461
+ * @throws Error when `vault` is missing, is a Stellar vault, is not an
3462
+ * address, or the vault or its history cannot be read.
3451
3463
  */
3452
3464
  async function getVaultPnl({ vault, options, }) {
3453
3465
  try {
@@ -3456,60 +3468,33 @@ async function getVaultPnl({ vault, options, }) {
3456
3468
  (0, utils_3.assertNotStellar)(vault, 'Vault PnL');
3457
3469
  if (!(0, ethers_1.isAddress)(vault))
3458
3470
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
3459
- // Get vault data
3460
- const vaultData = await getVault({
3461
- vault,
3462
- loans: false,
3463
- allocations: false,
3464
- options,
3465
- });
3471
+ // The vault row only supplies decimals, chain and receipt token, so skip
3472
+ // its subaccounts and snapshots. 3650 days reads the full history, as
3473
+ // `fetchShareRatios` does.
3474
+ const [vaultData, { data: history }] = await Promise.all([
3475
+ getVault({
3476
+ vault,
3477
+ loans: false,
3478
+ allocations: false,
3479
+ options,
3480
+ loadSubaccounts: false,
3481
+ loadSnapshots: false,
3482
+ }),
3483
+ (0, core_1.fetchVaultHistoricalTimeseries)(vault, 3650, options?.headers),
3484
+ ]);
3466
3485
  if (!vaultData) {
3467
3486
  throw new Error(`Vault ${vault} not found`);
3468
3487
  }
3469
- // Check if vault has daily_pnl_per_share and historical_snapshots
3470
- if (!vaultData.dailyPnlPerShare ||
3471
- !Array.isArray(vaultData.dailyPnlPerShare) ||
3472
- vaultData.dailyPnlPerShare.length === 0) {
3473
- return {
3474
- totalPnl: (0, core_1.toNormalizedBn)(0, vaultData.decimals),
3475
- pnlUsd: 0,
3476
- };
3477
- }
3478
- if (!vaultData.historical_snapshots ||
3479
- !Array.isArray(vaultData.historical_snapshots) ||
3480
- vaultData.historical_snapshots.length === 0) {
3481
- return {
3482
- totalPnl: (0, core_1.toNormalizedBn)(0, vaultData.decimals),
3483
- pnlUsd: 0,
3484
- };
3485
- }
3486
3488
  const decimals = vaultData.decimals;
3487
- // Filter out dates with zero PnL
3488
- const validDailyPnl = vaultData.dailyPnlPerShare.filter((dayData) => dayData.value && dayData.value !== 0);
3489
- // Create a map of historical_snapshots by date (YYYY-MM-DD) for quick lookup
3490
- const snapshotsByDate = new Map();
3491
- vaultData.historical_snapshots.forEach((snapshot) => {
3492
- const snapshotDate = new Date(snapshot.snapshot_datetime);
3493
- const dateKey = snapshotDate.toISOString().split('T')[0]; // YYYY-MM-DD
3494
- snapshotsByDate.set(dateKey, snapshot);
3495
- });
3496
- // Calculate PnL for each day using historical_snapshots
3489
+ // `daily_pnl` is the day's change in assets per share. It is zero on the
3490
+ // first day and on forward-filled (`missing`) days, so those add nothing.
3497
3491
  let totalPnlRaw = BigInt(0);
3498
- validDailyPnl.forEach((dayData) => {
3499
- const dayTimestamp = dayData.timestamp;
3500
- const dailyPnlPerShare = dayData.value;
3501
- // Get date key (YYYY-MM-DD) from timestamp
3502
- const dayDate = new Date(dayTimestamp);
3503
- const dateKey = dayDate.toISOString().split('T')[0];
3504
- // Find matching snapshot for this date
3505
- const snapshot = snapshotsByDate.get(dateKey);
3506
- if (!snapshot?.total_shares) {
3507
- core_1.Logger.log.warn('getVaultPnl:snapshotNotFound', `No snapshot found for date ${dateKey}`);
3492
+ Object.values(history ?? {}).forEach((day) => {
3493
+ if (!day.daily_pnl || !day.total_shares)
3508
3494
  return;
3509
- }
3510
3495
  // Convert normalized numbers to BigInt using toNormalizedBn's normalized string
3511
- const dailyPnlNorm = (0, core_1.toNormalizedBn)(dailyPnlPerShare, decimals);
3512
- const totalSharesNorm = (0, core_1.toNormalizedBn)(snapshot.total_shares, decimals);
3496
+ const dailyPnlNorm = (0, core_1.toNormalizedBn)(day.daily_pnl, decimals);
3497
+ const totalSharesNorm = (0, core_1.toNormalizedBn)(day.total_shares, decimals);
3513
3498
  // Convert normalized strings to BigInt (split, pad fraction, combine) - all inline
3514
3499
  const [dailyWhole = '0', dailyFrac = ''] = dailyPnlNorm.normalized.split('.');
3515
3500
  const dailyPnlPerShareScaled = BigInt(dailyWhole + (dailyFrac || '').padEnd(decimals, '0').slice(0, decimals));
@@ -3520,6 +3505,10 @@ async function getVaultPnl({ vault, options, }) {
3520
3505
  const dayPnlRaw = (dailyPnlPerShareScaled * totalSharesScaled) / BigInt(10 ** decimals);
3521
3506
  totalPnlRaw += dayPnlRaw;
3522
3507
  });
3508
+ // No history (or no PnL in it) prices to zero, so skip the price read.
3509
+ if (totalPnlRaw === BigInt(0)) {
3510
+ return { totalPnl: (0, core_1.toNormalizedBn)(0, decimals), pnlUsd: 0 };
3511
+ }
3523
3512
  // Convert totalPnlRaw (BigInt) to normalized number using toNormalizedBn
3524
3513
  const totalPnl = (0, core_1.toNormalizedBn)(totalPnlRaw, decimals);
3525
3514
  const totalPnlNormalized = Number(totalPnl.normalized);
@@ -82,6 +82,14 @@ export declare function formatVaultApy(tokenizedVault: ITokenizedVault): IVault[
82
82
  * the trailing `Z` is preserved.
83
83
  */
84
84
  export declare function mapVaultFreshness(tokenizedVault: ITokenizedVault | undefined | null): IVaultFreshness | null;
85
+ /**
86
+ * Map a wrapper vault's link to the vault it wraps.
87
+ *
88
+ * @param tokenizedVault - Backend tokenized-vault payload.
89
+ * @returns The underlying vault address (casing preserved) and chain id, both
90
+ * null for a non-wrapper vault. A chain id without an address is dropped.
91
+ */
92
+ export declare function mapUnderlyingVault(tokenizedVault: ITokenizedVault | undefined | null): Pick<IVault, 'underlyingVaultAddress' | 'underlyingChainId'>;
85
93
  /**
86
94
  * Map strategists from backend subaccounts or hardcoded list.
87
95
  * Shared across all chain adapters.
@@ -7,6 +7,7 @@ exports.getIdleAssets = getIdleAssets;
7
7
  exports.getYieldLastRealizedOn = getYieldLastRealizedOn;
8
8
  exports.formatVaultApy = formatVaultApy;
9
9
  exports.mapVaultFreshness = mapVaultFreshness;
10
+ exports.mapUnderlyingVault = mapUnderlyingVault;
10
11
  exports.mapStrategists = mapStrategists;
11
12
  exports.mapComposabilityIntegrations = mapComposabilityIntegrations;
12
13
  exports.backendTvlToNormalizedBn = backendTvlToNormalizedBn;
@@ -268,6 +269,22 @@ function mapVaultFreshness(tokenizedVault) {
268
269
  cachedAt: freshness.cached_at ?? null,
269
270
  };
270
271
  }
272
+ /**
273
+ * Map a wrapper vault's link to the vault it wraps.
274
+ *
275
+ * @param tokenizedVault - Backend tokenized-vault payload.
276
+ * @returns The underlying vault address (casing preserved) and chain id, both
277
+ * null for a non-wrapper vault. A chain id without an address is dropped.
278
+ */
279
+ function mapUnderlyingVault(tokenizedVault) {
280
+ const address = tokenizedVault?.underlying_vault_address;
281
+ if (!address)
282
+ return { underlyingVaultAddress: null, underlyingChainId: null };
283
+ return {
284
+ underlyingVaultAddress: address,
285
+ underlyingChainId: tokenizedVault?.underlying_chain ?? null,
286
+ };
287
+ }
271
288
  /**
272
289
  * Map strategists from backend subaccounts or hardcoded list.
273
290
  * Shared across all chain adapters.
@@ -437,6 +454,7 @@ function buildBackendVault(tokenizedVault, overrides) {
437
454
  dailyPnlPerShare: mapDailyPnlPerShare(tokenizedVault.daily_pnl_per_share),
438
455
  enabled_historical_price_horizons: tokenizedVault.enabled_historical_price_horizons || [],
439
456
  latest_reported_tvl: tokenizedVault.latest_reported_tvl,
457
+ ...mapUnderlyingVault(tokenizedVault),
440
458
  defaultApyHorizon: tokenizedVault.default_apy_horizon,
441
459
  ...(tokenizedVault.instant_redeem_config
442
460
  ? {
@@ -659,6 +677,7 @@ async function buildFormattedVault(provider, tokenizedVault, contractCalls) {
659
677
  enabled_historical_price_horizons: tokenizedVault?.enabled_historical_price_horizons,
660
678
  defaultApyHorizon: tokenizedVault?.default_apy_horizon ?? null,
661
679
  latest_reported_tvl: tokenizedVault?.latest_reported_tvl,
680
+ ...mapUnderlyingVault(tokenizedVault),
662
681
  cachedAt: tokenizedVault?.cached_at ?? null,
663
682
  freshness: mapVaultFreshness(tokenizedVault),
664
683
  showCapFilled: tokenizedVault?.show_cap_filled ?? null,
package/lib/sdk.d.ts CHANGED
@@ -20178,9 +20178,21 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
20178
20178
  * Calculate PnL for a vault (vault-level, not user-specific).
20179
20179
  * Returns the vault's overall profit and loss across all users.
20180
20180
  *
20181
+ * Sums, over the vault's whole history, each day's change in assets per share
20182
+ * times that day's total shares, then prices the result at the receipt
20183
+ * token's current USD price. The daily history comes from
20184
+ * `GET /tokenized_vault/{vault}/historical-timeseries`, the replacement for the
20185
+ * deprecated `load_snapshots` flag on the vault read.
20186
+ *
20187
+ * Network: one backend vault read, one timeseries read and one price read.
20188
+ *
20181
20189
  * @param vault - Vault contract address
20182
20190
  * @param options - RPC configuration and service options
20183
- * @returns Vault PnL in USD and notional value
20191
+ * @returns Vault PnL in the deposit asset (`totalPnl`) and in USD (`pnlUsd`).
20192
+ * Both are zero for a vault with no recorded history. `pnlUsd` is also zero
20193
+ * when the receipt token price cannot be fetched.
20194
+ * @throws Error when `vault` is missing, is a Stellar vault, is not an
20195
+ * address, or the vault or its history cannot be read.
20184
20196
  */
20185
20197
  export declare function getVaultPnl({ vault, options, }: {
20186
20198
  vault: IAddress;
@@ -24276,6 +24288,14 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
24276
24288
  enabled_historical_price_horizons?: number[];
24277
24289
  defaultApyHorizon?: 7 | 30 | null;
24278
24290
  latest_reported_tvl?: number | null;
24291
+ /**
24292
+ * Wrapper vaults only: the vault this one wraps, which holds the assets. A
24293
+ * wrapper's own on-chain `totalAssets` reads 0, so its TVL is the underlying
24294
+ * vault's. Null on a non-wrapper vault. Address casing is preserved verbatim.
24295
+ */
24296
+ underlyingVaultAddress?: VaultAddress | null;
24297
+ /** Chain id of {@link IVault.underlyingVaultAddress}; null on a non-wrapper vault. */
24298
+ underlyingChainId?: number | null;
24279
24299
  cachedAt?: string | null;
24280
24300
  /**
24281
24301
  * Provenance timestamps for the vault's server-side data — when its APY was last
@@ -25621,6 +25641,15 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
25621
25641
  website_url: string;
25622
25642
  }[];
25623
25643
 
25644
+ /**
25645
+ * Map a wrapper vault's link to the vault it wraps.
25646
+ *
25647
+ * @param tokenizedVault - Backend tokenized-vault payload.
25648
+ * @returns The underlying vault address (casing preserved) and chain id, both
25649
+ * null for a non-wrapper vault. A chain id without an address is dropped.
25650
+ */
25651
+ export declare function mapUnderlyingVault(tokenizedVault: ITokenizedVault | undefined | null): Pick<IVault, 'underlyingVaultAddress' | 'underlyingChainId'>;
25652
+
25624
25653
  /**
25625
25654
  * Map the backend `freshness` object onto the camelCased {@link IVaultFreshness}
25626
25655
  * shape carried on `IVault`. Shared across all chain adapters (EVM, Solana,
@@ -383,6 +383,14 @@ export interface IVault {
383
383
  enabled_historical_price_horizons?: number[];
384
384
  defaultApyHorizon?: 7 | 30 | null;
385
385
  latest_reported_tvl?: number | null;
386
+ /**
387
+ * Wrapper vaults only: the vault this one wraps, which holds the assets. A
388
+ * wrapper's own on-chain `totalAssets` reads 0, so its TVL is the underlying
389
+ * vault's. Null on a non-wrapper vault. Address casing is preserved verbatim.
390
+ */
391
+ underlyingVaultAddress?: VaultAddress | null;
392
+ /** Chain id of {@link IVault.underlyingVaultAddress}; null on a non-wrapper vault. */
393
+ underlyingChainId?: number | null;
386
394
  cachedAt?: string | null;
387
395
  /**
388
396
  * Provenance timestamps for the vault's server-side data — when its APY was last
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "9.12.0",
3
+ "version": "9.13.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [