@augustdigital/sdk 8.19.0 → 8.20.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.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getManagementFeePercent = exports.getSymbol = exports.getReceiptTokenAddress = exports.getReceiptTokenAddressOrThrow = exports.getWhitelistedAssets = exports.getDecimalsOrThrow = exports.getDecimals = exports.explorerLink = exports.getInfuraProvider = exports.createProvider = exports.getChainId = exports.determineBlockSkipInternal = exports.determineSecondsPerBlock = exports.determineBlockCutoff = void 0;
3
+ exports.getManagementFeePercent = exports.getSymbol = exports.getReceiptTokenAddress = exports.getReceiptTokenAddressOrThrow = exports.getWhitelistedAssets = exports.getDecimalsOrThrow = exports.getDecimals = exports.explorerLink = exports.getInfuraProvider = exports.createProvider = exports.getChainId = exports.determineRpcBatchMaxCount = exports.determineBlockSkipInternal = exports.determineSecondsPerBlock = exports.determineBlockCutoff = void 0;
4
4
  exports.createContract = createContract;
5
5
  exports.getTokenMetadata = getTokenMetadata;
6
6
  exports.simulateTransaction = simulateTransaction;
@@ -87,10 +87,54 @@ const determineBlockSkipInternal = (chain) => {
87
87
  case 999: // HyperEVM — rpc.hypurrscan.io limits eth_getLogs to 1000 blocks
88
88
  return 1_000;
89
89
  default:
90
- return 50_000;
90
+ // 10k blocks is the eth_getLogs range cap enforced by every mainstream
91
+ // provider (Alchemy, Infura, dRPC, QuickNode). The previous 50k default
92
+ // was rejected outright with JSON-RPC -32600 ("You can make eth_getLogs
93
+ // requests with up to a 10000 block range") on Ethereum mainnet, which
94
+ // failed `getVaultRedemptionHistory` for every vault on an unlisted
95
+ // chain. RPC-count impact: a 150k-block cutoff now costs 15 getLogs
96
+ // calls instead of 3, batched 20-concurrent, so still one round trip.
97
+ return 10_000;
91
98
  }
92
99
  };
93
100
  exports.determineBlockSkipInternal = determineBlockSkipInternal;
