@augustdigital/sdk 9.6.0 → 9.7.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/README.md CHANGED
@@ -36,7 +36,7 @@ const sdk = new AugustSDK({
36
36
  -1: 'https://api.mainnet-beta.solana.com', // Solana
37
37
  },
38
38
  keys: {
39
- august: 'YOUR_API_KEY', // Optional: required for allocations, health factors, and sub-account operations
39
+ august: 'YOUR_API_KEY', // Optional: vault reads, allocations and vault-linked sub-account reads work without it
40
40
  },
41
41
  monitoring: {
42
42
  env: 'DEV', // Optional: 'DEV' enables console logging (defaults to 'PROD')
@@ -85,6 +85,10 @@ export interface ISolanaDepositOptions {
85
85
  * Skips the quote and the single snapshot read it needs. `0n` restores the
86
86
  * unguarded behaviour of the plain `deposit` instruction.
87
87
  *
88
+ * When the handler's `idl` predates `deposit_checked`, a non-zero floor or
89
+ * any `slippageBps` throws {@link AugustValidationError} instead of being
90
+ * silently dropped; with neither, the plain `deposit` is sent.
91
+ *
88
92
  * Must be a `bigint` in `0 .. 2^64-1`; anything else throws
89
93
  * {@link AugustValidationError} before the transaction is built.
90
94
  */
@@ -107,6 +111,10 @@ export interface ISolanaRedeemOptions {
107
111
  * Explicit floor in raw deposit-mint units, net of the withdrawal fee,
108
112
  * passed to `redeem_checked` as is. Skips the quote. `0n` restores the
109
113
  * unguarded behaviour of the plain `redeem` instruction.
114
+ *
115
+ * When the handler's `idl` predates `redeem_checked`, a non-zero floor or
116
+ * any `slippageBps` throws {@link AugustValidationError} instead of being
117
+ * silently dropped; with neither, the plain `redeem` is sent.
110
118
  */
111
119
  minAssetsOut?: bigint;
112
120
  }
@@ -55,7 +55,9 @@ export declare function slippageHint(e: unknown): string;
55
55
  * is given, the vault state and share mint are read to quote the shares this
56
56
  * deposit should mint, and that quote lowered by `options.slippageBps`
57
57
  * (default {@link DEFAULT_SLIPPAGE_BPS}) is passed as the floor; the program
58
- * reverts with `SlippageExceeded` if execution would mint fewer.
58
+ * reverts with `SlippageExceeded` if execution would mint fewer. An `idl`
59
+ * that predates `deposit_checked` gets the plain `deposit` with no floor,
60
+ * unless `options` asks for one — then it throws {@link AugustValidationError}.
59
61
  */
60
62
  export declare function handleSolanaDeposit({ provider, connection, network, vaultProgramId, vaultAddress, depositAmount, publicKey, idl, options, }: {
61
63
  vaultProgramId: PublicKey | string;
@@ -83,6 +85,9 @@ export declare function handleSolanaDeposit({ provider, connection, network, vau
83
85
  * handler already reads, **net of the withdrawal fee**, and that quote
84
86
  * lowered by `options.slippageBps` (default {@link DEFAULT_SLIPPAGE_BPS}) is
85
87
  * passed as the floor; the program reverts with `SlippageExceeded` below it.
88
+ * An `idl` that predates `redeem_checked` gets the plain `redeem` with no
89
+ * floor, unless `options` asks for one — then it throws
90
+ * {@link AugustValidationError}.
86
91
  * @throws AugustValidationError on missing wallet/programId or invalid amount,
87
92
  * or when the wallet holds fewer shares than `redeemShares`.
88
93
  * @throws AugustSDKError when a candidate token account's balance cannot be
@@ -99,6 +99,52 @@ function validateExplicitFloor(value, label) {
99
99
  }
100
100
  return value;
101
101
  }
102
+ /**
103
+ * Decide whether a handler can send the slippage-checked instruction, or must
104
+ * fall back to the plain one.
105
+ *
106
+ * `idl` is caller-supplied, and an IDL generated before the program shipped
107
+ * `deposit_checked` / `redeem_checked` produces a `Program` with no such
108
+ * method. Until 9.4.0 the handlers sent the plain instructions, so those same
109
+ * inputs used to work; calling the checked method on them throws a TypeError
110
+ * before anything is sent (AUGUST-8023). The program still accepts the plain
111
+ * instructions, with the behaviour a floor of `0` gives the checked ones, so
112
+ * falling back preserves what those callers had.
113
+ *
114
+ * The fallback is refused when the caller asked for protection — a non-zero
115
+ * explicit floor, or any `slippageBps` — since the plain instruction would
116
+ * silently drop it. An explicit floor of `0n` is the documented "no floor" and
117
+ * falls back.
118
+ *
119
+ * Probes `program.methods` rather than `idl.instructions`: that is the object
120
+ * the handler calls, and it already reflects Anchor's camelCase conversion.
121
+ *
122
+ * @param program - Anchor program built from the caller's IDL.
123
+ * @param checkedMethod - `'depositChecked'` or `'redeemChecked'`.
124
+ * @param floor - The caller's explicit `minSharesOut` / `minAssetsOut`, if any.
125
+ * @param slippageBps - The caller's tolerance, if any.
126
+ * @param handler - Handler name, for the log line and the error.
127
+ * @returns `true` to send the checked instruction, `false` for the plain one.
128
+ * @throws {@link AugustValidationError} when the IDL lacks the checked
129
+ * instruction and the caller asked for a floor.
130
+ */
131
+ function sendsCheckedInstruction({ program, checkedMethod, floor, slippageBps, handler, }) {
132
+ const methods = program.methods;
133
+ if (typeof methods[checkedMethod] === 'function')
134
+ return true;
135
+ const instruction = checkedMethod === 'depositChecked' ? 'deposit_checked' : 'redeem_checked';
136
+ const floorOption = checkedMethod === 'depositChecked' ? 'minSharesOut' : 'minAssetsOut';
137
+ if ((floor !== undefined && floor !== 0n) || slippageBps !== undefined) {
138
+ throw new core_1.AugustValidationError('INVALID_INPUT', `${handler}: the supplied IDL does not declare \`${instruction}\`, so ` +
139
+ `the requested ${floorOption} / slippageBps cannot be enforced. Pass ` +
140
+ "the SDK's bundled IDL (`Solana.constants.vaultIdl`), or omit both " +
141
+ 'options to send the unguarded instruction.');
142
+ }
143
+ core_1.Logger.log.warn(handler, `Supplied IDL does not declare \`${instruction}\`; sending the plain ` +
144
+ "instruction without a slippage floor. Pass the SDK's bundled IDL to " +
145
+ 'enable slippage protection.');
146
+ return false;
147
+ }
102
148
  /**
103
149
  * The vault state and share-mint supply as of a **single slot**.
104
150
  *
@@ -265,7 +311,9 @@ async function resolveUserTokenAccountPair({ connection, owner, mints, }) {
265
311
  * is given, the vault state and share mint are read to quote the shares this
266
312
  * deposit should mint, and that quote lowered by `options.slippageBps`
267
313
  * (default {@link DEFAULT_SLIPPAGE_BPS}) is passed as the floor; the program
268
- * reverts with `SlippageExceeded` if execution would mint fewer.
314
+ * reverts with `SlippageExceeded` if execution would mint fewer. An `idl`
315
+ * that predates `deposit_checked` gets the plain `deposit` with no floor,
316
+ * unless `options` asks for one — then it throws {@link AugustValidationError}.
269
317
  */
270
318
  async function handleSolanaDeposit({ provider, connection, network = constants_1.fallbackNetwork, vaultProgramId, vaultAddress, depositAmount, publicKey, idl, options = {}, }) {
271
319
  try {
@@ -281,6 +329,21 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
281
329
  // Before any RPC: an unusable floor should cost the caller nothing.
282
330
  if (options.minSharesOut !== undefined)
283
331
  validateExplicitFloor(options.minSharesOut, 'minSharesOut');
332
+ const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
333
+ const program = utils_1.SolanaUtils.getProgram({
334
+ provider,
335
+ idl,
336
+ programId: _vaultProgramId.toBase58(),
337
+ });
338
+ // Also before any RPC: a floor the caller's IDL cannot enforce is refused
339
+ // on the spot rather than after the mint and token-account reads.
340
+ const checked = sendsCheckedInstruction({
341
+ program,
342
+ checkedMethod: 'depositChecked',
343
+ floor: options.minSharesOut,
344
+ slippageBps: options.slippageBps,
345
+ handler: 'handleSolanaDeposit',
346
+ });
284
347
  const { depositMint, shareMint, vaultVersion } = await utils_1.SolanaUtils.getVaultMints({
285
348
  network,
286
349
  connection,
@@ -291,14 +354,8 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
291
354
  if (!depositMint || !shareMint) {
292
355
  throw new Error('Failed to read vault mints from on-chain state');
293
356
  }
294
- const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
295
357
  const _publicKey = new web3_js_1.PublicKey(publicKey);
296
358
  const _depositMint = new web3_js_1.PublicKey(depositMint);
297
- const program = utils_1.SolanaUtils.getProgram({
298
- provider,
299
- idl,
300
- programId: _vaultProgramId.toBase58(),
301
- });
302
359
  core_1.Logger.log.info('handleSolanaDeposit', 'Program', program);
303
360
  const vaultStatePda = vaultAddress
304
361
  ? new web3_js_1.PublicKey(vaultAddress)
@@ -394,7 +451,10 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
394
451
  core_1.Logger.log.info('handleSolanaDeposit', 'Deposit mint', _depositMint?.toBase58());
395
452
  core_1.Logger.log.info('handleSolanaDeposit', 'Signer', _publicKey.toBase58());
396
453
  let minSharesOut;
397
- if (options.minSharesOut !== undefined) {
454
+ if (!checked) {
455
+ // The plain instruction takes no floor, so there is nothing to quote.
456
+ }
457
+ else if (options.minSharesOut !== undefined) {
398
458
  minSharesOut = options.minSharesOut;
399
459
  }
400
460
  else {
@@ -417,9 +477,11 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
417
477
  slippageBps: options.slippageBps ?? pricing_1.DEFAULT_SLIPPAGE_BPS,
418
478
  });
419
479
  }
420
- core_1.Logger.log.info('handleSolanaDeposit', 'Min shares out (raw)', minSharesOut.toString());
421
- const tx = await program.methods
422
- .depositChecked(depositAmountRaw, new anchor_1.BN(minSharesOut.toString()))
480
+ core_1.Logger.log.info('handleSolanaDeposit', 'Min shares out (raw)', minSharesOut?.toString() ?? 'none (plain deposit)');
481
+ const methods = program.methods;
482
+ const tx = await (minSharesOut === undefined
483
+ ? methods.deposit(depositAmountRaw)
484
+ : methods.depositChecked(depositAmountRaw, new anchor_1.BN(minSharesOut.toString())))
423
485
  .accounts({
424
486
  vaultState: vaultStatePda,
425
487
  vaultTokenAta: vaultTokenAtaPda,
@@ -478,6 +540,9 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
478
540
  * handler already reads, **net of the withdrawal fee**, and that quote
479
541
  * lowered by `options.slippageBps` (default {@link DEFAULT_SLIPPAGE_BPS}) is
480
542
  * passed as the floor; the program reverts with `SlippageExceeded` below it.
543
+ * An `idl` that predates `redeem_checked` gets the plain `redeem` with no
544
+ * floor, unless `options` asks for one — then it throws
545
+ * {@link AugustValidationError}.
481
546
  * @throws AugustValidationError on missing wallet/programId or invalid amount,
482
547
  * or when the wallet holds fewer shares than `redeemShares`.
483
548
  * @throws AugustSDKError when a candidate token account's balance cannot be
@@ -503,6 +568,20 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
503
568
  // Before any RPC: an unusable floor should cost the caller nothing.
504
569
  if (options.minAssetsOut !== undefined)
505
570
  validateExplicitFloor(options.minAssetsOut, 'minAssetsOut');
571
+ const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
572
+ const program = utils_1.SolanaUtils.getProgram({
573
+ provider,
574
+ idl,
575
+ programId: _vaultProgramId.toBase58(),
576
+ });
577
+ // See `handleSolanaDeposit`: refused before any RPC.
578
+ const checked = sendsCheckedInstruction({
579
+ program,
580
+ checkedMethod: 'redeemChecked',
581
+ floor: options.minAssetsOut,
582
+ slippageBps: options.slippageBps,
583
+ handler: 'handleSolanaRedeem',
584
+ });
506
585
  const { depositMint, shareMint, vaultVersion } = await utils_1.SolanaUtils.getVaultMints({
507
586
  network: provider.connection.rpcEndpoint.includes('devnet')
508
587
  ? 'devnet'
@@ -515,14 +594,8 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
515
594
  if (!depositMint || !shareMint) {
516
595
  throw new Error('Failed to read vault mints from on-chain state');
517
596
  }
518
- const _vaultProgramId = new web3_js_1.PublicKey(vaultProgramId);
519
597
  const _depositMint = new web3_js_1.PublicKey(depositMint);
520
598
  const _publicKey = new web3_js_1.PublicKey(publicKey);
521
- const program = utils_1.SolanaUtils.getProgram({
522
- provider,
523
- idl,
524
- programId: _vaultProgramId.toBase58(),
525
- });
526
599
  const vaultStatePda = vaultAddress
527
600
  ? new web3_js_1.PublicKey(vaultAddress)
528
601
  : utils_1.SolanaUtils.deriveVaultStatePda(_vaultProgramId);
@@ -598,7 +671,10 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
598
671
  // No extra reads here: the share mint (supply) and vault state (assets,
599
672
  // offset, fee, fee recipient) came from the snapshot above.
600
673
  let minAssetsOut;
601
- if (options.minAssetsOut !== undefined) {
674
+ if (!checked) {
675
+ // The plain instruction takes no floor, so there is nothing to quote.
676
+ }
677
+ else if (options.minAssetsOut !== undefined) {
602
678
  minAssetsOut = options.minAssetsOut;
603
679
  }
604
680
  else {
@@ -639,9 +715,11 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
639
715
  core_1.Logger.log.info('handleSolanaRedeem', 'Share mint:', shareMintAddr.toBase58());
640
716
  core_1.Logger.log.info('handleSolanaRedeem', 'Deposit mint:', _depositMint?.toBase58());
641
717
  core_1.Logger.log.info('handleSolanaRedeem', 'Signer:', _publicKey.toBase58());
642
- core_1.Logger.log.info('handleSolanaRedeem', 'Min assets out, net of fee (raw):', minAssetsOut.toString());
643
- const tx = await program.methods
644
- .redeemChecked(redeemSharesRaw, new anchor_1.BN(minAssetsOut.toString()))
718
+ core_1.Logger.log.info('handleSolanaRedeem', 'Min assets out, net of fee (raw):', minAssetsOut?.toString() ?? 'none (plain redeem)');
719
+ const methods = program.methods;
720
+ const tx = await (minAssetsOut === undefined
721
+ ? methods.redeem(redeemSharesRaw)
722
+ : methods.redeemChecked(redeemSharesRaw, new anchor_1.BN(minAssetsOut.toString())))
645
723
  .accounts({
646
724
  vaultState: vaultStatePda,
647
725
  vaultDepositAta: vaultTokenAtaPda,
@@ -12,6 +12,19 @@ export declare function sanitizeString(input: string): string;
12
12
  * …), and `cause`. Subclass constructors are NOT invoked — they may have
13
13
  * positional signatures (`new AugustAuthError(code, message, opts)`) that would
14
14
  * misalign if we naively passed the sanitized message as the first arg.
15
+ *
16
+ * Every write onto the clone goes through `Object.defineProperty` rather than
17
+ * assignment: the clone inherits `err`'s prototype, and some libraries make
18
+ * properties read-only there — `@solana/web3.js` defines `name` as non-writable
19
+ * on its error classes (`TransactionExpiredTimeoutError`, …). Assigning to an
20
+ * inherited non-writable property throws a `TypeError` in strict mode, which
21
+ * would escape from inside a caller's `catch` (e.g. `Logger.log.error`) and
22
+ * replace the error being reported. Defining an own property shadows the
23
+ * prototype's instead; each one is writable, configurable and enumerable,
24
+ * exactly as the plain assignment used to create it.
25
+ *
26
+ * @param err - Any caught value; non-`Error` values are returned unchanged.
27
+ * @returns A redacted clone for `Error` instances, otherwise `err` itself.
15
28
  */
16
29
  export declare function sanitizeError(err: unknown): unknown;
17
30
  /** Sanitize arbitrary log input (strings, errors, objects, arrays, primitives). */
@@ -72,30 +72,42 @@ function sanitizeString(input) {
72
72
  * …), and `cause`. Subclass constructors are NOT invoked — they may have
73
73
  * positional signatures (`new AugustAuthError(code, message, opts)`) that would
74
74
  * misalign if we naively passed the sanitized message as the first arg.
75
+ *
76
+ * Every write onto the clone goes through `Object.defineProperty` rather than
77
+ * assignment: the clone inherits `err`'s prototype, and some libraries make
78
+ * properties read-only there — `@solana/web3.js` defines `name` as non-writable
79
+ * on its error classes (`TransactionExpiredTimeoutError`, …). Assigning to an
80
+ * inherited non-writable property throws a `TypeError` in strict mode, which
81
+ * would escape from inside a caller's `catch` (e.g. `Logger.log.error`) and
82
+ * replace the error being reported. Defining an own property shadows the
83
+ * prototype's instead; each one is writable, configurable and enumerable,
84
+ * exactly as the plain assignment used to create it.
85
+ *
86
+ * @param err - Any caught value; non-`Error` values are returned unchanged.
87
+ * @returns A redacted clone for `Error` instances, otherwise `err` itself.
75
88
  */
76
89
  function sanitizeError(err) {
77
90
  if (!(err instanceof Error))
78
91
  return err;
79
92
  const safe = Object.create(Object.getPrototypeOf(err));
93
+ const define = (key, value) => Object.defineProperty(safe, key, {
94
+ value,
95
+ writable: true,
96
+ configurable: true,
97
+ enumerable: true,
98
+ });
80
99
  for (const key of Object.getOwnPropertyNames(err)) {
81
100
  const value = err[key];
82
- if (key === 'message' && typeof value === 'string') {
83
- safe[key] = sanitizeString(value);
84
- }
85
- else if (key === 'stack' && typeof value === 'string') {
86
- safe[key] = sanitizeString(value);
87
- }
88
- else {
89
- safe[key] = value;
90
- }
101
+ const redact = (key === 'message' || key === 'stack') && typeof value === 'string';
102
+ define(key, redact ? sanitizeString(value) : value);
91
103
  }
92
104
  if (!safe.message && typeof err.message === 'string') {
93
- safe.message = sanitizeString(err.message);
105
+ define('message', sanitizeString(err.message));
94
106
  }
95
107
  if (!safe.stack && typeof err.stack === 'string') {
96
- safe.stack = sanitizeString(err.stack);
108
+ define('stack', sanitizeString(err.stack));
97
109
  }
98
- safe.name = err.name;
110
+ define('name', err.name);
99
111
  return safe;
100
112
  }
101
113
  /** Sanitize arbitrary log input (strings, errors, objects, arrays, primitives). */
@@ -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.6.0";
6
+ export declare const SDK_VERSION = "9.7.1";
@@ -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.6.0';
9
+ exports.SDK_VERSION = '9.7.1';
10
10
  //# sourceMappingURL=version.js.map
@@ -15,8 +15,8 @@ async function verifyInfuraKey(key) {
15
15
  }
16
16
  async function verifyAugustKey(key) {
17
17
  // Fast path: no key means no verification possible. Returning false here
18
- // preserves the historical contract (`init()` throws a generic "API key is invalid")
19
- // 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.
20
20
  if (!key)
21
21
  return false;
22
22
  try {
@@ -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 = {
@@ -91,6 +93,7 @@ class AugustBase {
91
93
  }
92
94
  /**
93
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()`.
94
97
  * @throws Error when `keys.august` is missing or rejected by the API.
95
98
  */
96
99
  async init() {
@@ -21,8 +21,8 @@ export type IFetchAugustOptions = {
21
21
  /** Per-request timeout in ms. Defaults to `REQUEST_TIMEOUT_MS`. */
22
22
  timeoutMs?: number;
23
23
  /**
24
- * @deprecated Bypasses the API-key check for legacy unauthenticated endpoints.
25
- * Will be removed in a future major version; pass a valid `apiKey` instead.
24
+ * @deprecated No longer has any effect: an absent `apiKey` already sends an
25
+ * anonymous request. Will be removed in a future major version; drop it.
26
26
  */
27
27
  override?: boolean;
28
28
  };
@@ -92,15 +92,21 @@ export declare function getPublicApiBaseUrl(): string;
92
92
  import { CACHE, getSafeCache, setSafeCache } from './cache';
93
93
  export { CACHE, getSafeCache, setSafeCache };
94
94
  /**
95
- * Make authenticated requests to August backend services using API key.
95
+ * Make requests to August backend services, sending an API key when one is
96
+ * configured. Many backend routes — vault-linked sub-account reads, the two
97
+ * collateral risk routes, timelock requests — answer anonymous callers, so a
98
+ * missing key is not an error here: the request goes out without the
99
+ * `x-api-key` header and the backend decides. Routes that do require a key
100
+ * answer `401`, which surfaces as an `AugustAuthError` with code
101
+ * `AUTH_UNAUTHORIZED`.
96
102
  * Automatically logs errors with correlation IDs for debugging.
97
- * @param apiKey - August API key for authentication
103
+ * @param apiKey - August API key, or `undefined` for an anonymous request
98
104
  * @param relativeUrl - Endpoint path relative to base URL
99
105
  * @param options - Request configuration including method and headers
100
106
  * @returns Response object if successful
101
107
  * @throws Error with correlation ID if request fails
102
108
  */
103
- export declare function fetchAugustWithKey(apiKey: string, relativeUrl: string, options?: IFetchAugustOptions): Promise<Response>;
109
+ export declare function fetchAugustWithKey(apiKey: string | undefined, relativeUrl: string, options?: IFetchAugustOptions): Promise<Response>;
104
110
  /**
105
111
  * Make unauthenticated requests to August public API endpoints.
106
112
  * Used for fetching vault metadata and public market data.
@@ -258,7 +258,7 @@ function warnOverrideDeprecation(callerTag) {
258
258
  // notice must surface in the integrator's console in every environment.
259
259
  // Logger.log.warn would downgrade it to a prod-silent Sentry breadcrumb.
260
260
  // biome-ignore lint/suspicious/noConsole: integrator-facing deprecation notice must surface in every environment; Logger.log.warn would downgrade it to a prod-silent Sentry breadcrumb.
261
- console.warn(`[@augustdigital/sdk] ${callerTag}: option "override" is deprecated and will be removed in a future major version. Pass a valid apiKey instead.`);
261
+ console.warn(`[@augustdigital/sdk] ${callerTag}: option "override" is deprecated and has no effect — an absent apiKey already sends an anonymous request. It will be removed in a future major version; drop it.`);
262
262
  }
263
263
  /**
264
264
  * LRU cache for API responses and frequently accessed data.
@@ -384,9 +384,15 @@ function buildAugustUrl(server, relativeUrl) {
384
384
  return url.toString();
385
385
  }
386
386
  /**
387
- * Make authenticated requests to August backend services using API key.
387
+ * Make requests to August backend services, sending an API key when one is
388
+ * configured. Many backend routes — vault-linked sub-account reads, the two
389
+ * collateral risk routes, timelock requests — answer anonymous callers, so a
390
+ * missing key is not an error here: the request goes out without the
391
+ * `x-api-key` header and the backend decides. Routes that do require a key
392
+ * answer `401`, which surfaces as an `AugustAuthError` with code
393
+ * `AUTH_UNAUTHORIZED`.
388
394
  * Automatically logs errors with correlation IDs for debugging.
389
- * @param apiKey - August API key for authentication
395
+ * @param apiKey - August API key, or `undefined` for an anonymous request
390
396
  * @param relativeUrl - Endpoint path relative to base URL
391
397
  * @param options - Request configuration including method and headers
392
398
  * @returns Response object if successful
@@ -396,12 +402,9 @@ async function fetchAugustWithKey(apiKey, relativeUrl, options) {
396
402
  if (options?.override) {
397
403
  warnOverrideDeprecation('fetchAugustWithKey');
398
404
  }
399
- if (!apiKey && !options?.override) {
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).');
401
- }
402
405
  const defaultHeaders = {
403
406
  ...sdkClientHeaders(),
404
- 'x-api-key': apiKey,
407
+ ...(apiKey ? { 'x-api-key': apiKey } : {}),
405
408
  'content-type': 'application/json',
406
409
  accept: 'application/json',
407
410
  };
package/lib/main.d.ts CHANGED
@@ -356,7 +356,8 @@ export declare class AugustSDK extends AugustBase {
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
358
  * @throws {@link AugustHistoryUnavailableError} (`HISTORY_UNAVAILABLE`) when a
359
- * live position has no indexed deposits or withdrawals.
359
+ * live position has no indexed deposits, withdrawals or priceable share
360
+ * transfers.
360
361
  * @throws {@link AugustPriceUnavailableError} (`PRICE_UNAVAILABLE`) when the
361
362
  * vault's underlying asset has no USD price — the USD fields are never
362
363
  * computed from a stand-in price.
package/lib/main.js CHANGED
@@ -431,7 +431,8 @@ class AugustSDK extends core_1.AugustBase {
431
431
  * @param props - Vault address, wallet address, and optional chain ID
432
432
  * @returns Lifetime PnL data including realized and unrealized PnL in both native token and USD
433
433
  * @throws {@link AugustHistoryUnavailableError} (`HISTORY_UNAVAILABLE`) when a
434
- * live position has no indexed deposits or withdrawals.
434
+ * live position has no indexed deposits, withdrawals or priceable share
435
+ * transfers.
435
436
  * @throws {@link AugustPriceUnavailableError} (`PRICE_UNAVAILABLE`) when the
436
437
  * vault's underlying asset has no USD price — the USD fields are never
437
438
  * computed from a stand-in price.
@@ -54,9 +54,10 @@ export declare class AugustApi extends AugustBase {
54
54
  * token.
55
55
  *
56
56
  * Backed by `GET /risk/collateral_excess_or_deficit` (60-second server-side
57
- * cache), which resolves the subaccount and reads its current health factor,
58
- * so an authenticated (admin-scoped) August API key is required. Makes
59
- * exactly one HTTP request and no RPC calls.
57
+ * cache), which resolves the subaccount and reads its current health factor.
58
+ * The backend serves this route to anonymous callers today, so no August API
59
+ * key is needed; pass one if you get `AUTH_UNAUTHORIZED`. Makes exactly one
60
+ * HTTP request and no RPC calls.
60
61
  *
61
62
  * @param params.subaccount Subaccount (smart-contract wallet) address.
62
63
  * @param params.tokenAddress Collateral token address to evaluate.
@@ -86,9 +87,8 @@ export declare class AugustApi extends AugustBase {
86
87
  * This is a pure, read-only simulation: the backend `POST
87
88
  * /risk/collateral_simulation` endpoint (60-second server-side cache)
88
89
  * computes required collateral and effective discount factors and changes
89
- * no state. It runs against the authenticated backend, so an
90
- * (admin-scoped) August API key is required. Makes exactly one HTTP request
91
- * and no RPC calls.
90
+ * no state. The route is public, so no August API key is needed. Makes
91
+ * exactly one HTTP request and no RPC calls.
92
92
  *
93
93
  * @param input Simulation parameters — see {@link ICollateralSimulationInput}. `collateral_tokens` and `collateral_token_allocation` must be non-empty and equal length; when `on_platform` is `true`, both `loan_redeployed_token_*` fields are required.
94
94
  * @returns The simulated {@link ICollateralSimulationResults}: total debt, required collateral, resulting health factor, and a per-token breakdown.
@@ -204,9 +204,10 @@ class AugustApi extends base_class_1.AugustBase {
204
204
  * token.
205
205
  *
206
206
  * Backed by `GET /risk/collateral_excess_or_deficit` (60-second server-side
207
- * cache), which resolves the subaccount and reads its current health factor,
208
- * so an authenticated (admin-scoped) August API key is required. Makes
209
- * exactly one HTTP request and no RPC calls.
207
+ * cache), which resolves the subaccount and reads its current health factor.
208
+ * The backend serves this route to anonymous callers today, so no August API
209
+ * key is needed; pass one if you get `AUTH_UNAUTHORIZED`. Makes exactly one
210
+ * HTTP request and no RPC calls.
210
211
  *
211
212
  * @param params.subaccount Subaccount (smart-contract wallet) address.
212
213
  * @param params.tokenAddress Collateral token address to evaluate.
@@ -244,9 +245,8 @@ class AugustApi extends base_class_1.AugustBase {
244
245
  * This is a pure, read-only simulation: the backend `POST
245
246
  * /risk/collateral_simulation` endpoint (60-second server-side cache)
246
247
  * computes required collateral and effective discount factors and changes
247
- * no state. It runs against the authenticated backend, so an
248
- * (admin-scoped) August API key is required. Makes exactly one HTTP request
249
- * and no RPC calls.
248
+ * no state. The route is public, so no August API key is needed. Makes
249
+ * exactly one HTTP request and no RPC calls.
250
250
  *
251
251
  * @param input Simulation parameters — see {@link ICollateralSimulationInput}. `collateral_tokens` and `collateral_token_allocation` must be non-empty and equal length; when `on_platform` is `true`, both `loan_redeployed_token_*` fields are required.
252
252
  * @returns The simulated {@link ICollateralSimulationResults}: total debt, required collateral, resulting health factor, and a per-token breakdown.
@@ -4,7 +4,13 @@ import type { IAddress, ILoanBookInfo, ISubaccountDebank, ISubaccountTransaction
4
4
  * Subaccount operation class interacting with August Subaccounts
5
5
  * Subaccount is a smart contract wallet that serves as the fundamental infrastructure for August's platform.
6
6
  * It functions as a cross-margin account designed for optimal capital efficiency.
7
- * Most of the operations require a August API key to perform
7
+ *
8
+ * `getSubaccountSummary`, `getSubaccountHealthFactor`, `getSubaccountLoans`,
9
+ * `getSubaccountCefiPositions` and `getSubaccountOtcPositions` work without an
10
+ * August API key for subaccounts linked to a vault; `getSubaccountDebank` is
11
+ * public. `getSubaccountTransactions` needs a key authorized for the
12
+ * subaccount, and `getAllSubaccounts` and `getSubaccountLoanByAddress` need an
13
+ * admin key.
8
14
  */
9
15
  export declare class AugustSubAccounts extends AugustBase {
10
16
  private headers;
@@ -25,7 +25,13 @@ function assertSubaccountAddress(address, method) {
25
25
  * Subaccount operation class interacting with August Subaccounts
26
26
  * Subaccount is a smart contract wallet that serves as the fundamental infrastructure for August's platform.
27
27
  * It functions as a cross-margin account designed for optimal capital efficiency.
28
- * Most of the operations require a August API key to perform
28
+ *
29
+ * `getSubaccountSummary`, `getSubaccountHealthFactor`, `getSubaccountLoans`,
30
+ * `getSubaccountCefiPositions` and `getSubaccountOtcPositions` work without an
31
+ * August API key for subaccounts linked to a vault; `getSubaccountDebank` is
32
+ * public. `getSubaccountTransactions` needs a key authorized for the
33
+ * subaccount, and `getAllSubaccounts` and `getSubaccountLoanByAddress` need an
34
+ * admin key.
29
35
  */
30
36
  class AugustSubAccounts extends core_1.AugustBase {
31
37
  headers = null;