@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,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared LayerZero utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.addressToBytes32 = addressToBytes32;
|
|
7
|
+
/**
|
|
8
|
+
* Convert Ethereum address to bytes32 format (left-padded with zeros)
|
|
9
|
+
* Used by LayerZero subgraph queries where addresses are stored in bytes32 format.
|
|
10
|
+
* @throws {Error} If address format is invalid
|
|
11
|
+
*/
|
|
12
|
+
function addressToBytes32(address) {
|
|
13
|
+
// Validate address format
|
|
14
|
+
if (!address.match(/^0x[a-fA-F0-9]{40}$/)) {
|
|
15
|
+
throw new Error(`Invalid Ethereum address format: ${address}. Expected format: 0x followed by 40 hexadecimal characters.`);
|
|
16
|
+
}
|
|
17
|
+
// Remove 0x prefix and convert to lowercase
|
|
18
|
+
const cleanAddress = address.replace(/^0x/i, '').toLowerCase();
|
|
19
|
+
// Pad with 24 zeros (12 bytes) to make it 32 bytes total
|
|
20
|
+
return '0x' + '0'.repeat(24) + cleanAddress;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IAddress, IWSMonitorHeaders } from '../../types';
|
|
2
|
+
import type { IOctavfiPortfolio } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Response of the Upshift API's vault-level Octav endpoint.
|
|
5
|
+
*
|
|
6
|
+
* Keys are the vault's Solana operator addresses (case-sensitive base58).
|
|
7
|
+
* Values are the operator's raw Octav portfolio, or an `{ error }` object when
|
|
8
|
+
* the backend holds no usable portfolio for that operator.
|
|
9
|
+
*/
|
|
10
|
+
export type IVaultOctavResponse = Record<string, IOctavfiPortfolio | {
|
|
11
|
+
error: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch the Octav portfolios of every Solana operator of a vault in a single
|
|
15
|
+
* request to the Upshift public API.
|
|
16
|
+
*
|
|
17
|
+
* The API serves these from a cache that a backend cron refreshes, so this
|
|
18
|
+
* function never calls Octav and needs no Octav credentials. It makes exactly
|
|
19
|
+
* one HTTP request per call and never throws.
|
|
20
|
+
*
|
|
21
|
+
* @param vaultAddress - Vault address: EVM hex or Solana base58.
|
|
22
|
+
* @param headers - Optional monitoring headers forwarded with the request.
|
|
23
|
+
* @returns Dictionary of operator address to portfolio or error on a 200 or
|
|
24
|
+
* 207 (partial success) response; `false` on any other status or when the
|
|
25
|
+
* request fails.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```ts
|
|
29
|
+
* const response = await fetchVaultOctavResponse(vaultAddress);
|
|
30
|
+
* const portfolio = response ? response[borrower] : undefined;
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function fetchVaultOctavResponse(vaultAddress: IAddress, headers?: IWSMonitorHeaders): Promise<IVaultOctavResponse | false>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchVaultOctavResponse = fetchVaultOctavResponse;
|
|
4
|
+
const core_1 = require("../../core");
|
|
5
|
+
/**
|
|
6
|
+
* Fetch the Octav portfolios of every Solana operator of a vault in a single
|
|
7
|
+
* request to the Upshift public API.
|
|
8
|
+
*
|
|
9
|
+
* The API serves these from a cache that a backend cron refreshes, so this
|
|
10
|
+
* function never calls Octav and needs no Octav credentials. It makes exactly
|
|
11
|
+
* one HTTP request per call and never throws.
|
|
12
|
+
*
|
|
13
|
+
* @param vaultAddress - Vault address: EVM hex or Solana base58.
|
|
14
|
+
* @param headers - Optional monitoring headers forwarded with the request.
|
|
15
|
+
* @returns Dictionary of operator address to portfolio or error on a 200 or
|
|
16
|
+
* 207 (partial success) response; `false` on any other status or when the
|
|
17
|
+
* request fails.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const response = await fetchVaultOctavResponse(vaultAddress);
|
|
22
|
+
* const portfolio = response ? response[borrower] : undefined;
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
async function fetchVaultOctavResponse(vaultAddress, headers) {
|
|
26
|
+
try {
|
|
27
|
+
const response = await (0, core_1.fetchUpshiftPublic)(core_1.WEBSERVER_ENDPOINTS.public.tokenizedVault.octav(vaultAddress), { headers: headers });
|
|
28
|
+
if (response.status === 200 || response.status === 207) {
|
|
29
|
+
return (await response.json());
|
|
30
|
+
}
|
|
31
|
+
core_1.Logger.log.error('fetchVaultOctavResponse', new Error(`HTTP ${response.status} ${response.statusText}`), { status: response.status, statusText: response.statusText });
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
core_1.Logger.log.error('fetchVaultOctavResponse', e);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=fetcher.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./fetcher"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./utils"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IAddress } from '../../types';
|
|
2
|
+
export type IOctavfiEndpoint = 'portfolio';
|
|
3
|
+
export interface IOctavfiAsset {
|
|
4
|
+
balance: string;
|
|
5
|
+
symbol: string;
|
|
6
|
+
price: string;
|
|
7
|
+
value: string;
|
|
8
|
+
contractAddress?: IAddress;
|
|
9
|
+
chain: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IOctavfiProtocolBreakdown {
|
|
12
|
+
key: string;
|
|
13
|
+
name: string;
|
|
14
|
+
value: string;
|
|
15
|
+
assets: IOctavfiAsset[];
|
|
16
|
+
}
|
|
17
|
+
export interface IOctavfiChainBreakdown {
|
|
18
|
+
key: string;
|
|
19
|
+
name: string;
|
|
20
|
+
value: string;
|
|
21
|
+
protocols: string[];
|
|
22
|
+
}
|
|
23
|
+
export interface IOctavfiPortfolio {
|
|
24
|
+
address: IAddress;
|
|
25
|
+
cashBalance: string;
|
|
26
|
+
dailyIncome: string;
|
|
27
|
+
dailyExpense: string;
|
|
28
|
+
fees: string;
|
|
29
|
+
feesFiat: string;
|
|
30
|
+
lastUpdated: string;
|
|
31
|
+
networth: string;
|
|
32
|
+
assetByProtocols: Record<string, IOctavfiProtocolBreakdown>;
|
|
33
|
+
chains: Record<string, IOctavfiChainBreakdown>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { IOctavfiPortfolio } from './types';
|
|
2
|
+
import type { IDebankNormalizedResponse } from '../debank/utils';
|
|
3
|
+
/**
|
|
4
|
+
* Transforms Octavfi portfolio response to DeBank-compatible format.
|
|
5
|
+
* This allows Solana addresses to use Octavfi data while maintaining
|
|
6
|
+
* compatibility with existing DeBank parsing functions.
|
|
7
|
+
*
|
|
8
|
+
* @param octavfiPortfolio - Octavfi portfolio response
|
|
9
|
+
* @returns DeBank-compatible response structure
|
|
10
|
+
*/
|
|
11
|
+
export declare function transformOctavfiToDebank(octavfiPortfolio: IOctavfiPortfolio | null | undefined): IDebankNormalizedResponse;
|
|
12
|
+
/**
|
|
13
|
+
* Transforms multiple Octavfi portfolios to DeBank format.
|
|
14
|
+
* Used when fetching multiple addresses.
|
|
15
|
+
*/
|
|
16
|
+
export declare function transformOctavfiPortfoliosToDebank(portfolios: IOctavfiPortfolio[]): IDebankNormalizedResponse[];
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transformOctavfiToDebank = transformOctavfiToDebank;
|
|
4
|
+
exports.transformOctavfiPortfoliosToDebank = transformOctavfiPortfoliosToDebank;
|
|
5
|
+
/**
|
|
6
|
+
* Transforms Octavfi portfolio response to DeBank-compatible format.
|
|
7
|
+
* This allows Solana addresses to use Octavfi data while maintaining
|
|
8
|
+
* compatibility with existing DeBank parsing functions.
|
|
9
|
+
*
|
|
10
|
+
* @param octavfiPortfolio - Octavfi portfolio response
|
|
11
|
+
* @returns DeBank-compatible response structure
|
|
12
|
+
*/
|
|
13
|
+
function transformOctavfiToDebank(octavfiPortfolio) {
|
|
14
|
+
if (!octavfiPortfolio) {
|
|
15
|
+
return {
|
|
16
|
+
subaccount: {
|
|
17
|
+
positions: [],
|
|
18
|
+
tokens: [],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const positions = [];
|
|
23
|
+
const tokens = [];
|
|
24
|
+
// Transform protocols (assetByProtocols) into DeBank positions format
|
|
25
|
+
const assetByProtocols = octavfiPortfolio.assetByProtocols || {};
|
|
26
|
+
Object.entries(assetByProtocols).forEach(([protocolKey, protocol]) => {
|
|
27
|
+
// Skip wallet protocol - we'll handle it separately in tokens
|
|
28
|
+
if (protocolKey === 'wallet') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const { supplyAssets, borrowAssets } = collectProtocolLegs(protocol);
|
|
32
|
+
// Octav's protocol value is already net of debt, so it stays the net and
|
|
33
|
+
// the borrow legs are added back to give the gross supplied value.
|
|
34
|
+
const netUsdValue = parseFloat(protocol.value || '0') || 0;
|
|
35
|
+
const debtUsdValue = borrowAssets.reduce((sum, asset) => sum + assetUsdValue(asset), 0);
|
|
36
|
+
// Create position structure matching DeBank format
|
|
37
|
+
const position = {
|
|
38
|
+
id: protocolKey,
|
|
39
|
+
chain: getChainFromProtocol(protocol, octavfiPortfolio),
|
|
40
|
+
name: protocol.name || protocolKey,
|
|
41
|
+
logo_url: '', // Octavfi doesn't provide protocol logos
|
|
42
|
+
site_url: '', // Octavfi doesn't provide protocol URLs
|
|
43
|
+
portfolio_item_list: [
|
|
44
|
+
{
|
|
45
|
+
name: protocol.name || protocolKey,
|
|
46
|
+
stats: {
|
|
47
|
+
asset_usd_value: netUsdValue + debtUsdValue,
|
|
48
|
+
debt_usd_value: debtUsdValue,
|
|
49
|
+
net_usd_value: netUsdValue,
|
|
50
|
+
},
|
|
51
|
+
detail: {
|
|
52
|
+
supply_token_list: supplyAssets
|
|
53
|
+
.map((asset) => transformAssetToDebankToken(asset, 'supply'))
|
|
54
|
+
.filter((token) => token !== null),
|
|
55
|
+
borrow_token_list: borrowAssets
|
|
56
|
+
.map((asset) => transformAssetToDebankToken(asset, 'borrow'))
|
|
57
|
+
.filter((token) => token !== null),
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
};
|
|
62
|
+
positions.push(position);
|
|
63
|
+
});
|
|
64
|
+
// Transform wallet assets to tokens array
|
|
65
|
+
const walletProtocol = assetByProtocols['wallet'];
|
|
66
|
+
if (walletProtocol && walletProtocol.chains) {
|
|
67
|
+
// Extract assets from nested structure: chains -> protocolPositions -> assets
|
|
68
|
+
Object.values(walletProtocol.chains).forEach((chain) => {
|
|
69
|
+
if (chain.protocolPositions) {
|
|
70
|
+
Object.values(chain.protocolPositions).forEach((protocolPosition) => {
|
|
71
|
+
if (protocolPosition.assets &&
|
|
72
|
+
Array.isArray(protocolPosition.assets)) {
|
|
73
|
+
protocolPosition.assets.forEach((asset) => {
|
|
74
|
+
tokens.push({
|
|
75
|
+
...transformAssetToDebankToken(asset, 'wallet'),
|
|
76
|
+
is_wallet: true,
|
|
77
|
+
is_core: true, // Assume wallet tokens are core tokens
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// Also add protocol assets as tokens (non-wallet). Deliberately walks only
|
|
86
|
+
// `assets`, not the lending `supplyAssets`/`borrowAssets` legs that
|
|
87
|
+
// `collectProtocolLegs` puts on the positions above: downstream parsers
|
|
88
|
+
// count `tokens` as wallet holdings, so adding the legs here would count
|
|
89
|
+
// collateral twice and report debt as a positive holding.
|
|
90
|
+
Object.entries(assetByProtocols).forEach(([protocolKey, protocol]) => {
|
|
91
|
+
if (protocolKey === 'wallet')
|
|
92
|
+
return;
|
|
93
|
+
if (!protocol || !protocol.chains)
|
|
94
|
+
return;
|
|
95
|
+
// Extract assets from nested structure
|
|
96
|
+
Object.values(protocol.chains).forEach((chain) => {
|
|
97
|
+
if (chain.protocolPositions) {
|
|
98
|
+
Object.values(chain.protocolPositions).forEach((protocolPosition) => {
|
|
99
|
+
// Direct assets
|
|
100
|
+
if (protocolPosition.assets &&
|
|
101
|
+
Array.isArray(protocolPosition.assets)) {
|
|
102
|
+
protocolPosition.assets.forEach((asset) => {
|
|
103
|
+
// Check if token already exists (from wallet)
|
|
104
|
+
const existingToken = tokens.find((t) => t.symbol === asset.symbol &&
|
|
105
|
+
t.chain === (asset.chainKey || asset.chain));
|
|
106
|
+
if (!existingToken) {
|
|
107
|
+
tokens.push({
|
|
108
|
+
...transformAssetToDebankToken(asset, 'supply'),
|
|
109
|
+
is_wallet: false,
|
|
110
|
+
is_core: true, // Assume protocol tokens are core
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Nested protocolPositions (like in Kamino)
|
|
116
|
+
if (protocolPosition.protocolPositions &&
|
|
117
|
+
Array.isArray(protocolPosition.protocolPositions)) {
|
|
118
|
+
protocolPosition.protocolPositions.forEach((nestedPos) => {
|
|
119
|
+
if (nestedPos.assets && Array.isArray(nestedPos.assets)) {
|
|
120
|
+
nestedPos.assets.forEach((asset) => {
|
|
121
|
+
const existingToken = tokens.find((t) => t.symbol === asset.symbol &&
|
|
122
|
+
t.chain === (asset.chainKey || asset.chain));
|
|
123
|
+
if (!existingToken) {
|
|
124
|
+
tokens.push({
|
|
125
|
+
...transformAssetToDebankToken(asset, 'supply'),
|
|
126
|
+
is_wallet: false,
|
|
127
|
+
is_core: true,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
subaccount: {
|
|
140
|
+
positions,
|
|
141
|
+
tokens,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Collects a protocol's supply and borrow legs across its chains and position
|
|
147
|
+
* groups.
|
|
148
|
+
*
|
|
149
|
+
* Octav nests positions as `chains -> protocolPositions -> group`, where a
|
|
150
|
+
* group holds plain `assets` (vault shares) or a list of positions. A lending
|
|
151
|
+
* position (a Kamino obligation) keeps its collateral in `supplyAssets` and its
|
|
152
|
+
* debt in `borrowAssets` rather than in `assets`; reading only `assets` gave a
|
|
153
|
+
* lending position its net value with no collateral or debt behind it.
|
|
154
|
+
*
|
|
155
|
+
* @param protocol - One entry of a portfolio's `assetByProtocols`
|
|
156
|
+
* @returns The supply legs (plain and collateral assets) and the borrow legs
|
|
157
|
+
*/
|
|
158
|
+
function collectProtocolLegs(protocol) {
|
|
159
|
+
const supplyAssets = [];
|
|
160
|
+
const borrowAssets = [];
|
|
161
|
+
const collect = (position) => {
|
|
162
|
+
for (const key of ['assets', 'supplyAssets']) {
|
|
163
|
+
if (Array.isArray(position?.[key]))
|
|
164
|
+
supplyAssets.push(...position[key]);
|
|
165
|
+
}
|
|
166
|
+
if (Array.isArray(position?.borrowAssets)) {
|
|
167
|
+
borrowAssets.push(...position.borrowAssets);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
Object.values(protocol?.chains ?? {}).forEach((chain) => {
|
|
171
|
+
Object.values(chain?.protocolPositions ?? {}).forEach((group) => {
|
|
172
|
+
collect(group);
|
|
173
|
+
// Nested protocolPositions (like in Kamino)
|
|
174
|
+
if (Array.isArray(group?.protocolPositions)) {
|
|
175
|
+
group.protocolPositions.forEach(collect);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
return { supplyAssets, borrowAssets };
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* An Octav asset's USD value: its `value` when present, else balance × price.
|
|
183
|
+
*/
|
|
184
|
+
function assetUsdValue(asset) {
|
|
185
|
+
const value = parseFloat(asset?.value);
|
|
186
|
+
if (Number.isFinite(value))
|
|
187
|
+
return value;
|
|
188
|
+
return (parseFloat(asset?.balance) || 0) * (parseFloat(asset?.price) || 0);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Transforms Octavfi asset to DeBank token format
|
|
192
|
+
*/
|
|
193
|
+
function transformAssetToDebankToken(asset, // Using any since the actual structure differs from IOctavfiAsset
|
|
194
|
+
exposureType) {
|
|
195
|
+
if (!asset) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const balance = parseFloat(asset.balance || '0') || 0;
|
|
199
|
+
const price = parseFloat(asset.price || '0') || 0;
|
|
200
|
+
const amount = balance;
|
|
201
|
+
const chain = asset.chainKey || asset.chain || 'unknown';
|
|
202
|
+
const contract = asset.contract || asset.chainContract || asset.contractAddress;
|
|
203
|
+
const decimals = parseInt(asset.decimal || asset.decimals || '18', 10);
|
|
204
|
+
return {
|
|
205
|
+
id: contract || asset.symbol || 'unknown', // Use contract address if available, fallback to symbol
|
|
206
|
+
chain: chain,
|
|
207
|
+
name: asset.name || asset.symbol || 'Unknown',
|
|
208
|
+
symbol: asset.symbol || 'UNKNOWN',
|
|
209
|
+
optimized_symbol: asset.symbol || 'UNKNOWN',
|
|
210
|
+
decimals: decimals,
|
|
211
|
+
logo_url: '', // Octavfi doesn't provide token logos
|
|
212
|
+
amount,
|
|
213
|
+
price,
|
|
214
|
+
protocol_id: '', // Will be set by the calling context
|
|
215
|
+
supplying_exposure: exposureType === 'supply' ? 'true' : undefined,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Determines the chain from protocol data or portfolio chains
|
|
220
|
+
*/
|
|
221
|
+
function getChainFromProtocol(protocol, portfolio) {
|
|
222
|
+
// Try to get chain from protocol.chains structure
|
|
223
|
+
if (protocol.chains) {
|
|
224
|
+
const chainKeys = Object.keys(protocol.chains);
|
|
225
|
+
if (chainKeys.length > 0) {
|
|
226
|
+
return chainKeys[0];
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Fallback to first chain in portfolio
|
|
230
|
+
const chains = portfolio.chains || {};
|
|
231
|
+
const chainKeys = Object.keys(chains);
|
|
232
|
+
if (chainKeys.length > 0) {
|
|
233
|
+
return chainKeys[0];
|
|
234
|
+
}
|
|
235
|
+
return 'unknown';
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Transforms multiple Octavfi portfolios to DeBank format.
|
|
239
|
+
* Used when fetching multiple addresses.
|
|
240
|
+
*/
|
|
241
|
+
function transformOctavfiPortfoliosToDebank(portfolios) {
|
|
242
|
+
return portfolios.map(transformOctavfiToDebank);
|
|
243
|
+
}
|
|
244
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchSubgraph = fetchSubgraph;
|
|
4
|
+
exports.fetchSubgraphWithRetry = fetchSubgraphWithRetry;
|
|
5
|
+
const core_1 = require("../../core");
|
|
6
|
+
async function fetchSubgraph(graphUrl, query, apiKey) {
|
|
7
|
+
return fetchSubgraphWithRetry(graphUrl, query, apiKey);
|
|
8
|
+
}
|
|
9
|
+
async function fetchSubgraphWithRetry(graphUrl, query, apiKey, maxRetries = 3, baseDelay = 1000) {
|
|
10
|
+
if (!graphUrl) {
|
|
11
|
+
throw new Error('#fetchSubgraph: URL is not defined');
|
|
12
|
+
}
|
|
13
|
+
let lastError;
|
|
14
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
15
|
+
try {
|
|
16
|
+
// Abort a hung subgraph request after the SDK-wide REQUEST_TIMEOUT_MS
|
|
17
|
+
// (15 s). The retry loop below re-arms a fresh timer per attempt.
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const timeoutId = setTimeout(() => controller.abort(), core_1.REQUEST_TIMEOUT_MS);
|
|
20
|
+
try {
|
|
21
|
+
const headers = {
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
};
|
|
24
|
+
if (apiKey) {
|
|
25
|
+
headers['Authorization'] = `Bearer ${apiKey}`;
|
|
26
|
+
}
|
|
27
|
+
const response = await fetch(graphUrl, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
headers,
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
query: `query ${query}`,
|
|
32
|
+
}),
|
|
33
|
+
signal: controller.signal,
|
|
34
|
+
});
|
|
35
|
+
clearTimeout(timeoutId);
|
|
36
|
+
return response;
|
|
37
|
+
}
|
|
38
|
+
catch (fetchError) {
|
|
39
|
+
clearTimeout(timeoutId);
|
|
40
|
+
throw fetchError;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
lastError = error;
|
|
45
|
+
// Retry only transient failures (network drop, abort/timeout) while we
|
|
46
|
+
// have retries left. `fetch` can reject with non-Error values (e.g. a
|
|
47
|
+
// string from a polyfill), so narrow before touching `.message`.
|
|
48
|
+
const isRetryable = error instanceof Error &&
|
|
49
|
+
((error instanceof TypeError &&
|
|
50
|
+
error.message.includes('fetch failed')) ||
|
|
51
|
+
error.name === 'AbortError' ||
|
|
52
|
+
error.message.includes('ETIMEDOUT') ||
|
|
53
|
+
error.message.includes('timeout'));
|
|
54
|
+
if (attempt < maxRetries && isRetryable) {
|
|
55
|
+
const delay = baseDelay * 2 ** attempt; // Exponential backoff
|
|
56
|
+
core_1.Logger.log.warn(`fetchSubgraph`, `${graphUrl?.includes('/subgraphs') ? graphUrl?.split('/subgraphs/')?.[1]?.split('/')?.[0] : graphUrl}: Attempt ${attempt + 1} failed, retrying in ${delay}ms`);
|
|
57
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// If it's not a retryable error or we're out of retries, throw
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
throw lastError;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=fetcher.js.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./vaults"), exports);
|
|
18
|
+
__exportStar(require("./fetcher"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which field-naming schema a deployed Upshift vault subgraph uses:
|
|
3
|
+
* - `'old'` — snake_case fields (`block_number`, `timestamp_`, `transactionHash_`).
|
|
4
|
+
* - `'new'` — camelCase fields (`blockNumber`, `blockTimestamp`, `transactionHash`).
|
|
5
|
+
*
|
|
6
|
+
* The two templates are otherwise equivalent; the SDK aliases new-schema fields
|
|
7
|
+
* back to the old internal names when querying, so the rest of the code only ever
|
|
8
|
+
* sees the old (snake_case) shape.
|
|
9
|
+
*/
|
|
10
|
+
export type SubgraphSchema = 'old' | 'new';
|
|
11
|
+
/**
|
|
12
|
+
* True when a GraphQL error array reports an unknown field on the queried type
|
|
13
|
+
* (message contains "has no field") — the signature of a schema mismatch.
|
|
14
|
+
*
|
|
15
|
+
* @param errors - GraphQL `errors` array from a subgraph response (may be undefined).
|
|
16
|
+
* @returns `true` if any error message indicates an unknown field, else `false`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isSubgraphSchemaFieldError(errors: {
|
|
19
|
+
message?: string;
|
|
20
|
+
}[] | undefined): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Detects whether a deployed subgraph uses the old or new field schema by probing
|
|
23
|
+
* a single field (`blockTimestamp`) that exists only on the new template, on
|
|
24
|
+
* `withdrawalRequesteds`, or on `transfers` for a receipt-token subgraph that
|
|
25
|
+
* has no `withdrawalRequesteds` entity.
|
|
26
|
+
*
|
|
27
|
+
* This replaces the previous heuristic — "vault symbol present in the deprecated
|
|
28
|
+
* `SUBGRAPH_VAULT_URLS` map ⇒ old schema, else new" — which mis-guessed any
|
|
29
|
+
* newly-added vault whose subgraph shipped on the old template (e.g.
|
|
30
|
+
* `august-citrea-earn-ctusd`). A wrong guess made every subgraph read query
|
|
31
|
+
* non-existent field names, so the subgraph returned GraphQL errors with no
|
|
32
|
+
* `data` and the SDK silently returned empty sets — emptying the Pending
|
|
33
|
+
* Withdrawals and History tabs for that vault.
|
|
34
|
+
*
|
|
35
|
+
* Because the schema is immutable for a fixed subgraph deployment, the result is
|
|
36
|
+
* cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
|
|
37
|
+
* withdrawals reads this amounts to a single extra lightweight query per subgraph.
|
|
38
|
+
*
|
|
39
|
+
* Side effects: at most two HTTP POSTs to the subgraph per URL per TTL window
|
|
40
|
+
* (the second only for a subgraph without `withdrawalRequesteds`).
|
|
41
|
+
*
|
|
42
|
+
* @param goldskyUrl - Fully-qualified subgraph GraphQL endpoint.
|
|
43
|
+
* @param apiKey - Optional Goldsky API key sent as a Bearer token.
|
|
44
|
+
* @returns `'old'` or `'new'`. Defaults to `'new'` when the URL is empty or the
|
|
45
|
+
* probe is inconclusive (network error / unexpected response) — the schema the
|
|
46
|
+
* majority of current vaults use.
|
|
47
|
+
*/
|
|
48
|
+
export declare function resolveSubgraphSchema(goldskyUrl: string, apiKey?: string): Promise<SubgraphSchema>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSubgraphSchemaFieldError = isSubgraphSchemaFieldError;
|
|
4
|
+
exports.resolveSubgraphSchema = resolveSubgraphSchema;
|
|
5
|
+
const core_1 = require("../../core");
|
|
6
|
+
const fetcher_1 = require("./fetcher");
|
|
7
|
+
const SCHEMA_CACHE_PREFIX = 'subgraph-schema-';
|
|
8
|
+
// A subgraph's schema is fixed for a given deployment/version, so one probe can
|
|
9
|
+
// serve every subsequent read for a long time. Cache generously.
|
|
10
|
+
const SCHEMA_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
11
|
+
/**
|
|
12
|
+
* True when a GraphQL error array reports an unknown field on the queried type
|
|
13
|
+
* (message contains "has no field") — the signature of a schema mismatch.
|
|
14
|
+
*
|
|
15
|
+
* @param errors - GraphQL `errors` array from a subgraph response (may be undefined).
|
|
16
|
+
* @returns `true` if any error message indicates an unknown field, else `false`.
|
|
17
|
+
*/
|
|
18
|
+
function isSubgraphSchemaFieldError(errors) {
|
|
19
|
+
return Boolean(errors?.some((e) => e?.message?.includes('has no field')));
|
|
20
|
+
}
|
|
21
|
+
// GraphQL errors from querying `blockTimestamp` on one row of `entity`;
|
|
22
|
+
// undefined on a non-200 response or a clean result.
|
|
23
|
+
async function probeSchemaErrors(goldskyUrl, entity, apiKey) {
|
|
24
|
+
const result = await (0, fetcher_1.fetchSubgraph)(goldskyUrl, `{ ${entity}(first: 1) { blockTimestamp } }`, apiKey);
|
|
25
|
+
if (result.status !== 200)
|
|
26
|
+
return undefined;
|
|
27
|
+
const json = (await result.json());
|
|
28
|
+
return json?.errors;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Detects whether a deployed subgraph uses the old or new field schema by probing
|
|
32
|
+
* a single field (`blockTimestamp`) that exists only on the new template, on
|
|
33
|
+
* `withdrawalRequesteds`, or on `transfers` for a receipt-token subgraph that
|
|
34
|
+
* has no `withdrawalRequesteds` entity.
|
|
35
|
+
*
|
|
36
|
+
* This replaces the previous heuristic — "vault symbol present in the deprecated
|
|
37
|
+
* `SUBGRAPH_VAULT_URLS` map ⇒ old schema, else new" — which mis-guessed any
|
|
38
|
+
* newly-added vault whose subgraph shipped on the old template (e.g.
|
|
39
|
+
* `august-citrea-earn-ctusd`). A wrong guess made every subgraph read query
|
|
40
|
+
* non-existent field names, so the subgraph returned GraphQL errors with no
|
|
41
|
+
* `data` and the SDK silently returned empty sets — emptying the Pending
|
|
42
|
+
* Withdrawals and History tabs for that vault.
|
|
43
|
+
*
|
|
44
|
+
* Because the schema is immutable for a fixed subgraph deployment, the result is
|
|
45
|
+
* cached per URL ({@link SCHEMA_TTL_MS}); across a page's positions/history/
|
|
46
|
+
* withdrawals reads this amounts to a single extra lightweight query per subgraph.
|
|
47
|
+
*
|
|
48
|
+
* Side effects: at most two HTTP POSTs to the subgraph per URL per TTL window
|
|
49
|
+
* (the second only for a subgraph without `withdrawalRequesteds`).
|
|
50
|
+
*
|
|
51
|
+
* @param goldskyUrl - Fully-qualified subgraph GraphQL endpoint.
|
|
52
|
+
* @param apiKey - Optional Goldsky API key sent as a Bearer token.
|
|
53
|
+
* @returns `'old'` or `'new'`. Defaults to `'new'` when the URL is empty or the
|
|
54
|
+
* probe is inconclusive (network error / unexpected response) — the schema the
|
|
55
|
+
* majority of current vaults use.
|
|
56
|
+
*/
|
|
57
|
+
async function resolveSubgraphSchema(goldskyUrl, apiKey) {
|
|
58
|
+
if (!goldskyUrl)
|
|
59
|
+
return 'new';
|
|
60
|
+
const key = `${SCHEMA_CACHE_PREFIX}${goldskyUrl}`;
|
|
61
|
+
const cached = core_1.CACHE.get(key);
|
|
62
|
+
if (cached)
|
|
63
|
+
return cached;
|
|
64
|
+
try {
|
|
65
|
+
// `blockTimestamp` is a new-schema-only field. If the subgraph rejects it
|
|
66
|
+
// with an unknown-field error, the deployment is old-schema. Schema
|
|
67
|
+
// validation is static, so this is authoritative even when the entity has
|
|
68
|
+
// zero rows. A receipt-token subgraph indexes only `transfers`, so when
|
|
69
|
+
// `withdrawalRequesteds` itself is unknown the probe moves to `transfers`.
|
|
70
|
+
let errors = await probeSchemaErrors(goldskyUrl, 'withdrawalRequesteds', apiKey);
|
|
71
|
+
if (errors?.some((e) => e?.message?.includes('has no field `withdrawalRequesteds`'))) {
|
|
72
|
+
errors = await probeSchemaErrors(goldskyUrl, 'transfers', apiKey);
|
|
73
|
+
}
|
|
74
|
+
const schema = isSubgraphSchemaFieldError(errors)
|
|
75
|
+
? 'old'
|
|
76
|
+
: 'new';
|
|
77
|
+
core_1.CACHE.set(key, schema, { ttl: SCHEMA_TTL_MS });
|
|
78
|
+
return schema;
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
// Don't cache an inconclusive probe — let the next call retry. Default to
|
|
82
|
+
// 'new' so freshly-deployed vaults keep working when the probe is flaky.
|
|
83
|
+
core_1.Logger.log.warn('resolveSubgraphSchema', `probe failed for ${goldskyUrl}, defaulting to new schema: ${e instanceof Error ? e.message : 'unknown error'}`);
|
|
84
|
+
return 'new';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=schema.js.map
|