101
+ /**
102
+ * Default batch cap. Chosen to stay under the smallest limit among the
103
+ * providers we route to by default (e.g. rpc.hypurrscan.io rejects > 20).
104
+ */
105
+ const DEFAULT_RPC_BATCH_MAX_COUNT = 10;
106
+ /**
107
+ * Maximum JSON-RPC calls ethers may coalesce into a single batched HTTP
108
+ * request for a given endpoint.
109
+ *
110
+ * Providers advertise wildly different batch limits and reject the whole batch
111
+ * — not the excess — when exceeded, so one oversized batch fails every call
112
+ * inside it. dRPC's free tier caps batches at 3, which made every Mezo read
113
+ * fail with `server response 500 … "Batch of more than 3 requests are not
114
+ * allowed"` (the single highest-volume SDK error in production).
115
+ *
116
+ * Detection is host-based rather than chain-based because the limit is a
117
+ * property of the endpoint, not the chain: the same chain served by a
118
+ * self-hosted node has no such cap.
119
+ *
120
+ * @param rpcUrl - The RPC endpoint URL. Unparseable values fall back to the
121
+ * conservative default rather than throwing.
122
+ * @returns Batch size cap to pass to ethers as `batchMaxCount`.
123
+ */
124
+ const determineRpcBatchMaxCount = (rpcUrl) => {
125
+ let host = '';
126
+ try {
127
+ host = new URL(rpcUrl).hostname.toLowerCase();
128
+ }
129
+ catch {
130
+ return DEFAULT_RPC_BATCH_MAX_COUNT;
131
+ }
132
+ // dRPC free tier: "Batch of more than 3 requests are not allowed".
133
+ if (host === 'drpc.org' || host.endsWith('.drpc.org'))
134
+ return 3;
135
+ return DEFAULT_RPC_BATCH_MAX_COUNT;
136
+ };
137
+ exports.determineRpcBatchMaxCount = determineRpcBatchMaxCount;
94
138
  /**
95
139
  * Retrieve chain ID from web3 provider.
96
140
  * Handles both initialized and uninitialized provider states.
@@ -152,14 +196,16 @@ const createProvider = (rpcUrl, chainId) => {
152
196
  const cacheKey = chainId ? `${rpcUrl}|${chainId}` : rpcUrl;
153
197
  if (cache_1.CACHE.has(cacheKey))
154
198
  return cache_1.CACHE.get(cacheKey);
155
- // batchMaxCount caps server-side batch limits (e.g. rpc.hypurrscan.io > 20).
199
+ // batchMaxCount respects server-side batch limits providers reject the
200
+ // entire batch when it is exceeded (see determineRpcBatchMaxCount).
201
+ const batchMaxCount = (0, exports.determineRpcBatchMaxCount)(rpcUrl);
156
202
  const provider = chainId
157
203
  ? new ethers_1.JsonRpcProvider(rpcUrl, ethers_1.Network.from(chainId), {
158
204
  staticNetwork: ethers_1.Network.from(chainId),
159
- batchMaxCount: 10,
205
+ batchMaxCount,
160
206
  })
161
207
  : new ethers_1.JsonRpcProvider(rpcUrl, undefined, {
162
- batchMaxCount: 10,
208
+ batchMaxCount,
163
209
  });
164
210
  cache_1.CACHE.set(cacheKey, provider);
165
211
  return provider;
@@ -15,6 +15,7 @@ export * from './helpers/web3';
15
15
  export * from './helpers/multicall';
16
16
  export * from './helpers/vaults';
17
17
  export * from './helpers/chain-error';
18
+ export * from './helpers/chain-support';
18
19
  export * from './helpers/core';
19
20
  export * from './helpers/adapters';
20
21
  export * from './helpers/signer';
package/lib/core/index.js CHANGED
@@ -31,6 +31,7 @@ __exportStar(require("./helpers/web3"), exports);
31
31
  __exportStar(require("./helpers/multicall"), exports);
32
32
  __exportStar(require("./helpers/vaults"), exports);
33
33
  __exportStar(require("./helpers/chain-error"), exports);
34
+ __exportStar(require("./helpers/chain-support"), exports);
34
35
  __exportStar(require("./helpers/core"), exports);
35
36
  __exportStar(require("./helpers/adapters"), exports);
36
37
  __exportStar(require("./helpers/signer"), exports);
@@ -352,6 +352,51 @@ async function getVaultSubaccountLoans(vault, options) {
352
352
  throw new Error(`#getVaultSubaccountLoans::${vault}:${e?.message}`);
353
353
  }
354
354
  }
355
+ /**
356
+ * HTTP statuses that mean "no such record for this subaccount", not "something
357
+ * broke". The backend returns 404 for a subaccount with no CeFi/OTC position,
358
+ * which is the normal case for most vault borrowers.
359
+ */
360
+ const EXPECTED_SUBACCOUNT_FETCH_STATUSES = new Set([204, 404]);
361
+ /**
362
+ * Log a per-subaccount enrichment fetch failure at the right severity.
363
+ *
364
+ * Why: `getVaultAllocations` issues one CeFi and one OTC request per borrower
365
+ * on every call. Logging the "no record" responses at `error` level captured
366
+ * them as Sentry issues, producing thousands of `AugustServerError: Request
367
+ * failed: 404` events a day for a condition that is not a fault and that
368
+ * callers never need to act on. Expected statuses become breadcrumbs; genuine
369
+ * failures (5xx, auth, transport) stay at `error`.
370
+ *
371
+ * @param tag - Call-site tag, e.g. `getVaultAllocations:cefi`. Becomes the
372
+ * `sdk.origin` Sentry tag for grouping.
373
+ * @param status - HTTP status, or `undefined` when the failure was a thrown
374
+ * transport/typed error with no status attached.
375
+ * @param detail - Status text or error to attach as context.
376
+ * @param context - Identifiers scoping the failure (`vault`, `borrower`).
377
+ */
378
+ function logSubaccountFetchFailure(tag, status, detail, context) {
379
+ if (status !== undefined && EXPECTED_SUBACCOUNT_FETCH_STATUSES.has(status)) {
380
+ core_1.Logger.log.warn(tag, { ...context, status, reason: 'no record' });
381
+ return;
382
+ }
383
+ core_1.Logger.log.error(tag, detail, { ...context, status });
384
+ }
385
+ /**
386
+ * Extract the HTTP status from a thrown fetch error, when it carries one.
387
+ *
388
+ * `fetchAugustWithKey` throws `AugustServerError`/`AugustAuthError` for non-2xx
389
+ * responses, so the status-code branch in the callers is unreachable for those
390
+ * — the status has to be recovered from the error to classify it.
391
+ *
392
+ * @param error - Any thrown value.
393
+ * @returns The HTTP status, or `undefined` for errors without one (network
394
+ * failures, aborts, programming errors).
395
+ */
396
+ function httpStatusFromError(error) {
397
+ const status = error?.status;
398
+ return typeof status === 'number' ? status : undefined;
399
+ }
355
400
  /**
356
401
  * Vault Allocations
357
402
  */
