@augustdigital/sdk 9.13.0 → 9.13.2

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.
@@ -90,7 +90,7 @@ const getEvmVaultV1 = async (tokenizedVault, options) => {
90
90
  return (0, core_1.getSymbol)(provider, vault);
91
91
  }
92
92
  if (f === 'decimals') {
93
- return (0, core_1.getDecimals)(provider, vault);
93
+ return (0, core_1.getDecimalsOrThrow)(provider, vault, 'getEvmVaultV1');
94
94
  }
95
95
  return vaultContract[f]();
96
96
  }));
@@ -188,7 +188,7 @@ const getEvmVaultV2 = async (tokenizedVault, options) => {
188
188
  return (0, core_1.getSymbol)(provider, receiptAddress, false);
189
189
  }
190
190
  if (f === 'decimals') {
191
- return (0, core_1.getDecimals)(provider, receiptAddress, false);
191
+ return (0, core_1.getDecimalsOrThrow)(provider, receiptAddress, 'getEvmVaultV2');
192
192
  }
193
193
  return reciptContract[f]();
194
194
  })),
@@ -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.13.0";
6
+ export declare const SDK_VERSION = "9.13.2";
@@ -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.13.0';
9
+ exports.SDK_VERSION = '9.13.2';
10
10
  //# sourceMappingURL=version.js.map
@@ -467,6 +467,21 @@ const ARGUMENT_FREE_VIEW_SELECTORS = new Set([
467
467
  '0x06fdde03', // name()
468
468
  '0x18160ddd', // totalSupply()
469
469
  exports.LP_TOKEN_ADDRESS_SELECTOR, // lpTokenAddress()
470
+ // The vault views `getEvmVaultV1` / `getEvmVaultV2` read in one fan-out.
471
+ // Same caveat as `lpTokenAddress()`: each exists on one vault generation, so
472
+ // a misrouted vault answers empty deterministically and must still surface
473
+ // once the bounded retry is spent.
474
+ '0x38d52e0f', // asset()
475
+ '0x01e1d114', // totalAssets()
476
+ '0xd5abeb01', // maxSupply()
477
+ '0x8bc7e8c4', // withdrawalFee()
478
+ '0x24e86d67', // lagDuration()
479
+ '0xe9f2838e', // withdrawalsPaused()
480
+ '0x60da3e83', // depositsPaused()
481
+ '0x8ed83271', // maxDepositAmount()
482
+ '0xcdb1fb2b', // assetsWhitelistAddress()
483
+ '0x6e07302b', // getTotalAssets()
484
+ '0xdbd5edc7', // depositCap()
470
485
  ]);
471
486
  /**
472
487
  * Extract the 4-byte selector of the call an ethers `CALL_EXCEPTION` describes.
@@ -12,9 +12,17 @@ import { type Signer, type Wallet } from 'ethers';
12
12
  */
13
13
  export declare function isViemWalletClient(signer: any): boolean;
14
14
  /**
15
- * Convert a viem WalletClient to an ethers-compatible Signer
16
- * Uses the walletClient as a provider and wraps it for ethers compatibility
17
- * @param walletClient Viem WalletClient from wagmi or viem
15
+ * Convert a viem WalletClient to an ethers-compatible Signer.
16
+ *
17
+ * The account and chain are answered from the client itself, and
18
+ * transactions, personal messages and EIP-712 typed data are signed through
19
+ * the client's own `sendTransaction` / `signMessage` / `signTypedData`, so a
20
+ * local account (for example an embedded wallet built with
21
+ * `createWalletClient({ account, transport: http() })`) signs locally and
22
+ * broadcasts the raw transaction. Every other request goes to the client's
23
+ * transport.
24
+ *
25
+ * @param walletClient - Viem WalletClient from wagmi or viem
18
26
  * @returns Ethers Signer that can be used with the SDK
19
27
  */
20
28
  export declare function viemToEthersSigner(walletClient: any): Promise<Signer | Wallet>;
@@ -26,39 +26,76 @@ function isViemWalletClient(signer) {
26
26
  'transport' in signer &&
27
27
  typeof signer.writeContract === 'function');
28
28
  }
