@augustdigital/sdk 8.16.0 → 8.16.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 = "8.16.0";
6
+ export declare const SDK_VERSION = "8.16.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 = '8.16.0';
9
+ exports.SDK_VERSION = '8.16.1';
10
10
  //# sourceMappingURL=version.js.map
@@ -339,6 +339,31 @@ export interface PnlHistoryConsistencyParams {
339
339
  * ```
340
340
  */
341
341
  export declare function assertPnlHistoryConsistent({ vault, wallet, hasDeposits, totalWithdrawnRaw, currentPositionRaw, }: PnlHistoryConsistencyParams): void;
342
+ /**
343
+ * Sum a wallet's per-asset deposits into the vault's own decimals, at face
344
+ * value — 1 unit of any deposited asset is treated as 1 unit of the vault's
345
+ * reporting currency, with no live price conversion.
346
+ *
347
+ * Used by {@link getVaultUserLifetimePnl} for `totalDeposited`. Pre-deposit
348
+ * multi-asset vaults only accept dollar-pegged stablecoins (USDC, USDT, DAI,
349
+ * USDS, RLUSD, etc.) into a dollar-denominated vault, so face value is a
350
+ * reasonable stand-in for USD value. This intentionally does NOT re-quote
351
+ * through a live price oracle: doing so priced a historical deposit at
352
+ * today's market rate, so `totalDeposited` (and lifetimePnl) drifted between
353
+ * calls purely from stablecoin peg noise, and approximately re-inflated
354
+ * deposits back toward face value — which silently excluded the vault's
355
+ * entry fee from PnL. The fee is money the user actually paid, so PnL must
356
+ * be computed net of it.
357
+ *
358
+ * @param depositsByAsset - Raw deposited amount per asset, keyed by
359
+ * lowercased asset address (or `'default'` / `'lz-default'` for
360
+ * single-asset / cross-chain rows).
361
+ * @param assetDecimals - Decimals for each key in `depositsByAsset`.
362
+ * @param vaultDecimals - The vault's own decimals — the target scale every
363
+ * asset is rescaled to.
364
+ * @returns Total deposited, in raw base units at `vaultDecimals`.
365
+ */
366
+ export declare function sumDepositsAtFaceValue(depositsByAsset: Map<string, bigint>, assetDecimals: Map<string, number>, vaultDecimals: number): bigint;
342
367
  /**
343
368
  * Calculate lifetime PnL for a user in a specific vault.
344
369
  *
@@ -347,6 +372,15 @@ export declare function assertPnlHistoryConsistent({ vault, wallet, hasDeposits,
347
372
  * 2. Fetch user's current assets (balanceOf * sharePrice via convertToAssets)
348
373
  * 3. Calculate PnL = assets withdrawn + current assets - assets deposited
349
374
  *
375
+ * `totalDeposited` is the face value of what the user actually paid in
376
+ * (each deposited asset's raw amount, rescaled to the vault's decimals — no
377
+ * live price conversion), so any entry/exit fee the vault charges is
378
+ * automatically counted as a cost against PnL rather than excluded from it.
379
+ * Pre-deposit multi-asset vaults are assumed to only accept dollar-pegged
380
+ * stablecoins into a dollar-denominated vault; a vault accepting a
381
+ * non-pegged deposit asset would need deposit-time price conversion, which
382
+ * this function does not perform.
383
+ *
350
384
  * @param vault - Vault contract address
351
385
  * @param wallet - User wallet address
352
386
  * @param options - RPC configuration and service options
@@ -54,6 +54,7 @@ exports.registerUserForPoints = registerUserForPoints;
54
54
  exports.fetchPointsLeaderboard = fetchPointsLeaderboard;
55
55
  exports.getYieldLastRealizedOn = getYieldLastRealizedOn;
56
56
  exports.assertPnlHistoryConsistent = assertPnlHistoryConsistent;
57
+ exports.sumDepositsAtFaceValue = sumDepositsAtFaceValue;
57
58
  exports.getVaultUserLifetimePnl = getVaultUserLifetimePnl;
58
59
  exports.getVaultPnl = getVaultPnl;
59
60
  exports.getVaultHistoricalTimeseries = getVaultHistoricalTimeseries;
@@ -1898,6 +1899,46 @@ function assertPnlHistoryConsistent({ vault, wallet, hasDeposits, totalWithdrawn
1898
1899
  throw new errors_1.AugustHistoryUnavailableError(`#getVaultUserLifetimePnl::${vault}::${wallet}:transaction history unavailable — a live position exists but no deposits or withdrawals were indexed, so lifetime PnL cannot be computed without over-reporting the entire position as profit`, { context: { vault, wallet } });
1899
1900
  }