@@ -485,22 +530,26 @@ async function getVaultAllocations(vault, options) {
485
530
  }
486
531
  }
487
532
  else {
488
- core_1.Logger.log.error(`getVaultAllocations:no_fetcher`, new Error(`No portfolio fetcher for chain type: ${chainType}`), {
533
+ // Not an error: portfolio providers simply have no coverage for this
534
+ // chain type yet (Stellar, Sui). Reporting it as an exception filled
535
+ // Sentry with a known, permanent gap, and setting `debankErr` made
536
+ // every Stellar vault throw `failure to fetch debank response`
537
+ // instead of returning the CeFi/OTC/loan allocations it did resolve.
538
+ core_1.Logger.log.warn(`getVaultAllocations:no_fetcher`, {
489
539
  vault,
490
540
  borrower,
491
541
  chainType,
542
+ reason: `No portfolio fetcher for chain type: ${chainType}`,
492
543
  });
493
- debankErr = true;
494
544
  }
495
545
  }
496
546
  // fetch cefi_positions
497
547
  try {
498
548
  const cefiResponse = await (0, core_1.fetchAugustWithKey)(options.augustKey, core_1.WEBSERVER_ENDPOINTS.subaccount.cefi(borrower), { headers: options?.headers });
499
549
  if (cefiResponse.status !== 200) {
500
- core_1.Logger.log.error('getVaultAllocations:cefi', cefiResponse.statusText, {
501
- borrower,
502
- status: cefiResponse.status,
503
- });
550
+ // 404 means "this subaccount has no CeFi position", which is the
551
+ // common case for most borrowers — a breadcrumb, not an exception.
552
+ logSubaccountFetchFailure('getVaultAllocations:cefi', cefiResponse.status, cefiResponse.statusText, { vault, borrower });
504
553
  }
505
554
  if (cefiResponse.status === 200) {
506
555
  const cefiRes = (await cefiResponse.json());
@@ -508,16 +557,15 @@ async function getVaultAllocations(vault, options) {
508
557
  }
509
558
  }
510
559
  catch (e) {
511
- core_1.Logger.log.error('getVaultAllocations:cefi', e, { borrower });
560
+ logSubaccountFetchFailure('getVaultAllocations:cefi', httpStatusFromError(e), e, { vault, borrower });
512
561
  }
513
562
  // fetch otc_positions
514
563
  try {
515
564
  const otcResponse = await (0, core_1.fetchAugustWithKey)(options.augustKey, core_1.WEBSERVER_ENDPOINTS.subaccount.otc_positions(borrower), { headers: options?.headers });
516
565
  if (otcResponse.status !== 200) {
517
- core_1.Logger.log.error('getVaultAllocations:otc', otcResponse.statusText, {
518
- borrower,
519
- status: otcResponse.status,
520
- });
566
+ // 404 means "this subaccount has no OTC positions" — expected for
567
+ // nearly every borrower. See logSubaccountFetchFailure.
568
+ logSubaccountFetchFailure('getVaultAllocations:otc', otcResponse.status, otcResponse.statusText, { vault, borrower });
521
569
  }
522
570
  if (otcResponse.status === 200) {
523
571
  const otcRes = (await otcResponse.json());
@@ -525,7 +573,7 @@ async function getVaultAllocations(vault, options) {
525
573
  }
526
574
  }
527
575
  catch (e) {
528
- core_1.Logger.log.error('getVaultAllocations:otc', e, { borrower });
576
+ logSubaccountFetchFailure('getVaultAllocations:otc', httpStatusFromError(e), e, { vault, borrower });
529
577
  }
530
578
  }
531
579
  }
@@ -552,6 +600,34 @@ async function getVaultAllocations(vault, options) {
552
600
  unfilteredTokens: unfilteredTokens,
553
601
  };
554
602
  }