29
+ function toBigInt(value) {
30
+ return value == null ? undefined : BigInt(value);
31
+ }
32
+ function toViemTransaction(tx) {
33
+ return {
34
+ to: tx.to ?? undefined,
35
+ data: tx.data,
36
+ accessList: tx.accessList,
37
+ value: toBigInt(tx.value),
38
+ gas: toBigInt(tx.gas),
39
+ gasPrice: toBigInt(tx.gasPrice),
40
+ maxFeePerGas: toBigInt(tx.maxFeePerGas),
41
+ maxPriorityFeePerGas: toBigInt(tx.maxPriorityFeePerGas),
42
+ nonce: tx.nonce == null ? undefined : Number(tx.nonce),
43
+ };
44
+ }
29
45
  /**
30
- * Convert a viem WalletClient to an ethers-compatible Signer
31
- * Uses the walletClient as a provider and wraps it for ethers compatibility
32
- * @param walletClient Viem WalletClient from wagmi or viem
46
+ * Convert a viem WalletClient to an ethers-compatible Signer.
47
+ *
48
+ * The account and chain are answered from the client itself, and
49
+ * transactions, personal messages and EIP-712 typed data are signed through
50
+ * the client's own `sendTransaction` / `signMessage` / `signTypedData`, so a
51
+ * local account (for example an embedded wallet built with
52
+ * `createWalletClient({ account, transport: http() })`) signs locally and
53
+ * broadcasts the raw transaction. Every other request goes to the client's
54
+ * transport.
55
+ *
56
+ * @param walletClient - Viem WalletClient from wagmi or viem
33
57
  * @returns Ethers Signer that can be used with the SDK
34
58
  */
35
59
  async function viemToEthersSigner(walletClient) {
36
60
  if (!walletClient) {
37
61
  throw new Error('WalletClient is required');
38
62
  }
39
- // Create an EIP-1193 provider from the wallet client
40
63
  const { account, chain, transport } = walletClient;
41
64
  if (!account) {
42
65
  throw new Error('WalletClient must have an account');
43
66
  }
44
- // Create a custom transport that uses the walletClient
45
67
  const provider = new ethers_1.BrowserProvider({
46
- request: async ({ method, params }) => {
47
- // Use the wallet client's transport for all requests
48
- if (method === 'eth_sendTransaction') {
49
- // For transactions, use writeContract or sendTransaction
50
- const [tx] = params;
51
- return walletClient.sendTransaction({
52
- ...tx,
53
- account,
54
- chain,
55
- });
68
+ request: async ({ method, params = [] }) => {
69
+ switch (method) {
70
+ case 'eth_accounts':
71
+ case 'eth_requestAccounts':
72
+ return [account.address];
73
+ case 'eth_chainId':
74
+ if (chain)
75
+ return (0, ethers_1.toQuantity)(chain.id);
76
+ break;
77
+ case 'eth_sendTransaction':
78
+ return walletClient.sendTransaction({
79
+ ...toViemTransaction(params[0]),
80
+ account,
81
+ chain,
82
+ });
83
+ case 'personal_sign':
84
+ return walletClient.signMessage({
85
+ account,
86
+ message: { raw: params[0] },
87
+ });
88
+ case 'eth_signTypedData_v4':
89
+ return walletClient.signTypedData({
90
+ account,
91
+ ...(typeof params[1] === 'string'
92
+ ? JSON.parse(params[1])
93
+ : params[1]),
94
+ });
56
95
  }
57
- // For all other requests, use the transport directly
58
- return transport({ chain }).request({ method, params });
96
+ return transport.request({ method, params });
59
97
  },
60
98
  }, chain?.id);
61
- // Get the signer from the provider
62
99
  return provider.getSigner(account.address);
63
100
  }
64
101
  /**
@@ -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;
@@ -169,7 +169,11 @@ async function getVault({ vault, loans = false, allocations = false, options, lo
169
169
  }
170
170
  }
171
171
  catch (err) {
172
- core_1.Logger.log.error('getVault', err, { vault });
172
+ // A provider fault (rate limit, socket reset, an empty response to one of
173
+ // the vault's argument-free views) is not an SDK or caller defect: the
174
+ // caller sees the same throw either way, so it is recorded as a breadcrumb
175
+ // rather than a billed Sentry issue. Everything else stays at error.
176
+ (0, core_1.logChainError)('getVault', err, (0, core_1.isRetryableRpcError)(err) || (0, core_1.isEmptyViewResponse)(err), { vault });
173
177
  throw new Error(`#getVault::${vault}: ${err?.message}`);
174
178
  }
175
179
  // Loans enrichment stays EVM-only — there is no non-EVM loan book to read.
@@ -1625,7 +1629,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1625
1629
  // get vault metadata and balance based on version
1626
1630
  let bal = BigInt(0);
1627
1631
  if (version === 'evm-2') {
1628
- const receiptAddress = await (0, core_1.getReceiptTokenAddress)(provider, vault);
1632
+ const receiptAddress = await (0, core_1.getReceiptTokenAddress)(provider, v.address);
1629
1633
  decimals = await (0, core_1.getDecimals)(provider, receiptAddress, false);
1630
1634
  if (wallet && (0, ethers_1.isAddress)(wallet)) {
1631
1635
  if (typeof prefetched?.balance === 'bigint') {
@@ -1642,7 +1646,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1642
1646
  }
1643
1647
  }
1644
1648
  else {
1645
- decimals = await (0, core_1.getDecimals)(provider, vault);
1649
+ decimals = await (0, core_1.getDecimals)(provider, v.address);
1646
1650
  if (wallet && (0, ethers_1.isAddress)(wallet)) {
1647
1651
  bal =
1648
1652
  typeof prefetched?.balance === 'bigint'
@@ -1675,7 +1679,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1675
1679
  const aggregateAvailableRedemptions = availableRedemptions.reduce((acc, curr) => acc + BigInt(curr.amount.raw), BigInt(0));
1676
1680
  // return obj
1677
1681
  return {
1678
- vault,
1682
+ vault: v.address,
1679
1683
  status: renderStatus(availableRedemptions, balance),
1680
1684
  availableRedemptions,
1681
1685
  pendingRedemptions,
@@ -1686,7 +1690,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1686
1690
  catch (vaultError) {
1687
1691
  core_1.Logger.log.error(`getVaultPositions`, `Error processing vault ${v.address}: ${vaultError}`);
1688
1692
  return {
1689
- vault,
1693
+ vault: v.address,
1690
1694
  status: 'PENDING',
1691
1695
  availableRedemptions: [],
1692
1696
  pendingRedemptions: [],
@@ -3445,9 +3449,21 @@ async function getVaultUserLifetimePnl({ vault, wallet, options, }) {
3445
3449
  * Calculate PnL for a vault (vault-level, not user-specific).
3446
3450
  * Returns the vault's overall profit and loss across all users.
3447
3451
  *
3452
+ * Sums, over the vault's whole history, each day's change in assets per share
3453
+ * times that day's total shares, then prices the result at the receipt
3454
+ * token's current USD price. The daily history comes from
3455
+ * `GET /tokenized_vault/{vault}/historical-timeseries`, the replacement for the
3456
+ * deprecated `load_snapshots` flag on the vault read.
3457
+ *
3458
+ * Network: one backend vault read, one timeseries read and one price read.
3459
+ *
3448
3460
  * @param vault - Vault contract address
3449
3461
  * @param options - RPC configuration and service options
3450
- * @returns Vault PnL in USD and notional value
3462
+ * @returns Vault PnL in the deposit asset (`totalPnl`) and in USD (`pnlUsd`).
3463
+ * Both are zero for a vault with no recorded history. `pnlUsd` is also zero
3464
+ * when the receipt token price cannot be fetched.
3465
+ * @throws Error when `vault` is missing, is a Stellar vault, is not an
3466
+ * address, or the vault or its history cannot be read.
3451
3467
  */
3452
3468
  async function getVaultPnl({ vault, options, }) {
3453
3469
  try {
@@ -3456,60 +3472,33 @@ async function getVaultPnl({ vault, options, }) {
3456
3472
  (0, utils_3.assertNotStellar)(vault, 'Vault PnL');
3457
3473
  if (!(0, ethers_1.isAddress)(vault))
3458
3474
  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
- });
3475
+ // The vault row only supplies decimals, chain and receipt token, so skip
3476
+ // its subaccounts and snapshots. 3650 days reads the full history, as
3477
+ // `fetchShareRatios` does.
3478
+ const [vaultData, { data: history }] = await Promise.all([
3479
+ getVault({
3480
+ vault,
3481
+ loans: false,
3482
+ allocations: false,
3483
+ options,
3484
+ loadSubaccounts: false,
3485
+ loadSnapshots: false,
3486
+ }),
3487
+ (0, core_1.fetchVaultHistoricalTimeseries)(vault, 3650, options?.headers),
3488
+ ]);
3466
3489
  if (!vaultData) {
3467
3490
  throw new Error(`Vault ${vault} not found`);
3468
3491
  }
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
3492
  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
3493
+ // `daily_pnl` is the day's change in assets per share. It is zero on the
3494
+ // first day and on forward-filled (`missing`) days, so those add nothing.
3497
3495
  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}`);
3496
+ Object.values(history ?? {}).forEach((day) => {
3497
+ if (!day.daily_pnl || !day.total_shares)
3508
3498
  return;
3509
- }
3510
3499
  // 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);
3500
+ const dailyPnlNorm = (0, core_1.toNormalizedBn)(day.daily_pnl, decimals);
3501
+ const totalSharesNorm = (0, core_1.toNormalizedBn)(day.total_shares, decimals);
3513
3502
  // Convert normalized strings to BigInt (split, pad fraction, combine) - all inline
3514
3503
  const [dailyWhole = '0', dailyFrac = ''] = dailyPnlNorm.normalized.split('.');
3515
3504
  const dailyPnlPerShareScaled = BigInt(dailyWhole + (dailyFrac || '').padEnd(decimals, '0').slice(0, decimals));
@@ -3520,6 +3509,10 @@ async function getVaultPnl({ vault, options, }) {
3520
3509
  const dayPnlRaw = (dailyPnlPerShareScaled * totalSharesScaled) / BigInt(10 ** decimals);
3521
3510
  totalPnlRaw += dayPnlRaw;
3522
3511
  });
3512
+ // No history (or no PnL in it) prices to zero, so skip the price read.
3513
+ if (totalPnlRaw === BigInt(0)) {
3514
+ return { totalPnl: (0, core_1.toNormalizedBn)(0, decimals), pnlUsd: 0 };
3515
+ }
3523
3516
  // Convert totalPnlRaw (BigInt) to normalized number using toNormalizedBn
3524
3517
  const totalPnl = (0, core_1.toNormalizedBn)(totalPnlRaw, decimals);
3525
3518
  const totalPnlNormalized = Number(totalPnl.normalized);
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;
@@ -29773,9 +29785,17 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
29773
29785
  export declare function verifyInfuraKey(key: string): Promise<boolean>;
29774
29786
 
29775
29787
  /**
29776
- * Convert a viem WalletClient to an ethers-compatible Signer
29777
- * Uses the walletClient as a provider and wraps it for ethers compatibility
29778
- * @param walletClient Viem WalletClient from wagmi or viem
29788
+ * Convert a viem WalletClient to an ethers-compatible Signer.
29789
+ *
29790
+ * The account and chain are answered from the client itself, and
29791
+ * transactions, personal messages and EIP-712 typed data are signed through
29792
+ * the client's own `sendTransaction` / `signMessage` / `signTypedData`, so a
29793
+ * local account (for example an embedded wallet built with
29794
+ * `createWalletClient({ account, transport: http() })`) signs locally and
29795
+ * broadcasts the raw transaction. Every other request goes to the client's
29796
+ * transport.
29797
+ *
29798
+ * @param walletClient - Viem WalletClient from wagmi or viem
29779
29799
  * @returns Ethers Signer that can be used with the SDK
29780
29800
  */
29781
29801
  export declare function viemToEthersSigner(walletClient: any): Promise<Signer | Wallet>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@augustdigital/sdk",
3
- "version": "9.13.0",
3
+ "version": "9.13.2",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/sdk.d.ts",
6
6
  "keywords": [