@augustdigital/sdk 9.5.0 → 9.7.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.
Files changed (51) hide show
  1. package/README.md +1 -1
  2. package/lib/adapters/evm/index.d.ts +1 -1
  3. package/lib/adapters/evm/index.js +29 -29
  4. package/lib/adapters/solana/types.d.ts +8 -0
  5. package/lib/adapters/solana/vault.actions.d.ts +6 -1
  6. package/lib/adapters/solana/vault.actions.js +99 -21
  7. package/lib/core/analytics/app-name.js +1 -1
  8. package/lib/core/analytics/constants.d.ts +10 -0
  9. package/lib/core/analytics/constants.js +17 -1
  10. package/lib/core/analytics/index.d.ts +7 -4
  11. package/lib/core/analytics/index.js +8 -4
  12. package/lib/core/analytics/instrumentation.js +8 -4
  13. package/lib/core/analytics/method-taxonomy.js +13 -0
  14. package/lib/core/analytics/metrics.d.ts +25 -10
  15. package/lib/core/analytics/metrics.js +41 -15
  16. package/lib/core/analytics/sentry.d.ts +24 -3
  17. package/lib/core/analytics/sentry.js +49 -18
  18. package/lib/core/analytics/types.d.ts +11 -4
  19. package/lib/core/analytics/user-identity.d.ts +19 -5
  20. package/lib/core/analytics/user-identity.js +35 -21
  21. package/lib/core/analytics/version.d.ts +1 -1
  22. package/lib/core/analytics/version.js +1 -1
  23. package/lib/core/auth/verify.js +7 -3
  24. package/lib/core/base.class.d.ts +8 -1
  25. package/lib/core/base.class.js +7 -1
  26. package/lib/core/constants/core.d.ts +3 -0
  27. package/lib/core/constants/core.js +3 -0
  28. package/lib/core/constants/swap-router.d.ts +16 -0
  29. package/lib/core/constants/swap-router.js +16 -0
  30. package/lib/core/errors/index.d.ts +36 -1
  31. package/lib/core/errors/index.js +40 -1
  32. package/lib/core/fetcher.d.ts +24 -5
  33. package/lib/core/fetcher.js +43 -7
  34. package/lib/main.d.ts +6 -0
  35. package/lib/main.js +6 -0
  36. package/lib/modules/api/main.d.ts +6 -6
  37. package/lib/modules/api/main.js +6 -6
  38. package/lib/modules/sub-accounts/main.d.ts +7 -1
  39. package/lib/modules/sub-accounts/main.js +7 -1
  40. package/lib/modules/vaults/getters.d.ts +151 -10
  41. package/lib/modules/vaults/getters.js +226 -30
  42. package/lib/modules/vaults/main.d.ts +5 -0
  43. package/lib/modules/vaults/main.js +5 -0
  44. package/lib/modules/vaults/write.actions.d.ts +57 -1
  45. package/lib/modules/vaults/write.actions.js +86 -2
  46. package/lib/sdk.d.ts +13171 -12810
  47. package/lib/services/debank/fetcher.js +1 -1
  48. package/lib/services/subgraph/vaults.d.ts +18 -1
  49. package/lib/services/subgraph/vaults.js +19 -3
  50. package/lib/types/vaults.d.ts +5 -0
  51. package/package.json +2 -2
