@augustdigital/sdk 9.5.0 → 9.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/lib/adapters/evm/index.d.ts +1 -1
- package/lib/adapters/evm/index.js +29 -29
- package/lib/core/analytics/app-name.js +1 -1
- package/lib/core/analytics/constants.d.ts +10 -0
- package/lib/core/analytics/constants.js +17 -1
- package/lib/core/analytics/index.d.ts +7 -4
- package/lib/core/analytics/index.js +8 -4
- package/lib/core/analytics/instrumentation.js +8 -4
- package/lib/core/analytics/method-taxonomy.js +13 -0
- package/lib/core/analytics/metrics.d.ts +25 -10
- package/lib/core/analytics/metrics.js +41 -15
- package/lib/core/analytics/sentry.d.ts +24 -3
- package/lib/core/analytics/sentry.js +49 -18
- package/lib/core/analytics/types.d.ts +11 -4
- package/lib/core/analytics/user-identity.d.ts +19 -5
- package/lib/core/analytics/user-identity.js +35 -21
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/core/auth/verify.js +5 -1
- package/lib/core/base.class.js +3 -0
- package/lib/core/constants/core.d.ts +3 -0
- package/lib/core/constants/core.js +3 -0
- package/lib/core/constants/swap-router.d.ts +16 -0
- package/lib/core/constants/swap-router.js +16 -0
- package/lib/core/errors/index.d.ts +36 -1
- package/lib/core/errors/index.js +40 -1
- package/lib/core/fetcher.d.ts +13 -0
- package/lib/core/fetcher.js +33 -0
- package/lib/main.d.ts +5 -0
- package/lib/main.js +5 -0
- package/lib/modules/vaults/getters.d.ts +55 -0
- package/lib/modules/vaults/getters.js +58 -14
- package/lib/modules/vaults/main.d.ts +4 -0
- package/lib/modules/vaults/main.js +4 -0
- package/lib/modules/vaults/write.actions.d.ts +57 -1
- package/lib/modules/vaults/write.actions.js +86 -2
- package/lib/sdk.d.ts +13032 -12801
- package/package.json +2 -2
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSDKVersion = getSDKVersion;
|
|
3
4
|
exports.resetErrorDedupe = resetErrorDedupe;
|
|
4
5
|
exports.initializeSentry = initializeSentry;
|
|
5
6
|
exports.updateUser = updateUser;
|
|
6
7
|
exports.clearUser = clearUser;
|
|
7
8
|
exports.isAnalyticsEnabled = isAnalyticsEnabled;
|
|
9
|
+
exports.getSpanAttributes = getSpanAttributes;
|
|
8
10
|
exports.getSentry = getSentry;
|
|
9
11
|
exports.resetAnalytics = resetAnalytics;
|
|
10
12
|
exports.captureSdkException = captureSdkException;
|
|
@@ -22,9 +24,15 @@ let isEnabled = true;
|
|
|
22
24
|
let currentIdentity = null;
|
|
23
25
|
/** Cached API key for identity updates */
|
|
24
26
|
let cachedApiKey;
|
|
27
|
+
/** Identity tags resolved at init, mirrored onto every `sdk.method` span. */
|
|
28
|
+
let spanAttributes = {};
|
|
25
29
|
/**
|
|
26
|
-
*
|
|
27
|
-
* Falls back to 'development'
|
|
30
|
+
* The August SDK build version, read from the generated `version.ts`.
|
|
31
|
+
* Falls back to `'development'` in an unbuilt checkout, where that file does
|
|
32
|
+
* not exist. Shared by the Sentry `release` tag and the
|
|
33
|
+
* `x-august-sdk-version` request header so the two can never disagree.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
28
36
|
*/
|
|
29
37
|
function getSDKVersion() {
|
|
30
38
|
try {
|
|
@@ -326,7 +334,8 @@ function createSentrySink() {
|
|
|
326
334
|
* error rather than silently anonymous events.
|
|
327
335
|
*
|
|
328
336
|
* @param config - Analytics configuration. Pass `tracesSampleRate` to
|
|
329
|
-
* override the default of `0.1
|
|
337
|
+
* override the default of `0.1`, and `surface` to label the emitting
|
|
338
|
+
* surface (`sdk.surface` tag; defaults to `'sdk'`).
|
|
330
339
|
* @param environment - Current environment (DEV or PROD).
|
|
331
340
|
* @param appName - App-name slug, required. Set as the global `app.name`
|
|
332
341
|
* tag on every event and used to derive `partner.id`. Identifier-shaped:
|
|
@@ -463,17 +472,6 @@ function initializeSentry(config, environment, appName, walletAddress, apiKey) {
|
|
|
463
472
|
}
|
|
464
473
|
return event;
|
|
465
474
|
},
|
|
466
|
-
beforeSendTransaction(transaction) {
|
|
467
|
-
// Sub-sample the high-frequency network bookkeeping category (switchNetwork,
|
|
468
|
-
// updateWallet, clearWallet, setSigner) to 10% of whatever tracesSampleRate
|
|
469
|
-
// already passed — these fire on every wallet/chain update and are low signal
|
|
470
|
-
// for the partner-usage dashboard relative to read/write calls.
|
|
471
|
-
if (transaction.tags?.['sdk.category'] === 'network' &&
|
|
472
|
-
Math.random() > 0.1) {
|
|
473
|
-
return null;
|
|
474
|
-
}
|
|
475
|
-
return transaction;
|
|
476
|
-
},
|
|
477
475
|
});
|
|
478
476
|
// Set initial user identity
|
|
479
477
|
updateUser(walletAddress, environment);
|
|
@@ -500,13 +498,32 @@ function initializeSentry(config, environment, appName, walletAddress, apiKey) {
|
|
|
500
498
|
* dashboards, and alert rules keep resolving; remove in the next major.
|
|
501
499
|
*/
|
|
502
500
|
safeSetTag('sdk.version', sdkVersion);
|
|
503
|
-
|
|
501
|
+
const runtime = (0, sentry_runtime_1.getSentryRuntime)();
|
|
502
|
+
safeSetTag('sdk.runtime', runtime);
|
|
504
503
|
// `app.name` is the dimension we filter on in Sentry to attribute
|
|
505
504
|
// events to a specific consuming application — see SDK quickstart docs.
|
|
506
505
|
safeSetTag('app.name', validatedAppName);
|
|
507
506
|
// `unverified:` prefix until the backend API-key → partner-id endpoint exists.
|
|
508
|
-
|
|
509
|
-
safeSetTag('partner.
|
|
507
|
+
const partnerId = `unverified:${validatedAppName}`;
|
|
508
|
+
safeSetTag('partner.id', partnerId);
|
|
509
|
+
// First-party apps are labelled so `partner.tier:unverified` already
|
|
510
|
+
// means "external integrator" before verification exists.
|
|
511
|
+
const partnerTier = constants_1.FIRST_PARTY_APP_NAMES.has(validatedAppName)
|
|
512
|
+
? 'internal'
|
|
513
|
+
: 'unverified';
|
|
514
|
+
safeSetTag('partner.tier', partnerTier);
|
|
515
|
+
const surface = config.surface ?? 'sdk';
|
|
516
|
+
safeSetTag('sdk.surface', surface);
|
|
517
|
+
// Scope tags land only on the root span of a trace; child `sdk.method`
|
|
518
|
+
// spans get these copied on as attributes by `withMethodTracking`.
|
|
519
|
+
spanAttributes = {
|
|
520
|
+
'app.name': validatedAppName,
|
|
521
|
+
'partner.id': partnerId,
|
|
522
|
+
'partner.tier': partnerTier,
|
|
523
|
+
'sdk.runtime': runtime,
|
|
524
|
+
'sdk.surface': surface,
|
|
525
|
+
'august.sdk_version': sdkVersion,
|
|
526
|
+
};
|
|
510
527
|
// Bridge the SDK's structured logger into Sentry now that the SDK is live.
|
|
511
528
|
// Without this, Logger.log.error/warn are no-ops in production (no
|
|
512
529
|
// SDKLogger/structured logger is wired by default), so SDK-internal
|
|
@@ -594,6 +611,18 @@ function clearUser() {
|
|
|
594
611
|
function isAnalyticsEnabled() {
|
|
595
612
|
return isEnabled && isInitialized;
|
|
596
613
|
}
|
|
614
|
+
/**
|
|
615
|
+
* Identity tags resolved by `initializeSentry`, for `withMethodTracking` to
|
|
616
|
+
* copy onto each span as attributes. Sentry's span dataset carries scope tags
|
|
617
|
+
* on the root span only, so without this copy child `sdk.method` rows cannot
|
|
618
|
+
* be filtered by `app.name` or `partner.id`.
|
|
619
|
+
*
|
|
620
|
+
* @returns The tag snapshot, or `{}` until analytics has been enabled.
|
|
621
|
+
* @internal
|
|
622
|
+
*/
|
|
623
|
+
function getSpanAttributes() {
|
|
624
|
+
return spanAttributes;
|
|
625
|
+
}
|
|
597
626
|
/**
|
|
598
627
|
* Get the current Sentry instance for advanced usage.
|
|
599
628
|
* Returns null if analytics is disabled.
|
|
@@ -611,6 +640,7 @@ function resetAnalytics() {
|
|
|
611
640
|
isEnabled = true;
|
|
612
641
|
currentIdentity = null;
|
|
613
642
|
cachedApiKey = undefined;
|
|
643
|
+
spanAttributes = {};
|
|
614
644
|
logger_1.Logger.setSentrySink(null);
|
|
615
645
|
(0, sentry_runtime_1.resetSentryRuntime)();
|
|
616
646
|
// The error rate limiter is process-lifetime state; a reset analytics layer
|
|
@@ -624,7 +654,8 @@ function resetAnalytics() {
|
|
|
624
654
|
* surface. No-ops when analytics is disabled.
|
|
625
655
|
*
|
|
626
656
|
* @param error - Thrown value. Non-Error values are wrapped.
|
|
627
|
-
* @param options - `surface` ('cli' | 'sdk' | 'react' | string)
|
|
657
|
+
* @param options - `surface` ('cli' | 'mcp' | 'sdk' | 'react' | string)
|
|
658
|
+
* overriding the init-time `sdk.surface` tag for this event, extra `tags`,
|
|
628
659
|
* `extra` data, and a `flushTimeoutMs` to await before resolving (needed
|
|
629
660
|
* in Node when the process is about to exit).
|
|
630
661
|
*/
|
|
@@ -7,17 +7,24 @@ export interface IAnalyticsConfig {
|
|
|
7
7
|
/** Set to false to disable analytics. Default: true */
|
|
8
8
|
enabled?: boolean;
|
|
9
9
|
/**
|
|
10
|
-
* Sentry trace sample rate. Defaults to `1
|
|
11
|
-
*
|
|
10
|
+
* Sentry trace sample rate. Defaults to `0.1`; values outside `[0, 1]`
|
|
11
|
+
* are clamped.
|
|
12
12
|
*/
|
|
13
13
|
tracesSampleRate?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Which August surface is emitting telemetry, recorded once at init as the
|
|
16
|
+
* sticky `sdk.surface` tag on every event and span. The CLI passes `'cli'`
|
|
17
|
+
* and the MCP server `'mcp'`; applications embedding the SDK directly can
|
|
18
|
+
* leave the default `'sdk'`.
|
|
19
|
+
*/
|
|
20
|
+
surface?: 'sdk' | 'cli' | 'mcp' | 'react' | string;
|
|
14
21
|
}
|
|
15
22
|
/**
|
|
16
23
|
* User identity for analytics tracking.
|
|
17
|
-
* Multiple identifiers are used with priority: apiKeyHash
|
|
24
|
+
* Multiple identifiers are used with priority: apiKeyHash \> wallet \> domain \> fingerprint \> session
|
|
18
25
|
*/
|
|
19
26
|
export interface IUserIdentity {
|
|
20
|
-
/** SHA-256 hash
|
|
27
|
+
/** Hex-encoded SHA-256 hash of the API key. Never stores the raw key. */
|
|
21
28
|
apiKeyHash?: string;
|
|
22
29
|
/** User's wallet address (lowercased) */
|
|
23
30
|
walletAddress?: string;
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import type { IEnv } from '../../types';
|
|
2
2
|
import type { IUserIdentity } from './types';
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* Example: "abcdefghij12345" -> "**********12345"
|
|
4
|
+
* Hash an API key with SHA-256 for use as a Sentry-safe identity token.
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* Only the hash is ever returned. The most recently hashed key and its hash
|
|
7
|
+
* are cached in memory, so a repeat call skips the digest and a different key
|
|
8
|
+
* replaces the cache instead of returning the previous key's hash.
|
|
9
|
+
*
|
|
10
|
+
* When the runtime has no usable `crypto.createHash` (e.g. a browser bundle
|
|
11
|
+
* without a `crypto` shim) this returns `''` rather than throwing, so the
|
|
12
|
+
* Sentry identity falls back to the next identifier instead of being dropped.
|
|
13
|
+
*
|
|
14
|
+
* @param apiKey - The raw API key to hash
|
|
15
|
+
* @returns Hex-encoded SHA-256 hash of `apiKey`, or `''` for an empty input or
|
|
16
|
+
* when hashing is unavailable
|
|
9
17
|
*/
|
|
10
18
|
export declare function hashApiKey(apiKey: string): string;
|
|
11
19
|
/**
|
|
@@ -33,7 +41,13 @@ export declare function generateFingerprint(): string | undefined;
|
|
|
33
41
|
export declare function createUserIdentity(apiKey?: string, walletAddress?: string, environment?: IEnv): IUserIdentity;
|
|
34
42
|
/**
|
|
35
43
|
* Generate a unique user ID for Sentry from identity components.
|
|
36
|
-
* Priority: apiKeyHash
|
|
44
|
+
* Priority: apiKeyHash \> wallet \> domain \> fingerprint \> session
|
|
45
|
+
*
|
|
46
|
+
* An API key identifies the integrator and a wallet identifies the end user,
|
|
47
|
+
* so both outrank the hosting domain — otherwise every visitor of one web app
|
|
48
|
+
* collapses into a single Sentry user. `domain` still ranks above the
|
|
49
|
+
* fingerprint, which nearly every runtime produces, so hostname attribution
|
|
50
|
+
* is not lost.
|
|
37
51
|
*
|
|
38
52
|
* @param identity - User identity object
|
|
39
53
|
* @returns Prefixed user ID string
|
|
@@ -9,31 +9,39 @@ const crypto_1 = require("crypto");
|
|
|
9
9
|
const uuid_1 = require("uuid");
|
|
10
10
|
/** Session ID persists for SDK instance lifetime */
|
|
11
11
|
let sessionId = null;
|
|
12
|
-
/**
|
|
13
|
-
let
|
|
12
|
+
/** Raw API key the cached hash below was computed from — lets a key change invalidate the cache. */
|
|
13
|
+
let cachedApiKey = null;
|
|
14
|
+
/** SHA-256 hash of {@link cachedApiKey}. */
|
|
15
|
+
let cachedApiKeyHash = null;
|
|
14
16
|
/**
|
|
15
|
-
*
|
|
16
|
-
* Example: "abcdefghij12345" -> "**********12345"
|
|
17
|
+
* Hash an API key with SHA-256 for use as a Sentry-safe identity token.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
19
|
+
* Only the hash is ever returned. The most recently hashed key and its hash
|
|
20
|
+
* are cached in memory, so a repeat call skips the digest and a different key
|
|
21
|
+
* replaces the cache instead of returning the previous key's hash.
|
|
22
|
+
*
|
|
23
|
+
* When the runtime has no usable `crypto.createHash` (e.g. a browser bundle
|
|
24
|
+
* without a `crypto` shim) this returns `''` rather than throwing, so the
|
|
25
|
+
* Sentry identity falls back to the next identifier instead of being dropped.
|
|
26
|
+
*
|
|
27
|
+
* @param apiKey - The raw API key to hash
|
|
28
|
+
* @returns Hex-encoded SHA-256 hash of `apiKey`, or `''` for an empty input or
|
|
29
|
+
* when hashing is unavailable
|
|
20
30
|
*/
|
|
21
31
|
function hashApiKey(apiKey) {
|
|
22
32
|
if (!apiKey)
|
|
23
33
|
return '';
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return cachedMaskedApiKey;
|
|
27
|
-
const visibleChars = 5;
|
|
28
|
-
if (apiKey.length <= visibleChars) {
|
|
29
|
-
cachedMaskedApiKey = apiKey;
|
|
34
|
+
if (cachedApiKey === apiKey && cachedApiKeyHash) {
|
|
35
|
+
return cachedApiKeyHash;
|
|
30
36
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
try {
|
|
38
|
+
cachedApiKeyHash = (0, crypto_1.createHash)('sha256').update(apiKey).digest('hex');
|
|
39
|
+
cachedApiKey = apiKey;
|
|
40
|
+
return cachedApiKeyHash;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return '';
|
|
35
44
|
}
|
|
36
|
-
return cachedMaskedApiKey;
|
|
37
45
|
}
|
|
38
46
|
/**
|
|
39
47
|
* Generate a session ID that persists for the SDK instance lifetime.
|
|
@@ -118,21 +126,27 @@ function createUserIdentity(apiKey, walletAddress, environment = 'PROD') {
|
|
|
118
126
|
}
|
|
119
127
|
/**
|
|
120
128
|
* Generate a unique user ID for Sentry from identity components.
|
|
121
|
-
* Priority: apiKeyHash
|
|
129
|
+
* Priority: apiKeyHash \> wallet \> domain \> fingerprint \> session
|
|
130
|
+
*
|
|
131
|
+
* An API key identifies the integrator and a wallet identifies the end user,
|
|
132
|
+
* so both outrank the hosting domain — otherwise every visitor of one web app
|
|
133
|
+
* collapses into a single Sentry user. `domain` still ranks above the
|
|
134
|
+
* fingerprint, which nearly every runtime produces, so hostname attribution
|
|
135
|
+
* is not lost.
|
|
122
136
|
*
|
|
123
137
|
* @param identity - User identity object
|
|
124
138
|
* @returns Prefixed user ID string
|
|
125
139
|
*/
|
|
126
140
|
function getUserId(identity) {
|
|
127
|
-
if (identity.domain) {
|
|
128
|
-
return `domain:${identity.domain}`;
|
|
129
|
-
}
|
|
130
141
|
if (identity.apiKeyHash) {
|
|
131
142
|
return `apikey:${identity.apiKeyHash}`;
|
|
132
143
|
}
|
|
133
144
|
if (identity.walletAddress) {
|
|
134
145
|
return `wallet:${identity.walletAddress}`;
|
|
135
146
|
}
|
|
147
|
+
if (identity.domain) {
|
|
148
|
+
return `domain:${identity.domain}`;
|
|
149
|
+
}
|
|
136
150
|
if (identity.fingerprint) {
|
|
137
151
|
return `fp:${identity.fingerprint}`;
|
|
138
152
|
}
|
package/lib/core/auth/verify.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.verifyInfuraKey = verifyInfuraKey;
|
|
4
4
|
exports.verifyAugustKey = verifyAugustKey;
|
|
5
|
+
const analytics_1 = require("../analytics");
|
|
5
6
|
const core_1 = require("../constants/core");
|
|
6
7
|
const fetcher_1 = require("../fetcher");
|
|
7
8
|
async function verifyInfuraKey(key) {
|
|
@@ -20,11 +21,14 @@ async function verifyAugustKey(key) {
|
|
|
20
21
|
return false;
|
|
21
22
|
try {
|
|
22
23
|
const verify = await (0, fetcher_1.fetchAugustWithKey)(key, core_1.WEBSERVER_ENDPOINTS.auth.verify);
|
|
23
|
-
|
|
24
|
+
const success = verify.status === 200;
|
|
25
|
+
(0, analytics_1.trackKeyVerification)('august', success);
|
|
26
|
+
return success;
|
|
24
27
|
}
|
|
25
28
|
catch {
|
|
26
29
|
// Network errors, timeouts, and any future thrown auth errors all
|
|
27
30
|
// resolve to "key not verified" here. Callers handle this as a boolean.
|
|
31
|
+
(0, analytics_1.trackKeyVerification)('august', false);
|
|
28
32
|
return false;
|
|
29
33
|
}
|
|
30
34
|
}
|
package/lib/core/base.class.js
CHANGED
|
@@ -71,6 +71,9 @@ class AugustBase {
|
|
|
71
71
|
// prior staging instance would leak into a later prod instance in the same
|
|
72
72
|
// process — the inverse of the isolation this option exists to provide.
|
|
73
73
|
(0, fetcher_1.setPublicApiBaseUrl)(publicApiBaseUrl ?? null);
|
|
74
|
+
// Every backend request from this process now identifies the app
|
|
75
|
+
// (`x-august-app`) — same last-instance-wins contract as the base URL.
|
|
76
|
+
(0, fetcher_1.setSdkAppName)(this.appName);
|
|
74
77
|
// ERC-8021 attribution follows the same reset-on-omit contract as
|
|
75
78
|
// `publicApiBaseUrl`: called unconditionally so a prior instance's
|
|
76
79
|
// builder codes never leak into a later instance in the same process.
|
|
@@ -33,6 +33,7 @@ export declare const WEBSERVER_URL: {
|
|
|
33
33
|
};
|
|
34
34
|
export declare const WEBSERVER_ENDPOINTS: {
|
|
35
35
|
default: {
|
|
36
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
36
37
|
hello: string;
|
|
37
38
|
protected: string;
|
|
38
39
|
};
|
|
@@ -45,6 +46,7 @@ export declare const WEBSERVER_ENDPOINTS: {
|
|
|
45
46
|
};
|
|
46
47
|
subaccount: {
|
|
47
48
|
list: (offset?: number, limit?: number) => string;
|
|
49
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
48
50
|
rewards: (subaccount: IAddress) => string;
|
|
49
51
|
tokens: (subaccount: IAddress) => string;
|
|
50
52
|
twap: {
|
|
@@ -55,6 +57,7 @@ export declare const WEBSERVER_ENDPOINTS: {
|
|
|
55
57
|
debank: (subaccount: IAddress) => string;
|
|
56
58
|
health_factor: (subaccount: IAddress) => string;
|
|
57
59
|
summary: (subaccount: IAddress) => string;
|
|
60
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
58
61
|
batch: (subaccount: IAddress) => string;
|
|
59
62
|
loans: (subaccount: IAddress, side?: "BORROWER" | "LENDER" | "BOTH", active?: boolean) => string;
|
|
60
63
|
cefi: (subaccount: IAddress) => string;
|
|
@@ -63,6 +63,7 @@ exports.WEBSERVER_URL = {
|
|
|
63
63
|
};
|
|
64
64
|
exports.WEBSERVER_ENDPOINTS = {
|
|
65
65
|
default: {
|
|
66
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
66
67
|
hello: '/hello',
|
|
67
68
|
protected: '/protected',
|
|
68
69
|
},
|
|
@@ -75,6 +76,7 @@ exports.WEBSERVER_ENDPOINTS = {
|
|
|
75
76
|
},
|
|
76
77
|
subaccount: {
|
|
77
78
|
list: (offset = 0, limit = 100) => `/subaccount?offset=${offset}&limit=${limit}`,
|
|
79
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
78
80
|
rewards: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/rewards`,
|
|
79
81
|
tokens: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/tokens`,
|
|
80
82
|
twap: {
|
|
@@ -85,6 +87,7 @@ exports.WEBSERVER_ENDPOINTS = {
|
|
|
85
87
|
debank: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/debank`,
|
|
86
88
|
health_factor: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/health_factor`,
|
|
87
89
|
summary: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/summary`,
|
|
90
|
+
/** @deprecated No backend route. Removed in the next major release. */
|
|
88
91
|
batch: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/tx_batcher_integrations`,
|
|
89
92
|
loans: (subaccount, side = 'BOTH', active = true) => `/subaccount/${subaccountSegment(subaccount)}/loans?side=${side}&active=${active}`,
|
|
90
93
|
cefi: (subaccount) => `/subaccount/${subaccountSegment(subaccount)}/cefi_position`,
|
|
@@ -108,6 +108,22 @@ export declare const SWAP_ROUTER_MAX_SWAPS = 9;
|
|
|
108
108
|
* every dispatch. Used to validate that native-token deposits target a
|
|
109
109
|
* vault whose reference asset is the wrapped native — the only configuration
|
|
110
110
|
* the contract's `depositNativeToken` / `swapAndDepositNativeToken` accept.
|
|
111
|
+
*
|
|
112
|
+
* **Wrap-only, WETH-vaults-only limitation.** Both payable entry points on the
|
|
113
|
+
* deployed router (`depositNativeToken` and `swapAndDepositNativeToken`) only
|
|
114
|
+
* wrap native ETH to this address and deposit — neither has an ETH→other-asset
|
|
115
|
+
* swap leg. `swapAndDepositNativeToken`'s ABI takes no swap payload, so a DEX
|
|
116
|
+
* swap is structurally impossible on that path too; its only difference from
|
|
117
|
+
* `depositNativeToken` is applying the vault swap fee on the pure wrap. The
|
|
118
|
+
* practical consequence: **native ETH can only be deposited into a vault whose
|
|
119
|
+
* reference asset is this wrapped-native token** (e.g. a WETH-reference
|
|
120
|
+
* vault). There is no atomic native-ETH deposit into a non-WETH-reference
|
|
121
|
+
* vault (e.g. a USDC vault) — deposit the wrapped native token instead
|
|
122
|
+
* (already whitelisted, and it routes through the swap leg for a vault whose
|
|
123
|
+
* reference asset differs). True atomic ETH→any-asset support would require a
|
|
124
|
+
* contract change (a payable `swapAndDeposit` variant), which is out of scope
|
|
125
|
+
* for this SDK. Use {@link isNativeSwapRouterDepositSupported} to check a
|
|
126
|
+
* vault's eligibility for the native path before offering it in a UI.
|
|
111
127
|
*/
|
|
112
128
|
export declare const SWAP_ROUTER_WRAPPED_NATIVE: Readonly<Record<number, IAddress>>;
|
|
113
129
|
/**
|
|
@@ -121,6 +121,22 @@ exports.SWAP_ROUTER_MAX_SWAPS = 9;
|
|
|
121
121
|
* every dispatch. Used to validate that native-token deposits target a
|
|
122
122
|
* vault whose reference asset is the wrapped native — the only configuration
|
|
123
123
|
* the contract's `depositNativeToken` / `swapAndDepositNativeToken` accept.
|
|
124
|
+
*
|
|
125
|
+
* **Wrap-only, WETH-vaults-only limitation.** Both payable entry points on the
|
|
126
|
+
* deployed router (`depositNativeToken` and `swapAndDepositNativeToken`) only
|
|
127
|
+
* wrap native ETH to this address and deposit — neither has an ETH→other-asset
|
|
128
|
+
* swap leg. `swapAndDepositNativeToken`'s ABI takes no swap payload, so a DEX
|
|
129
|
+
* swap is structurally impossible on that path too; its only difference from
|
|
130
|
+
* `depositNativeToken` is applying the vault swap fee on the pure wrap. The
|
|
131
|
+
* practical consequence: **native ETH can only be deposited into a vault whose
|
|
132
|
+
* reference asset is this wrapped-native token** (e.g. a WETH-reference
|
|
133
|
+
* vault). There is no atomic native-ETH deposit into a non-WETH-reference
|
|
134
|
+
* vault (e.g. a USDC vault) — deposit the wrapped native token instead
|
|
135
|
+
* (already whitelisted, and it routes through the swap leg for a vault whose
|
|
136
|
+
* reference asset differs). True atomic ETH→any-asset support would require a
|
|
137
|
+
* contract change (a payable `swapAndDeposit` variant), which is out of scope
|
|
138
|
+
* for this SDK. Use {@link isNativeSwapRouterDepositSupported} to check a
|
|
139
|
+
* vault's eligibility for the native path before offering it in a UI.
|
|
124
140
|
*/
|
|
125
141
|
exports.SWAP_ROUTER_WRAPPED_NATIVE = {
|
|
126
142
|
1: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* ```
|
|
16
16
|
*/
|
|
17
17
|
/** Stable error codes attached to SDK errors. */
|
|
18
|
-
export type AugustErrorCode = 'AUTH_MISSING_KEY' | 'AUTH_INVALID_KEY' | 'AUTH_FORBIDDEN' | 'AUTH_UNAUTHORIZED' | 'INVALID_URL' | 'INVALID_INPUT' | 'INVALID_CHAIN' | 'INVALID_ADDRESS' | 'ACCOUNT_NOT_FUNDED' | 'NETWORK_ERROR' | 'TIMEOUT' | 'RATE_LIMITED' | 'SERVER_ERROR' | 'HISTORY_UNAVAILABLE' | 'UNKNOWN';
|
|
18
|
+
export type AugustErrorCode = 'AUTH_MISSING_KEY' | 'AUTH_INVALID_KEY' | 'AUTH_FORBIDDEN' | 'AUTH_UNAUTHORIZED' | 'INVALID_URL' | 'INVALID_INPUT' | 'INVALID_CHAIN' | 'INVALID_ADDRESS' | 'ACCOUNT_NOT_FUNDED' | 'NETWORK_ERROR' | 'TIMEOUT' | 'RATE_LIMITED' | 'SERVER_ERROR' | 'HISTORY_UNAVAILABLE' | 'PRICE_UNAVAILABLE' | 'UNKNOWN';
|
|
19
19
|
/** Options accepted by every SDK error constructor. */
|
|
20
20
|
export interface AugustErrorOptions {
|
|
21
21
|
/** Original error preserved for stack-trace chaining. */
|
|
@@ -110,5 +110,40 @@ export declare class AugustHistoryUnavailableError extends AugustSDKError {
|
|
|
110
110
|
*/
|
|
111
111
|
constructor(message: string, options?: AugustErrorOptions);
|
|
112
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* The USD price needed to convert a computed value could not be resolved, so
|
|
115
|
+
* any USD figure derived from it would be fabricated rather than merely
|
|
116
|
+
* missing.
|
|
117
|
+
*
|
|
118
|
+
* Motivation — `getVaultUserLifetimePnl` used to substitute a price of `1`
|
|
119
|
+
* whenever the price server returned nothing, which reported every
|
|
120
|
+
* USD field of a non-dollar vault (lsETH, tETH, BTC) at $1 per asset: a
|
|
121
|
+
* position worth ~$40k read as ~$13, indistinguishable from a real result.
|
|
122
|
+
* Throwing this typed error makes a missing price explicit so callers can hide
|
|
123
|
+
* the USD value instead of displaying a wrong one.
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* try {
|
|
128
|
+
* await sdk.getVaultUserLifetimePnl({ vault, wallet, chainId });
|
|
129
|
+
* } catch (err) {
|
|
130
|
+
* if (err instanceof AugustPriceUnavailableError) {
|
|
131
|
+
* // No USD price for the vault asset — hide the USD figures rather than
|
|
132
|
+
* // show a fabricated one.
|
|
133
|
+
* hideUsd(err.context);
|
|
134
|
+
* } else throw err;
|
|
135
|
+
* }
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare class AugustPriceUnavailableError extends AugustSDKError {
|
|
139
|
+
/**
|
|
140
|
+
* @param message - Human-readable description of the missing price. Callers
|
|
141
|
+
* pass the same `#<method>::<vault>::<wallet>` prefix the surrounding getter
|
|
142
|
+
* uses so log grouping stays consistent.
|
|
143
|
+
* @param options - Standard SDK error options. `context` should carry the
|
|
144
|
+
* identifiers that scope the failure (e.g. `{ vault, wallet, asset }`).
|
|
145
|
+
*/
|
|
146
|
+
constructor(message: string, options?: AugustErrorOptions);
|
|
147
|
+
}
|
|
113
148
|
/** Type guard. Works across realms (e.g. Web Worker / VM contexts). */
|
|
114
149
|
export declare function isAugustSDKError(err: unknown): err is AugustSDKError;
|
package/lib/core/errors/index.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.AugustHistoryUnavailableError = exports.AugustServerError = exports.AugustRateLimitError = exports.AugustValidationError = exports.AugustTimeoutError = exports.AugustNetworkError = exports.AugustAuthError = exports.AugustSDKError = void 0;
|
|
19
|
+
exports.AugustPriceUnavailableError = exports.AugustHistoryUnavailableError = exports.AugustServerError = exports.AugustRateLimitError = exports.AugustValidationError = exports.AugustTimeoutError = exports.AugustNetworkError = exports.AugustAuthError = exports.AugustSDKError = void 0;
|
|
20
20
|
exports.isAugustSDKError = isAugustSDKError;
|
|
21
21
|
/** Base class for all SDK errors. */
|
|
22
22
|
class AugustSDKError extends Error {
|
|
@@ -173,6 +173,45 @@ class AugustHistoryUnavailableError extends AugustSDKError {
|
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
exports.AugustHistoryUnavailableError = AugustHistoryUnavailableError;
|
|
176
|
+
/**
|
|
177
|
+
* The USD price needed to convert a computed value could not be resolved, so
|
|
178
|
+
* any USD figure derived from it would be fabricated rather than merely
|
|
179
|
+
* missing.
|
|
180
|
+
*
|
|
181
|
+
* Motivation — `getVaultUserLifetimePnl` used to substitute a price of `1`
|
|
182
|
+
* whenever the price server returned nothing, which reported every
|
|
183
|
+
* USD field of a non-dollar vault (lsETH, tETH, BTC) at $1 per asset: a
|
|
184
|
+
* position worth ~$40k read as ~$13, indistinguishable from a real result.
|
|
185
|
+
* Throwing this typed error makes a missing price explicit so callers can hide
|
|
186
|
+
* the USD value instead of displaying a wrong one.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* try {
|
|
191
|
+
* await sdk.getVaultUserLifetimePnl({ vault, wallet, chainId });
|
|
192
|
+
* } catch (err) {
|
|
193
|
+
* if (err instanceof AugustPriceUnavailableError) {
|
|
194
|
+
* // No USD price for the vault asset — hide the USD figures rather than
|
|
195
|
+
* // show a fabricated one.
|
|
196
|
+
* hideUsd(err.context);
|
|
197
|
+
* } else throw err;
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
class AugustPriceUnavailableError extends AugustSDKError {
|
|
202
|
+
/**
|
|
203
|
+
* @param message - Human-readable description of the missing price. Callers
|
|
204
|
+
* pass the same `#<method>::<vault>::<wallet>` prefix the surrounding getter
|
|
205
|
+
* uses so log grouping stays consistent.
|
|
206
|
+
* @param options - Standard SDK error options. `context` should carry the
|
|
207
|
+
* identifiers that scope the failure (e.g. `{ vault, wallet, asset }`).
|
|
208
|
+
*/
|
|
209
|
+
constructor(message, options) {
|
|
210
|
+
super('PRICE_UNAVAILABLE', message, options);
|
|
211
|
+
this.name = 'AugustPriceUnavailableError';
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
exports.AugustPriceUnavailableError = AugustPriceUnavailableError;
|
|
176
215
|
/** Type guard. Works across realms (e.g. Web Worker / VM contexts). */
|
|
177
216
|
function isAugustSDKError(err) {
|
|
178
217
|
return (err instanceof AugustSDKError ||
|
package/lib/core/fetcher.d.ts
CHANGED
|
@@ -41,6 +41,19 @@ export declare function setSdkRequestTimeout(ms?: number | null): void;
|
|
|
41
41
|
* otherwise the compiled-in `REQUEST_TIMEOUT_MS`.
|
|
42
42
|
*/
|
|
43
43
|
export declare function getSdkRequestTimeout(): number;
|
|
44
|
+
/**
|
|
45
|
+
* Record the consuming application's `appName` so every request to the
|
|
46
|
+
* August backend carries it as `x-august-app`, next to
|
|
47
|
+
* `x-august-sdk-version`. This gives the backend per-integrator request
|
|
48
|
+
* counts that do not depend on Sentry sampling.
|
|
49
|
+
*
|
|
50
|
+
* Process-global, last writer wins — the same contract as
|
|
51
|
+
* `setSdkRequestTimeout` and `setPublicApiBaseUrl`. The `AugustSDK`
|
|
52
|
+
* constructor calls this with its validated `appName`.
|
|
53
|
+
*
|
|
54
|
+
* @param appName - Validated app-name slug, or `null` to stop sending it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function setSdkAppName(appName?: string | null): void;
|
|
44
57
|
/**
|
|
45
58
|
* Override the base URL used for `WEBSERVER_URL.public` requests — the
|
|
46
59
|
* unauthenticated vault-catalog API that `getVault` / `fetchTokenizedVault`
|
package/lib/core/fetcher.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.setSafeCache = exports.getSafeCache = exports.CACHE = void 0;
|
|
4
4
|
exports.setSdkRequestTimeout = setSdkRequestTimeout;
|
|
5
5
|
exports.getSdkRequestTimeout = getSdkRequestTimeout;
|
|
6
|
+
exports.setSdkAppName = setSdkAppName;
|
|
6
7
|
exports.setPublicApiBaseUrl = setPublicApiBaseUrl;
|
|
7
8
|
exports.getPublicApiBaseUrl = getPublicApiBaseUrl;
|
|
8
9
|
exports.fetchAugustWithKey = fetchAugustWithKey;
|
|
@@ -32,6 +33,7 @@ const core_2 = require("./constants/core");
|
|
|
32
33
|
const vault_version_1 = require("./helpers/vault-version");
|
|
33
34
|
const analytics_1 = require("./analytics");
|
|
34
35
|
const sanitize_1 = require("./analytics/sanitize");
|
|
36
|
+
const sentry_1 = require("./analytics/sentry");
|
|
35
37
|
const errors_1 = require("./errors");
|
|
36
38
|
/** Map an HTTP status to the appropriate typed SDK error subclass. */
|
|
37
39
|
function errorFromResponseStatus(status, message, options) {
|
|
@@ -76,6 +78,34 @@ function setSdkRequestTimeout(ms = null) {
|
|
|
76
78
|
function getSdkRequestTimeout() {
|
|
77
79
|
return SDK_REQUEST_TIMEOUT_OVERRIDE ?? core_2.REQUEST_TIMEOUT_MS;
|
|
78
80
|
}
|
|
81
|
+
let SDK_APP_NAME = null;
|
|
82
|
+
/**
|
|
83
|
+
* Record the consuming application's `appName` so every request to the
|
|
84
|
+
* August backend carries it as `x-august-app`, next to
|
|
85
|
+
* `x-august-sdk-version`. This gives the backend per-integrator request
|
|
86
|
+
* counts that do not depend on Sentry sampling.
|
|
87
|
+
*
|
|
88
|
+
* Process-global, last writer wins — the same contract as
|
|
89
|
+
* `setSdkRequestTimeout` and `setPublicApiBaseUrl`. The `AugustSDK`
|
|
90
|
+
* constructor calls this with its validated `appName`.
|
|
91
|
+
*
|
|
92
|
+
* @param appName - Validated app-name slug, or `null` to stop sending it.
|
|
93
|
+
*/
|
|
94
|
+
function setSdkAppName(appName = null) {
|
|
95
|
+
SDK_APP_NAME = appName;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Client-identification headers merged into every backend fetcher's
|
|
99
|
+
* defaults. Both values are low-cardinality slugs, never credentials.
|
|
100
|
+
*/
|
|
101
|
+
function sdkClientHeaders() {
|
|
102
|
+
const headers = {
|
|
103
|
+
'x-august-sdk-version': (0, sentry_1.getSDKVersion)(),
|
|
104
|
+
};
|
|
105
|
+
if (SDK_APP_NAME)
|
|
106
|
+
headers['x-august-app'] = SDK_APP_NAME;
|
|
107
|
+
return headers;
|
|
108
|
+
}
|
|
79
109
|
let PUBLIC_API_BASE_OVERRIDE = null;
|
|
80
110
|
/**
|
|
81
111
|
* Override the base URL used for `WEBSERVER_URL.public` requests — the
|
|
@@ -370,6 +400,7 @@ async function fetchAugustWithKey(apiKey, relativeUrl, options) {
|
|
|
370
400
|
throw new errors_1.AugustAuthError('AUTH_MISSING_KEY', 'fetchAugustWithKey: apiKey is required (set keys.august on the SDK constructor, or pass an explicit apiKey).');
|
|
371
401
|
}
|
|
372
402
|
const defaultHeaders = {
|
|
403
|
+
...sdkClientHeaders(),
|
|
373
404
|
'x-api-key': apiKey,
|
|
374
405
|
'content-type': 'application/json',
|
|
375
406
|
accept: 'application/json',
|
|
@@ -426,6 +457,7 @@ async function fetchAugustWithKey(apiKey, relativeUrl, options) {
|
|
|
426
457
|
*/
|
|
427
458
|
async function fetchAugustPublic(relativeUrl, options) {
|
|
428
459
|
const defaultHeaders = {
|
|
460
|
+
...sdkClientHeaders(),
|
|
429
461
|
'content-type': 'application/json',
|
|
430
462
|
accept: 'application/json',
|
|
431
463
|
};
|
|
@@ -480,6 +512,7 @@ async function fetchAugustPublic(relativeUrl, options) {
|
|
|
480
512
|
*/
|
|
481
513
|
async function fetchAugustWithBearer(bearerToken, relativeUrl, options) {
|
|
482
514
|
const defaultHeaders = {
|
|
515
|
+
...sdkClientHeaders(),
|
|
483
516
|
authorization: `Bearer ${bearerToken}`,
|
|
484
517
|
'content-type': 'application/json',
|
|
485
518
|
accept: 'application/json',
|
package/lib/main.d.ts
CHANGED
|
@@ -355,6 +355,11 @@ export declare class AugustSDK extends AugustBase {
|
|
|
355
355
|
* Calculates realized and unrealized PnL based on deposit/withdrawal history and current position.
|
|
356
356
|
* @param props - Vault address, wallet address, and optional chain ID
|
|
357
357
|
* @returns Lifetime PnL data including realized and unrealized PnL in both native token and USD
|
|
358
|
+
* @throws {@link AugustHistoryUnavailableError} (`HISTORY_UNAVAILABLE`) when a
|
|
359
|
+
* live position has no indexed deposits or withdrawals.
|
|
360
|
+
* @throws {@link AugustPriceUnavailableError} (`PRICE_UNAVAILABLE`) when the
|
|
361
|
+
* vault's underlying asset has no USD price — the USD fields are never
|
|
362
|
+
* computed from a stand-in price.
|
|
358
363
|
*/
|
|
359
364
|
getVaultUserLifetimePnl(props: {
|
|
360
365
|
vault: IAddress;
|