@augustdigital/sdk 8.21.0 → 8.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/core/analytics/sentry.js +26 -2
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/core/constants/vaults.d.ts +1 -1
- package/lib/core/constants/vaults.js +1 -1
- package/lib/core/constants/web3.d.ts +4 -2
- package/lib/core/constants/web3.js +11 -2
- package/lib/core/helpers/web3.d.ts +10 -4
- package/lib/core/helpers/web3.js +31 -5
- package/lib/core/logger/slack.d.ts +35 -2
- package/lib/core/logger/slack.js +59 -5
- package/lib/modules/vaults/getters.js +120 -4
- package/lib/sdk.d.ts +52 -8
- package/lib/services/subgraph/vaults.js +7 -7
- package/package.json +2 -1
|
@@ -384,12 +384,16 @@ function initializeSentry(config, environment, walletAddress, apiKey, appName) {
|
|
|
384
384
|
? config.tracesSampleRate
|
|
385
385
|
: 0.1; // Phase 2 default — verified partners can opt into 1.0 explicitly
|
|
386
386
|
const tracesSampleRate = Math.max(0, Math.min(1, rawSampleRate));
|
|
387
|
+
// Hoisted so `release`, `august.sdk_version`, and the deprecated
|
|
388
|
+
// `sdk.version` are provably the same value rather than three separate
|
|
389
|
+
// reads of `./version`.
|
|
390
|
+
const sdkVersion = getSDKVersion();
|
|
387
391
|
sdk.init({
|
|
388
392
|
dsn: constants_1.SENTRY_DSN,
|
|
389
393
|
tracesSampleRate,
|
|
390
394
|
enableTracing: true,
|
|
391
395
|
environment: environment.toLowerCase(),
|
|
392
|
-
release: `august-sdk@${
|
|
396
|
+
release: `august-sdk@${sdkVersion}`,
|
|
393
397
|
sendDefaultPii: true,
|
|
394
398
|
// SDK errors route through Logger.setSentrySink → captureException directly,
|
|
395
399
|
// so captureConsoleIntegration is redundant here. Omitting it also prevents
|
|
@@ -445,7 +449,27 @@ function initializeSentry(config, environment, walletAddress, apiKey, appName) {
|
|
|
445
449
|
updateUser(walletAddress, environment);
|
|
446
450
|
// Set global SDK tags
|
|
447
451
|
safeSetTag('sdk', 'august-digital');
|
|
448
|
-
|
|
452
|
+
// `august.sdk_version` is the queryable dimension for "which SDK build is
|
|
453
|
+
// this partner on" — the question that decides whether an error is a live
|
|
454
|
+
// defect or an already-shipped fix the consumer hasn't picked up.
|
|
455
|
+
//
|
|
456
|
+
// It exists because `sdk.version` (set below, kept for back-compat) is a
|
|
457
|
+
// RESERVED Sentry field: Sentry populates it with the version of its own
|
|
458
|
+
// client (`@sentry/core`). The custom tag is still stored, but a bare
|
|
459
|
+
// `sdk.version` in Discover resolves to Sentry's value, so the natural
|
|
460
|
+
// query silently answers the wrong question — uniform across every
|
|
461
|
+
// consumer, which makes it look like a working answer. Reaching the real
|
|
462
|
+
// value requires `tags[sdk.version]`, which nobody remembers to type.
|
|
463
|
+
//
|
|
464
|
+
// Both are low-cardinality version strings, so carrying the pair costs
|
|
465
|
+
// nothing against the tag budget (CLAUDE.md §8.4).
|
|
466
|
+
safeSetTag('august.sdk_version', sdkVersion);
|
|
467
|
+
/**
|
|
468
|
+
* @deprecated Shadowed by Sentry's reserved `sdk.version` field. Query
|
|
469
|
+
* `august.sdk_version` instead. Retained so existing saved queries,
|
|
470
|
+
* dashboards, and alert rules keep resolving; remove in the next major.
|
|
471
|
+
*/
|
|
472
|
+
safeSetTag('sdk.version', sdkVersion);
|
|
449
473
|
safeSetTag('sdk.runtime', (0, sentry_runtime_1.getSentryRuntime)());
|
|
450
474
|
// `app.name` is the dimension we filter on in Sentry to attribute
|
|
451
475
|
// events to a specific consuming application — see SDK quickstart docs.
|
|
@@ -69,7 +69,7 @@ export declare const NEMO_VAULT_ADDRESS = "0xa422c3018c46ba90a14acd14f96cb60616f
|
|
|
69
69
|
* Subgraph base URL
|
|
70
70
|
* @deprecated use getVaultMetadata to fetch subgraph URLs from the backend
|
|
71
71
|
*/
|
|
72
|
-
export declare const GOLDSKY_BASE_URL = "https://api.goldsky.com/api/
|
|
72
|
+
export declare const GOLDSKY_BASE_URL = "https://api.goldsky.com/api/public/project_cm9g0xy3o4j6v01vd34r3hvv9/subgraphs";
|
|
73
73
|
/**
|
|
74
74
|
* Subgraph URLs
|
|
75
75
|
* @deprecated use getVaultMetadata to fetch subgraph URLs from the backend
|
|
@@ -131,7 +131,7 @@ exports.NEMO_VAULT_ADDRESS = '0xa422c3018c46ba90a14acd14f96cb60616f5c91b';
|
|
|
131
131
|
* Subgraph base URL
|
|
132
132
|
* @deprecated use getVaultMetadata to fetch subgraph URLs from the backend
|
|
133
133
|
*/
|
|
134
|
-
exports.GOLDSKY_BASE_URL = 'https://api.goldsky.com/api/
|
|
134
|
+
exports.GOLDSKY_BASE_URL = 'https://api.goldsky.com/api/public/project_cm9g0xy3o4j6v01vd34r3hvv9/subgraphs';
|
|
135
135
|
/**
|
|
136
136
|
* Subgraph URLs
|
|
137
137
|
* @deprecated use getVaultMetadata to fetch subgraph URLs from the backend
|
|
@@ -32,7 +32,8 @@ export declare const NATIVE_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEe
|
|
|
32
32
|
/**
|
|
33
33
|
* Decimal precision of the native gas token on every EVM chain this SDK
|
|
34
34
|
* supports (ETH, Base, Arbitrum, Avalanche, Polygon, BNB, HyperEVM, Unichain,
|
|
35
|
-
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo
|
|
35
|
+
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo, X Layer —
|
|
36
|
+
* whose native OKB is also 18 decimals).
|
|
36
37
|
*
|
|
37
38
|
* All of them use 18-decimal native tokens, so this is a single constant rather
|
|
38
39
|
* than a per-chain map. It exists because the native token has no ERC-20
|
|
@@ -73,7 +74,8 @@ export declare const MULTICALL3_ADDRESS = "0xcA11bde05977b3631167028862bE2a17397
|
|
|
73
74
|
/**
|
|
74
75
|
* Chains where the canonical Multicall3 deployment was **verified on-chain**
|
|
75
76
|
* (`eth_getCode` returned the 3808-byte runtime at {@link MULTICALL3_ADDRESS};
|
|
76
|
-
* checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15
|
|
77
|
+
* checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15,
|
|
78
|
+
* X Layer on 2026-08-11) —
|
|
77
79
|
* deterministic-deployer presence is NOT assumed. Chains outside this set
|
|
78
80
|
* keep the per-call read path.
|
|
79
81
|
*
|
|
@@ -40,7 +40,8 @@ exports.NATIVE_ADDRESS = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
|
|
|
40
40
|
/**
|
|
41
41
|
* Decimal precision of the native gas token on every EVM chain this SDK
|
|
42
42
|
* supports (ETH, Base, Arbitrum, Avalanche, Polygon, BNB, HyperEVM, Unichain,
|
|
43
|
-
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo
|
|
43
|
+
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo, X Layer —
|
|
44
|
+
* whose native OKB is also 18 decimals).
|
|
44
45
|
*
|
|
45
46
|
* All of them use 18-decimal native tokens, so this is a single constant rather
|
|
46
47
|
* than a per-chain map. It exists because the native token has no ERC-20
|
|
@@ -160,6 +161,11 @@ exports.NETWORKS = {
|
|
|
160
161
|
chainId: 4217,
|
|
161
162
|
explorer: 'https://explore.tempo.xyz',
|
|
162
163
|
},
|
|
164
|
+
196: {
|
|
165
|
+
name: 'X Layer',
|
|
166
|
+
chainId: 196,
|
|
167
|
+
explorer: 'https://xlayerscan.com',
|
|
168
|
+
},
|
|
163
169
|
};
|
|
164
170
|
exports.AVAILABLE_CHAINS = Object.keys(exports.NETWORKS).map((c) => Number(c));
|
|
165
171
|
/**
|
|
@@ -171,7 +177,8 @@ exports.MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
|
|
|
171
177
|
/**
|
|
172
178
|
* Chains where the canonical Multicall3 deployment was **verified on-chain**
|
|
173
179
|
* (`eth_getCode` returned the 3808-byte runtime at {@link MULTICALL3_ADDRESS};
|
|
174
|
-
* checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15
|
|
180
|
+
* checked per chain on 2026-07-14, Tempo checked separately on 2026-07-15,
|
|
181
|
+
* X Layer on 2026-08-11) —
|
|
175
182
|
* deterministic-deployer presence is NOT assumed. Chains outside this set
|
|
176
183
|
* keep the per-call read path.
|
|
177
184
|
*
|
|
@@ -197,6 +204,7 @@ exports.MULTICALL3_VERIFIED_CHAINS = new Set([
|
|
|
197
204
|
747474, // Katana
|
|
198
205
|
25363, // Fluent
|
|
199
206
|
4217, // Tempo
|
|
207
|
+
196, // X Layer
|
|
200
208
|
]);
|
|
201
209
|
/**
|
|
202
210
|
* Fallbacks
|
|
@@ -225,5 +233,6 @@ exports.FALLBACK_RPC_URLS = {
|
|
|
225
233
|
4114: ['https://rpc.mainnet.citrea.xyz'],
|
|
226
234
|
25363: ['https://rpc.fluent.xyz'],
|
|
227
235
|
4217: ['https://rpc.mainnet.tempo.xyz'],
|
|
236
|
+
196: ['https://rpc.xlayer.tech'],
|
|
228
237
|
};
|
|
229
238
|
//# sourceMappingURL=web3.js.map
|
|
@@ -95,10 +95,16 @@ export { explorerLink } from './explorer-link';
|
|
|
95
95
|
* Fetch token decimals from contract or Solana mint.
|
|
96
96
|
* Results are cached to minimize RPC calls.
|
|
97
97
|
*
|
|
98
|
-
* **Never throws** — a failed read
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
98
|
+
* **Never throws** — a failed read resolves `undefined`. Callers that must not
|
|
99
|
+
* silently proceed on an unknown scale (any path that encodes an amount) should
|
|
100
|
+
* use {@link getDecimalsOrThrow} instead: feeding `undefined` into
|
|
101
|
+
* `toNormalizedBn` silently defaults to 18 decimals.
|
|
102
|
+
*
|
|
103
|
+
* Transient transport faults (provider rate limits, socket resets, an empty
|
|
104
|
+
* response to `decimals()`) are logged at `warn` — a breadcrumb, not a
|
|
105
|
+
* standalone Sentry issue — since the caller sees the same `undefined` either
|
|
106
|
+
* way. Everything else is logged at `error`. The read itself is **not**
|
|
107
|
+
* retried here; that is opt-in via {@link getDecimalsOrThrow}.
|
|
102
108
|
*
|
|
103
109
|
* @param provider Web3 provider
|
|
104
110
|
* @param address Token contract address or Solana mint
|
package/lib/core/helpers/web3.js
CHANGED
|
@@ -395,10 +395,16 @@ async function fetchDecimals(runner, address, isVault) {
|
|
|
395
395
|
* Fetch token decimals from contract or Solana mint.
|
|
396
396
|
* Results are cached to minimize RPC calls.
|
|
397
397
|
*
|
|
398
|
-
* **Never throws** — a failed read
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
398
|
+
* **Never throws** — a failed read resolves `undefined`. Callers that must not
|
|
399
|
+
* silently proceed on an unknown scale (any path that encodes an amount) should
|
|
400
|
+
* use {@link getDecimalsOrThrow} instead: feeding `undefined` into
|
|
401
|
+
* `toNormalizedBn` silently defaults to 18 decimals.
|
|
402
|
+
*
|
|
403
|
+
* Transient transport faults (provider rate limits, socket resets, an empty
|
|
404
|
+
* response to `decimals()`) are logged at `warn` — a breadcrumb, not a
|
|
405
|
+
* standalone Sentry issue — since the caller sees the same `undefined` either
|
|
406
|
+
* way. Everything else is logged at `error`. The read itself is **not**
|
|
407
|
+
* retried here; that is opt-in via {@link getDecimalsOrThrow}.
|
|
402
408
|
*
|
|
403
409
|
* @param provider Web3 provider
|
|
404
410
|
* @param address Token contract address or Solana mint
|
|
@@ -422,7 +428,27 @@ const getDecimals = async (provider, address, isVault = true) => {
|
|
|
422
428
|
return await sharedDecimalsRequest(key, () => fetchDecimals(provider, address, isVault));
|
|
423
429
|
}
|
|
424
430
|
catch (e) {
|
|
425
|
-
|
|
431
|
+
// Severity split. A provider rate-limit or socket fault is not a defect in
|
|
432
|
+
// the SDK or the caller's input — the read resolves `undefined` either way,
|
|
433
|
+
// exactly as documented, and logging it at error level made a QuickNode
|
|
434
|
+
// `50/second request limit reached` burst the fourth highest-volume issue
|
|
435
|
+
// in Sentry with nothing actionable in it. Genuine failures (a non-ERC-20
|
|
436
|
+
// at this address, a real revert) stay at error.
|
|
437
|
+
//
|
|
438
|
+
// Note this only changes the log level. The no-retry contract of this
|
|
439
|
+
// lenient reader is deliberate and unchanged — callers that must not
|
|
440
|
+
// proceed on an unknown scale use `getDecimalsOrThrow`, which retries.
|
|
441
|
+
const isTransient = (0, chain_error_1.isRetryableRpcError)(e) || (0, chain_error_1.isEmptyViewResponse)(e, DECIMALS_SELECTOR);
|
|
442
|
+
if (isTransient) {
|
|
443
|
+
logger_1.Logger.log.warn('getDecimals', {
|
|
444
|
+
address,
|
|
445
|
+
reason: 'transient RPC failure',
|
|
446
|
+
message: e instanceof Error ? e.message : String(e),
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
logger_1.Logger.log.error('getDecimals', `${address}::${e}`);
|
|
451
|
+
}
|
|
426
452
|
return undefined;
|
|
427
453
|
}
|
|
428
454
|
};
|
|
@@ -1,7 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Environment variable holding the Slack incoming-webhook to post SDK alerts
|
|
3
|
+
* to. Accepts either the full `https://hooks.slack.com/services/T…/B…/x…` URL
|
|
4
|
+
* or the bare `T…/B…/x…` path suffix.
|
|
3
5
|
*/
|
|
4
|
-
export declare const
|
|
6
|
+
export declare const SLACK_WEBHOOK_ENV_VAR = "AUGUST_SDK_SLACK_WEBHOOK_URL";
|
|
7
|
+
/**
|
|
8
|
+
* Resolve the Slack webhook to alert through.
|
|
9
|
+
*
|
|
10
|
+
* Why this replaced a hardcoded constant: a webhook path is a **bearer
|
|
11
|
+
* credential** — anyone holding it can post to the channel. The previous
|
|
12
|
+
* default embedded August's own webhook as a string literal, which shipped in
|
|
13
|
+
* every published tarball and in the generated `.d.ts`, handing every consumer
|
|
14
|
+
* of the SDK write access to an internal Slack channel (CLAUDE.md §5: no
|
|
15
|
+
* secrets in client-reachable code). It also meant a consumer's alerts went to
|
|
16
|
+
* August's channel rather than their own, with no way to redirect them.
|
|
17
|
+
*
|
|
18
|
+
* Resolution order:
|
|
19
|
+
* 1. `explicit` — passed by the caller, wins outright;
|
|
20
|
+
* 2. `AUGUST_SDK_SLACK_WEBHOOK_URL` in the environment;
|
|
21
|
+
* 3. none — alerting is disabled and the call becomes a no-op.
|
|
22
|
+
*
|
|
23
|
+
* Reading the env var per call (rather than once at module load) means a
|
|
24
|
+
* consumer configuring it after import still gets alerts, and a test can set
|
|
25
|
+
* and unset it without re-importing the module.
|
|
26
|
+
*
|
|
27
|
+
* @param explicit - Caller-supplied webhook, full URL or bare path suffix.
|
|
28
|
+
* @returns The bare `T…/B…/x…` path suffix, or `''` when unconfigured.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveSlackWebhookUrl(explicit?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* @deprecated Was a hardcoded webhook credential baked into the published
|
|
33
|
+
* bundle. It now resolves from {@link SLACK_WEBHOOK_ENV_VAR} and is `''` when
|
|
34
|
+
* unset. Call {@link resolveSlackWebhookUrl} instead — this export exists only
|
|
35
|
+
* so existing imports keep compiling, and is removed in the next major.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_SLACK_WEBHOOK_URL = "";
|
|
5
38
|
declare function error(options: {
|
|
6
39
|
title: string;
|
|
7
40
|
error: string;
|
package/lib/core/logger/slack.js
CHANGED
|
@@ -1,16 +1,70 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SLACK = exports.DEFAULT_SLACK_WEBHOOK_URL = void 0;
|
|
3
|
+
exports.SLACK = exports.DEFAULT_SLACK_WEBHOOK_URL = exports.SLACK_WEBHOOK_ENV_VAR = void 0;
|
|
4
|
+
exports.resolveSlackWebhookUrl = resolveSlackWebhookUrl;
|
|
4
5
|
const core_1 = require("../helpers/core");
|
|
5
6
|
const explorer_link_1 = require("../helpers/explorer-link");
|
|
6
7
|
const sanitize_1 = require("../analytics/sanitize");
|
|
8
|
+
const env_1 = require("../analytics/env");
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
10
|
+
* Environment variable holding the Slack incoming-webhook to post SDK alerts
|
|
11
|
+
* to. Accepts either the full `https://hooks.slack.com/services/T…/B…/x…` URL
|
|
12
|
+
* or the bare `T…/B…/x…` path suffix.
|
|
9
13
|
*/
|
|
10
|
-
exports.
|
|
14
|
+
exports.SLACK_WEBHOOK_ENV_VAR = 'AUGUST_SDK_SLACK_WEBHOOK_URL';
|
|
15
|
+
/** `https://hooks.slack.com/services/` — stripped so both forms are accepted. */
|
|
16
|
+
const SLACK_WEBHOOK_PREFIX = 'https://hooks.slack.com/services/';
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the Slack webhook to alert through.
|
|
19
|
+
*
|
|
20
|
+
* Why this replaced a hardcoded constant: a webhook path is a **bearer
|
|
21
|
+
* credential** — anyone holding it can post to the channel. The previous
|
|
22
|
+
* default embedded August's own webhook as a string literal, which shipped in
|
|
23
|
+
* every published tarball and in the generated `.d.ts`, handing every consumer
|
|
24
|
+
* of the SDK write access to an internal Slack channel (CLAUDE.md §5: no
|
|
25
|
+
* secrets in client-reachable code). It also meant a consumer's alerts went to
|
|
26
|
+
* August's channel rather than their own, with no way to redirect them.
|
|
27
|
+
*
|
|
28
|
+
* Resolution order:
|
|
29
|
+
* 1. `explicit` — passed by the caller, wins outright;
|
|
30
|
+
* 2. `AUGUST_SDK_SLACK_WEBHOOK_URL` in the environment;
|
|
31
|
+
* 3. none — alerting is disabled and the call becomes a no-op.
|
|
32
|
+
*
|
|
33
|
+
* Reading the env var per call (rather than once at module load) means a
|
|
34
|
+
* consumer configuring it after import still gets alerts, and a test can set
|
|
35
|
+
* and unset it without re-importing the module.
|
|
36
|
+
*
|
|
37
|
+
* @param explicit - Caller-supplied webhook, full URL or bare path suffix.
|
|
38
|
+
* @returns The bare `T…/B…/x…` path suffix, or `''` when unconfigured.
|
|
39
|
+
*/
|
|
40
|
+
function resolveSlackWebhookUrl(explicit) {
|
|
41
|
+
const raw = explicit?.trim() || (0, env_1.readEnv)(exports.SLACK_WEBHOOK_ENV_VAR)?.trim() || '';
|
|
42
|
+
return raw.startsWith(SLACK_WEBHOOK_PREFIX)
|
|
43
|
+
? raw.slice(SLACK_WEBHOOK_PREFIX.length)
|
|
44
|
+
: raw;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated Was a hardcoded webhook credential baked into the published
|
|
48
|
+
* bundle. It now resolves from {@link SLACK_WEBHOOK_ENV_VAR} and is `''` when
|
|
49
|
+
* unset. Call {@link resolveSlackWebhookUrl} instead — this export exists only
|
|
50
|
+
* so existing imports keep compiling, and is removed in the next major.
|
|
51
|
+
*/
|
|
52
|
+
exports.DEFAULT_SLACK_WEBHOOK_URL = '';
|
|
53
|
+
/** One-shot guard so an unconfigured webhook warns once, not per alert. */
|
|
54
|
+
let warnedUnconfigured = false;
|
|
11
55
|
function error(options) {
|
|
12
56
|
const { title, error, poolAddress, chainId, slackWebookUrl, address } = options;
|
|
13
|
-
|
|
57
|
+
// Falls back to the environment so a caller that passes nothing still
|
|
58
|
+
// alerts, provided the deployment configured a webhook of its own.
|
|
59
|
+
const webhookPath = resolveSlackWebhookUrl(slackWebookUrl);
|
|
60
|
+
if (!webhookPath) {
|
|
61
|
+
// Silence here used to be the hardcoded-default's job. Say it once, so a
|
|
62
|
+
// deployment that expected alerts learns they are off instead of watching
|
|
63
|
+
// an empty channel. Never log the webhook value itself.
|
|
64
|
+
if (!warnedUnconfigured) {
|
|
65
|
+
warnedUnconfigured = true;
|
|
66
|
+
console.warn(`#Slack.error: no webhook configured — set ${exports.SLACK_WEBHOOK_ENV_VAR} to enable Slack alerts. Alerts are disabled.`);
|
|
67
|
+
}
|
|
14
68
|
return;
|
|
15
69
|
}
|
|
16
70
|
if (!error) {
|
|
@@ -34,7 +88,7 @@ function error(options) {
|
|
|
34
88
|
return;
|
|
35
89
|
}
|
|
36
90
|
(async () => {
|
|
37
|
-
const webhookUrl =
|
|
91
|
+
const webhookUrl = `${SLACK_WEBHOOK_PREFIX}${webhookPath}`;
|
|
38
92
|
const safeError = (0, sanitize_1.sanitizeString)(String(error));
|
|
39
93
|
const safeTitle = (0, sanitize_1.sanitizeString)(String(title));
|
|
40
94
|
const data = {
|
|
@@ -68,6 +68,7 @@ const abis_1 = require("../../abis");
|
|
|
68
68
|
const types_1 = require("../../types");
|
|
69
69
|
const core_1 = require("../../core");
|
|
70
70
|
const ethers_1 = require("ethers");
|
|
71
|
+
const cache_1 = require("../../core/cache");
|
|
71
72
|
const utils_1 = require("./utils");
|
|
72
73
|
const subgraph_1 = require("../../services/subgraph");
|
|
73
74
|
const vaults_1 = require("../../services/subgraph/vaults");
|
|
@@ -356,8 +357,30 @@ async function getVaultSubaccountLoans(vault, options) {
|
|
|
356
357
|
* HTTP statuses that mean "no such record for this subaccount", not "something
|
|
357
358
|
* broke". The backend returns 404 for a subaccount with no CeFi/OTC position,
|
|
358
359
|
* which is the normal case for most vault borrowers.
|
|
360
|
+
*
|
|
361
|
+
* `400` is here for the same reason. The CeFi and OTC endpoints answer `400`
|
|
362
|
+
* for a borrower they do not track — a well-formed, checksummed EVM address
|
|
363
|
+
* that simply has no record on that side — and every `getVaultAllocations`
|
|
364
|
+
* call re-asks for the same untracked borrowers on every render. In Sentry
|
|
365
|
+
* that produced ~2.7k `AugustServerError: Request failed: 400` events across
|
|
366
|
+
* two issues in two days, all from the same handful of borrowers, none of them
|
|
367
|
+
* actionable. Both fetches are strictly best-effort enrichment: the vault's
|
|
368
|
+
* allocations are returned either way, so a `400` here can never mean the
|
|
369
|
+
* caller's request was malformed.
|
|
370
|
+
*
|
|
371
|
+
* This demotes the *log severity* only — nothing about the response handling
|
|
372
|
+
* changes, and any other status (401, 5xx, transport failures) is still an
|
|
373
|
+
* error-level Sentry issue.
|
|
374
|
+
*
|
|
375
|
+
* **Maintainer note on the `400` entry specifically.** Unlike `204`/`404`, a
|
|
376
|
+
* `400` is semantically "the client sent something wrong", so this demotion is
|
|
377
|
+
* safe only for as long as these two endpoints use `400` to mean "unknown
|
|
378
|
+
* borrower". If either ever starts returning `400` for a genuinely malformed
|
|
379
|
+
* request — a real defect in how the SDK builds the URL or body — this set
|
|
380
|
+
* would silence it. Should that contract change, drop `400` from here and let
|
|
381
|
+
* the backend distinguish the two cases with a status of its own.
|
|
359
382
|
*/
|
|
360
|
-
const EXPECTED_SUBACCOUNT_FETCH_STATUSES = new Set([204, 404]);
|
|
383
|
+
const EXPECTED_SUBACCOUNT_FETCH_STATUSES = new Set([204, 400, 404]);
|
|
361
384
|
/**
|
|
362
385
|
* Log a per-subaccount enrichment fetch failure at the right severity.
|
|
363
386
|
*
|
|
@@ -628,6 +651,87 @@ function subgraphAmountToBigInt(value) {
|
|
|
628
651
|
return BigInt(0);
|
|
629
652
|
}
|
|
630
653
|
}
|
|
654
|
+
/**
|
|
655
|
+
* Read `lagDuration()` off a vault, tolerating vaults that do not implement it.
|
|
656
|
+
*
|
|
657
|
+
* Why this exists: `getVaultAvailableRedemptions` binds every vault — v1 and
|
|
658
|
+
* v2 — to `ABI_LENDING_POOL_V2` because that ABI carries the superset of
|
|
659
|
+
* methods the scan needs. `lagDuration()` is not in that superset for every
|
|
660
|
+
* deployed pool. Calling it on a pool without the function reaches the
|
|
661
|
+
* fallback-less contract, which returns empty calldata, and ethers reports it
|
|
662
|
+
* as `missing revert data (action="call", data=null, …, code=CALL_EXCEPTION)`.
|
|
663
|
+
* That threw out of the whole redemption scan and became the single
|
|
664
|
+
* highest-volume error in production Sentry (~5.5k events over two days from
|
|
665
|
+
* three server deployments), while also returning an empty redemption list to
|
|
666
|
+
* every caller for the affected vaults.
|
|
667
|
+
*
|
|
668
|
+
* A missing `lagDuration()` means "this pool has no claim lag", which is what
|
|
669
|
+
* `0` encodes — the same value the v1 branch of the caller assumes.
|
|
670
|
+
*
|
|
671
|
+
* The empty response is **retried before it is believed**, because a provider
|
|
672
|
+
* that truncates an `eth_call` produces the identical shape: falling straight
|
|
673
|
+
* to `0` for a vault that really does have a lag would shift every computed
|
|
674
|
+
* claimable date. Only after the retries agree is the function treated as
|
|
675
|
+
* absent. A genuine revert carrying revert data still propagates, so real
|
|
676
|
+
* breakage stays loud.
|
|
677
|
+
*
|
|
678
|
+
* **The absence is memoized, the value is not.** Paying the retry budget (3
|
|
679
|
+
* `eth_call`s plus ~750ms of backoff) on every call for a vault that will never
|
|
680
|
+
* implement `lagDuration()` would trade an error flood for a latency and
|
|
681
|
+
* RPC-volume regression on exactly the vaults this path targets — a dashboard
|
|
682
|
+
* re-rendering redemptions pays it per render (CLAUDE.md §4.1, §4.2). Whether a
|
|
683
|
+
* deployed pool implements the function is fixed by its bytecode, so a
|
|
684
|
+
* confirmed absence is cacheable forever; the lag *value* is operator-settable
|
|
685
|
+
* and is deliberately never cached.
|
|
686
|
+
*
|
|
687
|
+
* Caveat on "fixed by its bytecode": an **upgradeable proxy** could gain a
|
|
688
|
+
* `lagDuration()` in a later implementation, and a process holding the memo
|
|
689
|
+
* would keep answering `0` for it. Bounded, not unbounded — `CACHE` carries a
|
|
690
|
+
* 24h TTL and `allowStale: true`, which serves an expired entry exactly once
|
|
691
|
+
* before evicting it, so the vault is re-read on the following call. Vaults
|
|
692
|
+
* behind an upgradeable proxy that add the function mid-process therefore
|
|
693
|
+
* misreport a zero lag for at most that window. Accepted deliberately: no
|
|
694
|
+
* deployed pool does this today, and the alternative is re-paying the retry
|
|
695
|
+
* budget forever for the vaults this path exists to serve.
|
|
696
|
+
*
|
|
697
|
+
* @param vaultContract - Anything exposing the vault's `lagDuration()` view;
|
|
698
|
+
* structurally typed so both `ethers.Contract` and the ABI-typed contract
|
|
699
|
+
* returned by `createContract` satisfy it.
|
|
700
|
+
* @param vault - Vault address, for the breadcrumb only.
|
|
701
|
+
* @param scope - Cache scope for the absence memo — the RPC endpoint the read
|
|
702
|
+
* went through. Scoping by endpoint (rather than globally by address) keeps
|
|
703
|
+
* the same address on two chains in separate entries.
|
|
704
|
+
* @returns The lag in seconds, or `0` when the vault has no `lagDuration()`.
|
|
705
|
+
* @throws The original error for any failure that is not an empty response.
|
|
706
|
+
*/
|
|
707
|
+
async function readLagDuration(vaultContract, vault, scope) {
|
|
708
|
+
const absenceKey = `lag-absent-${scope}-${vault.toLowerCase()}`;
|
|
709
|
+
// A vault proven not to implement the function cannot start implementing it.
|
|
710
|
+
if (cache_1.CACHE.get(absenceKey) === true)
|
|
711
|
+
return 0;
|
|
712
|
+
try {
|
|
713
|
+
return Number(await (0, core_1.retryOnTransientRpc)('getVaultAvailableRedemptions:lagDuration', () => vaultContract.lagDuration(), { vault }, (error) => (0, core_1.isRetryableRpcError)(error) ||
|
|
714
|
+
(0, core_1.isEmptyViewResponse)(error, LAG_DURATION_SELECTOR)));
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
if (!(0, core_1.isEmptyViewResponse)(error, LAG_DURATION_SELECTOR))
|
|
718
|
+
throw error;
|
|
719
|
+
// Retries agreed the response is empty — record the absence so the next
|
|
720
|
+
// call short-circuits instead of re-paying the full retry budget.
|
|
721
|
+
cache_1.CACHE.set(absenceKey, true);
|
|
722
|
+
core_1.Logger.log.warn('getVaultAvailableRedemptions', {
|
|
723
|
+
vault,
|
|
724
|
+
reason: 'vault does not implement lagDuration(); assuming no claim lag',
|
|
725
|
+
});
|
|
726
|
+
return 0;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* `lagDuration()` — `keccak256("lagDuration()")[0..4]`. Scopes the
|
|
731
|
+
* empty-response tolerance in {@link readLagDuration} to exactly that call, so
|
|
732
|
+
* an empty response to any *other* view still surfaces as an error.
|
|
733
|
+
*/
|
|
734
|
+
const LAG_DURATION_SELECTOR = '0x24e86d67';
|
|
631
735
|
async function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }) {
|
|
632
736
|
try {
|
|
633
737
|
// Stellar vaults don't support on-chain redemptions yet
|
|
@@ -674,7 +778,7 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
|
|
|
674
778
|
}
|
|
675
779
|
const lagDuration = typeof prefetchedReads?.lagDuration === 'number'
|
|
676
780
|
? prefetchedReads.lagDuration
|
|
677
|
-
:
|
|
781
|
+
: await readLagDuration(vaultContract, vault, options.rpcUrl);
|
|
678
782
|
const { withdrawalRequesteds, withdrawalProcesseds } = await (0, subgraph_1.getSubgraphAllWithdrawals)(vault, provider);
|
|
679
783
|
// format
|
|
680
784
|
const availableRedemptions = [];
|
|
@@ -954,7 +1058,13 @@ async function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, option
|
|
|
954
1058
|
const currentBlock = await provider.getBlockNumber();
|
|
955
1059
|
const blockSkip = (0, core_1.determineBlockSkipInternal)(chainId);
|
|
956
1060
|
const cutoffBlock = currentBlock - (lookbackBlocks ?? (0, core_1.determineBlockCutoff)(chainId));
|
|
957
|
-
|
|
1061
|
+
// Max concurrent `eth_getLogs` requests per batch. Kept well under the
|
|
1062
|
+
// per-second cap of the smallest provider plan we run against (QuickNode:
|
|
1063
|
+
// 50/s) because this scan is not the only caller on the connection — a
|
|
1064
|
+
// page rendering several vaults runs several of these concurrently. At 20
|
|
1065
|
+
// the batches reliably tripped `-32007 50/second request limit reached`,
|
|
1066
|
+
// which the retry below now absorbs and this ceiling mostly avoids.
|
|
1067
|
+
const BATCH_SIZE = 8;
|
|
958
1068
|
core_1.Logger.log.info('getVaultRedemptionHistory', {
|
|
959
1069
|
vault,
|
|
960
1070
|
version,
|
|
@@ -987,7 +1097,13 @@ async function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, option
|
|
|
987
1097
|
const logs = [];
|
|
988
1098
|
for (let i = 0; i < ranges.length; i += BATCH_SIZE) {
|
|
989
1099
|
const batch = ranges.slice(i, i + BATCH_SIZE);
|
|
990
|
-
const batchResults = await Promise.allSettled(batch.map((r) =>
|
|
1100
|
+
const batchResults = await Promise.allSettled(batch.map((r) =>
|
|
1101
|
+
// `eth_getLogs` over a fixed block range is idempotent, so a chunk
|
|
1102
|
+
// rejected by a rate limiter or a flaky socket is safe to repeat.
|
|
1103
|
+
// Without this a single `-32007` burst aborted the whole scan and
|
|
1104
|
+
// the caller lost the redemption history entirely — the same failure
|
|
1105
|
+
// mode the throw below was added to make visible.
|
|
1106
|
+
(0, core_1.retryOnTransientRpc)('getVaultRedemptionHistory:chunk', () => poolContract.queryFilter('WithdrawalProcessed', BigInt(r.from), BigInt(r.to)), { vault, fromBlock: r.from, toBlock: r.to })));
|
|
991
1107
|
const failed = batchResults.filter((r) => r.status === 'rejected');
|
|
992
1108
|
if (failed.length > 0) {
|
|
993
1109
|
const firstReason = failed[0].reason;
|
package/lib/sdk.d.ts
CHANGED
|
@@ -17419,9 +17419,12 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
17419
17419
|
};
|
|
17420
17420
|
|
|
17421
17421
|
/**
|
|
17422
|
-
*
|
|
17422
|
+
* @deprecated Was a hardcoded webhook credential baked into the published
|
|
17423
|
+
* bundle. It now resolves from {@link SLACK_WEBHOOK_ENV_VAR} and is `''` when
|
|
17424
|
+
* unset. Call {@link resolveSlackWebhookUrl} instead — this export exists only
|
|
17425
|
+
* so existing imports keep compiling, and is removed in the next major.
|
|
17423
17426
|
*/
|
|
17424
|
-
declare const DEFAULT_SLACK_WEBHOOK_URL = "
|
|
17427
|
+
declare const DEFAULT_SLACK_WEBHOOK_URL = "";
|
|
17425
17428
|
|
|
17426
17429
|
/**
|
|
17427
17430
|
* Deposit a native token (ETH / AVAX / etc.) into a vault via the
|
|
@@ -17568,7 +17571,8 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
17568
17571
|
/**
|
|
17569
17572
|
* Decimal precision of the native gas token on every EVM chain this SDK
|
|
17570
17573
|
* supports (ETH, Base, Arbitrum, Avalanche, Polygon, BNB, HyperEVM, Unichain,
|
|
17571
|
-
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo
|
|
17574
|
+
* Mezo, Monad, Plasma, Ink, Flare, Katana, Citrea, Fluent, Tempo, X Layer —
|
|
17575
|
+
* whose native OKB is also 18 decimals).
|
|
17572
17576
|
*
|
|
17573
17577
|
* All of them use 18-decimal native tokens, so this is a single constant rather
|
|
17574
17578
|
* than a per-chain map. It exists because the native token has no ERC-20
|
|
@@ -18322,10 +18326,16 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
18322
18326
|
* Fetch token decimals from contract or Solana mint.
|
|
18323
18327
|
* Results are cached to minimize RPC calls.
|
|
18324
18328
|
*
|
|
18325
|
-
* **Never throws** — a failed read
|
|
18326
|
-
*
|
|
18327
|
-
*
|
|
18328
|
-
*
|
|
18329
|
+
* **Never throws** — a failed read resolves `undefined`. Callers that must not
|
|
18330
|
+
* silently proceed on an unknown scale (any path that encodes an amount) should
|
|
18331
|
+
* use {@link getDecimalsOrThrow} instead: feeding `undefined` into
|
|
18332
|
+
* `toNormalizedBn` silently defaults to 18 decimals.
|
|
18333
|
+
*
|
|
18334
|
+
* Transient transport faults (provider rate limits, socket resets, an empty
|
|
18335
|
+
* response to `decimals()`) are logged at `warn` — a breadcrumb, not a
|
|
18336
|
+
* standalone Sentry issue — since the caller sees the same `undefined` either
|
|
18337
|
+
* way. Everything else is logged at `error`. The read itself is **not**
|
|
18338
|
+
* retried here; that is opt-in via {@link getDecimalsOrThrow}.
|
|
18329
18339
|
*
|
|
18330
18340
|
* @param provider Web3 provider
|
|
18331
18341
|
* @param address Token contract address or Solana mint
|
|
@@ -19429,7 +19439,7 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
19429
19439
|
* Subgraph base URL
|
|
19430
19440
|
* @deprecated use getVaultMetadata to fetch subgraph URLs from the backend
|
|
19431
19441
|
*/
|
|
19432
|
-
export declare const GOLDSKY_BASE_URL = "https://api.goldsky.com/api/
|
|
19442
|
+
export declare const GOLDSKY_BASE_URL = "https://api.goldsky.com/api/public/project_cm9g0xy3o4j6v01vd34r3hvv9/subgraphs";
|
|
19433
19443
|
|
|
19434
19444
|
/**
|
|
19435
19445
|
* Deposit funds into a Solana August vault and mint share tokens.
|
|
@@ -24058,6 +24068,31 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
24058
24068
|
*/
|
|
24059
24069
|
export declare function resolveOriginCode(provided?: `0x${string}`): `0x${string}`;
|
|
24060
24070
|
|
|
24071
|
+
/**
|
|
24072
|
+
* Resolve the Slack webhook to alert through.
|
|
24073
|
+
*
|
|
24074
|
+
* Why this replaced a hardcoded constant: a webhook path is a **bearer
|
|
24075
|
+
* credential** — anyone holding it can post to the channel. The previous
|
|
24076
|
+
* default embedded August's own webhook as a string literal, which shipped in
|
|
24077
|
+
* every published tarball and in the generated `.d.ts`, handing every consumer
|
|
24078
|
+
* of the SDK write access to an internal Slack channel (CLAUDE.md §5: no
|
|
24079
|
+
* secrets in client-reachable code). It also meant a consumer's alerts went to
|
|
24080
|
+
* August's channel rather than their own, with no way to redirect them.
|
|
24081
|
+
*
|
|
24082
|
+
* Resolution order:
|
|
24083
|
+
* 1. `explicit` — passed by the caller, wins outright;
|
|
24084
|
+
* 2. `AUGUST_SDK_SLACK_WEBHOOK_URL` in the environment;
|
|
24085
|
+
* 3. none — alerting is disabled and the call becomes a no-op.
|
|
24086
|
+
*
|
|
24087
|
+
* Reading the env var per call (rather than once at module load) means a
|
|
24088
|
+
* consumer configuring it after import still gets alerts, and a test can set
|
|
24089
|
+
* and unset it without re-importing the module.
|
|
24090
|
+
*
|
|
24091
|
+
* @param explicit - Caller-supplied webhook, full URL or bare path suffix.
|
|
24092
|
+
* @returns The bare `T…/B…/x…` path suffix, or `''` when unconfigured.
|
|
24093
|
+
*/
|
|
24094
|
+
declare function resolveSlackWebhookUrl(explicit?: string): string;
|
|
24095
|
+
|
|
24061
24096
|
/* Excluded from this release type: resolveSpender */
|
|
24062
24097
|
|
|
24063
24098
|
/**
|
|
@@ -25088,12 +25123,21 @@ declare type AsArray<T> = T extends readonly unknown[] ? T : never;
|
|
|
25088
25123
|
|
|
25089
25124
|
declare namespace Slack {
|
|
25090
25125
|
export {
|
|
25126
|
+
resolveSlackWebhookUrl,
|
|
25127
|
+
SLACK_WEBHOOK_ENV_VAR,
|
|
25091
25128
|
DEFAULT_SLACK_WEBHOOK_URL,
|
|
25092
25129
|
SLACK
|
|
25093
25130
|
}
|
|
25094
25131
|
}
|
|
25095
25132
|
export { Slack }
|
|
25096
25133
|
|
|
25134
|
+
/**
|
|
25135
|
+
* Environment variable holding the Slack incoming-webhook to post SDK alerts
|
|
25136
|
+
* to. Accepts either the full `https://hooks.slack.com/services/T…/B…/x…` URL
|
|
25137
|
+
* or the bare `T…/B…/x…` path suffix.
|
|
25138
|
+
*/
|
|
25139
|
+
declare const SLACK_WEBHOOK_ENV_VAR = "AUGUST_SDK_SLACK_WEBHOOK_URL";
|
|
25140
|
+
|
|
25097
25141
|
export declare const Solana: {
|
|
25098
25142
|
utils: {
|
|
25099
25143
|
getExplorerLink: ({ signature, type, network, }: {
|
|
@@ -16,7 +16,7 @@ const fetcher_2 = require("../../modules/vaults/fetcher");
|
|
|
16
16
|
/**
|
|
17
17
|
* Utils
|
|
18
18
|
*/
|
|
19
|
-
const GOLDSKY_API_KEY = '
|
|
19
|
+
const GOLDSKY_API_KEY = '';
|
|
20
20
|
// Dedupe window for "Missing Subgraph" alerts (per pool).
|
|
21
21
|
const MISSING_SUBGRAPH_ALERT_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
22
22
|
/**
|
|
@@ -371,7 +371,7 @@ const TRANSFER_QUERY_PROPS = `
|
|
|
371
371
|
* @param provider
|
|
372
372
|
* @returns
|
|
373
373
|
*/
|
|
374
|
-
async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slack_1.
|
|
374
|
+
async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)()) {
|
|
375
375
|
// setup
|
|
376
376
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
377
377
|
if (vaultSymbol === undefined) {
|
|
@@ -443,7 +443,7 @@ async function getSubgraphWithdrawRequests(pool, provider, slackWebookUrl = slac
|
|
|
443
443
|
requests.push(...(json?.data?.withdrawalRequesteds || []));
|
|
444
444
|
return requests;
|
|
445
445
|
}
|
|
446
|
-
async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = slack_1.
|
|
446
|
+
async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)()) {
|
|
447
447
|
try {
|
|
448
448
|
// setup
|
|
449
449
|
let vaultSymbol = await (0, core_1.getVaultSymbol)(pool, provider);
|
|
@@ -526,7 +526,7 @@ async function getSubgraphWithdrawProccessed(pool, provider, slackWebookUrl = sl
|
|
|
526
526
|
* @param provider
|
|
527
527
|
* @returns
|
|
528
528
|
*/
|
|
529
|
-
async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = slack_1.
|
|
529
|
+
async function getSubgraphAllWithdrawals(pool, provider, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)()) {
|
|
530
530
|
let query = '';
|
|
531
531
|
try {
|
|
532
532
|
// setup
|
|
@@ -695,7 +695,7 @@ async function getArchivedVaultUserHistory(user, provider, pool) {
|
|
|
695
695
|
// chronology. The backend returns rows in arbitrary order, so re-sort here.
|
|
696
696
|
.sort((a, b) => Number(a.timestamp_) - Number(b.timestamp_)));
|
|
697
697
|
}
|
|
698
|
-
async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = slack_1.
|
|
698
|
+
async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)()) {
|
|
699
699
|
try {
|
|
700
700
|
// This path is EVM-only: it reads chain id and network from an EVM
|
|
701
701
|
// JsonRpcProvider (eth_chainId / getNetwork) and queries an EVM subgraph.
|
|
@@ -847,7 +847,7 @@ async function getSubgraphUserHistory(user, provider, pool, slackWebookUrl = sla
|
|
|
847
847
|
return [];
|
|
848
848
|
}
|
|
849
849
|
}
|
|
850
|
-
async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
|
|
850
|
+
async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)(), opts = {}) {
|
|
851
851
|
try {
|
|
852
852
|
// setup
|
|
853
853
|
const requests = [];
|
|
@@ -1008,7 +1008,7 @@ async function getSubgraphVaultHistory(provider, pool, slackWebookUrl = slack_1.
|
|
|
1008
1008
|
return [];
|
|
1009
1009
|
}
|
|
1010
1010
|
}
|
|
1011
|
-
async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = slack_1.
|
|
1011
|
+
async function getSubgraphUserTransfers(user, provider, pool, slackWebookUrl = (0, slack_1.resolveSlackWebhookUrl)()) {
|
|
1012
1012
|
try {
|
|
1013
1013
|
// setup
|
|
1014
1014
|
let amountOfTransfers = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@augustdigital/sdk",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.22.1",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/sdk.d.ts",
|
|
6
6
|
"keywords": [
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"test:jest:watch": "jest --config jest.config.unit.js --watch",
|
|
67
67
|
"test:jest:coverage": "jest --config jest.config.unit.js --coverage",
|
|
68
68
|
"test:forknet": "node tests/forknet/run.mjs",
|
|
69
|
+
"test:solana-localnet": "node tests/solana-localnet/run.mjs",
|
|
69
70
|
"test:solana-idl": "jest --config jest.config.idl-drift.js",
|
|
70
71
|
"clean": "rm -rf ./lib",
|
|
71
72
|
"format": "biome check --write .",
|