@@ -64,6 +64,7 @@ exports.METHOD_CATEGORIES = {
64
64
  getVaultWithdrawals: 'read.redemption',
65
65
  getWithdrawalRequestsWithStatus: 'read.redemption',
66
66
  previewRedemption: 'read.redemption',
67
+ previewRwaRedemption: 'read.redemption',
67
68
  getBurnableAmountByReceiver: 'read.redemption',
68
69
  getRequirementByDate: 'read.redemption',
69
70
  getScheduledTransactionsByDate: 'read.redemption',
@@ -94,6 +95,7 @@ exports.METHOD_CATEGORIES = {
94
95
  // sees program-targeting calls instead of dropping them into 'unknown'.
95
96
  getProgram: 'read.solana',
96
97
  getProgramId: 'read.solana',
98
+ setWalletProvider: 'network',
97
99
  // submitTransaction broadcasts a signed Soroban tx — it mutates on-chain
98
100
  // state and belongs in the write bucket even though Stellar adapter call
99
101
  // shape mirrors the read helpers (returns a hash, takes signed XDR).
@@ -102,8 +104,19 @@ exports.METHOD_CATEGORIES = {
102
104
  // convertToShares is a read-only Soroban simulation despite its mutative-
103
105
  // sounding name — runs through queryContract, no broadcast.
104
106
  convertToShares: 'read.stellar',
107
+ // Offline helpers on the public adapter surface, classified under the
108
+ // chain's read bucket like getProgram/getProgramId above rather than
109
+ // leaking into 'unknown'.
110
+ isStellarAddress: 'read.stellar',
111
+ getExplorerLink: 'read.stellar',
105
112
  getEmberVaults: 'read.sui',
106
113
  getEmberTVL: 'read.sui',
114
+ convertFromE9: 'read.sui',
115
+ calculateUtilization: 'read.sui',
116
+ isSuiAddress: 'read.sui',
117
+ isSuiVault: 'read.sui',
118
+ transformEmberVaultToIVault: 'read.sui',
119
+ transformEmberVaultsToIVaults: 'read.sui',
107
120
  vaultAllowance: 'read.evm',
108
121
  sendersWhitelistAddress: 'read.evm',
109
122
  isWhitelisted: 'read.evm',
@@ -1,11 +1,3 @@
1
- /**
2
- * Aggregated cache statistics for monitoring.
3
- */
4
- declare let cacheStats: {
5
- hits: number;
6
- misses: number;
7
- sets: number;
8
- };
9
1
  /**
10
2
  * Track API response times and status.
11
3
  *
@@ -23,11 +15,34 @@ export declare function trackApiCall(endpoint: string, method: string, startTime
23
15
  */
24
16
  export declare function trackNetworkSwitch(chainId: number): void;
25
17
  /**
26
- * Get current cache statistics.
18
+ * Track the outcome of an API-key verification check (e.g. `verifyAugustKey`).
19
+ * Records success/failure as a breadcrumb and a low-cardinality tag so
20
+ * verification failures are visible in the dashboard without leaking the key
21
+ * itself — callers must never pass the raw key value.
22
+ *
23
+ * @param keyType - Which key was verified (e.g. `'august'`)
24
+ * @param success - Whether the key was accepted
25
+ */
26
+ export declare function trackKeyVerification(keyType: string, success: boolean): void;
27
+ declare let cacheStats: {
28
+ hits: number;
29
+ misses: number;
30
+ sets: number;
31
+ };
32
+ /**
33
+ * Cache statistics snapshot. The SDK never recorded cache hits, misses, or
34
+ * sets, so every field is always `0`.
35
+ *
36
+ * @deprecated Always returns zeros. Kept only for API compatibility and will
37
+ * be removed in the next major release; there is no replacement.
27
38
  */
28
39
  export declare function getCacheStats(): typeof cacheStats;
29
40
  /**
30
- * Reset cache statistics (useful for testing).
41
+ * Reset the cache statistics snapshot to zeros. The SDK never records any, so
42
+ * this has no observable effect.
43
+ *
44
+ * @deprecated Has no effect. Kept only for API compatibility and will be
45
+ * removed in the next major release; there is no replacement.
31
46
  */
32
47
  export declare function resetCacheStats(): void;
33
48
  export {};
@@ -2,19 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.trackApiCall = trackApiCall;
4
4
  exports.trackNetworkSwitch = trackNetworkSwitch;
5
+ exports.trackKeyVerification = trackKeyVerification;
5
6
  exports.getCacheStats = getCacheStats;
6
7
  exports.resetCacheStats = resetCacheStats;
7
8
  const chain_name_1 = require("./chain-name");
8
9
  const sentry_runtime_1 = require("./sentry-runtime");
9
10
  const sentry_1 = require("./sentry");
10
- /**
11
- * Aggregated cache statistics for monitoring.
12
- */
13
- let cacheStats = {
14
- hits: 0,
15
- misses: 0,
16
- sets: 0,
17
- };
18
11
  /**
19
12
  * Track API response times and status.
20
13
  *
@@ -47,11 +40,7 @@ function trackApiCall(endpoint, method, startTime, status, server) {
47
40
  server,
48
41
  },
49
42
  });
50
- // Set measurement for performance tracking
51
43
  sdk.setMeasurement('api.duration', duration, 'millisecond');
52
- // Update tags for filtering
53
- sdk.setTag('api.last_endpoint', normalizedEndpoint);
54
- sdk.setTag('api.server', server);
55
44
  }
56
45
  catch {
57
46
  // Silently fail - analytics should never break SDK
@@ -76,13 +65,41 @@ function trackNetworkSwitch(chainId) {
76
65
  level: 'info',
77
66
  data: { chainId, chain: chainLabel },
78
67
  });
79
- sdk.setTag('active.chainId', chainId.toString());
80
68
  sdk.setTag('sdk.chain', chainLabel);
81
69
  }
82
70
  catch {
83
71
  // Silently fail - analytics should never break SDK
84
72
  }
85
73
  }
74
+ /**
75
+ * Track the outcome of an API-key verification check (e.g. `verifyAugustKey`).
76
+ * Records success/failure as a breadcrumb and a low-cardinality tag so
77
+ * verification failures are visible in the dashboard without leaking the key
78
+ * itself — callers must never pass the raw key value.
79
+ *
80
+ * @param keyType - Which key was verified (e.g. `'august'`)
81
+ * @param success - Whether the key was accepted
82
+ */
83
+ function trackKeyVerification(keyType, success) {
84
+ if (!(0, sentry_1.isAnalyticsEnabled)())
85
+ return;
86
+ try {
87
+ const sdk = (0, sentry_runtime_1.getSentrySDK)();
88
+ if (!sdk)
89
+ return;
90
+ sdk.addBreadcrumb({
91
+ category: 'auth.verify',
92
+ message: `${keyType} key verification ${success ? 'succeeded' : 'failed'}`,
93
+ level: success ? 'info' : 'warning',
94
+ data: { keyType, success },
95
+ });
96
+ sdk.setTag('auth.last_verified_key_type', keyType);
97
+ sdk.setTag('auth.last_verification_result', success ? 'success' : 'failure');
98
+ }
99
+ catch {
100
+ // Silently fail - analytics should never break SDK
101
+ }
102
+ }
86
103
  /**
87
104
  * Normalize endpoint URLs for aggregation.
88
105
  * Replaces dynamic segments (addresses, IDs) with placeholders.
@@ -101,14 +118,23 @@ function normalizeEndpoint(endpoint) {
101
118
  // Replace numeric IDs in paths
102
119
  .replace(/\/\d+(?=\/|$)/g, '/:id'));
103
120
  }
121
+ let cacheStats = { hits: 0, misses: 0, sets: 0 };
104
122
  /**
105
- * Get current cache statistics.
123
+ * Cache statistics snapshot. The SDK never recorded cache hits, misses, or
124
+ * sets, so every field is always `0`.
125
+ *
126
+ * @deprecated Always returns zeros. Kept only for API compatibility and will
127
+ * be removed in the next major release; there is no replacement.
106
128
  */
107
129
  function getCacheStats() {
108
130
  return { ...cacheStats };
109
131
  }
110
132
  /**
111
- * Reset cache statistics (useful for testing).
133
+ * Reset the cache statistics snapshot to zeros. The SDK never records any, so
134
+ * this has no observable effect.
135
+ *
136
+ * @deprecated Has no effect. Kept only for API compatibility and will be
137
+ * removed in the next major release; there is no replacement.
112
138
  */
113
139
  function resetCacheStats() {
114
140
  cacheStats = { hits: 0, misses: 0, sets: 0 };
@@ -1,6 +1,15 @@
1
1
  import type * as Sentry from '@sentry/browser';
2
2
  import type { IEnv } from '../../types';
3
3
  import type { IAnalyticsConfig } from './types';
4
+ /**
5
+ * The August SDK build version, read from the generated `version.ts`.
6
+ * Falls back to `'development'` in an unbuilt checkout, where that file does
7
+ * not exist. Shared by the Sentry `release` tag and the
8
+ * `x-august-sdk-version` request header so the two can never disagree.
9
+ *
10
+ * @internal
11
+ */
12
+ export declare function getSDKVersion(): string;
4
13
  /**
5
14
  * Clear the error dedupe bookkeeping. Test-only — the rate limiter is process
6
15
  * lifetime state and would otherwise leak between test cases.
@@ -19,7 +28,8 @@ export declare function resetErrorDedupe(): void;
19
28
  * error rather than silently anonymous events.
20
29
  *
21
30
  * @param config - Analytics configuration. Pass `tracesSampleRate` to
22
- * override the default of `0.1`.
31
+ * override the default of `0.1`, and `surface` to label the emitting
32
+ * surface (`sdk.surface` tag; defaults to `'sdk'`).
23
33
  * @param environment - Current environment (DEV or PROD).
24
34
  * @param appName - App-name slug, required. Set as the global `app.name`
25
35
  * tag on every event and used to derive `partner.id`. Identifier-shaped:
@@ -51,6 +61,16 @@ export declare function clearUser(): void;
51
61
  * Check if analytics is enabled and initialized.
52
62
  */
53
63
  export declare function isAnalyticsEnabled(): boolean;
64
+ /**
65
+ * Identity tags resolved by `initializeSentry`, for `withMethodTracking` to
66
+ * copy onto each span as attributes. Sentry's span dataset carries scope tags
67
+ * on the root span only, so without this copy child `sdk.method` rows cannot
68
+ * be filtered by `app.name` or `partner.id`.
69
+ *
70
+ * @returns The tag snapshot, or `{}` until analytics has been enabled.
71
+ * @internal
72
+ */
73
+ export declare function getSpanAttributes(): Readonly<Record<string, string>>;
54
74
  /**
55
75
  * Get the current Sentry instance for advanced usage.
56
76
  * Returns null if analytics is disabled.
@@ -67,12 +87,13 @@ export declare function resetAnalytics(): void;
67
87
  * surface. No-ops when analytics is disabled.
68
88
  *
69
89
  * @param error - Thrown value. Non-Error values are wrapped.
70
- * @param options - `surface` ('cli' | 'sdk' | 'react' | string), extra `tags`,
90
+ * @param options - `surface` ('cli' | 'mcp' | 'sdk' | 'react' | string)
91
+ * overriding the init-time `sdk.surface` tag for this event, extra `tags`,
71
92
  * `extra` data, and a `flushTimeoutMs` to await before resolving (needed
72
93
  * in Node when the process is about to exit).
73
94
  */
74
95
  export declare function captureSdkException(error: unknown, options?: {
75
- surface?: 'cli' | 'sdk' | 'react' | string;
96
+ surface?: 'cli' | 'mcp' | 'sdk' | 'react' | string;
76
97
  tags?: Record<string, string>;
77
98
  extra?: Record<string, unknown>;
78
99
  flushTimeoutMs?: number;
@@ -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
- * Get the SDK version from the generated version file.
27
- * Falls back to 'development' if file doesn't exist (during local dev).
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
- safeSetTag('sdk.runtime', (0, sentry_runtime_1.getSentryRuntime)());
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
- safeSetTag('partner.id', `unverified:${validatedAppName}`);
509
- safeSetTag('partner.tier', 'unverified');
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), extra `tags`,
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.0` for the Phase 1/2 rollout;
11
- * values outside `[0, 1]` are clamped.
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 > wallet > fingerprint > session
24
+ * Multiple identifiers are used with priority: apiKeyHash \> wallet \> domain \> fingerprint \> session
18
25
  */
19
26
  export interface IUserIdentity {
20
- /** SHA-256 hash prefix of API key (first 16 chars). Never stores raw key. */
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
- * Mask an API key, keeping only the last 5 characters visible.
5
- * Example: "abcdefghij12345" -> "**********12345"
4
+ * Hash an API key with SHA-256 for use as a Sentry-safe identity token.
6
5
  *
7
- * @param apiKey - The raw API key to mask
8
- * @returns Masked API key with last 5 characters visible
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 > wallet > fingerprint > session
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
- /** Cached masked API key */
13
- let cachedMaskedApiKey = null;
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
- * Mask an API key, keeping only the last 5 characters visible.
16
- * Example: "abcdefghij12345" -> "**********12345"
17
+ * Hash an API key with SHA-256 for use as a Sentry-safe identity token.
17
18
  *
18
- * @param apiKey - The raw API key to mask
19
- * @returns Masked API key with last 5 characters visible
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
- // Use cached masked key if available
25
- if (cachedMaskedApiKey)
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
- else {
32
- const masked = '*'.repeat(apiKey.length - visibleChars);
33
- const visible = apiKey.slice(-visibleChars);
34
- cachedMaskedApiKey = masked + visible;
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 > wallet > fingerprint > session
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
  }
@@ -3,4 +3,4 @@
3
3
  * Generated during publish from package.json version
4
4
  * This file is gitignored and created at publish time
5
5
  */
6
- export declare const SDK_VERSION = "9.5.0";
6
+ export declare const SDK_VERSION = "9.7.0";
@@ -6,5 +6,5 @@ exports.SDK_VERSION = void 0;
6
6
  * Generated during publish from package.json version
7
7
  * This file is gitignored and created at publish time
8
8
  */
9
- exports.SDK_VERSION = '9.5.0';
9
+ exports.SDK_VERSION = '9.7.0';
10
10
  //# sourceMappingURL=version.js.map
@@ -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) {
@@ -14,17 +15,20 @@ async function verifyInfuraKey(key) {
14
15
  }
15
16
  async function verifyAugustKey(key) {
16
17
  // Fast path: no key means no verification possible. Returning false here
17
- // preserves the historical contract (`init()` throws a generic "API key is invalid")
18
- // and avoids letting an AUTH_MISSING_KEY error bubble up from the fetcher.
18
+ // preserves the historical contract (`init()` throws a generic "API key is
19
+ // invalid") and saves a request the backend would reject with a 401.
19
20
  if (!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
- return verify.status === 200;
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
  }
@@ -63,7 +63,13 @@ export interface IAugustBase {
63
63
  providers?: IProvidersConfig;
64
64
  solana?: ISolanaConfig;
65
65
  stellar?: IStellarConfig;
66
- keys: IKeys;
66
+ /**
67
+ * Provider keys. Optional: vault reads and vault-linked sub-account reads
68
+ * work without an August key. Supply `august` for admin and curator methods,
69
+ * for authenticated-user reads such as `getDiscountFactors`, and for
70
+ * sub-account reads where the subaccount is not linked to a vault.
71
+ */
72
+ keys?: IKeys;
67
73
  monitoring?: IMonitoring;
68
74
  /** Analytics configuration. Enabled by default (opt-out model). */
69
75
  analytics?: IAnalyticsConfig;
@@ -149,6 +155,7 @@ export declare class AugustBase {
149
155
  constructor({ appName, providers, keys, monitoring, analytics, versionCheck, timeoutMs, publicApiBaseUrl, attribution, }: IAugustBase);
150
156
  /**
151
157
  * Verify the configured August API key and mark this instance as authorized.
158
+ * Only for SDKs built with `keys.august`; a keyless SDK skips `init()`.
152
159
  * @throws Error when `keys.august` is missing or rejected by the API.
153
160
  */
154
161
  init(): Promise<void>;
@@ -46,7 +46,9 @@ class AugustBase {
46
46
  rpcUrl: Object.values(providers)[0],
47
47
  };
48
48
  }
49
- this.keys = keys;
49
+ // Default to an empty set so the api and sub-account modules can read
50
+ // `this.keys.august` (undefined) instead of throwing on a keyless SDK.
51
+ this.keys = keys ?? {};
50
52
  // Set environment (defaults to PROD for safety)
51
53
  const environment = monitoring?.env || monitoring?.['x-environment'] || 'PROD';
52
54
  this.monitoring = {
@@ -71,6 +73,9 @@ class AugustBase {
71
73
  // prior staging instance would leak into a later prod instance in the same
72
74
  // process — the inverse of the isolation this option exists to provide.
73
75
  (0, fetcher_1.setPublicApiBaseUrl)(publicApiBaseUrl ?? null);
76
+ // Every backend request from this process now identifies the app
77
+ // (`x-august-app`) — same last-instance-wins contract as the base URL.
78
+ (0, fetcher_1.setSdkAppName)(this.appName);
74
79
  // ERC-8021 attribution follows the same reset-on-omit contract as
75
80
  // `publicApiBaseUrl`: called unconditionally so a prior instance's
76
81
  // builder codes never leak into a later instance in the same process.
@@ -88,6 +93,7 @@ class AugustBase {
88
93
  }
89
94
  /**
90
95
  * Verify the configured August API key and mark this instance as authorized.
96
+ * Only for SDKs built with `keys.august`; a keyless SDK skips `init()`.
91
97
  * @throws Error when `keys.august` is missing or rejected by the API.
92
98
  */
93
99
  async init() {
@@ -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;