@upshiftfinance/sdk 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +408 -2
- package/lib/abis/AddressResolver.d.ts +28 -0
- package/lib/abis/AddressResolver.js +23 -0
- package/lib/abis/ChainlinkV3.d.ts +87 -0
- package/lib/abis/ChainlinkV3.js +117 -0
- package/lib/abis/ERC20.d.ts +168 -0
- package/lib/abis/ERC20.js +226 -0
- package/lib/abis/ERC20_Bytes32.d.ts +139 -0
- package/lib/abis/ERC20_Bytes32.js +196 -0
- package/lib/abis/ERC4626.d.ts +364 -0
- package/lib/abis/ERC4626.js +507 -0
- package/lib/abis/ERC721.d.ts +231 -0
- package/lib/abis/ERC721.js +321 -0
- package/lib/abis/FeeOracle.d.ts +120 -0
- package/lib/abis/FeeOracle.js +162 -0
- package/lib/abis/LendingPool.d.ts +1393 -0
- package/lib/abis/LendingPool.js +1807 -0
- package/lib/abis/LendingPoolV2.d.ts +1413 -0
- package/lib/abis/LendingPoolV2.js +1833 -0
- package/lib/abis/LendingPoolV3.d.ts +1677 -0
- package/lib/abis/LendingPoolV3.js +1160 -0
- package/lib/abis/Loan.d.ts +837 -0
- package/lib/abis/Loan.js +1080 -0
- package/lib/abis/MultiAssetNativeDepositWrapper.d.ts +137 -0
- package/lib/abis/MultiAssetNativeDepositWrapper.js +125 -0
- package/lib/abis/Multicall3.d.ts +30 -0
- package/lib/abis/Multicall3.js +97 -0
- package/lib/abis/OFT.d.ts +116 -0
- package/lib/abis/OFT.js +85 -0
- package/lib/abis/PoolAdapter.d.ts +36 -0
- package/lib/abis/PoolAdapter.js +51 -0
- package/lib/abis/RewardDistributor.d.ts +267 -0
- package/lib/abis/RewardDistributor.js +352 -0
- package/lib/abis/RwaRedeemSubaccount.d.ts +747 -0
- package/lib/abis/RwaRedeemSubaccount.js +548 -0
- package/lib/abis/SmartAccount.d.ts +17 -0
- package/lib/abis/SmartAccount.js +19 -0
- package/lib/abis/SwapRouter.d.ts +953 -0
- package/lib/abis/SwapRouter.js +1228 -0
- package/lib/abis/TextResolver.d.ts +16 -0
- package/lib/abis/TextResolver.js +16 -0
- package/lib/abis/TokenizedVaultV2.d.ts +1364 -0
- package/lib/abis/TokenizedVaultV2.js +1041 -0
- package/lib/abis/TokenizedVaultV2DepositWithPermit.d.ts +1456 -0
- package/lib/abis/TokenizedVaultV2DepositWithPermit.js +1878 -0
- package/lib/abis/TokenizedVaultV2Receipt.d.ts +1568 -0
- package/lib/abis/TokenizedVaultV2Receipt.js +1061 -0
- package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.d.ts +454 -0
- package/lib/abis/TokenizedVaultV2SenderAllocationWhitelist.js +327 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAllocation.d.ts +1466 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAllocation.js +1092 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAssets.d.ts +274 -0
- package/lib/abis/TokenizedVaultV2WhitelistedAssets.js +167 -0
- package/lib/abis/UniversalResolverResolve.d.ts +69 -0
- package/lib/abis/UniversalResolverResolve.js +35 -0
- package/lib/abis/UniversalSignatureValidator.d.ts +17 -0
- package/lib/abis/UniversalSignatureValidator.js +30 -0
- package/lib/abis/WrapperAdapter.d.ts +71 -0
- package/lib/abis/WrapperAdapter.js +77 -0
- package/lib/abis/index.d.ts +34 -0
- package/lib/abis/index.js +51 -0
- package/lib/adapters/evm/getters.d.ts +19 -0
- package/lib/adapters/evm/getters.js +249 -0
- package/lib/adapters/evm/index.d.ts +539 -0
- package/lib/adapters/evm/index.js +656 -0
- package/lib/adapters/evm/utils.d.ts +8 -0
- package/lib/adapters/evm/utils.js +51 -0
- package/lib/adapters/solana/confirm.d.ts +88 -0
- package/lib/adapters/solana/confirm.js +291 -0
- package/lib/adapters/solana/constants.d.ts +42 -0
- package/lib/adapters/solana/constants.js +59 -0
- package/lib/adapters/solana/getters.d.ts +42 -0
- package/lib/adapters/solana/getters.js +275 -0
- package/lib/adapters/solana/idl/vault-idl.d.ts +700 -0
- package/lib/adapters/solana/idl/vault-idl.js +2101 -0
- package/lib/adapters/solana/idl/withdrawal-queue-idl.d.ts +795 -0
- package/lib/adapters/solana/idl/withdrawal-queue-idl.js +1864 -0
- package/lib/adapters/solana/index.d.ts +372 -0
- package/lib/adapters/solana/index.js +459 -0
- package/lib/adapters/solana/pricing.d.ts +184 -0
- package/lib/adapters/solana/pricing.js +239 -0
- package/lib/adapters/solana/queue-hints.d.ts +29 -0
- package/lib/adapters/solana/queue-hints.js +59 -0
- package/lib/adapters/solana/queue.actions.d.ts +97 -0
- package/lib/adapters/solana/queue.actions.js +468 -0
- package/lib/adapters/solana/token-reads.d.ts +108 -0
- package/lib/adapters/solana/token-reads.js +145 -0
- package/lib/adapters/solana/types.d.ts +325 -0
- package/lib/adapters/solana/types.js +3 -0
- package/lib/adapters/solana/utils.d.ts +229 -0
- package/lib/adapters/solana/utils.js +773 -0
- package/lib/adapters/solana/vault.actions.d.ts +140 -0
- package/lib/adapters/solana/vault.actions.js +657 -0
- package/lib/adapters/solana/withdrawal-queue.d.ts +125 -0
- package/lib/adapters/solana/withdrawal-queue.js +301 -0
- package/lib/adapters/stellar/actions.d.ts +41 -0
- package/lib/adapters/stellar/actions.js +126 -0
- package/lib/adapters/stellar/constants.d.ts +43 -0
- package/lib/adapters/stellar/constants.js +53 -0
- package/lib/adapters/stellar/getters.d.ts +68 -0
- package/lib/adapters/stellar/getters.js +290 -0
- package/lib/adapters/stellar/index.d.ts +126 -0
- package/lib/adapters/stellar/index.js +187 -0
- package/lib/adapters/stellar/invocation.d.ts +55 -0
- package/lib/adapters/stellar/invocation.js +92 -0
- package/lib/adapters/stellar/soroban.d.ts +131 -0
- package/lib/adapters/stellar/soroban.js +617 -0
- package/lib/adapters/stellar/submit.d.ts +42 -0
- package/lib/adapters/stellar/submit.js +195 -0
- package/lib/adapters/stellar/types.d.ts +57 -0
- package/lib/adapters/stellar/types.js +6 -0
- package/lib/adapters/stellar/utils.d.ts +24 -0
- package/lib/adapters/stellar/utils.js +34 -0
- package/lib/adapters/sui/client.d.ts +83 -0
- package/lib/adapters/sui/client.js +216 -0
- package/lib/adapters/sui/constants.d.ts +33 -0
- package/lib/adapters/sui/constants.js +31 -0
- package/lib/adapters/sui/index.d.ts +57 -0
- package/lib/adapters/sui/index.js +100 -0
- package/lib/adapters/sui/targets.d.ts +171 -0
- package/lib/adapters/sui/targets.js +225 -0
- package/lib/adapters/sui/utils.d.ts +8 -0
- package/lib/adapters/sui/utils.js +17 -0
- package/lib/core/analytics/app-name.d.ts +27 -0
- package/lib/core/analytics/app-name.js +48 -0
- package/lib/core/analytics/chain-name.d.ts +9 -0
- package/lib/core/analytics/chain-name.js +34 -0
- package/lib/core/analytics/constants.d.ts +15 -0
- package/lib/core/analytics/constants.js +28 -0
- package/lib/core/analytics/env.d.ts +46 -0
- package/lib/core/analytics/env.js +147 -0
- package/lib/core/analytics/index.d.ts +39 -0
- package/lib/core/analytics/index.js +83 -0
- package/lib/core/analytics/instrumentation.d.ts +29 -0
- package/lib/core/analytics/instrumentation.js +292 -0
- package/lib/core/analytics/method-taxonomy.d.ts +19 -0
- package/lib/core/analytics/method-taxonomy.js +156 -0
- package/lib/core/analytics/metrics.d.ts +48 -0
- package/lib/core/analytics/metrics.js +142 -0
- package/lib/core/analytics/sanitize.d.ts +57 -0
- package/lib/core/analytics/sanitize.js +272 -0
- package/lib/core/analytics/sentry-runtime.d.ts +15 -0
- package/lib/core/analytics/sentry-runtime.js +131 -0
- package/lib/core/analytics/sentry.d.ts +100 -0
- package/lib/core/analytics/sentry.js +696 -0
- package/lib/core/analytics/types.d.ts +55 -0
- package/lib/core/analytics/types.js +3 -0
- package/lib/core/analytics/user-identity.d.ts +55 -0
- package/lib/core/analytics/user-identity.js +218 -0
- package/lib/core/analytics/version.d.ts +6 -0
- package/lib/core/analytics/version.js +10 -0
- package/lib/core/attribution.d.ts +159 -0
- package/lib/core/attribution.js +194 -0
- package/lib/core/auth/index.d.ts +1 -0
- package/lib/core/auth/index.js +18 -0
- package/lib/core/auth/verify.d.ts +2 -0
- package/lib/core/auth/verify.js +35 -0
- package/lib/core/base.class.d.ts +193 -0
- package/lib/core/base.class.js +163 -0
- package/lib/core/cache.d.ts +9 -0
- package/lib/core/cache.js +31 -0
- package/lib/core/constants/adapters.d.ts +103 -0
- package/lib/core/constants/adapters.js +180 -0
- package/lib/core/constants/core.d.ts +162 -0
- package/lib/core/constants/core.js +281 -0
- package/lib/core/constants/swap-router.d.ts +180 -0
- package/lib/core/constants/swap-router.js +203 -0
- package/lib/core/constants/vaults.d.ts +93 -0
- package/lib/core/constants/vaults.js +277 -0
- package/lib/core/constants/web3.d.ts +106 -0
- package/lib/core/constants/web3.js +251 -0
- package/lib/core/errors/index.d.ts +177 -0
- package/lib/core/errors/index.js +257 -0
- package/lib/core/fetcher.d.ts +237 -0
- package/lib/core/fetcher.js +1103 -0
- package/lib/core/helpers/adapters.d.ts +13 -0
- package/lib/core/helpers/adapters.js +39 -0
- package/lib/core/helpers/chain-address.d.ts +13 -0
- package/lib/core/helpers/chain-address.js +47 -0
- package/lib/core/helpers/chain-error.d.ts +207 -0
- package/lib/core/helpers/chain-error.js +697 -0
- package/lib/core/helpers/chain-support.d.ts +98 -0
- package/lib/core/helpers/chain-support.js +139 -0
- package/lib/core/helpers/concurrency.d.ts +51 -0
- package/lib/core/helpers/concurrency.js +79 -0
- package/lib/core/helpers/core.d.ts +92 -0
- package/lib/core/helpers/core.js +368 -0
- package/lib/core/helpers/explorer-link.d.ts +16 -0
- package/lib/core/helpers/explorer-link.js +26 -0
- 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/signer.d.ts +61 -0
- package/lib/core/helpers/signer.js +184 -0
- package/lib/core/helpers/swap-router.d.ts +269 -0
- package/lib/core/helpers/swap-router.js +542 -0
- package/lib/core/helpers/vault-version.d.ts +24 -0
- package/lib/core/helpers/vault-version.js +83 -0
- package/lib/core/helpers/vaults.d.ts +89 -0
- package/lib/core/helpers/vaults.js +241 -0
- package/lib/core/helpers/web3.d.ts +366 -0
- package/lib/core/helpers/web3.js +1034 -0
- package/lib/core/index.d.ts +23 -0
- package/lib/core/index.js +40 -0
- package/lib/core/logger/curator-alert.d.ts +217 -0
- package/lib/core/logger/curator-alert.js +276 -0
- package/lib/core/logger/index.d.ts +99 -0
- package/lib/core/logger/index.js +163 -0
- package/lib/core/logger/slack.d.ts +49 -0
- package/lib/core/logger/slack.js +111 -0
- package/lib/core/vault-metadata.d.ts +12 -0
- package/lib/core/vault-metadata.js +42 -0
- package/lib/core/version-check.d.ts +58 -0
- package/lib/core/version-check.js +182 -0
- package/lib/evm/index.d.ts +2 -0
- package/lib/evm/index.js +19 -0
- package/lib/evm/methods/crossChainVault.d.ts +132 -0
- package/lib/evm/methods/crossChainVault.js +857 -0
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +92 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +239 -0
- package/lib/evm/methods/index.d.ts +2 -0
- package/lib/evm/methods/index.js +19 -0
- package/lib/evm/types/crossChain.d.ts +363 -0
- package/lib/evm/types/crossChain.js +20 -0
- package/lib/evm/types/index.d.ts +1 -0
- package/lib/evm/types/index.js +18 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +52 -0
- package/lib/main.d.ts +596 -0
- package/lib/main.js +681 -0
- package/lib/modules/api/fetcher.d.ts +108 -0
- package/lib/modules/api/fetcher.js +187 -0
- package/lib/modules/api/index.d.ts +1 -0
- package/lib/modules/api/index.js +6 -0
- package/lib/modules/api/main.d.ts +587 -0
- package/lib/modules/api/main.js +911 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
- package/lib/modules/sub-accounts/fetcher.js +96 -0
- package/lib/modules/sub-accounts/index.d.ts +2 -0
- package/lib/modules/sub-accounts/index.js +19 -0
- package/lib/modules/sub-accounts/main.d.ts +249 -0
- package/lib/modules/sub-accounts/main.js +211 -0
- package/lib/modules/sub-accounts/utils.d.ts +106 -0
- package/lib/modules/sub-accounts/utils.js +112 -0
- package/lib/modules/vaults/adapter.helpers.d.ts +84 -0
- package/lib/modules/vaults/adapter.helpers.js +202 -0
- package/lib/modules/vaults/fetcher.d.ts +147 -0
- package/lib/modules/vaults/fetcher.js +357 -0
- package/lib/modules/vaults/getters.d.ts +1060 -0
- package/lib/modules/vaults/getters.js +4079 -0
- package/lib/modules/vaults/index.d.ts +20 -0
- package/lib/modules/vaults/index.js +44 -0
- package/lib/modules/vaults/main.d.ts +607 -0
- package/lib/modules/vaults/main.js +1687 -0
- package/lib/modules/vaults/prefetch.d.ts +65 -0
- package/lib/modules/vaults/prefetch.js +120 -0
- package/lib/modules/vaults/read.actions.d.ts +406 -0
- package/lib/modules/vaults/read.actions.js +891 -0
- package/lib/modules/vaults/types.d.ts +149 -0
- package/lib/modules/vaults/types.js +3 -0
- package/lib/modules/vaults/utils/call-data-decoder.d.ts +61 -0
- package/lib/modules/vaults/utils/call-data-decoder.js +194 -0
- package/lib/modules/vaults/utils/date-utils.d.ts +50 -0
- package/lib/modules/vaults/utils/date-utils.js +84 -0
- package/lib/modules/vaults/utils.d.ts +153 -0
- package/lib/modules/vaults/utils.js +818 -0
- package/lib/modules/vaults/write.actions.d.ts +812 -0
- package/lib/modules/vaults/write.actions.js +2377 -0
- package/lib/polyfills.d.ts +1 -0
- package/lib/polyfills.js +12 -0
- package/lib/sdk.d.ts +30173 -0
- package/lib/services/coingecko/fetcher.d.ts +15 -0
- package/lib/services/coingecko/fetcher.js +67 -0
- package/lib/services/coingecko/index.d.ts +2 -0
- package/lib/services/coingecko/index.js +19 -0
- package/lib/services/coingecko/utils.d.ts +1 -0
- package/lib/services/coingecko/utils.js +24 -0
- package/lib/services/debank/fetcher.d.ts +126 -0
- package/lib/services/debank/fetcher.js +47 -0
- package/lib/services/debank/index.d.ts +2 -0
- package/lib/services/debank/index.js +19 -0
- package/lib/services/debank/utils.d.ts +50 -0
- package/lib/services/debank/utils.js +325 -0
- package/lib/services/layerzero/deposits.d.ts +55 -0
- package/lib/services/layerzero/deposits.js +174 -0
- package/lib/services/layerzero/redeems.d.ts +20 -0
- package/lib/services/layerzero/redeems.js +92 -0
- package/lib/services/layerzero/utils.d.ts +9 -0
- package/lib/services/layerzero/utils.js +22 -0
- package/lib/services/octavfi/fetcher.d.ts +33 -0
- package/lib/services/octavfi/fetcher.js +39 -0
- package/lib/services/octavfi/index.d.ts +3 -0
- package/lib/services/octavfi/index.js +20 -0
- package/lib/services/octavfi/types.d.ts +34 -0
- package/lib/services/octavfi/types.js +3 -0
- package/lib/services/octavfi/utils.d.ts +16 -0
- package/lib/services/octavfi/utils.js +244 -0
- package/lib/services/subgraph/fetcher.d.ts +2 -0
- package/lib/services/subgraph/fetcher.js +66 -0
- package/lib/services/subgraph/index.d.ts +2 -0
- package/lib/services/subgraph/index.js +19 -0
- package/lib/services/subgraph/schema.d.ts +48 -0
- package/lib/services/subgraph/schema.js +87 -0
- package/lib/services/subgraph/vaults.d.ts +83 -0
- package/lib/services/subgraph/vaults.js +1282 -0
- package/lib/services/swap-quotes/index.d.ts +105 -0
- package/lib/services/swap-quotes/index.js +77 -0
- package/lib/services/swap-quotes/paraswap.d.ts +51 -0
- package/lib/services/swap-quotes/paraswap.js +138 -0
- package/lib/services/untangled/fetcher.d.ts +40 -0
- package/lib/services/untangled/fetcher.js +110 -0
- package/lib/services/untangled/index.d.ts +3 -0
- package/lib/services/untangled/index.js +20 -0
- package/lib/services/untangled/types.d.ts +83 -0
- package/lib/services/untangled/types.js +10 -0
- package/lib/services/untangled/utils.d.ts +91 -0
- package/lib/services/untangled/utils.js +339 -0
- package/lib/types/api.d.ts +498 -0
- package/lib/types/api.js +3 -0
- package/lib/types/index.d.ts +12 -0
- package/lib/types/index.js +28 -0
- package/lib/types/points.d.ts +28 -0
- package/lib/types/points.js +3 -0
- package/lib/types/pools.d.ts +144 -0
- package/lib/types/pools.js +3 -0
- package/lib/types/staking.d.ts +28 -0
- package/lib/types/staking.js +3 -0
- package/lib/types/sub-accounts.d.ts +150 -0
- package/lib/types/sub-accounts.js +3 -0
- package/lib/types/subgraph.d.ts +84 -0
- package/lib/types/subgraph.js +3 -0
- package/lib/types/typed-contract.d.ts +102 -0
- package/lib/types/typed-contract.js +3 -0
- package/lib/types/user.d.ts +1 -0
- package/lib/types/user.js +3 -0
- package/lib/types/vaults.d.ts +886 -0
- package/lib/types/vaults.js +30 -0
- package/lib/types/web3.d.ts +100 -0
- package/lib/types/web3.js +14 -0
- package/lib/types/webserver.d.ts +730 -0
- package/lib/types/webserver.js +3 -0
- package/package.json +79 -3
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filterOutBySize = void 0;
|
|
4
|
+
exports.toNormalizedBn = toNormalizedBn;
|
|
5
|
+
exports.getFallbackRpcUrls = getFallbackRpcUrls;
|
|
6
|
+
exports.toTitleCase = toTitleCase;
|
|
7
|
+
exports.truncate = truncate;
|
|
8
|
+
exports.round = round;
|
|
9
|
+
exports.loanStateToReadable = loanStateToReadable;
|
|
10
|
+
exports.dateToUnix = dateToUnix;
|
|
11
|
+
exports.unixToDate = unixToDate;
|
|
12
|
+
exports.isEarlierThanNow = isEarlierThanNow;
|
|
13
|
+
exports.daysAgo = daysAgo;
|
|
14
|
+
exports.prepareDateForDb = prepareDateForDb;
|
|
15
|
+
exports.orderObjArrByDate = orderObjArrByDate;
|
|
16
|
+
exports.calculateWeights = calculateWeights;
|
|
17
|
+
exports.calculateWeightedAverage = calculateWeightedAverage;
|
|
18
|
+
exports.toRawBigInt = toRawBigInt;
|
|
19
|
+
const web3_1 = require("../constants/web3");
|
|
20
|
+
const ethers_1 = require("ethers");
|
|
21
|
+
const errors_1 = require("../errors");
|
|
22
|
+
/**
|
|
23
|
+
* Table of Contents
|
|
24
|
+
* - Formatters
|
|
25
|
+
* - Datetime
|
|
26
|
+
* - Arrays
|
|
27
|
+
* - Caching
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Normalize an amount into both its human-readable and raw (integer) forms.
|
|
31
|
+
*
|
|
32
|
+
* @param value - Amount as a decimal string (`"1.5"`), a JS number, or a raw
|
|
33
|
+
* `bigint` already scaled by `decimals`. Strings/numbers are treated as
|
|
34
|
+
* human-readable values and scaled UP; bigints are treated as raw values
|
|
35
|
+
* and scaled DOWN. Exponential notation (`1e-7`, `1e21`) is accepted for
|
|
36
|
+
* strings and numbers.
|
|
37
|
+
* @param decimals - Token decimals used for scaling. Default `18`.
|
|
38
|
+
* @returns `{ normalized, raw }` where `normalized` is the decimal string
|
|
39
|
+
* (fraction trimmed to `decimals` places) and `raw` is the integer string.
|
|
40
|
+
* Falsy input yields `{ normalized: '0', raw: '0' }`.
|
|
41
|
+
* @throws Whatever ethers' `parseUnits` throws for a string that is not a
|
|
42
|
+
* decimal number (e.g. `"abc"`).
|
|
43
|
+
*/
|
|
44
|
+
function toNormalizedBn(value, decimals = 18) {
|
|
45
|
+
if (!value)
|
|
46
|
+
return { normalized: '0', raw: BigInt(0).toString() };
|
|
47
|
+
const sanitize = (val, decimals) => {
|
|
48
|
+
const [whole, frac = ''] = val.split('.');
|
|
49
|
+
const trimmedFrac = frac.slice(0, decimals); // trim to allowed precision
|
|
50
|
+
return trimmedFrac ? `${whole}.${trimmedFrac}` : whole;
|
|
51
|
+
};
|
|
52
|
+
// Convert number or exponential string to fixed decimal string
|
|
53
|
+
const toFixedDecimalString = (val) => {
|
|
54
|
+
const strRep = typeof val === 'number' ? String(val) : val;
|
|
55
|
+
// Check if the string representation contains exponential notation
|
|
56
|
+
if (strRep.includes('e') || strRep.includes('E')) {
|
|
57
|
+
// Parse as number and use toFixed with high precision to convert exponential to fixed decimal
|
|
58
|
+
// 100 decimals should handle even extremely small numbers like 1e-20
|
|
59
|
+
const num = typeof val === 'number' ? val : parseFloat(strRep);
|
|
60
|
+
// `Number#toFixed` itself falls back to exponential notation for
|
|
61
|
+
// magnitudes >= 1e21 ("1e+21"), which `parseUnits` rejects. Every IEEE
|
|
62
|
+
// double of that size is an integer (well past 2^53), so `BigInt` yields
|
|
63
|
+
// the exact plain-digit string. The digits are those of the IEEE double,
|
|
64
|
+
// not of the literal input (`"1.5e21"` is parsed to the nearest double
|
|
65
|
+
// before this point), so precision beyond ~15-17 significant digits was
|
|
66
|
+
// already lost at `parseFloat`/`Number`.
|
|
67
|
+
if (Number.isFinite(num) && Math.abs(num) >= 1e21) {
|
|
68
|
+
return BigInt(num).toString();
|
|
69
|
+
}
|
|
70
|
+
return num.toFixed(100).replace(/\.?0+$/, '');
|
|
71
|
+
}
|
|
72
|
+
// For regular numbers/strings, return as is
|
|
73
|
+
return strRep;
|
|
74
|
+
};
|
|
75
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
76
|
+
// Convert to fixed decimal string to avoid exponential notation
|
|
77
|
+
const strVal = toFixedDecimalString(value);
|
|
78
|
+
const safeVal = sanitize(strVal, Number(decimals));
|
|
79
|
+
return {
|
|
80
|
+
normalized: safeVal,
|
|
81
|
+
raw: (0, ethers_1.parseUnits)(safeVal, Number(decimals)).toString(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return {
|
|
86
|
+
normalized: (0, ethers_1.formatUnits)(value, Number(decimals)) ?? '0',
|
|
87
|
+
raw: value.toString(),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get fallback RPC URLs for a specific chain
|
|
93
|
+
*/
|
|
94
|
+
function getFallbackRpcUrls(chainId) {
|
|
95
|
+
return web3_1.FALLBACK_RPC_URLS[chainId] || [];
|
|
96
|
+
}
|
|
97
|
+
const filterOutBySize = (usdAmount) => usdAmount > 3_000;
|
|
98
|
+
exports.filterOutBySize = filterOutBySize;
|
|
99
|
+
/**
|
|
100
|
+
* Formatters
|
|
101
|
+
*/
|
|
102
|
+
function toTitleCase(str, type) {
|
|
103
|
+
if (!str)
|
|
104
|
+
return;
|
|
105
|
+
switch (type) {
|
|
106
|
+
case 'camel': {
|
|
107
|
+
// Expand camelCase by inserting a space before each uppercase letter,
|
|
108
|
+
// then title-case the resulting words. The split must operate on the
|
|
109
|
+
// EXPANDED string (not the original) and skip empty tokens: a leading
|
|
110
|
+
// uppercase letter produces a leading space, and the previous version
|
|
111
|
+
// indexed the original's word list by the expanded string's length,
|
|
112
|
+
// which threw on any multi-character input.
|
|
113
|
+
const expanded = Array.from(str)
|
|
114
|
+
.map((letter) => {
|
|
115
|
+
// letter is uppercase
|
|
116
|
+
if (letter === letter.toUpperCase()) {
|
|
117
|
+
return ` ${letter}`;
|
|
118
|
+
}
|
|
119
|
+
// else
|
|
120
|
+
return letter;
|
|
121
|
+
})
|
|
122
|
+
.join('');
|
|
123
|
+
return expanded
|
|
124
|
+
.split(' ')
|
|
125
|
+
.filter((w) => w.length > 0)
|
|
126
|
+
.map((w) => w[0].toUpperCase() + w.slice(1).toLowerCase())
|
|
127
|
+
.join(' ');
|
|
128
|
+
}
|
|
129
|
+
default: {
|
|
130
|
+
const words = str.split(' ')?.map((w) => w.toLowerCase());
|
|
131
|
+
for (let i = 0; i < words.length; i++) {
|
|
132
|
+
words[i] = words[i][0].toUpperCase() + words[i].substr(1);
|
|
133
|
+
}
|
|
134
|
+
return words.join(' ');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function truncate(s, amount) {
|
|
139
|
+
if (typeof s !== 'string') {
|
|
140
|
+
// Leaf string util: importing Logger here would create an import cycle
|
|
141
|
+
// (helpers/core → logger/index → slack → helpers/core) that the madge CI
|
|
142
|
+
// check forbids (CLAUDE.md §9). Keep a direct console.error for this
|
|
143
|
+
// defensive type-guard diagnostic.
|
|
144
|
+
// biome-ignore lint/suspicious/noConsole: leaf util cannot import Logger without a cycle (CLAUDE.md §9); keep a direct console.error for this defensive type-guard diagnostic.
|
|
145
|
+
if (s !== undefined)
|
|
146
|
+
console.error('#truncate: not a string', s);
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
if (!s)
|
|
150
|
+
return s;
|
|
151
|
+
if (s === 'N/A')
|
|
152
|
+
return s;
|
|
153
|
+
return `${s.slice(0, amount ? amount : 4)}...${s.slice(amount ? amount * -1 : -4)}`;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Formats any numeric value (number, string, or bigint) to a standardized string.
|
|
157
|
+
*
|
|
158
|
+
* @param value - amount to be formatted
|
|
159
|
+
* @param options - formatting options:
|
|
160
|
+
* `showing` is the number of decimals to cut off at (or `'all'`);
|
|
161
|
+
* `usd` toggles USD-value display;
|
|
162
|
+
* `decimals` is how many decimals to parse to when `value` is a bigint.
|
|
163
|
+
*
|
|
164
|
+
* @returns standardized string type value
|
|
165
|
+
*/
|
|
166
|
+
function round(value, options) {
|
|
167
|
+
// standardize to string
|
|
168
|
+
let _value;
|
|
169
|
+
if (typeof value === 'bigint') {
|
|
170
|
+
_value = toNormalizedBn(value, options?.decimals ?? web3_1.FALLBACK_DECIMALS).normalized;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
_value = String(value);
|
|
174
|
+
// if string passed includes something like a symbol (i.e. 0.1 ETH --> 0.1)
|
|
175
|
+
if (_value.includes(' '))
|
|
176
|
+
_value = _value.split(' ')[0];
|
|
177
|
+
}
|
|
178
|
+
// if wanting USD value
|
|
179
|
+
if (options?.usd) {
|
|
180
|
+
const usdFormatter = new Intl.NumberFormat('en-US', {
|
|
181
|
+
style: 'currency',
|
|
182
|
+
currency: 'USD',
|
|
183
|
+
});
|
|
184
|
+
const valueNumber = Number(_value);
|
|
185
|
+
return usdFormatter.format(valueNumber) !== 'NaN'
|
|
186
|
+
? usdFormatter.format(valueNumber)
|
|
187
|
+
: '0';
|
|
188
|
+
}
|
|
189
|
+
// else slice if decimal places is more than 6 and display
|
|
190
|
+
if (_value === '0' || _value === '0.0')
|
|
191
|
+
return '0.000';
|
|
192
|
+
if (options?.showing === 'all') {
|
|
193
|
+
return _value;
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
const _showing = () => {
|
|
197
|
+
if (options?.showing && typeof options.showing === 'number')
|
|
198
|
+
return options?.showing;
|
|
199
|
+
if (options?.usd)
|
|
200
|
+
return 2;
|
|
201
|
+
if (_value?.includes('.') && _value.split('.')[0].length > 2)
|
|
202
|
+
return 3;
|
|
203
|
+
if (_value?.length && _value?.length > 6)
|
|
204
|
+
return 6;
|
|
205
|
+
return 4;
|
|
206
|
+
};
|
|
207
|
+
const numberFormatter = new Intl.NumberFormat('en-US', {
|
|
208
|
+
minimumFractionDigits: _showing(),
|
|
209
|
+
maximumFractionDigits: _showing(),
|
|
210
|
+
});
|
|
211
|
+
return numberFormatter.format(Number(_value)) !== 'NaN'
|
|
212
|
+
? numberFormatter.format(Number(_value))
|
|
213
|
+
: '0';
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function loanStateToReadable(loanState) {
|
|
217
|
+
switch (Number(loanState)) {
|
|
218
|
+
case 1:
|
|
219
|
+
return 'PREAPPROVED';
|
|
220
|
+
case 2:
|
|
221
|
+
return 'FUNDING_REQUIRED';
|
|
222
|
+
case 3:
|
|
223
|
+
return 'FUNDED';
|
|
224
|
+
case 4:
|
|
225
|
+
return 'ACTIVE';
|
|
226
|
+
case 5:
|
|
227
|
+
return 'CANCELLED';
|
|
228
|
+
case 6:
|
|
229
|
+
return 'MATURED';
|
|
230
|
+
case 7:
|
|
231
|
+
return 'CLOSED';
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Datetime
|
|
236
|
+
*/
|
|
237
|
+
function dateToUnix(date) {
|
|
238
|
+
if (!date)
|
|
239
|
+
return Math.floor(Date.now());
|
|
240
|
+
return Math.floor(new Date(date).getTime());
|
|
241
|
+
}
|
|
242
|
+
function unixToDate(epoch) {
|
|
243
|
+
if (!epoch)
|
|
244
|
+
return new Date();
|
|
245
|
+
return new Date(new Date(epoch).getTime());
|
|
246
|
+
}
|
|
247
|
+
function isEarlierThanNow(startTime) {
|
|
248
|
+
if (!startTime)
|
|
249
|
+
return true;
|
|
250
|
+
if (startTime <= new Date())
|
|
251
|
+
return true;
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
function daysAgo(days) {
|
|
255
|
+
const today = new Date();
|
|
256
|
+
return new Date(new Date().setDate(today.getDate() - days));
|
|
257
|
+
}
|
|
258
|
+
function prepareDateForDb(date) {
|
|
259
|
+
return new Date(date).toISOString();
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Arrays
|
|
263
|
+
*/
|
|
264
|
+
function orderObjArrByDate(objectArray, options) {
|
|
265
|
+
const selectedOrder = options?.order ?? 'desc';
|
|
266
|
+
const selectedKey = options?.key ?? 'date';
|
|
267
|
+
const toTime = (item) => new Date(item[selectedKey]).valueOf();
|
|
268
|
+
return objectArray.sort((a, b) => {
|
|
269
|
+
// Turn your strings into dates, and then subtract them
|
|
270
|
+
// to get a value that is either negative, positive, or zero.
|
|
271
|
+
if (selectedOrder === 'asc')
|
|
272
|
+
return toTime(a) - toTime(b);
|
|
273
|
+
return toTime(b) - toTime(a);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Calculate weights based on a specific property in array of objects.
|
|
278
|
+
* @param data - Array of objects to calculate weights for
|
|
279
|
+
* @param weightProperty - Property name to base weights on
|
|
280
|
+
* @returns Original data with each item's `weight` added
|
|
281
|
+
*/
|
|
282
|
+
function calculateWeights(data, weightProperty) {
|
|
283
|
+
if (!data || data.length === 0 || !weightProperty)
|
|
284
|
+
return [];
|
|
285
|
+
// Get total of the property we're using for weight calculation
|
|
286
|
+
const total = data.reduce((sum, item) => sum + item[weightProperty], 0);
|
|
287
|
+
// A zero (or NaN) total would make every weight NaN; report zero weights
|
|
288
|
+
// instead so downstream weighted averages collapse to 0 rather than NaN.
|
|
289
|
+
if (!total) {
|
|
290
|
+
return data.map((item) => ({ ...item, weight: 0 }));
|
|
291
|
+
}
|
|
292
|
+
// Add weight property to each item
|
|
293
|
+
return data.map((item) => ({
|
|
294
|
+
...item,
|
|
295
|
+
weight: item[weightProperty] / total,
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Calculate weighted average for array of objects.
|
|
300
|
+
* @param data - Array of objects with values
|
|
301
|
+
* @param valueProperty - Property name containing the value to average
|
|
302
|
+
* @param weightProperty - Optional property to base weights on
|
|
303
|
+
* @returns Weighted average
|
|
304
|
+
*/
|
|
305
|
+
function calculateWeightedAverage(data, valueProperty, weightProperty) {
|
|
306
|
+
if (!data || data.length === 0 || !valueProperty)
|
|
307
|
+
return 0;
|
|
308
|
+
let weightedData;
|
|
309
|
+
// If no weightProperty specified, use equal weights
|
|
310
|
+
if (!weightProperty) {
|
|
311
|
+
weightedData = data.map((item) => ({
|
|
312
|
+
...item,
|
|
313
|
+
weight: 1 / data.length,
|
|
314
|
+
}));
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
weightedData = calculateWeights(data, weightProperty);
|
|
318
|
+
}
|
|
319
|
+
// Calculate weighted average
|
|
320
|
+
const weightedAverage = weightedData.reduce((acc, item) => acc + item[valueProperty] * item.weight, 0);
|
|
321
|
+
return weightedAverage;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Coerce a caller-supplied integer (`string | bigint | number`) to a `bigint`,
|
|
325
|
+
* rejecting anything that is not a non-negative safe integer. `label` names the
|
|
326
|
+
* calling method and `noun` the field being validated, so bad input surfaces as
|
|
327
|
+
* `UpshiftValidationError('INVALID_INPUT')` at the SDK boundary instead of a
|
|
328
|
+
* `BigInt()` SyntaxError wrapped as `UNKNOWN`.
|
|
329
|
+
* @internal
|
|
330
|
+
*/
|
|
331
|
+
function toRawBigInt(value, label, noun = 'amount') {
|
|
332
|
+
if (typeof value === 'bigint')
|
|
333
|
+
return value;
|
|
334
|
+
if (typeof value === 'number') {
|
|
335
|
+
if (!Number.isFinite(value)) {
|
|
336
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} must be finite, got ${value}`);
|
|
337
|
+
}
|
|
338
|
+
if (value < 0) {
|
|
339
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} must be non-negative, got ${value}`);
|
|
340
|
+
}
|
|
341
|
+
if (!Number.isInteger(value)) {
|
|
342
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} must be an integer, got ${value}`);
|
|
343
|
+
}
|
|
344
|
+
if (!Number.isSafeInteger(value)) {
|
|
345
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} ${value} exceeds Number.MAX_SAFE_INTEGER; pass a string or bigint to preserve precision`);
|
|
346
|
+
}
|
|
347
|
+
return BigInt(value);
|
|
348
|
+
}
|
|
349
|
+
if (typeof value === 'string') {
|
|
350
|
+
if (value.trim() === '') {
|
|
351
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} string must not be empty`);
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
const parsed = BigInt(value);
|
|
355
|
+
if (parsed < 0n) {
|
|
356
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} must be non-negative, got ${value}`);
|
|
357
|
+
}
|
|
358
|
+
return parsed;
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
if (e instanceof errors_1.UpshiftValidationError)
|
|
362
|
+
throw e;
|
|
363
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} "${value}" is not a valid integer`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${label}: ${noun} must be a string, bigint, or number`);
|
|
367
|
+
}
|
|
368
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IAddress, IChainId, IExplorerType } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate a block-explorer URL for an address or transaction hash.
|
|
4
|
+
*
|
|
5
|
+
* Returns an empty string when `chain` is falsy or unknown so the return
|
|
6
|
+
* type stays assignable to `string` — preserves the historical public
|
|
7
|
+
* shape from before the file split out of `web3.ts`, where the SDK's
|
|
8
|
+
* `strictNullChecks: false` masked the implicit `undefined` branch and
|
|
9
|
+
* consumers pinned to `string` via the emitted `.d.ts`.
|
|
10
|
+
*
|
|
11
|
+
* @param hex Address or transaction hash
|
|
12
|
+
* @param chain Chain ID
|
|
13
|
+
* @param type Explorer view type (`address`, `tx`, `block`)
|
|
14
|
+
* @returns Full explorer URL, or `''` when `chain` is falsy / unknown.
|
|
15
|
+
*/
|
|
16
|
+
export declare const explorerLink: (hex: IAddress, chain: IChainId, type: IExplorerType) => string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.explorerLink = void 0;
|
|
4
|
+
const web3_1 = require("../constants/web3");
|
|
5
|
+
/**
|
|
6
|
+
* Generate a block-explorer URL for an address or transaction hash.
|
|
7
|
+
*
|
|
8
|
+
* Returns an empty string when `chain` is falsy or unknown so the return
|
|
9
|
+
* type stays assignable to `string` — preserves the historical public
|
|
10
|
+
* shape from before the file split out of `web3.ts`, where the SDK's
|
|
11
|
+
* `strictNullChecks: false` masked the implicit `undefined` branch and
|
|
12
|
+
* consumers pinned to `string` via the emitted `.d.ts`.
|
|
13
|
+
*
|
|
14
|
+
* @param hex Address or transaction hash
|
|
15
|
+
* @param chain Chain ID
|
|
16
|
+
* @param type Explorer view type (`address`, `tx`, `block`)
|
|
17
|
+
* @returns Full explorer URL, or `''` when `chain` is falsy / unknown.
|
|
18
|
+
*/
|
|
19
|
+
const explorerLink = (hex, chain, type) => {
|
|
20
|
+
const network = chain ? web3_1.NETWORKS[chain] : undefined;
|
|
21
|
+
if (!network)
|
|
22
|
+
return '';
|
|
23
|
+
return `${network.explorer}/${type}/${hex}`;
|
|
24
|
+
};
|
|
25
|
+
exports.explorerLink = explorerLink;
|
|
26
|
+
//# sourceMappingURL=explorer-link.js.map
|
|
@@ -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 UpshiftValidationError 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 UpshiftValidationError 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.UpshiftValidationError('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
|