upshift-config 0.5.14
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 +349 -0
- 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 +1043 -0
- package/lib/abis/SwapRouter.js +740 -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 +209 -0
- package/lib/adapters/evm/index.d.ts +353 -0
- package/lib/adapters/evm/index.js +434 -0
- package/lib/adapters/evm/utils.d.ts +8 -0
- package/lib/adapters/evm/utils.js +51 -0
- package/lib/adapters/solana/constants.d.ts +33 -0
- package/lib/adapters/solana/constants.js +52 -0
- package/lib/adapters/solana/getters.d.ts +11 -0
- package/lib/adapters/solana/getters.js +165 -0
- package/lib/adapters/solana/idl/vault-idl.d.ts +272 -0
- package/lib/adapters/solana/idl/vault-idl.js +1084 -0
- package/lib/adapters/solana/index.d.ts +233 -0
- package/lib/adapters/solana/index.js +291 -0
- package/lib/adapters/solana/types.d.ts +67 -0
- package/lib/adapters/solana/types.js +3 -0
- package/lib/adapters/solana/utils.d.ts +141 -0
- package/lib/adapters/solana/utils.js +595 -0
- package/lib/adapters/solana/vault.actions.d.ts +57 -0
- package/lib/adapters/solana/vault.actions.js +379 -0
- package/lib/adapters/stellar/actions.d.ts +28 -0
- package/lib/adapters/stellar/actions.js +77 -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 +114 -0
- package/lib/adapters/stellar/index.js +175 -0
- package/lib/adapters/stellar/soroban.d.ts +123 -0
- package/lib/adapters/stellar/soroban.js +613 -0
- package/lib/adapters/stellar/submit.d.ts +34 -0
- package/lib/adapters/stellar/submit.js +149 -0
- package/lib/adapters/stellar/types.d.ts +58 -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/constants.d.ts +14 -0
- package/lib/adapters/sui/constants.js +29 -0
- package/lib/adapters/sui/getters.d.ts +9 -0
- package/lib/adapters/sui/getters.js +60 -0
- package/lib/adapters/sui/index.d.ts +45 -0
- package/lib/adapters/sui/index.js +101 -0
- package/lib/adapters/sui/transformer.d.ts +10 -0
- package/lib/adapters/sui/transformer.js +107 -0
- package/lib/adapters/sui/types.d.ts +66 -0
- package/lib/adapters/sui/types.js +3 -0
- package/lib/adapters/sui/utils.d.ts +10 -0
- package/lib/adapters/sui/utils.js +29 -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 +5 -0
- package/lib/core/analytics/constants.js +9 -0
- package/lib/core/analytics/env.d.ts +29 -0
- package/lib/core/analytics/env.js +59 -0
- package/lib/core/analytics/index.d.ts +36 -0
- package/lib/core/analytics/index.js +79 -0
- package/lib/core/analytics/instrumentation.d.ts +29 -0
- package/lib/core/analytics/instrumentation.js +277 -0
- package/lib/core/analytics/method-taxonomy.d.ts +19 -0
- package/lib/core/analytics/method-taxonomy.js +128 -0
- package/lib/core/analytics/metrics.d.ts +33 -0
- package/lib/core/analytics/metrics.js +116 -0
- package/lib/core/analytics/sanitize.d.ts +44 -0
- package/lib/core/analytics/sanitize.js +260 -0
- package/lib/core/analytics/sentry-runtime.d.ts +15 -0
- package/lib/core/analytics/sentry-runtime.js +97 -0
- package/lib/core/analytics/sentry.d.ts +67 -0
- package/lib/core/analytics/sentry.js +613 -0
- package/lib/core/analytics/types.d.ts +48 -0
- package/lib/core/analytics/types.js +3 -0
- package/lib/core/analytics/user-identity.d.ts +41 -0
- package/lib/core/analytics/user-identity.js +141 -0
- package/lib/core/analytics/version.d.ts +6 -0
- package/lib/core/analytics/version.js +10 -0
- package/lib/core/attribution.d.ts +111 -0
- package/lib/core/attribution.js +142 -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 +31 -0
- package/lib/core/base.class.d.ts +152 -0
- package/lib/core/base.class.js +172 -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 +133 -0
- package/lib/core/constants/core.js +209 -0
- package/lib/core/constants/swap-router.d.ts +150 -0
- package/lib/core/constants/swap-router.js +169 -0
- package/lib/core/constants/vaults.d.ts +93 -0
- package/lib/core/constants/vaults.js +273 -0
- package/lib/core/constants/web3.d.ts +91 -0
- package/lib/core/constants/web3.js +229 -0
- package/lib/core/errors/index.d.ts +114 -0
- package/lib/core/errors/index.js +183 -0
- package/lib/core/fetcher.d.ts +198 -0
- package/lib/core/fetcher.js +903 -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 +682 -0
- package/lib/core/helpers/chain-support.d.ts +80 -0
- package/lib/core/helpers/chain-support.js +115 -0
- package/lib/core/helpers/core.d.ts +68 -0
- package/lib/core/helpers/core.js +285 -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 +52 -0
- package/lib/core/helpers/signer.js +145 -0
- package/lib/core/helpers/swap-router.d.ts +211 -0
- package/lib/core/helpers/swap-router.js +480 -0
- package/lib/core/helpers/vault-version.d.ts +23 -0
- package/lib/core/helpers/vault-version.js +75 -0
- package/lib/core/helpers/vaults.d.ts +89 -0
- package/lib/core/helpers/vaults.js +235 -0
- package/lib/core/helpers/web3.d.ts +353 -0
- package/lib/core/helpers/web3.js +992 -0
- package/lib/core/index.d.ts +23 -0
- package/lib/core/index.js +40 -0
- package/lib/core/logger/index.d.ts +98 -0
- package/lib/core/logger/index.js +144 -0
- package/lib/core/logger/slack.d.ts +16 -0
- package/lib/core/logger/slack.js +57 -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 +128 -0
- package/lib/evm/methods/crossChainVault.js +853 -0
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +240 -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 +527 -0
- package/lib/main.js +601 -0
- package/lib/modules/api/fetcher.d.ts +82 -0
- package/lib/modules/api/fetcher.js +150 -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 +313 -0
- package/lib/modules/api/main.js +479 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +53 -0
- package/lib/modules/sub-accounts/fetcher.js +120 -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 +243 -0
- package/lib/modules/sub-accounts/main.js +205 -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 +64 -0
- package/lib/modules/vaults/adapter.helpers.js +184 -0
- package/lib/modules/vaults/fetcher.d.ts +147 -0
- package/lib/modules/vaults/fetcher.js +368 -0
- package/lib/modules/vaults/getters.d.ts +570 -0
- package/lib/modules/vaults/getters.js +3051 -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 +601 -0
- package/lib/modules/vaults/main.js +1623 -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 +225 -0
- package/lib/modules/vaults/read.actions.js +596 -0
- package/lib/modules/vaults/types.d.ts +71 -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 +140 -0
- package/lib/modules/vaults/utils.js +799 -0
- package/lib/modules/vaults/write.actions.d.ts +529 -0
- package/lib/modules/vaults/write.actions.js +1749 -0
- package/lib/polyfills.d.ts +1 -0
- package/lib/polyfills.js +12 -0
- package/lib/sdk.d.ts +26721 -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 +38 -0
- package/lib/services/debank/utils.js +297 -0
- package/lib/services/layerzero/deposits.d.ts +49 -0
- package/lib/services/layerzero/deposits.js +166 -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 +9 -0
- package/lib/services/octavfi/fetcher.js +103 -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 +212 -0
- package/lib/services/subgraph/fetcher.d.ts +2 -0
- package/lib/services/subgraph/fetcher.js +61 -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 +45 -0
- package/lib/services/subgraph/schema.js +75 -0
- package/lib/services/subgraph/vaults.d.ts +25 -0
- package/lib/services/subgraph/vaults.js +1106 -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/types/api.d.ts +280 -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 +140 -0
- package/lib/types/sub-accounts.js +3 -0
- package/lib/types/subgraph.d.ts +74 -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 +714 -0
- package/lib/types/vaults.js +24 -0
- package/lib/types/web3.d.ts +51 -0
- package/lib/types/web3.js +14 -0
- package/lib/types/webserver.d.ts +698 -0
- package/lib/types/webserver.js +3 -0
- package/package.json +78 -0
|
@@ -0,0 +1,799 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ERC_20_PERMIT_HASH = exports.getRewardMultiplierByTimestamp = void 0;
|
|
4
|
+
exports.walletClientToSigner = walletClientToSigner;
|
|
5
|
+
exports.getVaultRewards = getVaultRewards;
|
|
6
|
+
exports.getIdleAssets = getIdleAssets;
|
|
7
|
+
exports.getYieldLastRealizedOn = getYieldLastRealizedOn;
|
|
8
|
+
exports.formatVaultApy = formatVaultApy;
|
|
9
|
+
exports.mapVaultFreshness = mapVaultFreshness;
|
|
10
|
+
exports.mapStrategists = mapStrategists;
|
|
11
|
+
exports.mapComposabilityIntegrations = mapComposabilityIntegrations;
|
|
12
|
+
exports.backendTvlToNormalizedBn = backendTvlToNormalizedBn;
|
|
13
|
+
exports.buildBackendVault = buildBackendVault;
|
|
14
|
+
exports.buildFormattedVault = buildFormattedVault;
|
|
15
|
+
exports.generatePermitSignature = generatePermitSignature;
|
|
16
|
+
exports.createDeadline = createDeadline;
|
|
17
|
+
const abis_1 = require("../../abis");
|
|
18
|
+
const core_1 = require("../../core");
|
|
19
|
+
const vaults_1 = require("../../core/helpers/vaults");
|
|
20
|
+
const ethers_1 = require("ethers");
|
|
21
|
+
/**
|
|
22
|
+
* @param walletClient a wagmi-derived client (from useWalletClient)
|
|
23
|
+
* @returns An ethers JsonRpcSigner object used in sdk.evm.setSigner
|
|
24
|
+
*/
|
|
25
|
+
async function walletClientToSigner(walletClient) {
|
|
26
|
+
const { account, chain, transport } = walletClient;
|
|
27
|
+
const network = {
|
|
28
|
+
chainId: chain.id,
|
|
29
|
+
name: chain.name,
|
|
30
|
+
ensAddress: chain.contracts?.ensRegistry?.address,
|
|
31
|
+
};
|
|
32
|
+
//@ts-expect-error
|
|
33
|
+
const provider = new ethers_1.BrowserProvider(transport, network);
|
|
34
|
+
const signer = await provider.getSigner(account.address);
|
|
35
|
+
return signer;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Calculates the reward multiplier based on the vault and optional timestamp.
|
|
39
|
+
* Returns the applicable multiplier for a given vault at a specific timestamp,
|
|
40
|
+
* or the latest multiplier if no timestamp is provided.
|
|
41
|
+
* @param foundPool The vault to get the multiplier for
|
|
42
|
+
* @param timestamp Optional timestamp to get historical multiplier
|
|
43
|
+
* @returns The reward multiplier value
|
|
44
|
+
*/
|
|
45
|
+
const getRewardMultiplierByTimestamp = (foundPool, timestamp) => {
|
|
46
|
+
const multipliers = foundPool.rewards?.multipliers;
|
|
47
|
+
if (!multipliers?.length) {
|
|
48
|
+
return 1; // default multiplier if multipliers are not found
|
|
49
|
+
}
|
|
50
|
+
const multipliersByTimestamp = multipliers.reduce((acc, curr) => {
|
|
51
|
+
return {
|
|
52
|
+
...acc,
|
|
53
|
+
[curr.timestamp]: curr.value,
|
|
54
|
+
};
|
|
55
|
+
}, {});
|
|
56
|
+
if (!multipliersByTimestamp) {
|
|
57
|
+
return 1; // default multiplier if pool is not found
|
|
58
|
+
}
|
|
59
|
+
// return the latest if timestamp not provided
|
|
60
|
+
if (!timestamp) {
|
|
61
|
+
const latest = Object.keys(multipliersByTimestamp)
|
|
62
|
+
.map(Number)
|
|
63
|
+
.sort((a, b) => b - a)[0];
|
|
64
|
+
return latest !== undefined ? (multipliersByTimestamp[latest] ?? 1) : 1;
|
|
65
|
+
}
|
|
66
|
+
const applicableTimestamp = Object.keys(multipliersByTimestamp)
|
|
67
|
+
.map(Number)
|
|
68
|
+
.filter((ts) => ts <= timestamp) // filter only timestamps before or equal to the given timestamp
|
|
69
|
+
.sort((a, b) => b - a)[0]; // get the latest applicable timestamp
|
|
70
|
+
return applicableTimestamp !== undefined
|
|
71
|
+
? (multipliersByTimestamp[applicableTimestamp] ?? 1)
|
|
72
|
+
: 1;
|
|
73
|
+
};
|
|
74
|
+
exports.getRewardMultiplierByTimestamp = getRewardMultiplierByTimestamp;
|
|
75
|
+
/**
|
|
76
|
+
* Build the human-readable display label for a single reward.
|
|
77
|
+
*
|
|
78
|
+
* The format is `"{multiplier}x {text}"`, with the multiplier prefix omitted
|
|
79
|
+
* when it equals 1 (e.g. `"2x Cores"`, `" Cores"` when multiplier is 1 — the
|
|
80
|
+
* leading space is preserved to keep `additionalPoints` and the
|
|
81
|
+
* `additionalPointsDetailed` label in lockstep). This is a display string only;
|
|
82
|
+
* consumers that need a stable key should join on the reward's `id`
|
|
83
|
+
* (see {@link IVaultRewardDetail}), not on this label.
|
|
84
|
+
*
|
|
85
|
+
* @param reward - The raw tokenized-vault reward.
|
|
86
|
+
* @returns The display label string.
|
|
87
|
+
*/
|
|
88
|
+
function getRewardLabel(reward) {
|
|
89
|
+
return `${reward.multiplier !== 1 ? `${reward.multiplier}x` : ''} ${reward.text}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get the rewards for the vault.
|
|
93
|
+
*
|
|
94
|
+
* Builds the display-facing rewards summary from the raw tokenized-vault
|
|
95
|
+
* rewards array. In addition to the legacy `additionalPoints` string list, it
|
|
96
|
+
* emits `additionalPointsDetailed`, which pairs each label with its
|
|
97
|
+
* backend-provided `img_url`. Consumers (e.g. the Upshift app) resolve a
|
|
98
|
+
* reward's logo from this `imgUrl` first, falling back to a bundled asset only
|
|
99
|
+
* when it is absent — so a newly-added reward with a backend logo (e.g.
|
|
100
|
+
* "Cores") renders its icon without any client-side keyword mapping.
|
|
101
|
+
*
|
|
102
|
+
* @param tokenizedVault - The tokenized vault.
|
|
103
|
+
* @returns The rewards summary, including `additionalPointsDetailed`.
|
|
104
|
+
*/
|
|
105
|
+
function getVaultRewards(tokenizedVault) {
|
|
106
|
+
const upshiftPointRewards = tokenizedVault.rewards?.filter((r) => r.text === 'Upshift Points');
|
|
107
|
+
const sortedPointsMultipliers = upshiftPointRewards?.sort((a, b) => new Date(b.start_datetime).getTime() -
|
|
108
|
+
new Date(a.start_datetime).getTime());
|
|
109
|
+
const upshiftPointsMultipliers = sortedPointsMultipliers?.map((r) => ({
|
|
110
|
+
timestamp: new Date(r.start_datetime).getTime() / 1000,
|
|
111
|
+
value: r.multiplier,
|
|
112
|
+
}));
|
|
113
|
+
const latestUpshiftPointMultiplier = upshiftPointsMultipliers?.[0]?.value;
|
|
114
|
+
const rewards = {
|
|
115
|
+
points: upshiftPointRewards.length
|
|
116
|
+
? `${latestUpshiftPointMultiplier}x Upshift Points`
|
|
117
|
+
: '',
|
|
118
|
+
multiplier: latestUpshiftPointMultiplier,
|
|
119
|
+
multipliers: upshiftPointsMultipliers,
|
|
120
|
+
additionalPoints: tokenizedVault.rewards.map(getRewardLabel),
|
|
121
|
+
additionalPointsDetailed: tokenizedVault.rewards.map((r) => ({
|
|
122
|
+
id: r.id,
|
|
123
|
+
label: getRewardLabel(r),
|
|
124
|
+
text: r.text,
|
|
125
|
+
imgUrl: r.img_url || null,
|
|
126
|
+
multiplier: r.multiplier,
|
|
127
|
+
})),
|
|
128
|
+
};
|
|
129
|
+
return rewards;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get the idle assets for the vault
|
|
133
|
+
* @param provider - The provider
|
|
134
|
+
* @param vaultAddress - The vault address
|
|
135
|
+
* @param totalAssets - The total assets of the vault
|
|
136
|
+
* @returns The idle assets
|
|
137
|
+
*/
|
|
138
|
+
async function getIdleAssets(provider, vaultAddress, underlying, totalAssets) {
|
|
139
|
+
const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(vaultAddress))?.[0];
|
|
140
|
+
const version = (0, vaults_1.getVaultVersionV2)(tokenizedVault);
|
|
141
|
+
let idleAssets;
|
|
142
|
+
switch (version) {
|
|
143
|
+
case 'evm-0': {
|
|
144
|
+
// old lending pool
|
|
145
|
+
const globalLoansAmount = await (0, core_1.createContract)({
|
|
146
|
+
provider,
|
|
147
|
+
address: vaultAddress,
|
|
148
|
+
abi: abis_1.ABI_LENDING_POOLS,
|
|
149
|
+
}).globalLoansAmount();
|
|
150
|
+
idleAssets = BigInt(totalAssets.raw) - BigInt(globalLoansAmount);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
case 'evm-2': {
|
|
154
|
+
const vaultContract = (0, core_1.createContract)({
|
|
155
|
+
provider,
|
|
156
|
+
address: vaultAddress,
|
|
157
|
+
abi: abis_1.ABI_TOKENIZED_VAULT_V2,
|
|
158
|
+
});
|
|
159
|
+
const primaryAsset = await vaultContract.asset();
|
|
160
|
+
idleAssets = await (0, core_1.createContract)({
|
|
161
|
+
provider,
|
|
162
|
+
address: primaryAsset,
|
|
163
|
+
abi: abis_1.ABI_ERC20,
|
|
164
|
+
}).balanceOf(vaultAddress);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
default: {
|
|
168
|
+
// tokenized vault
|
|
169
|
+
idleAssets = await (0, core_1.createContract)({
|
|
170
|
+
provider,
|
|
171
|
+
address: underlying,
|
|
172
|
+
abi: abis_1.ABI_ERC20,
|
|
173
|
+
}).balanceOf(vaultAddress);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return idleAssets;
|
|
178
|
+
}
|
|
179
|
+
async function getYieldLastRealizedOn(provider, vaultAddress) {
|
|
180
|
+
const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(vaultAddress))?.[0];
|
|
181
|
+
if (!tokenizedVault) {
|
|
182
|
+
throw new Error(`Vault ${vaultAddress} not found`);
|
|
183
|
+
}
|
|
184
|
+
const version = (0, vaults_1.getVaultVersionV2)(tokenizedVault);
|
|
185
|
+
let assetsUpdatedOn;
|
|
186
|
+
switch (version) {
|
|
187
|
+
case 'evm-2': {
|
|
188
|
+
const contract = (0, core_1.createContract)({
|
|
189
|
+
provider,
|
|
190
|
+
address: vaultAddress,
|
|
191
|
+
abi: abis_1.ABI_TOKENIZED_VAULT_V2,
|
|
192
|
+
});
|
|
193
|
+
assetsUpdatedOn = await contract.assetsUpdatedOn();
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'evm-0': {
|
|
197
|
+
const contract = (0, core_1.createContract)({
|
|
198
|
+
provider,
|
|
199
|
+
address: vaultAddress,
|
|
200
|
+
abi: abis_1.ABI_LENDING_POOL_V3,
|
|
201
|
+
});
|
|
202
|
+
assetsUpdatedOn = await contract.assetsUpdatedOn();
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
case 'sol-0':
|
|
206
|
+
case 'stellar-0': {
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
default: {
|
|
210
|
+
// Default to V3 ABI which has assetsUpdatedOn
|
|
211
|
+
const contract = (0, core_1.createContract)({
|
|
212
|
+
provider,
|
|
213
|
+
address: vaultAddress,
|
|
214
|
+
abi: abis_1.ABI_LENDING_POOL_V3,
|
|
215
|
+
});
|
|
216
|
+
assetsUpdatedOn = await contract.assetsUpdatedOn();
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return Number(assetsUpdatedOn);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Format APY data from backend tokenized vault into the unified IVaultApy shape.
|
|
224
|
+
* Shared across all chain adapters (EVM, Solana, Stellar).
|
|
225
|
+
*/
|
|
226
|
+
function formatVaultApy(tokenizedVault) {
|
|
227
|
+
const { reported_apy, campaign_apy } = tokenizedVault;
|
|
228
|
+
return {
|
|
229
|
+
apy: (reported_apy?.apy ?? 0) * 100,
|
|
230
|
+
explainer: reported_apy?.explainer ?? null,
|
|
231
|
+
pointsApy: reported_apy?.points_apy != null ? reported_apy.points_apy * 100 : null,
|
|
232
|
+
campaignApy: campaign_apy != null ? campaign_apy * 100 : null,
|
|
233
|
+
liquidApy: (reported_apy?.liquid_apy ?? 0) * 100,
|
|
234
|
+
rewardsClaimable: reported_apy?.rewards_claimable ?? null,
|
|
235
|
+
rewardsCompounded: reported_apy?.rewards_compounded ?? null,
|
|
236
|
+
underlyingApy: (reported_apy?.underlying_apy ?? 0) * 100,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Map the backend `freshness` object onto the camelCased {@link IVaultFreshness}
|
|
241
|
+
* shape carried on `IVault`. Shared across all chain adapters (EVM, Solana,
|
|
242
|
+
* Stellar) so every surface reports provenance identically.
|
|
243
|
+
*
|
|
244
|
+
* Each of the three stamps is passed through independently: a missing member
|
|
245
|
+
* becomes `null` and is never defaulted from one of the others. That is the point
|
|
246
|
+
* of the object — `apy_computed_at` and `share_ratio_snapshot_at` describe two
|
|
247
|
+
* different pipelines, and collapsing them would erase the very staleness signal
|
|
248
|
+
* (snapshot newer than APY) the field exists to expose.
|
|
249
|
+
*
|
|
250
|
+
* @param tokenizedVault - Backend tokenized-vault payload. `freshness` is absent on
|
|
251
|
+
* responses predating the backend change, and may be explicitly null.
|
|
252
|
+
* @returns The mapped freshness object, or `null` when the backend reported none.
|
|
253
|
+
* Values are the backend's RFC 3339 UTC strings verbatim — no reformatting, so
|
|
254
|
+
* the trailing `Z` is preserved.
|
|
255
|
+
*/
|
|
256
|
+
function mapVaultFreshness(tokenizedVault) {
|
|
257
|
+
const freshness = tokenizedVault?.freshness;
|
|
258
|
+
if (!freshness)
|
|
259
|
+
return null;
|
|
260
|
+
return {
|
|
261
|
+
apyComputedAt: freshness.apy_computed_at ?? null,
|
|
262
|
+
shareRatioSnapshotAt: freshness.share_ratio_snapshot_at ?? null,
|
|
263
|
+
cachedAt: freshness.cached_at ?? null,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Map strategists from backend subaccounts or hardcoded list.
|
|
268
|
+
* Shared across all chain adapters.
|
|
269
|
+
*/
|
|
270
|
+
function mapStrategists(tokenizedVault) {
|
|
271
|
+
const hasValidStrategists = tokenizedVault.subaccounts?.length > 0 &&
|
|
272
|
+
tokenizedVault.subaccounts.some((s) => s.strategist !== null);
|
|
273
|
+
return hasValidStrategists
|
|
274
|
+
? tokenizedVault.subaccounts
|
|
275
|
+
.filter((s) => s.strategist !== null)
|
|
276
|
+
.map((s) => ({
|
|
277
|
+
address: s.address,
|
|
278
|
+
logo: s.strategist?.strategist_logo,
|
|
279
|
+
name: s.strategist?.strategist_name,
|
|
280
|
+
type: 'subaccount',
|
|
281
|
+
website_url: s.strategist?.website_url ?? null,
|
|
282
|
+
}))
|
|
283
|
+
: (tokenizedVault.hardcoded_strategists || []).map((s) => ({
|
|
284
|
+
address: '0x',
|
|
285
|
+
logo: s.strategist_logo,
|
|
286
|
+
name: s.strategist_name,
|
|
287
|
+
type: 'subaccount',
|
|
288
|
+
website_url: s.website_url ?? null,
|
|
289
|
+
}));
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Map composability integrations from backend format to vault format.
|
|
293
|
+
* Shared across all chain adapters.
|
|
294
|
+
*/
|
|
295
|
+
function mapComposabilityIntegrations(tokenizedVault) {
|
|
296
|
+
return (tokenizedVault.composability_integrations?.map((integration) => ({
|
|
297
|
+
name: integration.name,
|
|
298
|
+
description: integration.description,
|
|
299
|
+
earningMultiplier: integration.earning_multiplier,
|
|
300
|
+
protocolUrl: integration.protocol_url,
|
|
301
|
+
logoUrl: integration.logo_url,
|
|
302
|
+
tokenizedVaultId: integration.tokenized_vault_id,
|
|
303
|
+
id: integration.id,
|
|
304
|
+
})) || []);
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Convert a backend-reported TVL (whole token units) to a NormalizedBn.
|
|
308
|
+
* Handles null, undefined, and non-finite values (NaN, Infinity) safely, defaulting to 0.
|
|
309
|
+
* Shared between non-EVM adapters (Solana, Stellar) and the module-level getVaultTvl handler.
|
|
310
|
+
*/
|
|
311
|
+
function backendTvlToNormalizedBn(tvl, decimals) {
|
|
312
|
+
if (tvl == null) {
|
|
313
|
+
core_1.Logger.log.warn('backendTvlToNormalizedBn', 'TVL is null/undefined, defaulting to 0 — check backend data pipeline', { decimals });
|
|
314
|
+
return (0, core_1.toNormalizedBn)(BigInt(0), decimals);
|
|
315
|
+
}
|
|
316
|
+
if (!Number.isFinite(tvl) || tvl < 0) {
|
|
317
|
+
core_1.Logger.log.warn('backendTvlToNormalizedBn', tvl < 0
|
|
318
|
+
? 'Negative TVL value, defaulting to 0'
|
|
319
|
+
: 'Non-finite TVL value, defaulting to 0', { tvl, decimals });
|
|
320
|
+
return (0, core_1.toNormalizedBn)(BigInt(0), decimals);
|
|
321
|
+
}
|
|
322
|
+
const scaleFactor = BigInt(10) ** BigInt(decimals);
|
|
323
|
+
const tvlWhole = BigInt(Math.round(tvl));
|
|
324
|
+
return (0, core_1.toNormalizedBn)(tvlWhole * scaleFactor, decimals);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Map daily PnL per share from backend Record format to array format.
|
|
328
|
+
* Shared across non-EVM adapters.
|
|
329
|
+
*/
|
|
330
|
+
function mapDailyPnlPerShare(dailyPnl) {
|
|
331
|
+
if (!dailyPnl)
|
|
332
|
+
return [];
|
|
333
|
+
return Object.entries(dailyPnl).map(([timestamp, value]) => ({
|
|
334
|
+
timestamp,
|
|
335
|
+
value,
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Build a base IVault from backend data, shared across non-EVM adapters (Solana, Stellar).
|
|
340
|
+
* Chain-specific fields (chainId, version, name, totalAssets, totalSupply, depositAssets, receipt)
|
|
341
|
+
* must be provided via the overrides parameter.
|
|
342
|
+
*/
|
|
343
|
+
function buildBackendVault(tokenizedVault, overrides) {
|
|
344
|
+
const apy = formatVaultApy(tokenizedVault);
|
|
345
|
+
const rewards = tokenizedVault.rewards?.length
|
|
346
|
+
? getVaultRewards(tokenizedVault)
|
|
347
|
+
: {
|
|
348
|
+
points: '0',
|
|
349
|
+
multiplier: 0,
|
|
350
|
+
multipliers: [],
|
|
351
|
+
additionalPoints: [],
|
|
352
|
+
additionalPointsDetailed: [],
|
|
353
|
+
};
|
|
354
|
+
return {
|
|
355
|
+
operator: '0x',
|
|
356
|
+
eoa_operators: [],
|
|
357
|
+
operators: [],
|
|
358
|
+
historical_snapshots: tokenizedVault.historical_snapshots || [],
|
|
359
|
+
address: tokenizedVault.address,
|
|
360
|
+
historical_apy: tokenizedVault.historical_apy,
|
|
361
|
+
historical_compound_apy: tokenizedVault.historical_compound_apy,
|
|
362
|
+
max_drawdown: tokenizedVault.max_drawdown,
|
|
363
|
+
logoUrl: tokenizedVault.vault_logo_url || '/img/strategist/august.svg',
|
|
364
|
+
description: tokenizedVault.description || '',
|
|
365
|
+
startDatetime: tokenizedVault.start_datetime
|
|
366
|
+
? new Date(tokenizedVault.start_datetime).toISOString()
|
|
367
|
+
: new Date(0).toISOString(),
|
|
368
|
+
status: tokenizedVault.status,
|
|
369
|
+
tags: [tokenizedVault.public_type || 'Defi Yield'],
|
|
370
|
+
isFeatured: tokenizedVault.is_featured || false,
|
|
371
|
+
isSpotlighted: tokenizedVault.is_spotlighted ?? false,
|
|
372
|
+
withdrawalOnly: tokenizedVault.withdrawal_only ?? false,
|
|
373
|
+
isVisible: tokenizedVault.is_visible || false,
|
|
374
|
+
reserveTarget: tokenizedVault.reserve_target || 0,
|
|
375
|
+
reserveTolerance: tokenizedVault.reserve_tolerance || 0,
|
|
376
|
+
// Vault decimals are derived from the receipt token decimals for non-EVM vaults
|
|
377
|
+
decimals: overrides.receipt.decimals,
|
|
378
|
+
maxSupply: (0, core_1.toNormalizedBn)(1_000_000_000),
|
|
379
|
+
depositCap: null,
|
|
380
|
+
apy,
|
|
381
|
+
rewards,
|
|
382
|
+
fees: {
|
|
383
|
+
performance: tokenizedVault.weekly_performance_fee_bps || 0,
|
|
384
|
+
management: tokenizedVault.platform_fee_override?.management_fee || 0,
|
|
385
|
+
isManagementWaived: (0, vaults_1.resolveFeeWaived)(tokenizedVault.platform_fee_override?.is_fee_waived ?? false, tokenizedVault.management_fee_waived_until_date ?? null, tokenizedVault.management_fee_waived_until_tvl ?? null),
|
|
386
|
+
managementFeeWaivedUntilDate: tokenizedVault.management_fee_waived_until_date ?? null,
|
|
387
|
+
managementFeeWaivedUntilTvl: tokenizedVault.management_fee_waived_until_tvl ?? null,
|
|
388
|
+
isPerformanceWaived: (0, vaults_1.resolveFeeWaived)(tokenizedVault.platform_fee_override?.is_fee_waived ?? false, tokenizedVault.performance_fee_waived_until_date ?? null, tokenizedVault.performance_fee_waived_until_tvl ?? null),
|
|
389
|
+
performanceFeeWaivedUntilDate: tokenizedVault.performance_fee_waived_until_date ?? null,
|
|
390
|
+
performanceFeeWaivedUntilTvl: tokenizedVault.performance_fee_waived_until_tvl ?? null,
|
|
391
|
+
},
|
|
392
|
+
lagDuration: 0,
|
|
393
|
+
withdrawalMarginSeconds: tokenizedVault.withdrawal_margin_seconds ?? null,
|
|
394
|
+
iatTraders: tokenizedVault.iat_traders ?? null,
|
|
395
|
+
maxDailyDrawdown: tokenizedVault.max_daily_drawdown || 0,
|
|
396
|
+
risk: tokenizedVault.risk || 'low',
|
|
397
|
+
isWithdrawalPaused: false,
|
|
398
|
+
isDepositPaused: false,
|
|
399
|
+
idleAssets: (0, core_1.toNormalizedBn)(0),
|
|
400
|
+
loans: [],
|
|
401
|
+
allocations: {
|
|
402
|
+
unfilteredTokens: [],
|
|
403
|
+
defi: [],
|
|
404
|
+
tokens: [],
|
|
405
|
+
cefi: [],
|
|
406
|
+
otc: {},
|
|
407
|
+
exposurePerCategory: {
|
|
408
|
+
borrowing: [],
|
|
409
|
+
supplying: [],
|
|
410
|
+
lending: [],
|
|
411
|
+
wallet: [],
|
|
412
|
+
cefiBalance: 0,
|
|
413
|
+
defiBalance: 0,
|
|
414
|
+
walletBalance: 0,
|
|
415
|
+
loanBalance: 0,
|
|
416
|
+
},
|
|
417
|
+
netValue: 0,
|
|
418
|
+
defiPerBorrower: {},
|
|
419
|
+
},
|
|
420
|
+
position: {
|
|
421
|
+
vault: tokenizedVault.address,
|
|
422
|
+
status: 'active',
|
|
423
|
+
availableRedemptions: [],
|
|
424
|
+
pendingRedemptions: [],
|
|
425
|
+
redeemable: (0, core_1.toNormalizedBn)(0),
|
|
426
|
+
walletBalance: (0, core_1.toNormalizedBn)(0),
|
|
427
|
+
},
|
|
428
|
+
composabilityIntegrations: mapComposabilityIntegrations(tokenizedVault),
|
|
429
|
+
strategists: mapStrategists(tokenizedVault),
|
|
430
|
+
cachedAt: tokenizedVault.cached_at ?? null,
|
|
431
|
+
freshness: mapVaultFreshness(tokenizedVault),
|
|
432
|
+
dailyPnlPerShare: mapDailyPnlPerShare(tokenizedVault.daily_pnl_per_share),
|
|
433
|
+
enabled_historical_price_horizons: tokenizedVault.enabled_historical_price_horizons || [],
|
|
434
|
+
latest_reported_tvl: tokenizedVault.latest_reported_tvl,
|
|
435
|
+
defaultApyHorizon: tokenizedVault.default_apy_horizon,
|
|
436
|
+
...(tokenizedVault.instant_redeem_config
|
|
437
|
+
? {
|
|
438
|
+
instant_redeem_config: {
|
|
439
|
+
subaccountAddress: tokenizedVault.instant_redeem_config
|
|
440
|
+
.subaccount_address,
|
|
441
|
+
outputAssetSymbol: tokenizedVault.instant_redeem_config.output_asset_symbol,
|
|
442
|
+
redeemableAssets: tokenizedVault.instant_redeem_config.redeemable_assets.map((a) => ({
|
|
443
|
+
address: a.address,
|
|
444
|
+
symbol: a.symbol,
|
|
445
|
+
decimals: a.decimals,
|
|
446
|
+
spreadBps: a.spread_bps,
|
|
447
|
+
})),
|
|
448
|
+
isPaused: tokenizedVault.instant_redeem_config.is_paused,
|
|
449
|
+
availableLiquidity: tokenizedVault.instant_redeem_config.available_liquidity,
|
|
450
|
+
},
|
|
451
|
+
}
|
|
452
|
+
: {}),
|
|
453
|
+
showCapFilled: tokenizedVault?.show_cap_filled ?? null,
|
|
454
|
+
apyOverride: tokenizedVault.apy_override ?? null,
|
|
455
|
+
// Spread chain-specific overrides last so they take precedence
|
|
456
|
+
...overrides,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
/**
|
|
460
|
+
* Build the formatted vault
|
|
461
|
+
* @param provider - The provider
|
|
462
|
+
* @param tokenizedVault - The tokenized vault
|
|
463
|
+
* @param contractCalls - The contract calls
|
|
464
|
+
* @returns The formatted vault
|
|
465
|
+
*/
|
|
466
|
+
async function buildFormattedVault(provider, tokenizedVault, contractCalls) {
|
|
467
|
+
const strategists = mapStrategists(tokenizedVault);
|
|
468
|
+
const operators = tokenizedVault?.operators || [];
|
|
469
|
+
const eoa_operators = tokenizedVault?.eoa_operators || [];
|
|
470
|
+
// Load offchain props
|
|
471
|
+
const baseProps = {
|
|
472
|
+
chainId: tokenizedVault.chain,
|
|
473
|
+
maxDailyDrawdown: tokenizedVault.max_daily_drawdown || 0,
|
|
474
|
+
risk: tokenizedVault.risk,
|
|
475
|
+
lagDuration: Number(contractCalls.lagDuration),
|
|
476
|
+
withdrawalMarginSeconds: tokenizedVault.withdrawal_margin_seconds ?? null,
|
|
477
|
+
iatTraders: tokenizedVault.iat_traders ?? null,
|
|
478
|
+
address: tokenizedVault.address,
|
|
479
|
+
name: tokenizedVault.vault_name,
|
|
480
|
+
logoUrl: tokenizedVault.vault_logo_url,
|
|
481
|
+
apy: {
|
|
482
|
+
apy: tokenizedVault?.reported_apy?.apy
|
|
483
|
+
? tokenizedVault.reported_apy.apy * 100
|
|
484
|
+
: null,
|
|
485
|
+
pointsApy: tokenizedVault?.reported_apy?.points_apy
|
|
486
|
+
? tokenizedVault.reported_apy.points_apy * 100
|
|
487
|
+
: null,
|
|
488
|
+
campaignApy: tokenizedVault?.campaign_apy
|
|
489
|
+
? tokenizedVault.campaign_apy * 100
|
|
490
|
+
: null,
|
|
491
|
+
explainer: tokenizedVault?.reported_apy?.explainer,
|
|
492
|
+
liquidApy: tokenizedVault?.reported_apy?.liquid_apy * 100,
|
|
493
|
+
rewardsClaimable: tokenizedVault?.reported_apy?.rewards_claimable,
|
|
494
|
+
rewardsCompounded: tokenizedVault?.reported_apy?.rewards_compounded,
|
|
495
|
+
underlyingApy: tokenizedVault?.reported_apy?.underlying_apy * 100,
|
|
496
|
+
},
|
|
497
|
+
strategists: strategists,
|
|
498
|
+
eoa_operators,
|
|
499
|
+
operators,
|
|
500
|
+
fees: {
|
|
501
|
+
performance: tokenizedVault.weekly_performance_fee_bps,
|
|
502
|
+
management: tokenizedVault.platform_fee_override.management_fee,
|
|
503
|
+
isManagementWaived: (0, vaults_1.resolveFeeWaived)(tokenizedVault.platform_fee_override.is_fee_waived, tokenizedVault.management_fee_waived_until_date, tokenizedVault.management_fee_waived_until_tvl),
|
|
504
|
+
managementFeeWaivedUntilDate: tokenizedVault.management_fee_waived_until_date,
|
|
505
|
+
managementFeeWaivedUntilTvl: tokenizedVault.management_fee_waived_until_tvl,
|
|
506
|
+
isPerformanceWaived: (0, vaults_1.resolveFeeWaived)(tokenizedVault.platform_fee_override.is_fee_waived, tokenizedVault.performance_fee_waived_until_date, tokenizedVault.performance_fee_waived_until_tvl),
|
|
507
|
+
performanceFeeWaivedUntilDate: tokenizedVault.performance_fee_waived_until_date,
|
|
508
|
+
performanceFeeWaivedUntilTvl: tokenizedVault.performance_fee_waived_until_tvl,
|
|
509
|
+
},
|
|
510
|
+
rewards: getVaultRewards(tokenizedVault),
|
|
511
|
+
version: (0, vaults_1.getVaultVersionV2)(tokenizedVault),
|
|
512
|
+
description: tokenizedVault.description,
|
|
513
|
+
startDatetime: String(tokenizedVault.start_datetime),
|
|
514
|
+
status: tokenizedVault.status,
|
|
515
|
+
tags: [tokenizedVault.public_type],
|
|
516
|
+
isFeatured: tokenizedVault.is_featured,
|
|
517
|
+
withdrawalOnly: tokenizedVault.withdrawal_only ?? false,
|
|
518
|
+
isSpotlighted: tokenizedVault.is_spotlighted ?? false,
|
|
519
|
+
isVisible: tokenizedVault.is_visible,
|
|
520
|
+
reserveTarget: tokenizedVault.reserve_target,
|
|
521
|
+
reserveTolerance: tokenizedVault.reserve_tolerance,
|
|
522
|
+
isDepositPaused: (0, vaults_1.isBadVault)(tokenizedVault.address),
|
|
523
|
+
decimals: contractCalls.decimals,
|
|
524
|
+
isWithdrawalPaused: contractCalls.withdrawalsPaused,
|
|
525
|
+
idleAssets: (0, core_1.toNormalizedBn)(await getIdleAssets(provider, tokenizedVault.address, contractCalls.asset, contractCalls.totalAssets), Number(contractCalls.decimals)),
|
|
526
|
+
};
|
|
527
|
+
// Version specific logic
|
|
528
|
+
const version = (0, vaults_1.getVaultVersionV2)(tokenizedVault);
|
|
529
|
+
let operator = '0x';
|
|
530
|
+
let depositAssets = [];
|
|
531
|
+
let totalAssets = (0, core_1.toNormalizedBn)(0);
|
|
532
|
+
let totalSupply = (0, core_1.toNormalizedBn)(0);
|
|
533
|
+
let maxSupply = (0, core_1.toNormalizedBn)(0);
|
|
534
|
+
let depositCap = null;
|
|
535
|
+
let maxDepositAmount = null;
|
|
536
|
+
let receipt = {
|
|
537
|
+
symbol: '',
|
|
538
|
+
address: '0x',
|
|
539
|
+
decimals: 0,
|
|
540
|
+
};
|
|
541
|
+
switch (version) {
|
|
542
|
+
case 'sol-0': {
|
|
543
|
+
// @todo
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
case 'evm-2': {
|
|
547
|
+
totalAssets = contractCalls.getTotalAssets;
|
|
548
|
+
depositAssets.push({
|
|
549
|
+
address: contractCalls.asset,
|
|
550
|
+
symbol: await (0, core_1.getSymbol)(provider, contractCalls.asset, false),
|
|
551
|
+
decimals: contractCalls.decimals,
|
|
552
|
+
});
|
|
553
|
+
const extraAssets = await Promise.all(contractCalls.getWhitelistedAssets.map(async (a) => {
|
|
554
|
+
const decimals = await (0, core_1.getDecimals)(provider, a, false);
|
|
555
|
+
const symbol = await (0, core_1.getSymbol)(provider, a, false);
|
|
556
|
+
return {
|
|
557
|
+
address: a,
|
|
558
|
+
symbol,
|
|
559
|
+
decimals,
|
|
560
|
+
};
|
|
561
|
+
}));
|
|
562
|
+
if (contractCalls.depositCap) {
|
|
563
|
+
depositCap = contractCalls.depositCap;
|
|
564
|
+
}
|
|
565
|
+
depositAssets = [...depositAssets, ...extraAssets];
|
|
566
|
+
totalSupply = contractCalls.totalSupply;
|
|
567
|
+
(maxSupply =
|
|
568
|
+
(0, core_1.toNormalizedBn)(1_000_000_000_000)), // @hardcoded: no maxSupply on here
|
|
569
|
+
(receipt = {
|
|
570
|
+
symbol: tokenizedVault.receipt_token_symbol,
|
|
571
|
+
address: contractCalls.lpTokenAddress,
|
|
572
|
+
decimals: contractCalls.decimals,
|
|
573
|
+
});
|
|
574
|
+
// @todo: get operator
|
|
575
|
+
// operator = contractCalls.loansOperator as IAddress;
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
default: {
|
|
579
|
+
// get idle assets
|
|
580
|
+
depositAssets = [
|
|
581
|
+
{
|
|
582
|
+
address: contractCalls.asset,
|
|
583
|
+
symbol: await (0, core_1.getSymbol)(provider, contractCalls.asset, false),
|
|
584
|
+
decimals: contractCalls.decimals,
|
|
585
|
+
},
|
|
586
|
+
];
|
|
587
|
+
totalAssets = contractCalls.totalAssets;
|
|
588
|
+
totalSupply = contractCalls.totalSupply;
|
|
589
|
+
maxSupply = contractCalls.maxSupply;
|
|
590
|
+
if (contractCalls.maxDepositAmount) {
|
|
591
|
+
maxDepositAmount = contractCalls.maxDepositAmount;
|
|
592
|
+
}
|
|
593
|
+
operator = contractCalls.loansOperator;
|
|
594
|
+
receipt = {
|
|
595
|
+
symbol: tokenizedVault.receipt_token_symbol,
|
|
596
|
+
address: tokenizedVault.address,
|
|
597
|
+
decimals: contractCalls.decimals,
|
|
598
|
+
};
|
|
599
|
+
break;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
// Check for adapter configuration and add adapter deposit tokens
|
|
603
|
+
const adapterConfig = (0, core_1.getVaultAdapterConfig)(tokenizedVault.address);
|
|
604
|
+
if (adapterConfig) {
|
|
605
|
+
const allDepositTokens = (0, core_1.getVaultDepositTokens)(tokenizedVault.address, contractCalls.asset);
|
|
606
|
+
// Build deposit assets array including adapter tokens
|
|
607
|
+
const depositAssetsWithAdapters = await Promise.all(allDepositTokens.map(async (tokenAddress) => {
|
|
608
|
+
// Skip if already in depositAssets
|
|
609
|
+
if (depositAssets.find((a) => a.address.toLowerCase() === tokenAddress.toLowerCase())) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
const decimals = await (0, core_1.getDecimals)(provider, tokenAddress, false);
|
|
613
|
+
const symbol = await (0, core_1.getSymbol)(provider, tokenAddress, false);
|
|
614
|
+
return {
|
|
615
|
+
address: tokenAddress,
|
|
616
|
+
symbol,
|
|
617
|
+
decimals,
|
|
618
|
+
};
|
|
619
|
+
}));
|
|
620
|
+
// Add adapter tokens to depositAssets
|
|
621
|
+
depositAssets = [
|
|
622
|
+
...depositAssets,
|
|
623
|
+
...depositAssetsWithAdapters.filter((a) => a !== null),
|
|
624
|
+
];
|
|
625
|
+
}
|
|
626
|
+
const result = {
|
|
627
|
+
...baseProps,
|
|
628
|
+
operator: operator,
|
|
629
|
+
depositAssets: depositAssets,
|
|
630
|
+
totalAssets: totalAssets,
|
|
631
|
+
totalSupply: totalSupply,
|
|
632
|
+
maxSupply: maxSupply,
|
|
633
|
+
depositCap: depositCap,
|
|
634
|
+
maxDepositAmount: maxDepositAmount,
|
|
635
|
+
receipt: receipt,
|
|
636
|
+
historical_apy: tokenizedVault?.historical_apy,
|
|
637
|
+
historical_compound_apy: tokenizedVault?.historical_compound_apy,
|
|
638
|
+
historical_snapshots: tokenizedVault?.historical_snapshots || [],
|
|
639
|
+
max_drawdown: tokenizedVault?.max_drawdown,
|
|
640
|
+
composabilityIntegrations: mapComposabilityIntegrations(tokenizedVault),
|
|
641
|
+
dailyPnlPerShare: tokenizedVault?.daily_pnl_per_share
|
|
642
|
+
? Object.entries(tokenizedVault.daily_pnl_per_share).map(([timestamp, value]) => ({
|
|
643
|
+
timestamp,
|
|
644
|
+
value,
|
|
645
|
+
}))
|
|
646
|
+
: [],
|
|
647
|
+
enabled_historical_price_horizons: tokenizedVault?.enabled_historical_price_horizons,
|
|
648
|
+
defaultApyHorizon: tokenizedVault?.default_apy_horizon ?? null,
|
|
649
|
+
latest_reported_tvl: tokenizedVault?.latest_reported_tvl,
|
|
650
|
+
cachedAt: tokenizedVault?.cached_at ?? null,
|
|
651
|
+
freshness: mapVaultFreshness(tokenizedVault),
|
|
652
|
+
showCapFilled: tokenizedVault?.show_cap_filled ?? null,
|
|
653
|
+
apyOverride: tokenizedVault?.apy_override ?? null,
|
|
654
|
+
};
|
|
655
|
+
if (tokenizedVault.instant_redeem_config) {
|
|
656
|
+
const config = tokenizedVault.instant_redeem_config;
|
|
657
|
+
result.instant_redeem_config = {
|
|
658
|
+
subaccountAddress: config.subaccount_address,
|
|
659
|
+
outputAssetSymbol: config.output_asset_symbol,
|
|
660
|
+
redeemableAssets: config.redeemable_assets.map((a) => ({
|
|
661
|
+
address: a.address,
|
|
662
|
+
symbol: a.symbol,
|
|
663
|
+
decimals: a.decimals,
|
|
664
|
+
spreadBps: a.spread_bps,
|
|
665
|
+
})),
|
|
666
|
+
isPaused: config.is_paused,
|
|
667
|
+
availableLiquidity: config.available_liquidity,
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
return result;
|
|
671
|
+
}
|
|
672
|
+
exports.ERC_20_PERMIT_HASH = '0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9';
|
|
673
|
+
/**
|
|
674
|
+
* Generate an ERC2612 permit signature
|
|
675
|
+
* @param token - The ERC20 token contract address
|
|
676
|
+
* @param owner - The token owner's address (signer)
|
|
677
|
+
* @param spender - The address that will be approved to spend (your pool contract)
|
|
678
|
+
* @param value - The amount to approve
|
|
679
|
+
* @param deadline - Unix timestamp for when the permit expires
|
|
680
|
+
* @param signer - The ethers.js Signer (wallet)
|
|
681
|
+
* @param provider - The ethers.js Provider
|
|
682
|
+
* @returns The signature components (v, r, s) and deadline
|
|
683
|
+
*/
|
|
684
|
+
async function generatePermitSignature(token, owner, spender, value, deadline, signer, chainId) {
|
|
685
|
+
const tokenContract = (0, core_1.createContract)({
|
|
686
|
+
address: token,
|
|
687
|
+
provider: signer,
|
|
688
|
+
abi: abis_1.ABI_TOKENIZED_VAULT_V2_RECEIPT,
|
|
689
|
+
});
|
|
690
|
+
const noncePromise = tokenContract.nonces(owner);
|
|
691
|
+
const domainSeparatorPromise = (async () => {
|
|
692
|
+
try {
|
|
693
|
+
return await tokenContract.DOMAIN_SEPARATOR();
|
|
694
|
+
}
|
|
695
|
+
catch (error) {
|
|
696
|
+
core_1.Logger.log.error('generatePermitSignature', error, {
|
|
697
|
+
message: 'Could not fetch DOMAIN_SEPARATOR from contract',
|
|
698
|
+
});
|
|
699
|
+
throw error;
|
|
700
|
+
}
|
|
701
|
+
})();
|
|
702
|
+
const [nonce, contractDomainSeparator] = await Promise.all([
|
|
703
|
+
noncePromise,
|
|
704
|
+
domainSeparatorPromise,
|
|
705
|
+
]);
|
|
706
|
+
const valueBigInt = typeof value === 'string' ? BigInt(value) : value;
|
|
707
|
+
const permitDomainCacheKey = `permit-domain-${chainId}-${token.toLowerCase()}`;
|
|
708
|
+
const cachedDomain = core_1.CACHE.get(permitDomainCacheKey);
|
|
709
|
+
let matchingDomain = null;
|
|
710
|
+
if (cachedDomain) {
|
|
711
|
+
const cachedHash = ethers_1.ethers.TypedDataEncoder.hashDomain(cachedDomain);
|
|
712
|
+
if (cachedHash.toLowerCase() === contractDomainSeparator.toLowerCase()) {
|
|
713
|
+
matchingDomain = cachedDomain;
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
core_1.CACHE.delete(permitDomainCacheKey);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (!matchingDomain) {
|
|
720
|
+
const name = (await tokenContract.name());
|
|
721
|
+
// Try different domain configurations to find which matches
|
|
722
|
+
const domainConfigs = [
|
|
723
|
+
// Standard EIP-2612
|
|
724
|
+
{ name, version: '1', chainId, verifyingContract: token },
|
|
725
|
+
{ name, version: '2', chainId, verifyingContract: token },
|
|
726
|
+
// Without version
|
|
727
|
+
{ name, chainId, verifyingContract: token },
|
|
728
|
+
// With different salt values (some contracts use this)
|
|
729
|
+
{
|
|
730
|
+
name,
|
|
731
|
+
version: '1',
|
|
732
|
+
chainId,
|
|
733
|
+
verifyingContract: token,
|
|
734
|
+
salt: ethers_1.ethers.zeroPadValue('0x', 32),
|
|
735
|
+
},
|
|
736
|
+
];
|
|
737
|
+
for (const domain of domainConfigs) {
|
|
738
|
+
const computed = ethers_1.ethers.TypedDataEncoder.hashDomain(domain);
|
|
739
|
+
if (computed.toLowerCase() === contractDomainSeparator.toLowerCase()) {
|
|
740
|
+
matchingDomain = domain;
|
|
741
|
+
break;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
if (!matchingDomain) {
|
|
745
|
+
// If no match, try to get the version from the contract
|
|
746
|
+
// Some token contracts have a version() method for EIP-2612 domain
|
|
747
|
+
try {
|
|
748
|
+
const version = await tokenContract.version();
|
|
749
|
+
matchingDomain = { name, version, chainId, verifyingContract: token };
|
|
750
|
+
const computed = ethers_1.ethers.TypedDataEncoder.hashDomain(matchingDomain);
|
|
751
|
+
if (computed.toLowerCase() !== contractDomainSeparator.toLowerCase()) {
|
|
752
|
+
throw new Error('Could not match DOMAIN_SEPARATOR even with contract version');
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
catch {
|
|
756
|
+
throw new Error(`Could not determine correct domain configuration. Contract DOMAIN_SEPARATOR: ${contractDomainSeparator}`);
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
core_1.CACHE.set(permitDomainCacheKey, matchingDomain, {
|
|
760
|
+
ttl: 60 * 60 * 1000,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
// EIP-2612 Permit type
|
|
764
|
+
const types = {
|
|
765
|
+
Permit: [
|
|
766
|
+
{ name: 'owner', type: 'address' },
|
|
767
|
+
{ name: 'spender', type: 'address' },
|
|
768
|
+
{ name: 'value', type: 'uint256' },
|
|
769
|
+
{ name: 'nonce', type: 'uint256' },
|
|
770
|
+
{ name: 'deadline', type: 'uint256' },
|
|
771
|
+
],
|
|
772
|
+
};
|
|
773
|
+
const message = {
|
|
774
|
+
owner: owner,
|
|
775
|
+
spender: spender,
|
|
776
|
+
value: valueBigInt,
|
|
777
|
+
nonce: Number(nonce),
|
|
778
|
+
deadline: deadline,
|
|
779
|
+
};
|
|
780
|
+
// Sign the typed data
|
|
781
|
+
const signature = await signer.signTypedData(matchingDomain, types, message);
|
|
782
|
+
// Split signature into r, s, v
|
|
783
|
+
const sig = ethers_1.ethers.Signature.from(signature);
|
|
784
|
+
return {
|
|
785
|
+
r: sig.r,
|
|
786
|
+
s: sig.s,
|
|
787
|
+
v: sig.v,
|
|
788
|
+
deadline: deadline,
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Helper to create a deadline (current time + offset in seconds)
|
|
793
|
+
* @param offsetSeconds - Number of seconds from now (default: 20 minutes)
|
|
794
|
+
* @returns Unix timestamp
|
|
795
|
+
*/
|
|
796
|
+
function createDeadline(offsetSeconds = 1200) {
|
|
797
|
+
return Math.floor(Date.now() / 1000) + offsetSeconds;
|
|
798
|
+
}
|
|
799
|
+
//# sourceMappingURL=utils.js.map
|