@augustdigital/sdk 8.11.0 → 8.13.0

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,5 +1,5 @@
1
1
  import { type IContractWriteOptions, type INativeDepositOptions, type ApproveResult } from '../../modules/vaults/write.actions';
2
- import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions, ISwapRouterDepositOptions } from '../../types';
2
+ import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions, ISwapRouterDepositOptions, ISwapRouterDepositResultOptions } from '../../types';
3
3
  import { type IPreviewDepositOptions, type IPreviewRedeemOptions, type IAllowanceOptions, type IBalanceOfOptions, type IMaxDepositOptions } from '../../modules/vaults/read.actions';
4
4
  import { type CompatibleSigner } from '../../core/helpers/signer';
5
5
  import type { IAddress } from '../../types';
@@ -214,6 +214,22 @@ declare class EVMAdapter {
214
214
  * ```
215
215
  */
216
216
  swapRouterDeposit(options: ISwapRouterDepositOptions): Promise<string>;
217
+ /**
218
+ * Resolves the real, post-execution outcome of a SwapRouter deposit from
219
+ * its mined receipt — the actual amount that reached the vault (and shares
220
+ * minted), decoded from the vault's own `Deposit` event, rather than the
221
+ * pre-trade quote shown before submission.
222
+ *
223
+ * @param options - {@link ISwapRouterDepositResultOptions}.
224
+ * @returns The decoded {@link ISwapRouterDepositResult}, or `null` if the
225
+ * receipt isn't found yet or carries no matching `Deposit` log.
226
+ * @example
227
+ * ```ts
228
+ * const hash = await augustSdk.evm.swapRouterDeposit({ ... });
229
+ * const result = await augustSdk.evm.getSwapRouterDepositResult({ txHash: hash, vault });
230
+ * ```
231
+ */
232
+ getSwapRouterDepositResult(options: ISwapRouterDepositResultOptions): Promise<import("../../types").ISwapRouterDepositResult>;
217
233
  /**
218
234
  * Claim assets from a matured redemption request on a dated-redemption
219
235
  * (RWA-style) vault. The `year`, `month`, `day`, and `receiverIndex` tuple
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  const write_actions_1 = require("../../modules/vaults/write.actions");
18
+ const swap_router_1 = require("../../core/helpers/swap-router");
18
19
  const read_actions_1 = require("../../modules/vaults/read.actions");
19
20
  const signer_1 = require("../../core/helpers/signer");
20
21
  __exportStar(require("./getters"), exports);
@@ -277,6 +278,25 @@ class EVMAdapter {
277
278
  const signer = await this.getSigner();
278
279
  return (0, write_actions_1.swapRouterDeposit)(signer, options);
279
280
  }
281
+ /**
282
+ * Resolves the real, post-execution outcome of a SwapRouter deposit from
283
+ * its mined receipt — the actual amount that reached the vault (and shares
284
+ * minted), decoded from the vault's own `Deposit` event, rather than the
285
+ * pre-trade quote shown before submission.
286
+ *
287
+ * @param options - {@link ISwapRouterDepositResultOptions}.
288
+ * @returns The decoded {@link ISwapRouterDepositResult}, or `null` if the
289
+ * receipt isn't found yet or carries no matching `Deposit` log.
290
+ * @example
291
+ * ```ts
292
+ * const hash = await augustSdk.evm.swapRouterDeposit({ ... });
293
+ * const result = await augustSdk.evm.getSwapRouterDepositResult({ txHash: hash, vault });
294
+ * ```
295
+ */
296
+ async getSwapRouterDepositResult(options) {
297
+ const signer = await this.getSigner();
298
+ return (0, swap_router_1.getSwapRouterDepositResult)(signer, options);
299
+ }
280
300
  /**
281
301
  * Claim assets from a matured redemption request on a dated-redemption
282
302
  * (RWA-style) vault. The `year`, `month`, `day`, and `receiverIndex` tuple
@@ -39,6 +39,9 @@ exports.METHOD_CATEGORIES = {
39
39
  getVaultBorrowerHealthFactor: 'read.vault',
40
40
  getYieldLastRealizedOn: 'read.vault',
41
41
  getVaultActivity: 'read.vault',
42
+ getSwapRouterDepositResult: 'read.vault',
43
+ getSwapRouterWhitelistedTokens: 'read.vault',
44
+ getSwapRouterEligibleVaults: 'read.vault',
42
45
  getVaultPositions: 'read.position',
43
46
  getVaultUserHistory: 'read.position',
44
47
  getUserHistory: 'read.position',
@@ -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.11.0";
6
+ export declare const SDK_VERSION = "8.13.0";
@@ -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.11.0';
9
+ exports.SDK_VERSION = '8.13.0';
10
10
  //# sourceMappingURL=version.js.map
@@ -8,6 +8,20 @@ import type { IAddress } from '../../types';
8
8
  * @see {@link getSwapRouterAddress} for the typed lookup helper.
9
9
  */
10
10
  export declare const SWAP_ROUTER_ADDRESSES: Readonly<Record<number, IAddress>>;
11
+ /**
12
+ * Human-readable display name of the `SwapRouter` periphery contract on each
13
+ * supported chain.
14
+ *
15
+ * The contract exposes no on-chain name (no `@title` accessor), so UIs that
16
+ * want to show *which contract* performed the swap-and-deposit — rather than a
17
+ * bare address — read it from here. Display metadata only: never derive
18
+ * routing or eligibility logic from it.
19
+ *
20
+ * Missing keys mean no SwapRouter is deployed on that chain.
21
+ *
22
+ * @see {@link getSwapRouterName} for the typed lookup helper.
23
+ */
24
+ export declare const SWAP_ROUTER_NAMES: Readonly<Record<number, string>>;
11
25
  /**
12
26
  * Vaults whose UI **may offer the any-token SwapRouter deposit surface** —
13
27
  * i.e. the SwapRouter is `enableVault`-ed for them on-chain.
@@ -31,15 +45,41 @@ export declare const SWAP_ROUTER_ADDRESSES: Readonly<Record<number, IAddress>>;
31
45
  *
32
46
  * Lowercase comparison is required when checking — use
33
47
  * {@link isSwapRouterEligible} rather than reading this set directly.
48
+ *
49
+ * @deprecated Superseded by {@link getSwapRouterEligibleVaults}, which derives
50
+ * the eligible set from the router's on-chain `VaultEnabled` history and
51
+ * verifies each vault's current registration (`vaultInfo.referenceAsset != 0`)
52
+ * — so new enablements surface without an SDK release. This static set stays
53
+ * functional as the zero-RPC fallback seed (e.g. TanStack Query `initialData`)
54
+ * and for SDK-internal sync consumers.
34
55
  */
35
56
  export declare const SWAP_ROUTER_ELIGIBLE_VAULTS: ReadonlySet<string>;
36
57
  /**
37
- * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS}, and the semantics
38
- * changed: this set no longer drives `vaultDeposit` auto-routing (that branch
39
- * was removed) it now only marks vaults whose UI may offer the swap-router
40
- * deposit surface. Kept as an alias for one release; migrate to the new name.
58
+ * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS} (itself now
59
+ * superseded by {@link getSwapRouterEligibleVaults}, the on-chain-derived
60
+ * resolver), and the semantics changed: this set no longer drives
61
+ * `vaultDeposit` auto-routing (that branch was removed) it only marks vaults
62
+ * whose UI may offer the swap-router deposit surface. Kept as an alias for one
63
+ * release; migrate to the async resolver.
41
64
  */
42
65
  export declare const VAULTS_USING_SWAP_ROUTER: ReadonlySet<string>;
66
+ /**
67
+ * Block at which each chain's `SwapRouter` was deployed/configured — the safe
68
+ * lower bound for scanning its `TokenEnabled` / `VaultEnabled` log history.
69
+ *
70
+ * The router stores its allowlist as `mapping(address => bool) whitelistedTokens`
71
+ * with no on-chain enumeration, so {@link getSwapRouterWhitelistedTokens} must
72
+ * reconstruct the candidate set from `TokenEnabled` events before verifying each
73
+ * against the current mapping. Starting the `eth_getLogs` scan here (rather than
74
+ * from genesis) bounds it to the router's own lifetime — a few chunks — instead
75
+ * of the whole chain.
76
+ *
77
+ * Mainnet value is the router's deployment block (its first emitted event, the
78
+ * constructor `OwnershipTransferred`). A too-low value only costs extra empty
79
+ * log ranges; a value ABOVE the first `TokenEnabled` would silently miss tokens,
80
+ * so err on the side of earlier.
81
+ */
82
+ export declare const SWAP_ROUTER_DEPLOY_BLOCKS: Readonly<Record<number, number>>;
43
83
  /**
44
84
  * 32-byte origin codes registered on the `SwapRouter` via `addOrigin`.
45
85
  * Drives origin/referral-fee accrual. The on-chain admin must register a
@@ -105,4 +145,6 @@ export declare const SWAP_ROUTER_DEX_AGGREGATOR: Readonly<Record<number, {
105
145
  router: IAddress;
106
146
  contractMethod: string;
107
147
  selector: `0x${string}`;
148
+ /** Human-readable aggregator name — for display; never derive routing logic from it. */
149
+ name: string;
108
150
  }>>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SWAP_ROUTER_DEX_AGGREGATOR = exports.SWAP_ROUTER_WRAPPED_NATIVE = exports.SWAP_ROUTER_MAX_SWAPS = exports.ORIGIN_CODES = exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ELIGIBLE_VAULTS = exports.SWAP_ROUTER_ADDRESSES = void 0;
3
+ exports.SWAP_ROUTER_DEX_AGGREGATOR = exports.SWAP_ROUTER_WRAPPED_NATIVE = exports.SWAP_ROUTER_MAX_SWAPS = exports.ORIGIN_CODES = exports.SWAP_ROUTER_DEPLOY_BLOCKS = exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ELIGIBLE_VAULTS = exports.SWAP_ROUTER_NAMES = exports.SWAP_ROUTER_ADDRESSES = void 0;
4
4
  /**
5
5
  * Address of the `SwapRouter` periphery contract on each supported chain.
6
6
  *
@@ -12,6 +12,22 @@ exports.SWAP_ROUTER_DEX_AGGREGATOR = exports.SWAP_ROUTER_WRAPPED_NATIVE = export
12
12
  exports.SWAP_ROUTER_ADDRESSES = {
13
13
  1: '0xAC771209FF2b71EECfF6E85a9AD01db8Ff2618B0',
14
14
  };
15
+ /**
16
+ * Human-readable display name of the `SwapRouter` periphery contract on each
17
+ * supported chain.
18
+ *
19
+ * The contract exposes no on-chain name (no `@title` accessor), so UIs that
20
+ * want to show *which contract* performed the swap-and-deposit — rather than a
21
+ * bare address — read it from here. Display metadata only: never derive
22
+ * routing or eligibility logic from it.
23
+ *
24
+ * Missing keys mean no SwapRouter is deployed on that chain.
25
+ *
26
+ * @see {@link getSwapRouterName} for the typed lookup helper.
27
+ */
28
+ exports.SWAP_ROUTER_NAMES = {
29
+ 1: 'Upshift Swap Router',
30
+ };
15
31
  /**
16
32
  * Vaults whose UI **may offer the any-token SwapRouter deposit surface** —
17
33
  * i.e. the SwapRouter is `enableVault`-ed for them on-chain.
@@ -35,6 +51,13 @@ exports.SWAP_ROUTER_ADDRESSES = {
35
51
  *
36
52
  * Lowercase comparison is required when checking — use
37
53
  * {@link isSwapRouterEligible} rather than reading this set directly.
54
+ *
55
+ * @deprecated Superseded by {@link getSwapRouterEligibleVaults}, which derives
56
+ * the eligible set from the router's on-chain `VaultEnabled` history and
57
+ * verifies each vault's current registration (`vaultInfo.referenceAsset != 0`)
58
+ * — so new enablements surface without an SDK release. This static set stays
59
+ * functional as the zero-RPC fallback seed (e.g. TanStack Query `initialData`)
60
+ * and for SDK-internal sync consumers.
38
61
  */
39
62
  exports.SWAP_ROUTER_ELIGIBLE_VAULTS = new Set([
40
63
  // Sentora USD — native multi-asset Tokenized Vault V2 (reference asset
@@ -43,12 +66,33 @@ exports.SWAP_ROUTER_ELIGIBLE_VAULTS = new Set([
43
66
  '0x74ad2f789ed583dbd141bbdafc673fe1f033718b',
44
67
  ]);
45
68
  /**
46
- * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS}, and the semantics
47
- * changed: this set no longer drives `vaultDeposit` auto-routing (that branch
48
- * was removed) it now only marks vaults whose UI may offer the swap-router
49
- * deposit surface. Kept as an alias for one release; migrate to the new name.
69
+ * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS} (itself now
70
+ * superseded by {@link getSwapRouterEligibleVaults}, the on-chain-derived
71
+ * resolver), and the semantics changed: this set no longer drives
72
+ * `vaultDeposit` auto-routing (that branch was removed) it only marks vaults
73
+ * whose UI may offer the swap-router deposit surface. Kept as an alias for one
74
+ * release; migrate to the async resolver.
50
75
  */
51
76
  exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ELIGIBLE_VAULTS;
77
+ /**
78
+ * Block at which each chain's `SwapRouter` was deployed/configured — the safe
79
+ * lower bound for scanning its `TokenEnabled` / `VaultEnabled` log history.
80
+ *
81
+ * The router stores its allowlist as `mapping(address => bool) whitelistedTokens`
82
+ * with no on-chain enumeration, so {@link getSwapRouterWhitelistedTokens} must
83
+ * reconstruct the candidate set from `TokenEnabled` events before verifying each
84
+ * against the current mapping. Starting the `eth_getLogs` scan here (rather than
85
+ * from genesis) bounds it to the router's own lifetime — a few chunks — instead
86
+ * of the whole chain.
87
+ *
88
+ * Mainnet value is the router's deployment block (its first emitted event, the
89
+ * constructor `OwnershipTransferred`). A too-low value only costs extra empty
90
+ * log ranges; a value ABOVE the first `TokenEnabled` would silently miss tokens,
91
+ * so err on the side of earlier.
92
+ */
93
+ exports.SWAP_ROUTER_DEPLOY_BLOCKS = {
94
+ 1: 25237804,
95
+ };
52
96
  /**
53
97
  * 32-byte origin codes registered on the `SwapRouter` via `addOrigin`.
54
98
  * Drives origin/referral-fee accrual. The on-chain admin must register a
@@ -119,6 +163,7 @@ exports.SWAP_ROUTER_DEX_AGGREGATOR = {
119
163
  router: '0x6A000F20005980200259B80c5102003040001068',
120
164
  contractMethod: 'swapExactAmountIn',
121
165
  selector: '0xe3ead59e',
166
+ name: 'ParaSwap',
122
167
  },
123
168
  };
124
169
  //# sourceMappingURL=swap-router.js.map
@@ -47,6 +47,25 @@ export declare const ORACLE_CONTRACTS: {
47
47
  };
48
48
  export declare const NETWORKS: Record<IChainId, IChainObj>;
49
49
  export declare const AVAILABLE_CHAINS: IChainId[];
50
+ /**
51
+ * Canonical [Multicall3](https://github.com/mds1/multicall) address, deployed
52
+ * via the deterministic deployer to the same address on most EVM chains.
53
+ * @internal
54
+ */
55
+ export declare const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11";
56
+ /**
57
+ * Chains where the canonical Multicall3 deployment was **verified on-chain**
58
+ * (`eth_getCode` returned the 3808-byte runtime at {@link MULTICALL3_ADDRESS};
59
+ * checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15) —
60
+ * deterministic-deployer presence is NOT assumed. Chains outside this set
61
+ * keep the per-call read path.
62
+ *
63
+ * Deliberately excluded from `NETWORKS`:
64
+ * - 4114 (Citrea) — `eth_getCode` returned `0x` (not deployed).
65
+ * - -1 (Solana), -3 (Stellar) — non-EVM, no Multicall3.
66
+ * @internal
67
+ */
68
+ export declare const MULTICALL3_VERIFIED_CHAINS: ReadonlySet<number>;
50
69
  /**
51
70
  * Fallbacks
52
71
  */
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FALLBACK_RPC_URLS = exports.FALLBACK_CHAINID = exports.FALLBACK_DECIMALS = exports.AVAILABLE_CHAINS = exports.NETWORKS = exports.ORACLE_CONTRACTS = exports.MIN_ABIS = exports.EVM_NATIVE_DECIMALS = exports.NATIVE_ADDRESS = exports.SPECIAL_CHAINS = void 0;
3
+ exports.FALLBACK_RPC_URLS = exports.FALLBACK_CHAINID = exports.FALLBACK_DECIMALS = exports.MULTICALL3_VERIFIED_CHAINS = exports.MULTICALL3_ADDRESS = exports.AVAILABLE_CHAINS = exports.NETWORKS = exports.ORACLE_CONTRACTS = exports.MIN_ABIS = exports.EVM_NATIVE_DECIMALS = exports.NATIVE_ADDRESS = exports.SPECIAL_CHAINS = void 0;
4
4
  // Special Chains
5
5
  exports.SPECIAL_CHAINS = {
6
6
  solana: {
@@ -141,6 +141,42 @@ exports.NETWORKS = {
141
141
  },
142
142
  };
143
143
  exports.AVAILABLE_CHAINS = Object.keys(exports.NETWORKS).map((c) => Number(c));
144
+ /**
145
+ * Canonical [Multicall3](https://github.com/mds1/multicall) address, deployed
146
+ * via the deterministic deployer to the same address on most EVM chains.
147
+ * @internal
148
+ */
149
+ exports.MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
150
+ /**
151
+ * Chains where the canonical Multicall3 deployment was **verified on-chain**
152
+ * (`eth_getCode` returned the 3808-byte runtime at {@link MULTICALL3_ADDRESS};
153
+ * checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15) —
154
+ * deterministic-deployer presence is NOT assumed. Chains outside this set
155
+ * keep the per-call read path.
156
+ *
157
+ * Deliberately excluded from `NETWORKS`:
158
+ * - 4114 (Citrea) — `eth_getCode` returned `0x` (not deployed).
159
+ * - -1 (Solana), -3 (Stellar) — non-EVM, no Multicall3.
160
+ * @internal
161
+ */
162
+ exports.MULTICALL3_VERIFIED_CHAINS = new Set([
163
+ 1, // Ethereum
164
+ 42161, // Arbitrum One
165
+ 8453, // Base
166
+ 43114, // Avalanche
167
+ 137, // Polygon
168
+ 56, // BNB Smart Chain
169
+ 999, // HyperEVM
170
+ 130, // Unichain
171
+ 31612, // Mezo
172
+ 143, // Monad
173
+ 9745, // Plasma
174
+ 57073, // Ink
175
+ 14, // Flare
176
+ 747474, // Katana
177
+ 25363, // Fluent
178
+ 4217, // Tempo
179
+ ]);
144
180
  /**
145
181
  * Fallbacks
146
182
  */
@@ -0,0 +1,68 @@
1
+ import { type InterfaceAbi } from 'ethers';
2
+ import type { IAddress, IContractRunner } from '../../types';
3
+ /**
4
+ * One read to fold into a Multicall3 `aggregate3` batch.
5
+ * @internal
6
+ */
7
+ export interface IMulticall3Request {
8
+ /** Contract to call. */
9
+ target: IAddress;
10
+ /** ABI containing `functionName` (full or minimal fragment). */
11
+ abi: InterfaceAbi;
12
+ /** View function to encode. */
13
+ functionName: string;
14
+ /** Positional arguments for the function. */
15
+ args?: unknown[];
16
+ }
17
+ /**
18
+ * Per-call result of an `aggregate3` batch. `success: false` means that one
19
+ * call reverted (or its chunk failed at the transport level) — it never
20
+ * implies anything about the other calls in the batch.
21
+ * @internal
22
+ */
23
+ export interface IMulticall3Result {
24
+ success: boolean;
25
+ /** First decoded return value; `undefined` when `success` is `false`. */
26
+ value?: unknown;
27
+ }
28
+ /**
29
+ * Calls per `aggregate3` chunk. Mirrors the `batchMaxCount: 10` cap on
30
+ * `createProvider` — some RPC providers (e.g. rpc.hypurrscan.io) enforce
31
+ * their own batch/response-size limits, so an unbounded batch for a wallet
32
+ * with many vaults risks exceeding response-size or `eth_call` gas ceilings.
33
+ * @internal
34
+ */
35
+ export declare const MULTICALL3_BATCH_SIZE = 10;
36
+ /**
37
+ * Whether Multicall3 read-aggregation is enabled for a chain. Only chains in
38
+ * {@link MULTICALL3_VERIFIED_CHAINS} (deployment verified via `eth_getCode`,
39
+ * never assumed) qualify — callers must fall back to individual reads for
40
+ * every other chain.
41
+ * @internal
42
+ */
43
+ export declare function isMulticall3Supported(chainId: number | undefined): boolean;
44
+ /**
45
+ * Aggregate independent view calls into chunked Multicall3 `aggregate3`
46
+ * batches (`allowFailure: true` per call).
47
+ *
48
+ * Failure semantics — the load-bearing detail:
49
+ * - A reverting inner call (paused/deprecated vault) yields `success: false`
50
+ * for that call only; every other call in the batch decodes normally.
51
+ * - A transport-level failure of one chunk degrades that chunk's calls to
52
+ * `success: false` instead of throwing, so a caller can always fall back
53
+ * to its per-call path. This function never rejects for RPC reasons.
54
+ *
55
+ * RPC cost: `ceil(calls.length / batchSize)` `eth_call`s, versus
56
+ * `calls.length` without aggregation.
57
+ *
58
+ * @param provider Provider for the target chain.
59
+ * @param chainId Chain the provider is connected to — must be in the
60
+ * verified allowlist; gate with {@link isMulticall3Supported} first.
61
+ * @param calls Reads to aggregate, in order.
62
+ * @param batchSize Max calls per `aggregate3` chunk.
63
+ * @returns One {@link IMulticall3Result} per request, index-aligned.
64
+ * @throws AugustValidationError when `chainId` is not on the verified
65
+ * allowlist — programming error, not a runtime condition to swallow.
66
+ * @internal
67
+ */
68
+ export declare function multicall3Aggregate(provider: IContractRunner, chainId: number, calls: IMulticall3Request[], batchSize?: number): Promise<IMulticall3Result[]>;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MULTICALL3_BATCH_SIZE = void 0;
4
+ exports.isMulticall3Supported = isMulticall3Supported;
5
+ exports.multicall3Aggregate = multicall3Aggregate;
6
+ const ethers_1 = require("ethers");
7
+ const Multicall3_1 = require("../../abis/Multicall3");
8
+ const web3_1 = require("../constants/web3");
9
+ const errors_1 = require("../errors");
10
+ const logger_1 = require("../logger");
11
+ /**
12
+ * Calls per `aggregate3` chunk. Mirrors the `batchMaxCount: 10` cap on
13
+ * `createProvider` — some RPC providers (e.g. rpc.hypurrscan.io) enforce
14
+ * their own batch/response-size limits, so an unbounded batch for a wallet
15
+ * with many vaults risks exceeding response-size or `eth_call` gas ceilings.
16
+ * @internal
17
+ */
18
+ exports.MULTICALL3_BATCH_SIZE = 10;
19
+ /**
20
+ * Whether Multicall3 read-aggregation is enabled for a chain. Only chains in
21
+ * {@link MULTICALL3_VERIFIED_CHAINS} (deployment verified via `eth_getCode`,
22
+ * never assumed) qualify — callers must fall back to individual reads for
23
+ * every other chain.
24
+ * @internal
25
+ */
26
+ function isMulticall3Supported(chainId) {
27
+ return typeof chainId === 'number' && web3_1.MULTICALL3_VERIFIED_CHAINS.has(chainId);
28
+ }
29
+ /**
30
+ * Aggregate independent view calls into chunked Multicall3 `aggregate3`
31
+ * batches (`allowFailure: true` per call).
32
+ *
33
+ * Failure semantics — the load-bearing detail:
34
+ * - A reverting inner call (paused/deprecated vault) yields `success: false`
35
+ * for that call only; every other call in the batch decodes normally.
36
+ * - A transport-level failure of one chunk degrades that chunk's calls to
37
+ * `success: false` instead of throwing, so a caller can always fall back
38
+ * to its per-call path. This function never rejects for RPC reasons.
39
+ *
40
+ * RPC cost: `ceil(calls.length / batchSize)` `eth_call`s, versus
41
+ * `calls.length` without aggregation.
42
+ *
43
+ * @param provider Provider for the target chain.
44
+ * @param chainId Chain the provider is connected to — must be in the
45
+ * verified allowlist; gate with {@link isMulticall3Supported} first.
46
+ * @param calls Reads to aggregate, in order.
47
+ * @param batchSize Max calls per `aggregate3` chunk.
48
+ * @returns One {@link IMulticall3Result} per request, index-aligned.
49
+ * @throws AugustValidationError when `chainId` is not on the verified
50
+ * allowlist — programming error, not a runtime condition to swallow.
51
+ * @internal
52
+ */
53
+ async function multicall3Aggregate(provider, chainId, calls, batchSize = exports.MULTICALL3_BATCH_SIZE) {
54
+ if (!isMulticall3Supported(chainId)) {
55
+ throw new errors_1.AugustValidationError('INVALID_INPUT', `multicall3Aggregate: Multicall3 deployment is not verified on chain ${chainId} — use the per-call read path instead`);
56
+ }
57
+ if (calls.length === 0)
58
+ return [];
59
+ const encoded = calls.map((c) => {
60
+ const iface = new ethers_1.Interface(c.abi);
61
+ return {
62
+ target: c.target,
63
+ allowFailure: true,
64
+ callData: iface.encodeFunctionData(c.functionName, c.args ?? []),
65
+ iface,
66
+ functionName: c.functionName,
67
+ };
68
+ });
69
+ const chunks = [];
70
+ for (let i = 0; i < encoded.length; i += batchSize) {
71
+ chunks.push(encoded.slice(i, i + batchSize));
72
+ }
73
+ const multicall = new ethers_1.Contract(web3_1.MULTICALL3_ADDRESS, Multicall3_1.ABI_MULTICALL3, provider);
74
+ const chunkResults = await Promise.all(chunks.map(async (chunk) => {
75
+ try {
76
+ const returned = (await multicall.aggregate3(chunk.map((c) => ({
77
+ target: c.target,
78
+ allowFailure: c.allowFailure,
79
+ callData: c.callData,
80
+ }))));
81
+ return chunk.map((c, i) => {
82
+ const r = returned[i];
83
+ if (!r?.success || !r.returnData || r.returnData === '0x') {
84
+ return { success: false, value: undefined };
85
+ }
86
+ try {
87
+ const decoded = c.iface.decodeFunctionResult(c.functionName, r.returnData);
88
+ return { success: true, value: decoded[0] };
89
+ }
90
+ catch (decodeError) {
91
+ logger_1.Logger.log.warn('multicall3Aggregate', `failed to decode ${c.functionName} result for ${c.target}`, decodeError);
92
+ return { success: false, value: undefined };
93
+ }
94
+ });
95
+ }
96
+ catch (chunkError) {
97
+ logger_1.Logger.log.warn('multicall3Aggregate', `aggregate3 chunk failed on chain ${chainId} (${chunk.length} calls) — callers fall back to per-call reads`, chunkError);
98
+ return chunk.map(() => ({ success: false, value: undefined }));
99
+ }
100
+ }));
101
+ return chunkResults.flat();
102
+ }
103
+ //# sourceMappingURL=multicall.js.map