@augustdigital/sdk 8.3.2 → 8.6.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/README.md +207 -117
- package/lib/abis/ERC20_Bytes32.d.ts +4 -0
- package/lib/abis/ERC20_Bytes32.js +4 -0
- package/lib/abis/ERC4626.d.ts +1 -0
- package/lib/abis/ERC4626.js +1 -0
- package/lib/abis/ERC721.d.ts +1 -0
- package/lib/abis/ERC721.js +1 -0
- package/lib/abis/FeeOracle.js +1 -0
- package/lib/abis/LendingPool.js +1 -0
- package/lib/abis/LendingPoolV2.js +1 -0
- package/lib/abis/Multicall3.js +3 -0
- package/lib/abis/OFT.d.ts +20 -0
- package/lib/abis/OFT.js +20 -0
- package/lib/abis/SmartAccount.d.ts +1 -0
- package/lib/abis/SmartAccount.js +3 -0
- package/lib/abis/SwapRouter.d.ts +1 -0
- package/lib/abis/SwapRouter.js +1 -0
- package/lib/abis/UniversalSignatureValidator.js +3 -0
- package/lib/abis/index.d.ts +5 -0
- package/lib/abis/index.js +5 -0
- package/lib/adapters/evm/getters.d.ts +17 -2
- package/lib/adapters/evm/getters.js +35 -3
- package/lib/adapters/evm/index.d.ts +266 -4
- package/lib/adapters/evm/index.js +270 -1
- package/lib/adapters/evm/utils.d.ts +6 -0
- package/lib/adapters/evm/utils.js +7 -0
- package/lib/adapters/solana/constants.d.ts +1 -1
- package/lib/adapters/solana/constants.js +4 -1
- package/lib/adapters/solana/getters.d.ts +9 -1
- package/lib/adapters/solana/getters.js +21 -0
- package/lib/adapters/solana/idl/vault-idl.js +9 -0
- package/lib/adapters/solana/index.d.ts +59 -4
- package/lib/adapters/solana/index.js +61 -0
- package/lib/adapters/solana/types.d.ts +1 -1
- package/lib/adapters/solana/utils.d.ts +31 -3
- package/lib/adapters/solana/utils.js +79 -4
- package/lib/adapters/solana/vault.actions.d.ts +23 -4
- package/lib/adapters/solana/vault.actions.js +47 -3
- package/lib/adapters/stellar/actions.d.ts +26 -1
- package/lib/adapters/stellar/actions.js +33 -0
- package/lib/adapters/stellar/constants.d.ts +26 -0
- package/lib/adapters/stellar/constants.js +29 -0
- package/lib/adapters/stellar/getters.d.ts +56 -0
- package/lib/adapters/stellar/getters.js +81 -0
- package/lib/adapters/stellar/index.d.ts +70 -0
- package/lib/adapters/stellar/index.js +71 -0
- package/lib/adapters/stellar/soroban.d.ts +21 -1
- package/lib/adapters/stellar/soroban.js +47 -1
- package/lib/adapters/stellar/submit.d.ts +29 -0
- package/lib/adapters/stellar/submit.js +90 -5
- package/lib/adapters/stellar/types.d.ts +27 -0
- package/lib/adapters/stellar/types.js +3 -0
- package/lib/adapters/stellar/utils.d.ts +10 -0
- package/lib/adapters/stellar/utils.js +10 -0
- package/lib/adapters/sui/getters.d.ts +7 -1
- package/lib/adapters/sui/getters.js +6 -0
- package/lib/adapters/sui/index.d.ts +16 -1
- package/lib/adapters/sui/index.js +17 -0
- package/lib/adapters/sui/transformer.d.ts +8 -2
- package/lib/adapters/sui/transformer.js +7 -0
- package/lib/adapters/sui/types.d.ts +1 -1
- package/lib/adapters/sui/utils.d.ts +6 -0
- package/lib/adapters/sui/utils.js +6 -0
- package/lib/core/analytics/chain-name.d.ts +8 -0
- package/lib/core/analytics/chain-name.js +8 -0
- package/lib/core/analytics/constants.d.ts +4 -0
- package/lib/core/analytics/constants.js +4 -0
- package/lib/core/analytics/env.d.ts +25 -0
- package/lib/core/analytics/env.js +26 -0
- package/lib/core/analytics/index.d.ts +26 -0
- package/lib/core/analytics/index.js +35 -0
- package/lib/core/analytics/instrumentation.d.ts +26 -0
- package/lib/core/analytics/instrumentation.js +66 -2
- package/lib/core/analytics/method-taxonomy.d.ts +16 -0
- package/lib/core/analytics/method-taxonomy.js +18 -0
- package/lib/core/analytics/metrics.d.ts +23 -0
- package/lib/core/analytics/metrics.js +40 -0
- package/lib/core/analytics/sanitize.d.ts +38 -0
- package/lib/core/analytics/sanitize.js +46 -0
- package/lib/core/analytics/sentry-runtime.d.ts +11 -0
- package/lib/core/analytics/sentry-runtime.js +20 -1
- package/lib/core/analytics/sentry.d.ts +47 -2
- package/lib/core/analytics/sentry.js +115 -2
- package/lib/core/analytics/types.d.ts +28 -1
- package/lib/core/analytics/user-identity.d.ts +36 -2
- package/lib/core/analytics/user-identity.js +43 -1
- package/lib/core/analytics/version.d.ts +6 -1
- package/lib/core/analytics/version.js +6 -1
- package/lib/core/auth/verify.js +5 -0
- package/lib/core/base.class.d.ts +78 -3
- package/lib/core/base.class.js +66 -4
- package/lib/core/cache.d.ts +5 -0
- package/lib/core/cache.js +6 -0
- package/lib/core/constants/adapters.d.ts +16 -1
- package/lib/core/constants/adapters.js +28 -8
- package/lib/core/constants/core.d.ts +14 -1
- package/lib/core/constants/core.js +18 -0
- package/lib/core/constants/swap-router.d.ts +83 -1
- package/lib/core/constants/swap-router.js +91 -1
- package/lib/core/constants/vaults.d.ts +57 -1
- package/lib/core/constants/vaults.js +66 -1
- package/lib/core/constants/web3.d.ts +4 -1
- package/lib/core/constants/web3.js +15 -5
- package/lib/core/errors/index.d.ts +38 -2
- package/lib/core/errors/index.js +38 -0
- package/lib/core/fetcher.d.ts +136 -2
- package/lib/core/fetcher.js +229 -25
- package/lib/core/helpers/adapters.d.ts +10 -1
- package/lib/core/helpers/adapters.js +11 -0
- package/lib/core/helpers/chain-address.d.ts +10 -0
- package/lib/core/helpers/chain-address.js +11 -0
- package/lib/core/helpers/core.d.ts +49 -4
- package/lib/core/helpers/core.js +74 -7
- package/lib/core/helpers/explorer-link.d.ts +15 -1
- package/lib/core/helpers/explorer-link.js +14 -0
- package/lib/core/helpers/signer.d.ts +27 -1
- package/lib/core/helpers/signer.js +39 -0
- package/lib/core/helpers/swap-router.d.ts +33 -1
- package/lib/core/helpers/swap-router.js +32 -0
- package/lib/core/helpers/vault-version.d.ts +2 -1
- package/lib/core/helpers/vault-version.js +2 -0
- package/lib/core/helpers/vaults.d.ts +9 -1
- package/lib/core/helpers/vaults.js +22 -8
- package/lib/core/helpers/web3.d.ts +154 -2
- package/lib/core/helpers/web3.js +192 -15
- package/lib/core/logger/index.d.ts +55 -0
- package/lib/core/logger/index.js +19 -0
- package/lib/core/logger/slack.d.ts +3 -0
- package/lib/core/logger/slack.js +3 -0
- package/lib/core/vault-metadata.d.ts +7 -1
- package/lib/core/vault-metadata.js +6 -0
- package/lib/core/version-check.d.ts +52 -0
- package/lib/core/version-check.js +82 -1
- package/lib/evm/methods/crossChainVault.d.ts +90 -0
- package/lib/evm/methods/crossChainVault.js +187 -2
- package/lib/evm/methods/crossChainVaultRegistry.d.ts +93 -0
- package/lib/evm/methods/crossChainVaultRegistry.js +240 -0
- package/lib/evm/methods/index.d.ts +1 -0
- package/lib/evm/methods/index.js +1 -0
- package/lib/evm/types/crossChain.d.ts +202 -0
- package/lib/evm/types/crossChain.js +12 -1
- package/lib/index.d.ts +16 -0
- package/lib/index.js +19 -0
- package/lib/main.d.ts +289 -6
- package/lib/main.js +312 -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 +52 -0
- package/lib/modules/api/main.js +130 -0
- package/lib/modules/sub-accounts/fetcher.d.ts +17 -2
- package/lib/modules/sub-accounts/fetcher.js +15 -0
- package/lib/modules/sub-accounts/main.d.ts +35 -2
- package/lib/modules/sub-accounts/main.js +39 -1
- package/lib/modules/sub-accounts/utils.d.ts +4 -1
- package/lib/modules/sub-accounts/utils.js +3 -0
- package/lib/modules/vaults/adapter.helpers.d.ts +21 -3
- package/lib/modules/vaults/adapter.helpers.js +34 -0
- package/lib/modules/vaults/fetcher.d.ts +45 -0
- package/lib/modules/vaults/fetcher.js +91 -4
- package/lib/modules/vaults/getters.d.ts +295 -0
- package/lib/modules/vaults/getters.js +567 -26
- package/lib/modules/vaults/index.d.ts +12 -0
- package/lib/modules/vaults/index.js +12 -0
- package/lib/modules/vaults/main.d.ts +292 -4
- package/lib/modules/vaults/main.js +382 -8
- package/lib/modules/vaults/read.actions.d.ts +170 -2
- package/lib/modules/vaults/read.actions.js +143 -0
- package/lib/modules/vaults/types.d.ts +34 -0
- package/lib/modules/vaults/utils/call-data-decoder.d.ts +48 -1
- package/lib/modules/vaults/utils/call-data-decoder.js +56 -0
- package/lib/modules/vaults/utils/date-utils.d.ts +39 -0
- package/lib/modules/vaults/utils/date-utils.js +47 -1
- package/lib/modules/vaults/utils.d.ts +85 -0
- package/lib/modules/vaults/utils.js +139 -7
- package/lib/modules/vaults/write.actions.d.ts +363 -3
- package/lib/modules/vaults/write.actions.js +399 -3
- package/lib/polyfills.js +4 -2
- package/lib/sdk.d.ts +23847 -0
- package/lib/services/coingecko/fetcher.d.ts +15 -1
- package/lib/services/coingecko/fetcher.js +30 -9
- package/lib/services/debank/fetcher.d.ts +15 -1
- package/lib/services/debank/fetcher.js +12 -0
- package/lib/services/debank/utils.d.ts +1 -1
- package/lib/services/debank/utils.js +18 -1
- package/lib/services/layerzero/deposits.d.ts +12 -1
- package/lib/services/layerzero/deposits.js +34 -11
- package/lib/services/layerzero/redeems.d.ts +11 -1
- package/lib/services/layerzero/redeems.js +13 -0
- package/lib/services/layerzero/utils.d.ts +8 -0
- package/lib/services/layerzero/utils.js +11 -0
- package/lib/services/octavfi/fetcher.d.ts +8 -1
- package/lib/services/octavfi/fetcher.js +25 -0
- package/lib/services/octavfi/types.d.ts +1 -1
- package/lib/services/octavfi/utils.d.ts +14 -2
- package/lib/services/octavfi/utils.js +44 -10
- package/lib/services/subgraph/fetcher.js +4 -2
- package/lib/services/subgraph/vaults.d.ts +12 -0
- package/lib/services/subgraph/vaults.js +119 -2
- package/lib/services/swap-quotes/index.d.ts +80 -0
- package/lib/services/swap-quotes/index.js +27 -1
- package/lib/services/swap-quotes/paraswap.d.ts +25 -0
- package/lib/services/swap-quotes/paraswap.js +22 -0
- package/lib/types/pools.d.ts +5 -2
- package/lib/types/staking.d.ts +1 -1
- package/lib/types/sub-accounts.d.ts +1 -1
- package/lib/types/subgraph.d.ts +10 -1
- package/lib/types/typed-contract.d.ts +64 -0
- package/lib/types/vaults.d.ts +163 -2
- package/lib/types/vaults.js +10 -0
- package/lib/types/web3.d.ts +9 -1
- package/lib/types/web3.js +1 -0
- package/lib/types/webserver.d.ts +47 -2
- package/package.json +6 -5
package/lib/core/fetcher.js
CHANGED
|
@@ -30,6 +30,7 @@ const vault_version_1 = require("./helpers/vault-version");
|
|
|
30
30
|
const analytics_1 = require("./analytics");
|
|
31
31
|
const sanitize_1 = require("./analytics/sanitize");
|
|
32
32
|
const errors_1 = require("./errors");
|
|
33
|
+
/** Map an HTTP status to the appropriate typed SDK error subclass. */
|
|
33
34
|
function errorFromResponseStatus(status, message, options) {
|
|
34
35
|
if (status === 401) {
|
|
35
36
|
return new errors_1.AugustAuthError('AUTH_UNAUTHORIZED', message, options);
|
|
@@ -43,6 +44,15 @@ function errorFromResponseStatus(status, message, options) {
|
|
|
43
44
|
return new errors_1.AugustServerError(status, message, options);
|
|
44
45
|
}
|
|
45
46
|
let SDK_REQUEST_TIMEOUT_OVERRIDE = null;
|
|
47
|
+
/**
|
|
48
|
+
* Override the default request timeout used by every August fetcher helper
|
|
49
|
+
* when the caller doesn't supply a per-call `timeoutMs`. Pass `null` (or
|
|
50
|
+
* call with no arguments) to clear the override and fall back to the
|
|
51
|
+
* compiled-in `REQUEST_TIMEOUT_MS`.
|
|
52
|
+
*
|
|
53
|
+
* @param ms - Positive number of milliseconds to wait before aborting, or
|
|
54
|
+
* `null` to clear.
|
|
55
|
+
*/
|
|
46
56
|
function setSdkRequestTimeout(ms = null) {
|
|
47
57
|
if (ms === null) {
|
|
48
58
|
SDK_REQUEST_TIMEOUT_OVERRIDE = null;
|
|
@@ -56,9 +66,21 @@ function setSdkRequestTimeout(ms = null) {
|
|
|
56
66
|
}
|
|
57
67
|
SDK_REQUEST_TIMEOUT_OVERRIDE = ms;
|
|
58
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Read the active default request timeout — the SDK-level override if set,
|
|
71
|
+
* otherwise the compiled-in `REQUEST_TIMEOUT_MS`.
|
|
72
|
+
*/
|
|
59
73
|
function getSdkRequestTimeout() {
|
|
60
74
|
return SDK_REQUEST_TIMEOUT_OVERRIDE ?? core_2.REQUEST_TIMEOUT_MS;
|
|
61
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Combine the per-request timeout signal with any caller-supplied signal.
|
|
78
|
+
* Uses `AbortSignal.any` (Node 22+) with a manual relay fallback.
|
|
79
|
+
*
|
|
80
|
+
* Returns `timedOut()` (a closure over an internal flag set when the timeout
|
|
81
|
+
* fires) so the caller can distinguish "we timed out" from "caller cancelled",
|
|
82
|
+
* and `cleanup()` to release the fallback-relay listener.
|
|
83
|
+
*/
|
|
62
84
|
function buildRequestAbortSignal(options) {
|
|
63
85
|
const timeoutMs = options?.timeoutMs ?? SDK_REQUEST_TIMEOUT_OVERRIDE ?? core_2.REQUEST_TIMEOUT_MS;
|
|
64
86
|
const timeoutController = new AbortController();
|
|
@@ -68,18 +90,23 @@ function buildRequestAbortSignal(options) {
|
|
|
68
90
|
timeoutController.abort();
|
|
69
91
|
}, timeoutMs);
|
|
70
92
|
let signal = timeoutController.signal;
|
|
71
|
-
|
|
93
|
+
// No-op by default; replaced with a real listener-removal closure only when
|
|
94
|
+
// the manual relay fallback path below registers an 'abort' listener.
|
|
95
|
+
let relayCleanup = () => undefined;
|
|
72
96
|
if (options?.signal) {
|
|
97
|
+
// Capture in a local so the cleanup closure below keeps the non-nullable
|
|
98
|
+
// narrowing (a closure over `options.signal` would otherwise be re-widened).
|
|
99
|
+
const callerSignal = options.signal;
|
|
73
100
|
if (typeof AbortSignal.any === 'function') {
|
|
74
|
-
signal = AbortSignal.any([timeoutController.signal,
|
|
101
|
+
signal = AbortSignal.any([timeoutController.signal, callerSignal]);
|
|
75
102
|
}
|
|
76
|
-
else if (
|
|
103
|
+
else if (callerSignal.aborted) {
|
|
77
104
|
timeoutController.abort();
|
|
78
105
|
}
|
|
79
106
|
else {
|
|
80
107
|
const relay = () => timeoutController.abort();
|
|
81
|
-
|
|
82
|
-
relayCleanup = () =>
|
|
108
|
+
callerSignal.addEventListener('abort', relay, { once: true });
|
|
109
|
+
relayCleanup = () => callerSignal.removeEventListener('abort', relay);
|
|
83
110
|
}
|
|
84
111
|
}
|
|
85
112
|
return {
|
|
@@ -98,8 +125,20 @@ function warnOverrideDeprecation(callerTag) {
|
|
|
98
125
|
if (_overrideDeprecationWarned)
|
|
99
126
|
return;
|
|
100
127
|
_overrideDeprecationWarned = true;
|
|
128
|
+
// Deliberately a direct console.warn, not Logger.log.warn: a deprecation
|
|
129
|
+
// notice must surface in the integrator's console in every environment.
|
|
130
|
+
// Logger.log.warn would downgrade it to a prod-silent Sentry breadcrumb.
|
|
131
|
+
// biome-ignore lint/suspicious/noConsole: integrator-facing deprecation notice must surface in every environment; Logger.log.warn would downgrade it to a prod-silent Sentry breadcrumb.
|
|
101
132
|
console.warn(`[@augustdigital/sdk] ${callerTag}: option "override" is deprecated and will be removed in a future major version. Pass a valid apiKey instead.`);
|
|
102
133
|
}
|
|
134
|
+
/**
|
|
135
|
+
* LRU cache for API responses and frequently accessed data.
|
|
136
|
+
* 24-hour TTL with 1000 item capacity.
|
|
137
|
+
*/
|
|
138
|
+
/**
|
|
139
|
+
* Read a response header tolerantly. Real `fetch` returns a `Headers` instance,
|
|
140
|
+
* but some test mocks supply a plain object; both shapes are supported here.
|
|
141
|
+
*/
|
|
103
142
|
function readResponseHeader(headers, name) {
|
|
104
143
|
if (!headers)
|
|
105
144
|
return undefined;
|
|
@@ -114,17 +153,33 @@ const cache_1 = require("./cache");
|
|
|
114
153
|
Object.defineProperty(exports, "CACHE", { enumerable: true, get: function () { return cache_1.CACHE; } });
|
|
115
154
|
Object.defineProperty(exports, "getSafeCache", { enumerable: true, get: function () { return cache_1.getSafeCache; } });
|
|
116
155
|
Object.defineProperty(exports, "setSafeCache", { enumerable: true, get: function () { return cache_1.setSafeCache; } });
|
|
156
|
+
/**
|
|
157
|
+
* Dedicated cache for token prices with short TTL to prevent rate limiting.
|
|
158
|
+
* 30-second TTL with 500 item capacity.
|
|
159
|
+
*/
|
|
117
160
|
const PRICE_CACHE = new lru_cache_1.LRUCache({
|
|
118
161
|
max: 500,
|
|
119
|
-
ttl: 1000 * 30,
|
|
162
|
+
ttl: 1000 * 30, // 30 seconds
|
|
120
163
|
allowStale: false,
|
|
121
164
|
});
|
|
165
|
+
/**
|
|
166
|
+
* Cache for failed price requests to prevent retry storms.
|
|
167
|
+
* 5-second TTL to allow quick retry after temporary failures.
|
|
168
|
+
*/
|
|
122
169
|
const PRICE_ERROR_CACHE = new lru_cache_1.LRUCache({
|
|
123
170
|
max: 100,
|
|
124
|
-
ttl: 1000 * 5,
|
|
171
|
+
ttl: 1000 * 5, // 5 seconds
|
|
125
172
|
allowStale: false,
|
|
126
173
|
});
|
|
174
|
+
/**
|
|
175
|
+
* In-flight price requests to prevent duplicate simultaneous API calls.
|
|
176
|
+
*/
|
|
127
177
|
const PRICE_REQUESTS = new Map();
|
|
178
|
+
/**
|
|
179
|
+
* Build an August backend URL, rejecting unknown server keys and any
|
|
180
|
+
* `relativeUrl` that would escape the configured origin.
|
|
181
|
+
* Throws `AugustValidationError` with `code: 'INVALID_URL'`.
|
|
182
|
+
*/
|
|
128
183
|
function buildAugustUrl(server, relativeUrl) {
|
|
129
184
|
const serverKey = server;
|
|
130
185
|
const base = core_2.WEBSERVER_URL[serverKey];
|
|
@@ -134,9 +189,12 @@ function buildAugustUrl(server, relativeUrl) {
|
|
|
134
189
|
if (typeof relativeUrl !== 'string' || relativeUrl.length === 0) {
|
|
135
190
|
throw new errors_1.AugustValidationError('INVALID_URL', 'relativeUrl must be a non-empty string');
|
|
136
191
|
}
|
|
192
|
+
// Reject anything that looks like a scheme or protocol-relative authority.
|
|
137
193
|
if (/^\s*[a-z][a-z0-9+.-]*:|^\s*\/\//i.test(relativeUrl)) {
|
|
138
194
|
throw new errors_1.AugustValidationError('INVALID_URL', `relativeUrl must be a path, not an absolute or protocol-relative URL`);
|
|
139
195
|
}
|
|
196
|
+
// Concat (rather than `new URL(rel, base)`) preserves base paths like /api/v1
|
|
197
|
+
// when relativeUrl starts with `/`. Origin check below is a second line.
|
|
140
198
|
const candidate = `${base}${relativeUrl}`;
|
|
141
199
|
let url;
|
|
142
200
|
try {
|
|
@@ -151,6 +209,15 @@ function buildAugustUrl(server, relativeUrl) {
|
|
|
151
209
|
}
|
|
152
210
|
return url.toString();
|
|
153
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Make authenticated requests to August backend services using API key.
|
|
214
|
+
* Automatically logs errors with correlation IDs for debugging.
|
|
215
|
+
* @param apiKey - August API key for authentication
|
|
216
|
+
* @param relativeUrl - Endpoint path relative to base URL
|
|
217
|
+
* @param options - Request configuration including method and headers
|
|
218
|
+
* @returns Response object if successful
|
|
219
|
+
* @throws Error with correlation ID if request fails
|
|
220
|
+
*/
|
|
154
221
|
async function fetchAugustWithKey(apiKey, relativeUrl, options) {
|
|
155
222
|
if (options?.override) {
|
|
156
223
|
warnOverrideDeprecation('fetchAugustWithKey');
|
|
@@ -178,6 +245,7 @@ async function fetchAugustWithKey(apiKey, relativeUrl, options) {
|
|
|
178
245
|
signal: requestSignal,
|
|
179
246
|
});
|
|
180
247
|
cleanup();
|
|
248
|
+
// Track API call
|
|
181
249
|
(0, analytics_1.trackApiCall)(relativeUrl, options?.method ?? 'GET', startTime, res.status, server);
|
|
182
250
|
const correlationId = readResponseHeader(res.headers, 'x-correlation-id');
|
|
183
251
|
const logger = logger_1.Logger.getLogger();
|
|
@@ -206,6 +274,14 @@ async function fetchAugustWithKey(apiKey, relativeUrl, options) {
|
|
|
206
274
|
throw err;
|
|
207
275
|
}
|
|
208
276
|
}
|
|
277
|
+
/**
|
|
278
|
+
* Make unauthenticated requests to August public API endpoints.
|
|
279
|
+
* Used for fetching vault metadata and public market data.
|
|
280
|
+
* @param relativeUrl - Endpoint path relative to public API base URL
|
|
281
|
+
* @param options - Request configuration including method and headers
|
|
282
|
+
* @returns Response object if successful
|
|
283
|
+
* @throws Error with correlation ID if request fails
|
|
284
|
+
*/
|
|
209
285
|
async function fetchAugustPublic(relativeUrl, options) {
|
|
210
286
|
const defaultHeaders = {
|
|
211
287
|
'content-type': 'application/json',
|
|
@@ -253,6 +329,15 @@ async function fetchAugustPublic(relativeUrl, options) {
|
|
|
253
329
|
throw err;
|
|
254
330
|
}
|
|
255
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* Make authenticated requests using Bearer token authentication.
|
|
334
|
+
* Typically used for user-specific operations requiring OAuth tokens.
|
|
335
|
+
* @param bearerToken - OAuth bearer token
|
|
336
|
+
* @param relativeUrl - Endpoint path relative to base URL
|
|
337
|
+
* @param options - Request configuration including method and headers
|
|
338
|
+
* @returns Response object if successful
|
|
339
|
+
* @throws Error with correlation ID if request fails
|
|
340
|
+
*/
|
|
256
341
|
async function fetchAugustWithBearer(bearerToken, relativeUrl, options) {
|
|
257
342
|
const defaultHeaders = {
|
|
258
343
|
authorization: `Bearer ${bearerToken}`,
|
|
@@ -302,6 +387,10 @@ async function fetchAugustWithBearer(bearerToken, relativeUrl, options) {
|
|
|
302
387
|
throw err;
|
|
303
388
|
}
|
|
304
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* Check if an error is network-related and suitable for retry.
|
|
392
|
+
* Identifies timeouts, connection resets, and fetch failures.
|
|
393
|
+
*/
|
|
305
394
|
function isRetryableError(error) {
|
|
306
395
|
return ((error instanceof TypeError && error.message.includes('fetch failed')) ||
|
|
307
396
|
error.name === 'AbortError' ||
|
|
@@ -311,6 +400,16 @@ function isRetryableError(error) {
|
|
|
311
400
|
error.message.includes('ENOTFOUND') ||
|
|
312
401
|
error.message.includes('ECONNREFUSED'));
|
|
313
402
|
}
|
|
403
|
+
/**
|
|
404
|
+
* Wrap async operations with exponential backoff retry logic.
|
|
405
|
+
* Retries on network errors with increasing delays between attempts.
|
|
406
|
+
* @param fn - Async function to execute with retry logic
|
|
407
|
+
* @param maxRetries - Maximum number of retry attempts
|
|
408
|
+
* @param baseDelay - Initial delay in milliseconds (doubles each retry)
|
|
409
|
+
* @param shouldRetry - Custom function to determine if error is retryable
|
|
410
|
+
* @returns Result of successful function execution
|
|
411
|
+
* @throws Last error if all retries exhausted
|
|
412
|
+
*/
|
|
314
413
|
async function withRetry(fn, maxRetries = 3, baseDelay = 1000, shouldRetry = isRetryableError) {
|
|
315
414
|
let lastError;
|
|
316
415
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
@@ -328,12 +427,22 @@ async function withRetry(fn, maxRetries = 3, baseDelay = 1000, shouldRetry = isR
|
|
|
328
427
|
throw error;
|
|
329
428
|
}
|
|
330
429
|
}
|
|
331
|
-
|
|
430
|
+
// Unreachable in practice: the final attempt re-throws inside the loop. This
|
|
431
|
+
// satisfies the compiler's control-flow analysis without a non-null assertion.
|
|
432
|
+
throw lastError ?? new Error('withRetry exhausted retries without an error');
|
|
332
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Fetch tokenized vault configurations from backend API.
|
|
436
|
+
* Results are cached to reduce API calls. Optionally filter by specific vault address.
|
|
437
|
+
* @param pool - Optional vault address to filter results
|
|
438
|
+
* @param headers - Monitoring headers for request tracking
|
|
439
|
+
* @returns Array of tokenized vault configurations
|
|
440
|
+
*/
|
|
333
441
|
async function fetchTokenizedVault(pool, headers, loadSubaccounts, loadSnapshots) {
|
|
334
442
|
if (!pool) {
|
|
335
443
|
return [];
|
|
336
444
|
}
|
|
445
|
+
// Build cache key based on loading options
|
|
337
446
|
const keyParts = [`tokenized-vault-${pool}`];
|
|
338
447
|
if (loadSubaccounts === false)
|
|
339
448
|
keyParts.push('no-subaccounts');
|
|
@@ -346,6 +455,7 @@ async function fetchTokenizedVault(pool, headers, loadSubaccounts, loadSnapshots
|
|
|
346
455
|
tokenizedVault = cachedResponse;
|
|
347
456
|
}
|
|
348
457
|
if (!tokenizedVault) {
|
|
458
|
+
// Build endpoint URL with optional query parameters
|
|
349
459
|
let endpoint = core_2.WEBSERVER_ENDPOINTS.public.tokenizedVault.byVaultAddress(pool);
|
|
350
460
|
const params = new URLSearchParams();
|
|
351
461
|
if (loadSubaccounts === false) {
|
|
@@ -356,21 +466,31 @@ async function fetchTokenizedVault(pool, headers, loadSubaccounts, loadSnapshots
|
|
|
356
466
|
}
|
|
357
467
|
const queryString = params.toString();
|
|
358
468
|
if (queryString) {
|
|
359
|
-
endpoint +=
|
|
469
|
+
endpoint += `?${queryString}`;
|
|
360
470
|
}
|
|
361
471
|
const tokenizedVaultsResponse = await fetchAugustPublic(endpoint, {
|
|
362
472
|
headers: headers,
|
|
363
473
|
});
|
|
364
474
|
tokenizedVault = (await tokenizedVaultsResponse.json());
|
|
365
|
-
cache_1.CACHE.set(key, tokenizedVault, { ttl: 1000 * 60 * 10 });
|
|
475
|
+
cache_1.CACHE.set(key, tokenizedVault, { ttl: 1000 * 60 * 10 }); // Cache for 10 minutes
|
|
366
476
|
}
|
|
477
|
+
// Filter by specific vault if address provided
|
|
367
478
|
if (pool &&
|
|
368
479
|
((0, ethers_1.isAddress)(pool) || (0, chain_address_1.isSolanaAddress)(pool) || (0, chain_address_1.isStellarAddress)(pool))) {
|
|
369
480
|
return tokenizedVault ? [tokenizedVault] : [];
|
|
370
481
|
}
|
|
371
482
|
return [tokenizedVault];
|
|
372
483
|
}
|
|
484
|
+
/**
|
|
485
|
+
* Fetch tokenized vault configurations from backend API.
|
|
486
|
+
* Results are cached to reduce API calls. Optionally filter by specific vault address.
|
|
487
|
+
* @param pool - Optional vault address to filter results
|
|
488
|
+
* @param headers - Monitoring headers for request tracking
|
|
489
|
+
* @param loadSubaccounts - Optional flag to load subaccounts and EOA operators (defaults to true on API)
|
|
490
|
+
* @returns Array of tokenized vault configurations
|
|
491
|
+
*/
|
|
373
492
|
async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshots) {
|
|
493
|
+
// Build cache key based on loading options
|
|
374
494
|
const keyParts = ['tokenized-vaults'];
|
|
375
495
|
if (pool)
|
|
376
496
|
keyParts.push(pool);
|
|
@@ -385,6 +505,7 @@ async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshot
|
|
|
385
505
|
tokenizedVaults = cachedResponse;
|
|
386
506
|
}
|
|
387
507
|
if (!tokenizedVaults) {
|
|
508
|
+
// Build endpoint URL with optional query parameters
|
|
388
509
|
let endpoint = core_2.WEBSERVER_ENDPOINTS.public.tokenizedVault.list;
|
|
389
510
|
const params = new URLSearchParams();
|
|
390
511
|
if (loadSubaccounts === false) {
|
|
@@ -395,16 +516,17 @@ async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshot
|
|
|
395
516
|
}
|
|
396
517
|
const queryString = params.toString();
|
|
397
518
|
if (queryString) {
|
|
398
|
-
endpoint +=
|
|
519
|
+
endpoint += `?${queryString}`;
|
|
399
520
|
}
|
|
400
521
|
const tokenizedVaultsResponse = await fetchAugustPublic(endpoint, {
|
|
401
522
|
headers: headers,
|
|
402
523
|
});
|
|
403
524
|
tokenizedVaults =
|
|
404
525
|
(await tokenizedVaultsResponse.json());
|
|
405
|
-
const ttl = 1000 * 60 * 15;
|
|
526
|
+
const ttl = 1000 * 60 * 15; // 15 minute cache
|
|
406
527
|
cache_1.CACHE.set(key, tokenizedVaults, { ttl });
|
|
407
528
|
}
|
|
529
|
+
// Filter by specific vault if address provided
|
|
408
530
|
if (pool &&
|
|
409
531
|
((0, ethers_1.isAddress)(pool) || (0, chain_address_1.isSolanaAddress)(pool) || (0, chain_address_1.isStellarAddress)(pool))) {
|
|
410
532
|
const foundObj = tokenizedVaults.find((t) => t.address.toLowerCase() === pool.toLowerCase());
|
|
@@ -412,57 +534,93 @@ async function fetchTokenizedVaults(pool, headers, loadSubaccounts, loadSnapshot
|
|
|
412
534
|
}
|
|
413
535
|
return tokenizedVaults;
|
|
414
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Fetch current USD price for a token symbol or vault LP token.
|
|
539
|
+
* For vault LP tokens, calculates share price using totalAssets/totalSupply ratio.
|
|
540
|
+
* Falls back to CoinGecko if primary source fails.
|
|
541
|
+
* @param symbol - Token symbol or contract address
|
|
542
|
+
* @param provider - Optional web3 provider for on-chain price calculations
|
|
543
|
+
* @param coinGeckoKey - Optional CoinGecko API key for fallback pricing
|
|
544
|
+
* @param headers - Monitoring headers for request tracking
|
|
545
|
+
* @returns Token price in USD
|
|
546
|
+
*/
|
|
415
547
|
async function fetchTokenPrice(symbol, provider, coinGeckoKey, headers) {
|
|
416
548
|
if (!symbol) {
|
|
417
549
|
logger_1.Logger.log.error('fetchTokenPrice', 'symbol parameter is undefined');
|
|
418
550
|
return 0;
|
|
419
551
|
}
|
|
552
|
+
// Normalize symbol and apply aliases BEFORE generating cache key
|
|
420
553
|
let normalizedSymbol = symbol.toLowerCase();
|
|
421
554
|
normalizedSymbol = normalizedSymbol === 'xbtc' ? 'btc' : normalizedSymbol;
|
|
422
555
|
normalizedSymbol = normalizedSymbol === 'strbtc' ? 'btc' : normalizedSymbol;
|
|
556
|
+
// Generate cache key based on normalized symbol and provider presence
|
|
423
557
|
const cacheKey = `price:${normalizedSymbol}:${provider ? 'with-provider' : 'no-provider'}`;
|
|
558
|
+
// Check error cache to prevent retry storms after failures
|
|
424
559
|
const cachedError = PRICE_ERROR_CACHE.get(cacheKey);
|
|
425
560
|
if (cachedError) {
|
|
426
561
|
logger_1.Logger.log.info('fetchTokenPrice', `Error cache HIT for ${normalizedSymbol} - throwing cached error`);
|
|
427
562
|
throw cachedError;
|
|
428
563
|
}
|
|
564
|
+
// Check price cache first to avoid rate limiting
|
|
429
565
|
const cachedPrice = PRICE_CACHE.get(cacheKey);
|
|
430
566
|
if (cachedPrice !== undefined) {
|
|
431
567
|
logger_1.Logger.log.info('fetchTokenPrice', `Cache HIT for ${normalizedSymbol}: $${cachedPrice}`);
|
|
432
568
|
return cachedPrice;
|
|
433
569
|
}
|
|
570
|
+
// Check for in-flight request to deduplicate simultaneous calls
|
|
434
571
|
const inflightRequest = PRICE_REQUESTS.get(cacheKey);
|
|
435
572
|
if (inflightRequest) {
|
|
436
573
|
logger_1.Logger.log.info('fetchTokenPrice', `In-flight request deduplication for ${normalizedSymbol}`);
|
|
437
574
|
return inflightRequest;
|
|
438
575
|
}
|
|
576
|
+
// Create the price fetching promise
|
|
439
577
|
const pricePromise = (async () => {
|
|
440
578
|
try {
|
|
441
579
|
const price = await _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers);
|
|
580
|
+
// Cache the successful result
|
|
442
581
|
PRICE_CACHE.set(cacheKey, price);
|
|
582
|
+
// Clear any previous error cache on success
|
|
443
583
|
PRICE_ERROR_CACHE.delete(cacheKey);
|
|
444
584
|
return price;
|
|
445
585
|
}
|
|
446
586
|
catch (error) {
|
|
587
|
+
// Cache the error temporarily to prevent retry storms
|
|
447
588
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
448
589
|
PRICE_ERROR_CACHE.set(cacheKey, err);
|
|
449
590
|
logger_1.Logger.log.info('fetchTokenPrice', `Cached error for ${normalizedSymbol}: ${err.message}`);
|
|
450
591
|
throw err;
|
|
451
592
|
}
|
|
452
593
|
finally {
|
|
594
|
+
// Clean up in-flight request tracking
|
|
453
595
|
PRICE_REQUESTS.delete(cacheKey);
|
|
454
596
|
}
|
|
455
597
|
})();
|
|
598
|
+
// Track this request to prevent duplicates
|
|
456
599
|
PRICE_REQUESTS.set(cacheKey, pricePromise);
|
|
457
600
|
return pricePromise;
|
|
458
601
|
}
|
|
602
|
+
// Normalize both raw integers to the same decimal scale BEFORE dividing —
|
|
603
|
+
// dividing the raw bigints first floors the ratio to ~1 and loses all
|
|
604
|
+
// fractional precision. Returns 1 for an empty vault (priced 1:1).
|
|
605
|
+
function normalizedSharePrice(totalAssets, totalSupply, decimals) {
|
|
606
|
+
const supply = Number((0, core_1.toNormalizedBn)(totalSupply, decimals).normalized);
|
|
607
|
+
if (!supply)
|
|
608
|
+
return 1;
|
|
609
|
+
return Number((0, core_1.toNormalizedBn)(totalAssets, decimals).normalized) / supply;
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Internal price fetching implementation.
|
|
613
|
+
* This is separated to allow caching and request deduplication in the public function.
|
|
614
|
+
*/
|
|
459
615
|
async function _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers) {
|
|
616
|
+
// Fetch vault metadata to check if symbol is a vault LP token
|
|
460
617
|
const tokenizedVaults = await fetchTokenizedVaults(undefined, headers, false, false);
|
|
461
618
|
const vaultArray = tokenizedVaults.map((vault) => ({
|
|
462
619
|
vault: vault.address,
|
|
463
620
|
symbol: vault.receipt_token_symbol,
|
|
464
621
|
}));
|
|
465
622
|
const foundVaultLpAsset = vaultArray.find((v) => v.symbol?.toLowerCase() === symbol?.toLowerCase());
|
|
623
|
+
// @todo: handle multi-asset vaults
|
|
466
624
|
const tokenizedVault = tokenizedVaults.find((vault) => vault.address === foundVaultLpAsset?.vault);
|
|
467
625
|
const version = (0, vault_version_1.getVaultVersionV2)(tokenizedVault);
|
|
468
626
|
if (foundVaultLpAsset?.vault && provider && version === 'evm-2') {
|
|
@@ -474,19 +632,22 @@ async function _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers)
|
|
|
474
632
|
const sharePrice = await vaultContract.getSharePrice();
|
|
475
633
|
return Number((0, core_1.toNormalizedBn)(sharePrice, decimals).normalized);
|
|
476
634
|
}
|
|
477
|
-
catch
|
|
635
|
+
catch {
|
|
478
636
|
throw new Error('failed to fetch token price for evm-2 vault');
|
|
479
637
|
}
|
|
480
638
|
}
|
|
639
|
+
// Apply symbol normalization and aliases for API calls
|
|
481
640
|
let _symbol = symbol?.toLowerCase();
|
|
482
641
|
_symbol = _symbol === 'xbtc' ? 'btc' : _symbol;
|
|
483
642
|
_symbol = _symbol === 'strbtc' ? 'btc' : _symbol;
|
|
484
643
|
try {
|
|
644
|
+
// Fetch base token price from August backend
|
|
485
645
|
const res = await fetch(`https://prices.augustdigital.io/price/${_symbol}`, { headers: headers });
|
|
486
646
|
if (res.status !== 200) {
|
|
487
647
|
throw new Error(`fetching ${_symbol} price: ${res?.statusText}`);
|
|
488
648
|
}
|
|
489
649
|
const json = (await res.json());
|
|
650
|
+
// For vault LP tokens, calculate share price using on-chain ratio
|
|
490
651
|
if (foundVaultLpAsset && provider) {
|
|
491
652
|
const vaultContract = new ethers_2.Contract((0, ethers_1.getAddress)(foundVaultLpAsset.vault), abis_1.ABI_LENDING_POOL_V2, provider);
|
|
492
653
|
const [totalAssets, totalSupply, rawDecimals] = await Promise.all([
|
|
@@ -495,12 +656,13 @@ async function _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers)
|
|
|
495
656
|
vaultContract.decimals(),
|
|
496
657
|
]);
|
|
497
658
|
const decimals = Number(rawDecimals);
|
|
498
|
-
const
|
|
499
|
-
return json.price *
|
|
659
|
+
const sharePrice = normalizedSharePrice(totalAssets, totalSupply, decimals);
|
|
660
|
+
return json.price * sharePrice;
|
|
500
661
|
}
|
|
501
662
|
return json.price;
|
|
502
663
|
}
|
|
503
|
-
catch
|
|
664
|
+
catch {
|
|
665
|
+
// Fallback to CoinGecko if primary source fails
|
|
504
666
|
const fallbackPrice = await (0, fetcher_1.fetchTokenPricesFromCoinGecko)(symbol, coinGeckoKey);
|
|
505
667
|
if (foundVaultLpAsset && provider) {
|
|
506
668
|
const vaultContract = new ethers_2.Contract((0, ethers_1.getAddress)(foundVaultLpAsset.vault), abis_1.ABI_LENDING_POOL_V2, provider);
|
|
@@ -510,8 +672,8 @@ async function _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers)
|
|
|
510
672
|
vaultContract.decimals(),
|
|
511
673
|
]);
|
|
512
674
|
const decimals = Number(rawDecimals);
|
|
513
|
-
const
|
|
514
|
-
return fallbackPrice *
|
|
675
|
+
const sharePrice = normalizedSharePrice(totalAssets, totalSupply, decimals);
|
|
676
|
+
return fallbackPrice * sharePrice;
|
|
515
677
|
}
|
|
516
678
|
if (fallbackPrice) {
|
|
517
679
|
return fallbackPrice;
|
|
@@ -521,6 +683,13 @@ async function _fetchTokenPriceInternal(symbol, provider, coinGeckoKey, headers)
|
|
|
521
683
|
}
|
|
522
684
|
}
|
|
523
685
|
}
|
|
686
|
+
/**
|
|
687
|
+
* Fetch token price by contract address and chain ID from August price server.
|
|
688
|
+
* @param address - Token contract address
|
|
689
|
+
* @param chainId - Network chain ID
|
|
690
|
+
* @param headers - Optional monitoring headers for request tracking
|
|
691
|
+
* @returns Token price in USD, or 0 if not found
|
|
692
|
+
*/
|
|
524
693
|
async function fetchTokenPriceByAddress(address, chainId, headers) {
|
|
525
694
|
if (!address || !chainId) {
|
|
526
695
|
return 0;
|
|
@@ -547,32 +716,58 @@ async function fetchTokenPriceByAddress(address, chainId, headers) {
|
|
|
547
716
|
return 0;
|
|
548
717
|
}
|
|
549
718
|
}
|
|
719
|
+
/**
|
|
720
|
+
* Fetch active loans for a specific vault from backend API.
|
|
721
|
+
* Results are cached per vault and chain to reduce API calls.
|
|
722
|
+
* @param pool - Vault address
|
|
723
|
+
* @param chainId - Network chain ID
|
|
724
|
+
* @param headers - Monitoring headers for request tracking
|
|
725
|
+
* @returns Array of active loan objects
|
|
726
|
+
*/
|
|
550
727
|
async function fetchTokenizedVaultLoans(pool, chainId, headers) {
|
|
551
728
|
const key = `loans-${chainId}-${pool}`;
|
|
552
729
|
let loans;
|
|
553
|
-
|
|
554
|
-
|
|
730
|
+
const cached = await (0, cache_1.getSafeCache)(key);
|
|
731
|
+
if (cached) {
|
|
732
|
+
loans = cached;
|
|
555
733
|
}
|
|
556
734
|
else {
|
|
557
735
|
const tokenizedVaultsResponse = await fetchAugustPublic(core_2.WEBSERVER_ENDPOINTS.public.tokenizedVault.loans(pool, chainId, true), { headers: headers });
|
|
558
736
|
loans = (await tokenizedVaultsResponse.json()).loans;
|
|
559
|
-
cache_1.
|
|
737
|
+
await (0, cache_1.setSafeCache)(key, loans);
|
|
560
738
|
}
|
|
561
739
|
return loans?.filter((l) => l.state.toLowerCase() === 'active');
|
|
562
740
|
}
|
|
741
|
+
/**
|
|
742
|
+
* Fetch subaccount loans for a specific tokenized vault (lending pool).
|
|
743
|
+
* Retrieves all active subaccount loan data from the backend.
|
|
744
|
+
* @param pool - Vault address
|
|
745
|
+
* @param chainId - Network chain ID
|
|
746
|
+
* @param headers - Monitoring headers for request tracking
|
|
747
|
+
* @returns Array of active subaccount loan objects
|
|
748
|
+
*/
|
|
563
749
|
async function fetchTokenizedVaultSubaccountLoans(pool, chainId, headers) {
|
|
564
750
|
const key = `subaccount-loans-${chainId}-${pool}`;
|
|
565
751
|
let loans;
|
|
566
|
-
|
|
567
|
-
|
|
752
|
+
const cached = await (0, cache_1.getSafeCache)(key);
|
|
753
|
+
if (cached) {
|
|
754
|
+
loans = cached;
|
|
568
755
|
}
|
|
569
756
|
else {
|
|
570
757
|
const tokenizedVaultsResponse = await fetchAugustPublic(core_2.WEBSERVER_ENDPOINTS.public.tokenizedVault.subaccountLoans(pool, chainId, true), { headers: headers });
|
|
571
758
|
loans = (await tokenizedVaultsResponse.json()).loans;
|
|
572
|
-
cache_1.
|
|
759
|
+
await (0, cache_1.setSafeCache)(key, loans);
|
|
573
760
|
}
|
|
574
761
|
return loans?.filter((l) => l.state.toLowerCase() === 'active');
|
|
575
762
|
}
|
|
763
|
+
/**
|
|
764
|
+
* Fetch historical timeseries data for a specific vault.
|
|
765
|
+
* Returns TVL, APY, PnL, and share price data over time.
|
|
766
|
+
* @param vaultAddress - Vault contract address
|
|
767
|
+
* @param nDays - Number of days of historical data to fetch (default 30, min 1)
|
|
768
|
+
* @param headers - Monitoring headers for request tracking
|
|
769
|
+
* @returns Historical timeseries data with date keys
|
|
770
|
+
*/
|
|
576
771
|
async function fetchVaultHistoricalTimeseries(vaultAddress, nDays, headers) {
|
|
577
772
|
const key = `vault-historical-timeseries-${vaultAddress}-${nDays}`;
|
|
578
773
|
const cachedResponse = await (0, cache_1.getSafeCache)(key);
|
|
@@ -584,9 +779,18 @@ async function fetchVaultHistoricalTimeseries(vaultAddress, nDays, headers) {
|
|
|
584
779
|
throw new Error(`Failed to fetch historical timeseries data: ${response.statusText}`);
|
|
585
780
|
}
|
|
586
781
|
const json = (await response.json());
|
|
587
|
-
cache_1.CACHE.set(key, json, { ttl: 1000 * 60 * 10 });
|
|
782
|
+
cache_1.CACHE.set(key, json, { ttl: 1000 * 60 * 10 }); // Cache for 10 minutes
|
|
588
783
|
return json;
|
|
589
784
|
}
|
|
785
|
+
/**
|
|
786
|
+
* Execute multiple promises with retry logic and allow partial failures.
|
|
787
|
+
* Unlike Promise.all, continues execution if some promises fail.
|
|
788
|
+
* Failed promises return null to maintain array index alignment.
|
|
789
|
+
* @param promises - Array of promises to execute
|
|
790
|
+
* @param maxRetries - Maximum retry attempts per promise
|
|
791
|
+
* @param baseDelay - Initial delay for exponential backoff
|
|
792
|
+
* @returns Array of results with null for failed promises
|
|
793
|
+
*/
|
|
590
794
|
async function promiseSettle(promises, maxRetries = 3, baseDelay = 1000) {
|
|
591
795
|
const promisesWithRetry = promises.map((promise, index) => withRetry(async () => {
|
|
592
796
|
try {
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { IAddress, IVaultAdapterConfig } from '../../types';
|
|
1
|
+
import type { IAddress, IVaultAdapterConfig } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Get adapter configuration for a vault
|
|
4
|
+
*/
|
|
2
5
|
export declare function getVaultAdapterConfig(vaultAddress: IAddress): IVaultAdapterConfig | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Check if vault has adapter support
|
|
8
|
+
*/
|
|
3
9
|
export declare function vaultHasAdapter(vaultAddress: IAddress): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get deposit tokens for a vault (includes underlying + adapter tokens)
|
|
12
|
+
*/
|
|
4
13
|
export declare function getVaultDepositTokens(vaultAddress: IAddress, underlyingToken: IAddress): IAddress[];
|
|
@@ -4,19 +4,30 @@ exports.getVaultAdapterConfig = getVaultAdapterConfig;
|
|
|
4
4
|
exports.vaultHasAdapter = vaultHasAdapter;
|
|
5
5
|
exports.getVaultDepositTokens = getVaultDepositTokens;
|
|
6
6
|
const adapters_1 = require("../constants/adapters");
|
|
7
|
+
/**
|
|
8
|
+
* Get adapter configuration for a vault
|
|
9
|
+
*/
|
|
7
10
|
function getVaultAdapterConfig(vaultAddress) {
|
|
8
11
|
return adapters_1.VAULT_ADAPTER_CONFIGS[vaultAddress];
|
|
9
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if vault has adapter support
|
|
15
|
+
*/
|
|
10
16
|
function vaultHasAdapter(vaultAddress) {
|
|
11
17
|
return !!adapters_1.VAULT_ADAPTER_CONFIGS[vaultAddress];
|
|
12
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Get deposit tokens for a vault (includes underlying + adapter tokens)
|
|
21
|
+
*/
|
|
13
22
|
function getVaultDepositTokens(vaultAddress, underlyingToken) {
|
|
14
23
|
const adapterConfig = getVaultAdapterConfig(vaultAddress);
|
|
15
24
|
if (!adapterConfig) {
|
|
16
25
|
return [underlyingToken];
|
|
17
26
|
}
|
|
27
|
+
// Return all tokens including the underlying
|
|
18
28
|
const allTokens = [underlyingToken];
|
|
19
29
|
if (adapterConfig.tokens && adapterConfig.tokens.length > 0) {
|
|
30
|
+
// Use configured tokens list
|
|
20
31
|
adapterConfig.tokens.forEach((token) => {
|
|
21
32
|
if (!allTokens.includes(token)) {
|
|
22
33
|
allTokens.push(token);
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a string is a valid Solana base58 address (including PDAs).
|
|
3
|
+
* Returns `false` for EVM hex addresses.
|
|
4
|
+
*/
|
|
1
5
|
export declare function isSolanaAddress(address: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Check if a string is a valid Stellar address.
|
|
8
|
+
* Muxed accounts (M prefix, per SEP-0023) are intentionally excluded — they are
|
|
9
|
+
* not valid vault or contract addresses.
|
|
10
|
+
*/
|
|
2
11
|
export declare function isStellarAddress(address: string): boolean;
|
|
12
|
+
/** Check if a string is a valid Sui address (0x + 64 hex chars). */
|
|
3
13
|
export declare function isSuiAddress(address: string): boolean;
|
|
@@ -5,7 +5,12 @@ exports.isStellarAddress = isStellarAddress;
|
|
|
5
5
|
exports.isSuiAddress = isSuiAddress;
|
|
6
6
|
const ethers_1 = require("ethers");
|
|
7
7
|
const web3_js_1 = require("@solana/web3.js");
|
|
8
|
+
/** Stellar uses RFC 4648 base32; 56 chars, prefixed by G (public key) or C (contract/Soroban). */
|
|
8
9
|
const STELLAR_ADDRESS_RE = /^[A-Z2-7]{56}$/;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a string is a valid Solana base58 address (including PDAs).
|
|
12
|
+
* Returns `false` for EVM hex addresses.
|
|
13
|
+
*/
|
|
9
14
|
function isSolanaAddress(address) {
|
|
10
15
|
if (!address)
|
|
11
16
|
return false;
|
|
@@ -19,6 +24,11 @@ function isSolanaAddress(address) {
|
|
|
19
24
|
return false;
|
|
20
25
|
}
|
|
21
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if a string is a valid Stellar address.
|
|
29
|
+
* Muxed accounts (M prefix, per SEP-0023) are intentionally excluded — they are
|
|
30
|
+
* not valid vault or contract addresses.
|
|
31
|
+
*/
|
|
22
32
|
function isStellarAddress(address) {
|
|
23
33
|
if (!address || typeof address !== 'string')
|
|
24
34
|
return false;
|
|
@@ -28,6 +38,7 @@ function isStellarAddress(address) {
|
|
|
28
38
|
return false;
|
|
29
39
|
return STELLAR_ADDRESS_RE.test(address);
|
|
30
40
|
}
|
|
41
|
+
/** Check if a string is a valid Sui address (0x + 64 hex chars). */
|
|
31
42
|
function isSuiAddress(address) {
|
|
32
43
|
if (!address || typeof address !== 'string')
|
|
33
44
|
return false;
|