1900
1901
  }
1902
+ /**
1903
+ * Sum a wallet's per-asset deposits into the vault's own decimals, at face
1904
+ * value — 1 unit of any deposited asset is treated as 1 unit of the vault's
1905
+ * reporting currency, with no live price conversion.
1906
+ *
1907
+ * Used by {@link getVaultUserLifetimePnl} for `totalDeposited`. Pre-deposit
1908
+ * multi-asset vaults only accept dollar-pegged stablecoins (USDC, USDT, DAI,
1909
+ * USDS, RLUSD, etc.) into a dollar-denominated vault, so face value is a
1910
+ * reasonable stand-in for USD value. This intentionally does NOT re-quote
1911
+ * through a live price oracle: doing so priced a historical deposit at
1912
+ * today's market rate, so `totalDeposited` (and lifetimePnl) drifted between
1913
+ * calls purely from stablecoin peg noise, and approximately re-inflated
1914
+ * deposits back toward face value — which silently excluded the vault's
1915
+ * entry fee from PnL. The fee is money the user actually paid, so PnL must
1916
+ * be computed net of it.
1917
+ *
1918
+ * @param depositsByAsset - Raw deposited amount per asset, keyed by
1919
+ * lowercased asset address (or `'default'` / `'lz-default'` for
1920
+ * single-asset / cross-chain rows).
1921
+ * @param assetDecimals - Decimals for each key in `depositsByAsset`.
1922
+ * @param vaultDecimals - The vault's own decimals — the target scale every
1923
+ * asset is rescaled to.
1924
+ * @returns Total deposited, in raw base units at `vaultDecimals`.
1925
+ */
1926
+ function sumDepositsAtFaceValue(depositsByAsset, assetDecimals, vaultDecimals) {
1927
+ let total = BigInt(0);
1928
+ for (const [assetAddress, rawAmount] of depositsByAsset) {
1929
+ const assetDec = assetDecimals.get(assetAddress) ?? vaultDecimals;
1930
+ if (assetDec === vaultDecimals) {
1931
+ total += rawAmount;
1932
+ }
1933
+ else if (assetDec > vaultDecimals) {
1934
+ total += rawAmount / BigInt(10 ** (assetDec - vaultDecimals));
1935
+ }
1936
+ else {
1937
+ total += rawAmount * BigInt(10 ** (vaultDecimals - assetDec));
1938
+ }
1939
+ }
1940
+ return total;
1941
+ }
1901
1942
  /**
1902
1943
  * Calculate lifetime PnL for a user in a specific vault.
1903
1944
  *
@@ -1906,6 +1947,15 @@ function assertPnlHistoryConsistent({ vault, wallet, hasDeposits, totalWithdrawn
1906
1947
  * 2. Fetch user's current assets (balanceOf * sharePrice via convertToAssets)
1907
1948
  * 3. Calculate PnL = assets withdrawn + current assets - assets deposited
1908
1949
  *
1950
+ * `totalDeposited` is the face value of what the user actually paid in
1951
+ * (each deposited asset's raw amount, rescaled to the vault's decimals — no
1952
+ * live price conversion), so any entry/exit fee the vault charges is
1953
+ * automatically counted as a cost against PnL rather than excluded from it.
1954
+ * Pre-deposit multi-asset vaults are assumed to only accept dollar-pegged
1955
+ * stablecoins into a dollar-denominated vault; a vault accepting a
1956
+ * non-pegged deposit asset would need deposit-time price conversion, which
1957
+ * this function does not perform.
1958
+ *
1909
1959
  * @param vault - Vault contract address
1910
1960
  * @param wallet - User wallet address
1911
1961
  * @param options - RPC configuration and service options
@@ -2069,32 +2119,7 @@ async function getVaultUserLifetimePnl({ vault, wallet, options, }) {
2069
2119
  assetDecimals.set(assetAddress, dec);
2070
2120
  }
2071
2121
  }));
2072
- // Store deposits as a map: assetAddress -> INormalizedNumber (with correct decimals)
2073
- const totalDepositedRaw = new Map();
2074
- for (const [assetAddress, rawAmount] of depositsByAsset) {
2075
- const assetDec = assetDecimals.get(assetAddress) ?? decimals;
2076
- totalDepositedRaw.set(assetAddress, (0, core_1.toNormalizedBn)(rawAmount, assetDec));
2077
- }
2078
- // Fetch USD prices for each unique deposit asset in parallel
2079
- const assetPrices = new Map();
2080
- if (tokenizedVault.chain) {
2081
- await Promise.all(Array.from(depositsByAsset.keys()).map(async (assetAddress) => {
2082
- if (assetAddress === 'default' || assetAddress === 'lz-default') {
2083
- // Will use underlying asset price later
2084
- assetPrices.set(assetAddress, 0);
2085
- }
2086
- else {
2087
- try {
2088
- const price = await (0, core_1.fetchTokenPriceByAddress)(assetAddress, tokenizedVault.chain, options?.headers);
2089
- assetPrices.set(assetAddress, price);
2090
- }
2091
- catch (error) {
2092
- core_1.Logger.log.warn('getVaultUserLifetimePnl:fetchAssetPrice', `Failed to fetch price for ${assetAddress}: ${error}`);
2093
- assetPrices.set(assetAddress, 0);
2094
- }
2095
- }
2096
- }));
2097
- }
2122
+ const totalDepositedNativeRaw = sumDepositsAtFaceValue(depositsByAsset, assetDecimals, decimals);
2098
2123
  const { underlyingTokenSymbol, underlyingAssetAddress } = await underlyingSymbolPromise;
2099
2124
  // Calculate current position value and fetch price in parallel
2100
2125
  let currentPositionValue = (0, core_1.toNormalizedBn)(0, decimals);
@@ -2246,15 +2271,12 @@ async function getVaultUserLifetimePnl({ vault, wallet, options, }) {
2246
2271
  if (tokenPriceUsd <= 0) {
2247
2272
  core_1.Logger.log.warn('getVaultUserLifetimePnl:tokenPrice', `Invalid underlying token price: ${tokenPriceUsd}, using fallback of 1`);
2248
2273
  }
2249
- // Sum all deposited amounts in USD using each asset's own price
2250
- let totalDepositedUsd = 0;
2251
- for (const [assetAddress, normalizedAmount] of totalDepositedRaw) {
2252
- // Use the asset-specific price, or underlying price for 'default'
2253
- const assetPrice = assetAddress === 'default' || assetAddress === 'lz-default'
2254
- ? effectiveTokenPrice
2255
- : assetPrices.get(assetAddress) || effectiveTokenPrice;
2256
- totalDepositedUsd += Number(normalizedAmount.normalized) * assetPrice;
2257
- }
2274
+ // totalDeposited is already in the vault's own decimals (face value,
2275
+ // computed above) — convert to USD with the same underlying price used
2276
+ // for the other two legs below, so all three legs share one conversion
2277
+ // factor instead of drifting independently against each other.
2278
+ const totalDeposited = (0, core_1.toNormalizedBn)(totalDepositedNativeRaw, decimals);
2279
+ const totalDepositedUsd = Number(totalDeposited.normalized) * effectiveTokenPrice;
2258
2280
  const totalWithdrawnUsd = Number(totalWithdrawn.normalized) * effectiveTokenPrice;
2259
2281
  const currentPositionValueUsd = Number(currentPositionValue.normalized) * effectiveTokenPrice;
2260
2282
  // Calculate lifetimePnl in USD first (since deposits may be in different tokens with different prices)
@@ -2262,12 +2284,6 @@ async function getVaultUserLifetimePnl({ vault, wallet, options, }) {
2262
2284
  // Use BigInt-scaled arithmetic to minimize precision loss when converting USD to native
2263
2285
  const scaleFactor = BigInt(10 ** 18); // High precision scale
2264
2286
  const tokenPriceScaled = BigInt(Math.round(effectiveTokenPrice * Number(scaleFactor)));
2265
- // Convert totalDepositedUsd to native units for backwards compatibility
2266
- const totalDepositedUsdScaled = BigInt(Math.round(totalDepositedUsd * Number(scaleFactor)));
2267
- const totalDepositedNativeRaw = tokenPriceScaled > BigInt(0)
2268
- ? (totalDepositedUsdScaled * BigInt(10 ** decimals)) / tokenPriceScaled
2269
- : BigInt(0);
2270
- const totalDeposited = (0, core_1.toNormalizedBn)(totalDepositedNativeRaw, decimals);
2271
2287
  // Convert lifetimePnlUsd to native units
2272
2288
  const lifetimePnlUsdScaled = BigInt(Math.round(lifetimePnlUsd * Number(scaleFactor)));
2273
2289
  const lifetimePnlRaw = tokenPriceScaled > BigInt(0)
package/lib/sdk.d.ts CHANGED
@@ -18986,6 +18986,15 @@ declare function assertNotStellar(address: string, operation: string): void;
18986
18986
  * 2. Fetch user's current assets (balanceOf * sharePrice via convertToAssets)
18987
18987
  * 3. Calculate PnL = assets withdrawn + current assets - assets deposited
18988
18988
  *
18989
+ * `totalDeposited` is the face value of what the user actually paid in
18990
+ * (each deposited asset's raw amount, rescaled to the vault's decimals — no
18991
+ * live price conversion), so any entry/exit fee the vault charges is
18992
+ * automatically counted as a cost against PnL rather than excluded from it.
18993
+ * Pre-deposit multi-asset vaults are assumed to only accept dollar-pegged
18994
+ * stablecoins into a dollar-denominated vault; a vault accepting a
18995
+ * non-pegged deposit asset would need deposit-time price conversion, which
18996
+ * this function does not perform.
18997
+ *
18989
18998
  * @param vault - Vault contract address
18990
18999
  * @param wallet - User wallet address
18991
19000
  * @param options - RPC configuration and service options
@@ -24959,6 +24968,32 @@ declare function assertNotStellar(address: string, operation: string): void;
24959
24968
  transformEmberVaultsToIVaults(emberVaults: IEmberVault[]): IVault[];
24960
24969
  }
24961
24970
 
24971
+ /**
24972
+ * Sum a wallet's per-asset deposits into the vault's own decimals, at face
24973
+ * value — 1 unit of any deposited asset is treated as 1 unit of the vault's
24974
+ * reporting currency, with no live price conversion.
24975
+ *
24976
+ * Used by {@link getVaultUserLifetimePnl} for `totalDeposited`. Pre-deposit
24977
+ * multi-asset vaults only accept dollar-pegged stablecoins (USDC, USDT, DAI,
24978
+ * USDS, RLUSD, etc.) into a dollar-denominated vault, so face value is a
24979
+ * reasonable stand-in for USD value. This intentionally does NOT re-quote
24980
+ * through a live price oracle: doing so priced a historical deposit at
24981
+ * today's market rate, so `totalDeposited` (and lifetimePnl) drifted between
24982
+ * calls purely from stablecoin peg noise, and approximately re-inflated
24983
+ * deposits back toward face value — which silently excluded the vault's
24984
+ * entry fee from PnL. The fee is money the user actually paid, so PnL must
24985
+ * be computed net of it.
24986
+ *
24987
+ * @param depositsByAsset - Raw deposited amount per asset, keyed by
24988
+ * lowercased asset address (or `'default'` / `'lz-default'` for
24989
+ * single-asset / cross-chain rows).
24990
+ * @param assetDecimals - Decimals for each key in `depositsByAsset`.
24991
+ * @param vaultDecimals - The vault's own decimals — the target scale every
24992
+ * asset is rescaled to.
24993
+ * @returns Total deposited, in raw base units at `vaultDecimals`.
24994
+ */
24995
+ export declare function sumDepositsAtFaceValue(depositsByAsset: Map<string, bigint>, assetDecimals: Map<string, number>, vaultDecimals: number): bigint;
24996
+
24962
24997
  /**
24963
24998
  * Address of the `SwapRouter` periphery contract on each supported chain.
24964
24999
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "8.16.0",
3
+ "version": "8.16.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [