@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.
- package/lib/adapters/evm/index.d.ts +17 -1
- package/lib/adapters/evm/index.js +20 -0
- package/lib/core/analytics/method-taxonomy.js +3 -0
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/core/constants/swap-router.d.ts +46 -4
- package/lib/core/constants/swap-router.js +50 -5
- package/lib/core/constants/web3.d.ts +19 -0
- package/lib/core/constants/web3.js +37 -1
- package/lib/core/helpers/multicall.d.ts +68 -0
- package/lib/core/helpers/multicall.js +103 -0
- package/lib/core/helpers/revert-decode.d.ts +248 -0
- package/lib/core/helpers/revert-decode.js +515 -0
- package/lib/core/helpers/swap-router.d.ts +168 -5
- package/lib/core/helpers/swap-router.js +417 -4
- package/lib/core/helpers/vault-version.d.ts +19 -1
- package/lib/core/helpers/vault-version.js +15 -1
- package/lib/core/helpers/vaults.d.ts +1 -1
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +2 -0
- package/lib/main.d.ts +46 -0
- package/lib/main.js +46 -0
- package/lib/modules/vaults/getters.d.ts +25 -2
- package/lib/modules/vaults/getters.js +41 -11
- package/lib/modules/vaults/main.d.ts +75 -0
- package/lib/modules/vaults/main.js +127 -0
- package/lib/modules/vaults/prefetch.d.ts +65 -0
- package/lib/modules/vaults/prefetch.js +120 -0
- package/lib/sdk.d.ts +7227 -6544
- package/lib/types/subgraph.d.ts +9 -0
- package/lib/types/vaults.d.ts +34 -0
- package/package.json +3 -3
|
@@ -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',
|
|
@@ -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}
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
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}
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
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
|