603
+ /**
604
+ * Coerce a subgraph numeric field to `bigint`, treating absent fields as zero.
605
+ *
606
+ * Why: the evm-1 and evm-2 subgraphs expose different field names on
607
+ * `WithdrawalRequested` — evm-1 emits `assets` plus explicit `year`/`month`/
608
+ * `day`, evm-2 emits `shares` and a raw `timestamp_`. Reading the wrong one
609
+ * yields `undefined`, and bare `BigInt(undefined)` throws
610
+ * `TypeError: Cannot convert undefined to a BigInt`, which aborted the whole
611
+ * redemption scan and returned an empty list to the caller (the second
612
+ * highest-volume SDK error in production).
613
+ *
614
+ * `BigInt(x) || BigInt(0)` does **not** protect against this — the throw
615
+ * happens before `||` is ever evaluated.
616
+ *
617
+ * @param value - Subgraph field: decimal string, number, bigint, `null`, or
618
+ * `undefined`.
619
+ * @returns The value as `bigint`, or `0n` when absent or non-numeric.
620
+ */
621
+ function subgraphAmountToBigInt(value) {
622
+ if (value === undefined || value === null || value === '')
623
+ return BigInt(0);
624
+ try {
625
+ return BigInt(value);
626
+ }
627
+ catch {
628
+ return BigInt(0);
629
+ }
630
+ }
555
631
  async function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }) {
556
632
  try {
557
633
  // Stellar vaults don't support on-chain redemptions yet
@@ -669,9 +745,12 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
669
745
  const redKey = (0, date_utils_1.formatDateKey)(redDate.getUTCFullYear(), redDate.getUTCMonth() + 1, redDate.getUTCDate());
670
746
  return redKey === requestDateKey;
671
747
  })
672
- : availableRedemptions.find((red) => BigInt(red.day.raw) === BigInt(ev.day) &&
673
- BigInt(red.month.raw) === BigInt(ev.month) &&
674
- BigInt(red.year.raw) === BigInt(ev.year));
748
+ : availableRedemptions.find((red) => subgraphAmountToBigInt(red.day.raw) ===
749
+ subgraphAmountToBigInt(ev.day) &&
750
+ subgraphAmountToBigInt(red.month.raw) ===
751
+ subgraphAmountToBigInt(ev.month) &&
752
+ subgraphAmountToBigInt(red.year.raw) ===
753
+ subgraphAmountToBigInt(ev.year));
675
754
  if (!(foundRedemptionAgainstClaim && alreadyRedeemed)) {
676
755
  // double check if user has already claimed
677
756
  try {
@@ -692,7 +771,7 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
692
771
  // Has passed lag duration - check if claim is not settled before adding to pending
693
772
  try {
694
773
  const burnableAmount = (await vaultContract?.getBurnableAmountByReceiver?.(BigInt(year), BigInt(month), BigInt(day), (0, ethers_1.getAddress)(ev.receiverAddr))) || BigInt(0);
695
- const claimAmount = BigInt(ev.shares) || BigInt(0);
774
+ const claimAmount = subgraphAmountToBigInt(ev.shares);
696
775
  // If burnableAmount >= claimAmount, claim hasn't been settled by processAllClaims
697
776
  // Only add to pending if it's still unsettled
698
777
  if (burnableAmount >= claimAmount) {
@@ -704,7 +783,7 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
704
783
  day: (0, core_1.toNormalizedBn)(day, 0),
705
784
  month: (0, core_1.toNormalizedBn)(month, 0),
706
785
  year: (0, core_1.toNormalizedBn)(year, 0),
707
- amount: (0, core_1.toNormalizedBn)(BigInt(ev.shares) || BigInt(0), decimals),
786
+ amount: (0, core_1.toNormalizedBn)(subgraphAmountToBigInt(ev.shares), decimals),
708
787
  date: fullDate,
709
788
  vault,
710
789
  status: types_1.VaultRedemptionStatus.READY_TO_CLAIM,
@@ -726,7 +805,7 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
726
805
  day: (0, core_1.toNormalizedBn)(day, 0),
727
806
  month: (0, core_1.toNormalizedBn)(month, 0),
728
807
  year: (0, core_1.toNormalizedBn)(year, 0),
729
- amount: (0, core_1.toNormalizedBn)(BigInt(ev.shares), decimals),
808
+ amount: (0, core_1.toNormalizedBn)(subgraphAmountToBigInt(ev.shares), decimals),
730
809
  date: fullDate,
731
810
  vault,
732
811
  status: types_1.VaultRedemptionStatus.AWAITING_COOLDOWN,
@@ -736,7 +815,12 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
736
815
  break;
737
816
  }
738
817
  default: {
739
- const trueClaimableAmount = await vaultContract?.getClaimableAmountByReceiver?.(BigInt(ev.year), BigInt(ev.month), BigInt(ev.day), (0, ethers_1.getAddress)(wallet));
818
+ // Safe to read the raw subgraph dates here: the validation
819
+ // block above `continue`s for any non-evm-2 event missing
820
+ // `year`/`month`/`day`, so this path is only reached with all
821
+ // three present. The coercion below therefore never
822
+ // substitutes 0 for a real date.
823
+ const trueClaimableAmount = await vaultContract?.getClaimableAmountByReceiver?.(subgraphAmountToBigInt(ev.year), subgraphAmountToBigInt(ev.month), subgraphAmountToBigInt(ev.day), (0, ethers_1.getAddress)(wallet));
740
824
  if (trueClaimableAmount > BigInt(0)) {
741
825
  // Use computeClaimableDate for UTC-correct date with lag
742
826
  const v1Claimable = (0, date_utils_1.computeClaimableDate)(Number(ev.timestamp_), lagDuration);
@@ -809,7 +893,7 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
809
893
  day: (0, core_1.toNormalizedBn)(ev.day, 0),
810
894
  month: (0, core_1.toNormalizedBn)(ev.month, 0),
811
895
  year: (0, core_1.toNormalizedBn)(ev.year, 0),
812
- amount: (0, core_1.toNormalizedBn)(BigInt(ev.assets) || BigInt(0), decimals),
896
+ amount: (0, core_1.toNormalizedBn)(subgraphAmountToBigInt(ev.assets), decimals),
813
897
  date: fullDate,
814
898
  vault,
815
899
  status: types_1.VaultRedemptionStatus.AWAITING_COOLDOWN,
@@ -910,7 +994,11 @@ async function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, option
910
994
  const firstMessage = firstReason instanceof Error
911
995
  ? firstReason.message
912
996
  : String(firstReason);
913
- core_1.Logger.log.error('getVaultRedemptionHistory', 'log fetch chunk(s) failed', {
997
+ // Breadcrumb only the throw below is caught and logged by this
998
+ // function's own catch block, so capturing here duplicated every
999
+ // failure into a second Sentry issue ("log fetch chunk(s) failed").
1000
+ core_1.Logger.log.warn('getVaultRedemptionHistory', {
1001
+ reason: 'log fetch chunk(s) failed',
914
1002
  failedChunks: failed.length,
915
1003
  totalChunks: batch.length,
916
1004
  firstReason: firstMessage,
@@ -107,6 +107,9 @@ export declare class AugustVaults extends AugustBase {
107
107
  * @param chainId Optional chain ID (uses active network if not provided)
108
108
  * @param options Enrichment and wallet options
109
109
  * @returns Single vault object with optional position data
110
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
111
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
112
+ * URL configured on this SDK instance.
110
113
  */
111
114
  getVault({ vault, chainId, options, loadSubaccounts, loadSnapshots, }: {
112
115
  vault: IAddress;
@@ -116,21 +119,39 @@ export declare class AugustVaults extends AugustBase {
116
119
  loadSnapshots?: boolean;
117
120
  }): Promise<import("../../types").IVault>;
118
121
  /**
119
- *
122
+ * Fetch the active loans issued by a vault.
123
+ * @param vault Vault contract address
124
+ * @param chainId Optional chain ID (uses active network if not provided)
125
+ * @returns Loan data for the vault
126
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
127
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
128
+ * URL configured on this SDK instance.
120
129
  */
121
130
  getVaultLoans({ vault, chainId, }: {
122
131
  vault: IAddress;
123
132
  chainId?: IChainId;
124
133
  }): Promise<import("../../types").IVaultLoan[]>;
125
134
  /**
126
- *
135
+ * Fetch a vault's loans broken down by sub-account.
136
+ * @param vault Vault contract address
137
+ * @param chainId Optional chain ID (uses active network if not provided)
138
+ * @returns Sub-account loan data for the vault
139
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
140
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
141
+ * URL configured on this SDK instance.
127
142
  */
128
143
  getVaultSubaccountLoans({ vault, chainId, }: {
129
144
  vault: IAddress;
130
145
  chainId?: IChainId;
131
146
  }): Promise<import("../../types").IVaultLoan[]>;
132
147
  /**
133
- *
148
+ * Fetch a vault's DeFi / CeFi / OTC allocation breakdown.
149
+ * @param vault Vault contract address
150
+ * @param chainId Optional chain ID (uses active network if not provided)
151
+ * @returns Allocation data for the vault
152
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
153
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
154
+ * URL configured on this SDK instance.
134
155
  */
135
156
  getVaultAllocations({ vault, chainId, }: {
136
157
  vault: IAddress;
@@ -326,6 +326,9 @@ class AugustVaults extends core_1.AugustBase {
326
326
  * @param chainId Optional chain ID (uses active network if not provided)
327
327
  * @param options Enrichment and wallet options
328
328
  * @returns Single vault object with optional position data
329
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
330
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
331
+ * URL configured on this SDK instance.
329
332
  */
330
333
  async getVault({ vault, chainId, options, loadSubaccounts, loadSnapshots, }) {
331
334
  if (!vault)
@@ -334,12 +337,8 @@ class AugustVaults extends core_1.AugustBase {
334
337
  // throw new Error(
335
338
  // `Vault input parameter is not an address: ${String(vault)}`,
336
339
  // );
337
- if (typeof chainId !== 'undefined') {
338
- if (!this.providers?.[chainId]) {
339
- const error = new Error(`Missing RPC URL for chainId ${chainId}`);
340
- core_1.Logger.log.error('getVault:missing_provider', error, { chainId });
341
- }
342
- }
340
+ (0, core_1.assertKnownChainId)(chainId, this.providers, 'getVault');
341
+ (0, core_1.assertEvmProviderConfigured)(chainId, this.providers, 'getVault');
343
342
  // get vault data
344
343
  const vaultResponse = await (0, getters_1.getVault)({
345
344
  vault: vault,
@@ -398,7 +397,13 @@ class AugustVaults extends core_1.AugustBase {
398
397
  return vaultResponse;
399
398
  }
400
399
  /**
401
- *
400
+ * Fetch the active loans issued by a vault.
401
+ * @param vault Vault contract address
402
+ * @param chainId Optional chain ID (uses active network if not provided)
403
+ * @returns Loan data for the vault
404
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
405
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
406
+ * URL configured on this SDK instance.
402
407
  */
403
408
  async getVaultLoans({ vault, chainId, }) {
404
409
  // Sanitize
@@ -407,12 +412,8 @@ class AugustVaults extends core_1.AugustBase {
407
412
  throw new Error('Vault input parameter is undefined.');
408
413
  if (!(0, ethers_1.isAddress)(vault))
409
414
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
410
- if (typeof chainId !== 'undefined') {
411
- if (!this.providers?.[chainId]) {
412
- const error = new Error(`Missing RPC URL for chainId ${chainId}`);
413
- core_1.Logger.log.error('getVaultLoans:missing_provider', error, { chainId });
414
- }
415
- }
415
+ (0, core_1.assertKnownChainId)(chainId, this.providers, 'getVaultLoans');
416
+ (0, core_1.assertEvmProviderConfigured)(chainId, this.providers, 'getVaultLoans');
416
417
  // get vault loans data
417
418
  const vaultResponse = await (0, getters_1.getVaultLoans)(vault, {
418
419
  rpcUrl: chainId
@@ -429,7 +430,13 @@ class AugustVaults extends core_1.AugustBase {
429
430
  return vaultResponse;
430
431
  }
431
432
  /**
432
- *
433
+ * Fetch a vault's loans broken down by sub-account.
434
+ * @param vault Vault contract address
435
+ * @param chainId Optional chain ID (uses active network if not provided)
436
+ * @returns Sub-account loan data for the vault
437
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
438
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
439
+ * URL configured on this SDK instance.
433
440
  */
434
441
  async getVaultSubaccountLoans({ vault, chainId, }) {
435
442
  // Sanitize
@@ -437,14 +444,8 @@ class AugustVaults extends core_1.AugustBase {
437
444
  throw new Error('Vault input parameter is undefined.');
438
445
  if (!(0, ethers_1.isAddress)(vault))
439
446
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
440
- if (typeof chainId !== 'undefined') {
441
- if (!this.providers?.[chainId]) {
442
- const error = new Error(`Missing RPC URL for chainId ${chainId}`);
443
- core_1.Logger.log.error('getVaultSubaccountLoans:missing_provider', error, {
444
- chainId,
445
- });
446
- }
447
- }
447
+ (0, core_1.assertKnownChainId)(chainId, this.providers, 'getVaultSubaccountLoans');
448
+ (0, core_1.assertEvmProviderConfigured)(chainId, this.providers, 'getVaultSubaccountLoans');
448
449
  // get vault subaccount loans data
449
450
  const vaultResponse = await (0, getters_1.getVaultSubaccountLoans)(vault, {
450
451
  rpcUrl: chainId
@@ -461,7 +462,13 @@ class AugustVaults extends core_1.AugustBase {
461
462
  return vaultResponse;
462
463
  }
463
464
  /**
464
- *
465
+ * Fetch a vault's DeFi / CeFi / OTC allocation breakdown.
466
+ * @param vault Vault contract address
467
+ * @param chainId Optional chain ID (uses active network if not provided)
468
+ * @returns Allocation data for the vault
469
+ * @throws {@link AugustValidationError} (`INVALID_CHAIN`) when `chainId` is
470
+ * not a chain the SDK recognises, or is a supported EVM chain with no RPC
471
+ * URL configured on this SDK instance.
465
472
  */
466
473
  async getVaultAllocations({ vault, chainId, }) {
467
474
  // Sanitize
@@ -472,14 +479,8 @@ class AugustVaults extends core_1.AugustBase {
472
479
  !utils_1.SolanaUtils.isSolanaAddress(vault) &&
473
480
  !(0, utils_2.isStellarAddress)(vault))
474
481
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
475
- if (typeof chainId !== 'undefined') {
476
- if (!this.providers?.[chainId]) {
477
- const error = new Error(`Missing RPC URL for chainId ${chainId}`);
478
- core_1.Logger.log.error('getVaultAllocations:missing_provider', error, {
479
- chainId,
480
- });
481
- }
482
- }
482
+ (0, core_1.assertKnownChainId)(chainId, this.providers, 'getVaultAllocations');
483
+ (0, core_1.assertEvmProviderConfigured)(chainId, this.providers, 'getVaultAllocations');
483
484
  // get vault allocations data
484
485
  try {
485
486
  const vaultResponse = await (0, getters_1.getVaultAllocations)(vault, {