@augustdigital/sdk 8.6.0 → 8.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.
@@ -1,5 +1,5 @@
1
1
  import { type IContractWriteOptions, type INativeDepositOptions, type ApproveResult } from '../../modules/vaults/write.actions';
2
- import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions } from '../../types';
2
+ import type { ISwapAndDepositOptions, ISwapRouterDirectDepositOptions, ISwapRouterNativeDepositOptions, ISwapRouterDepositOptions } from '../../types';
3
3
  import { type IPreviewDepositOptions, type IPreviewRedeemOptions, type IAllowanceOptions, type IBalanceOfOptions, type IMaxDepositOptions } from '../../modules/vaults/read.actions';
4
4
  import { type CompatibleSigner } from '../../core/helpers/signer';
5
5
  import type { IAddress } from '../../types';
@@ -191,6 +191,29 @@ declare class EVMAdapter {
191
191
  * @returns The transaction hash of the `depositNativeToken` call.
192
192
  */
193
193
  depositNativeViaSwapRouter(options: ISwapRouterNativeDepositOptions): Promise<string>;
194
+ /**
195
+ * Deposit into a vault through the on-chain `SwapRouter`, choosing the router
196
+ * path from `depositAsset` (direct deposit, native wrap, or a swap to the
197
+ * reference asset). The high-level, explicit counterpart to the SwapRouter
198
+ * branch inside {@link vaultDeposit} — the caller opts into the router
199
+ * deliberately, so a native-deposit vault is never accidentally swapped.
200
+ *
201
+ * Reads the vault's reference asset + decimals on-chain, resolves the swap
202
+ * quote and fail-closes on aggregator/whitelist drift, and sends the ERC-20
203
+ * approval to the SwapRouter when allowance is short.
204
+ *
205
+ * @param options - {@link ISwapRouterDepositOptions}.
206
+ * @returns The transaction hash of the router deposit call.
207
+ * @throws AugustValidationError on unsupported chain, invalid address, zero
208
+ * amount, a native deposit into a non-wrapped-native vault, or quote drift.
209
+ * @example
210
+ * ```ts
211
+ * const hash = await augustSdk.evm.swapRouterDeposit({
212
+ * chainId: 1, vault, depositAsset: USDT, amount: '100', slippageBps: 50,
213
+ * });
214
+ * ```
215
+ */
216
+ swapRouterDeposit(options: ISwapRouterDepositOptions): Promise<string>;
194
217
  /**
195
218
  * Claim assets from a matured redemption request on a dated-redemption
196
219
  * (RWA-style) vault. The `year`, `month`, `day`, and `receiverIndex` tuple
@@ -251,6 +251,32 @@ class EVMAdapter {
251
251
  const signer = await this.getSigner();
252
252
  return (0, write_actions_1.depositNativeViaSwapRouter)(signer, options);
253
253
  }
254
+ /**
255
+ * Deposit into a vault through the on-chain `SwapRouter`, choosing the router
256
+ * path from `depositAsset` (direct deposit, native wrap, or a swap to the
257
+ * reference asset). The high-level, explicit counterpart to the SwapRouter
258
+ * branch inside {@link vaultDeposit} — the caller opts into the router
259
+ * deliberately, so a native-deposit vault is never accidentally swapped.
260
+ *
261
+ * Reads the vault's reference asset + decimals on-chain, resolves the swap
262
+ * quote and fail-closes on aggregator/whitelist drift, and sends the ERC-20
263
+ * approval to the SwapRouter when allowance is short.
264
+ *
265
+ * @param options - {@link ISwapRouterDepositOptions}.
266
+ * @returns The transaction hash of the router deposit call.
267
+ * @throws AugustValidationError on unsupported chain, invalid address, zero
268
+ * amount, a native deposit into a non-wrapped-native vault, or quote drift.
269
+ * @example
270
+ * ```ts
271
+ * const hash = await augustSdk.evm.swapRouterDeposit({
272
+ * chainId: 1, vault, depositAsset: USDT, amount: '100', slippageBps: 50,
273
+ * });
274
+ * ```
275
+ */
276
+ async swapRouterDeposit(options) {
277
+ const signer = await this.getSigner();
278
+ return (0, write_actions_1.swapRouterDeposit)(signer, options);
279
+ }
254
280
  /**
255
281
  * Claim assets from a matured redemption request on a dated-redemption
256
282
  * (RWA-style) vault. The `year`, `month`, `day`, and `receiverIndex` tuple
@@ -2,6 +2,24 @@ import { type web3 } from '@coral-xyz/anchor';
2
2
  import { type Connection, PublicKey, Transaction } from '@solana/web3.js';
3
3
  import type { ISolanaConnectionOptions } from './types';
4
4
  import type { SendTransactionOptions } from '@solana/wallet-adapter-base';
5
+ /**
6
+ * Extract a human- and machine-readable reason from a thrown Solana/Anchor
7
+ * error.
8
+ *
9
+ * Anchor's {@link https://github.com/coral-xyz/anchor `ProgramError`} calls
10
+ * `super()` with no argument, so its `.message` is the empty string by
11
+ * construction — the real reason lives on `.msg`/`.code` (and `.toString()`).
12
+ * `AnchorError` puts it on `.error.errorMessage` / `.error.errorCode.number`.
13
+ * Reading `.message` directly (as this file used to) therefore rendered
14
+ * `"Solana deposit failed: "` for every recognized on-chain revert — dropping
15
+ * the numeric code the team needs to tell "Vault is paused" from
16
+ * "Insufficient amount" from an account-constraint violation.
17
+ *
18
+ * When no reason can be extracted, returns an actionable, user-facing fallback
19
+ * rather than an "unknown error" admission — the raw throwable is still
20
+ * preserved on the wrapped error's `cause` and in telemetry for diagnosis.
21
+ */
22
+ export declare function describeSolanaError(e: unknown): string;
5
23
  /**
6
24
  * Deposit funds into a Solana August vault and mint share tokens.
7
25
  *
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.describeSolanaError = describeSolanaError;
3
4
  exports.handleSolanaDeposit = handleSolanaDeposit;
4
5
  exports.handleSolanaRedeem = handleSolanaRedeem;
5
6
  const anchor_1 = require("@coral-xyz/anchor");
@@ -8,6 +9,46 @@ const spl_token_1 = require("@solana/spl-token");
8
9
  const constants_1 = require("./constants");
9
10
  const utils_1 = require("./utils");
10
11
  const core_1 = require("../../core");
12
+ /**
13
+ * User-facing fallback for a throwable that carries no extractable reason.
14
+ * Surfaces as e.g. `"Solana deposit failed: please try again"` — actionable,
15
+ * and without telling the user we couldn't classify the failure.
16
+ */
17
+ const REASONLESS_SOLANA_ERROR = 'please try again';
18
+ /**
19
+ * Extract a human- and machine-readable reason from a thrown Solana/Anchor
20
+ * error.
21
+ *
22
+ * Anchor's {@link https://github.com/coral-xyz/anchor `ProgramError`} calls
23
+ * `super()` with no argument, so its `.message` is the empty string by
24
+ * construction — the real reason lives on `.msg`/`.code` (and `.toString()`).
25
+ * `AnchorError` puts it on `.error.errorMessage` / `.error.errorCode.number`.
26
+ * Reading `.message` directly (as this file used to) therefore rendered
27
+ * `"Solana deposit failed: "` for every recognized on-chain revert — dropping
28
+ * the numeric code the team needs to tell "Vault is paused" from
29
+ * "Insufficient amount" from an account-constraint violation.
30
+ *
31
+ * When no reason can be extracted, returns an actionable, user-facing fallback
32
+ * rather than an "unknown error" admission — the raw throwable is still
33
+ * preserved on the wrapped error's `cause` and in telemetry for diagnosis.
34
+ */
35
+ function describeSolanaError(e) {
36
+ if (!(e instanceof Error))
37
+ return REASONLESS_SOLANA_ERROR;
38
+ const anchor = e;
39
+ const reason = anchor.error?.errorMessage ?? anchor.msg ?? '';
40
+ const code = anchor.error?.errorCode?.number ?? anchor.code;
41
+ if (reason)
42
+ return code === undefined ? reason : `${reason} (code ${code})`;
43
+ // SendTransactionError / generic Error carry a non-empty `.message`.
44
+ if (e.message)
45
+ return e.message;
46
+ // Last resort: a subclass may override `toString()` (never the empty string).
47
+ const str = e.toString();
48
+ return str && str !== e.name && str !== `${e.name}: `
49
+ ? str
50
+ : REASONLESS_SOLANA_ERROR;
51
+ }
11
52
  /**
12
53
  * Deposit funds into a Solana August vault and mint share tokens.
13
54
  *
@@ -159,7 +200,7 @@ async function handleSolanaDeposit({ provider, connection, network = constants_1
159
200
  vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
160
201
  depositAmount: depositAmountForLog,
161
202
  });
162
- throw new core_1.AugustSDKError('UNKNOWN', `Solana deposit failed: ${e instanceof Error ? e.message : 'Unknown error'}`, {
203
+ throw new core_1.AugustSDKError('UNKNOWN', `Solana deposit failed: ${describeSolanaError(e)}`, {
163
204
  cause: e,
164
205
  context: {
165
206
  vaultProgramId: String(vaultProgramId),
@@ -325,7 +366,7 @@ async function handleSolanaRedeem({ provider, connection, vaultProgramId, vaultA
325
366
  vaultAddress: vaultAddress ? String(vaultAddress) : undefined,
326
367
  redeemShares: redeemSharesForLog,
327
368
  });
328
- throw new core_1.AugustSDKError('UNKNOWN', `Solana redeem failed: ${e instanceof Error ? e.message : 'Unknown error'}`, {
369
+ throw new core_1.AugustSDKError('UNKNOWN', `Solana redeem failed: ${describeSolanaError(e)}`, {
329
370
  cause: e,
330
371
  context: {
331
372
  vaultProgramId: String(vaultProgramId),
@@ -123,15 +123,11 @@ function trackMethodCall(methodName, metrics, args) {
123
123
  // Counters: SUM(invocation) → total calls; SUM(error)/SUM(invocation) → error rate.
124
124
  sdk.setMeasurement('sdk.method.invocation', 1, 'none');
125
125
  sdk.setMeasurement('sdk.method.error', metrics.success ? 0 : 1, 'none');
126
- // Update tags for filtering
126
+ // Only sticky-tag the last method name — useful for attributing errors that fire
127
+ // outside an active SDK span. sdk.category and sdk.chain are already recorded as
128
+ // span attributes on each call, so mutating the global scope with them here would
129
+ // just contaminate subsequent unrelated events with stale values.
127
130
  sdk.setTag('sdk.last_method', methodName);
128
- if (metrics.category) {
129
- sdk.setTag('sdk.category', metrics.category);
130
- }
131
- if (metrics.chainId !== undefined) {
132
- sdk.setTag('sdk.chain', (0, chain_name_1.chainIdToTagValue)(metrics.chainId));
133
- sdk.setTag('sdk.last_chainId', metrics.chainId.toString());
134
- }
135
131
  }
136
132
  catch {
137
133
  // Silently fail - analytics should never break SDK
@@ -223,9 +219,9 @@ function trackSyncMethodCall(methodName, metrics, args) {
223
219
  ...args,
224
220
  },
225
221
  });
226
- // Counters sync calls attach to whatever span is active on the scope.
227
- sdk.setMeasurement('sdk.method.invocation', 1, 'none');
228
- sdk.setMeasurement('sdk.method.error', metrics.success ? 0 : 1, 'none');
222
+ // Measurements omitted: sync methods have no span of their own, so setMeasurement
223
+ // would attach to whatever parent transaction happens to be active on the scope,
224
+ // overwriting its counters. The breadcrumb above already captures success/failure.
229
225
  sdk.setTag('sdk.last_sync_method', methodName);
230
226
  if (metrics.category) {
231
227
  sdk.setTag('sdk.category', metrics.category);
@@ -26,6 +26,7 @@ exports.METHOD_CATEGORIES = {
26
26
  getLatestUnrealizedPnl: 'read.vault',
27
27
  getVaultBorrowerHealthFactor: 'read.vault',
28
28
  getYieldLastRealizedOn: 'read.vault',
29
+ getVaultActivity: 'read.vault',
29
30
  getVaultPositions: 'read.position',
30
31
  getVaultUserHistory: 'read.position',
31
32
  getUserHistory: 'read.position',
@@ -82,6 +83,7 @@ exports.METHOD_CATEGORIES = {
82
83
  swapAndDeposit: 'write.deposit',
83
84
  depositViaSwapRouter: 'write.deposit',
84
85
  depositNativeViaSwapRouter: 'write.deposit',
86
+ swapRouterDeposit: 'write.deposit',
85
87
  vaultRedeem: 'write.redeem',
86
88
  vaultRequestRedeem: 'write.redeem',
87
89
  rwaRedeemAsset: 'write.redeem',
@@ -6,7 +6,7 @@ import type { IAnalyticsConfig } from './types';
6
6
  * only refresh user identity and the cached API-key hash.
7
7
  *
8
8
  * @param config - Analytics configuration. Pass `tracesSampleRate` to
9
- * override the Phase 1/2 default of `1.0`.
9
+ * override the default of `0.1`.
10
10
  * @param environment - Current environment (DEV or PROD).
11
11
  * @param walletAddress - Optional wallet address for user identification.
12
12
  * @param apiKey - Optional API key (hashed for identification).
@@ -138,7 +138,7 @@ function createSentrySink() {
138
138
  * only refresh user identity and the cached API-key hash.
139
139
  *
140
140
  * @param config - Analytics configuration. Pass `tracesSampleRate` to
141
- * override the Phase 1/2 default of `1.0`.
141
+ * override the default of `0.1`.
142
142
  * @param environment - Current environment (DEV or PROD).
143
143
  * @param walletAddress - Optional wallet address for user identification.
144
144
  * @param apiKey - Optional API key (hashed for identification).
@@ -214,17 +214,36 @@ function initializeSentry(config, environment, walletAddress, apiKey, appName) {
214
214
  const rawSampleRate = typeof config.tracesSampleRate === 'number' &&
215
215
  Number.isFinite(config.tracesSampleRate)
216
216
  ? config.tracesSampleRate
217
- : 1.0;
217
+ : 0.1; // Phase 2 default — verified partners can opt into 1.0 explicitly
218
218
  const tracesSampleRate = Math.max(0, Math.min(1, rawSampleRate));
219
219
  sdk.init({
220
220
  dsn: constants_1.SENTRY_DSN,
221
- // TODO(post-verified-partner): ramp default down to ~0.1.
222
221
  tracesSampleRate,
223
222
  enableTracing: true,
224
223
  environment: environment.toLowerCase(),
225
224
  release: `august-sdk@${getSDKVersion()}`,
226
225
  sendDefaultPii: true,
227
- integrations: [sdk.captureConsoleIntegration({ levels: ['error'] })],
226
+ // SDK errors route through Logger.setSentrySink captureException directly,
227
+ // so captureConsoleIntegration is redundant here. Omitting it also prevents
228
+ // consumer app console.error calls from being billed as SDK error events (the
229
+ // global sdk:'august-digital' tag would otherwise cause them to pass beforeSend).
230
+ integrations: [],
231
+ // Drop classes of event that are never SDK signal, as a backstop to the
232
+ // call-site demotions (see `logChainError` / `isUserRejectionError`).
233
+ // Scope is deliberately narrow: only categories that are noise in EVERY
234
+ // code path. Generic contract reverts (`CALL_EXCEPTION` / "missing revert
235
+ // data") are intentionally NOT listed — a reverted *write* tx is a real
236
+ // error we keep at `error` level, and only read-path reverts are demoted
237
+ // (surgically, at the call site).
238
+ ignoreErrors: [
239
+ // Wallet user-rejections are normal product behaviour, not an SDK fault.
240
+ /user rejected/i,
241
+ /user denied/i,
242
+ 'ACTION_REJECTED',
243
+ // Local dev/test node leaking into a prod DSN: :8545 is the canonical
244
+ // Anvil/Hardhat port and is never a production RPC endpoint.
245
+ /ECONNREFUSED .*:8545/,
246
+ ],
228
247
  beforeSend(event) {
229
248
  // Only send events tagged as SDK-related
230
249
  if (event.tags?.sdk !== 'august-digital') {
@@ -233,7 +252,14 @@ function initializeSentry(config, environment, walletAddress, apiKey, appName) {
233
252
  return event;
234
253
  },
235
254
  beforeSendTransaction(transaction) {
236
- // Always include transactions for performance tracking
255
+ // Sub-sample the high-frequency network bookkeeping category (switchNetwork,
256
+ // updateWallet, clearWallet, setSigner) to 10% of whatever tracesSampleRate
257
+ // already passed — these fire on every wallet/chain update and are low signal
258
+ // for the partner-usage dashboard relative to read/write calls.
259
+ if (transaction.tags?.['sdk.category'] === 'network' &&
260
+ Math.random() > 0.1) {
261
+ return null;
262
+ }
237
263
  return transaction;
238
264
  },
239
265
  });
@@ -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 = "8.6.0";
6
+ export declare const SDK_VERSION = "8.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 = '8.6.0';
9
+ exports.SDK_VERSION = '8.7.0';
10
10
  //# sourceMappingURL=version.js.map
@@ -9,17 +9,35 @@ import type { IAddress } from '../../types';
9
9
  */
10
10
  export declare const SWAP_ROUTER_ADDRESSES: Readonly<Record<number, IAddress>>;
11
11
  /**
12
- * Vault addresses registered on a `SwapRouter` via `enableVault`. The
13
- * presence of a vault here is the signal to route its deposits through the
14
- * SwapRouter rather than the legacy adapter path.
12
+ * Vaults whose UI **may offer the any-token SwapRouter deposit surface**
13
+ * i.e. the SwapRouter is `enableVault`-ed for them on-chain.
15
14
  *
16
- * Entries mirror the on-chain `vaultInfo[addr].referenceAsset != 0` state of
17
- * the `SwapRouter` deployment. Verify against the deployed contract before
18
- * adding a new entry — a vault that is not registered on-chain will revert
19
- * with `InvalidVault` at deposit time.
15
+ * This is *eligibility metadata only*. It is consumed by:
16
+ * - the app UI, to decide whether to render the (flag-gated) swap-router
17
+ * deposit surface for a vault; and
18
+ * - {@link swapRouterDeposit}, optionally, as a fail-fast eligibility check.
19
+ *
20
+ * It is deliberately **NOT** read by {@link vaultDeposit}: `vaultDeposit` is the
21
+ * native/multiasset/adapter path and never routes through the SwapRouter. That
22
+ * separation is what stops a natively-accepted asset from being silently
23
+ * swapped — the regression that implicit auto-routing caused. Any-token swap
24
+ * deposits are the explicit, opt-in job of {@link swapRouterDeposit}.
25
+ *
26
+ * Membership requires the vault to be registered on-chain
27
+ * (`vaultInfo[addr].referenceAsset != 0`) — an unregistered vault reverts with
28
+ * `InvalidVault` at deposit time. A listed vault's natively-accepted assets
29
+ * (for a multi-asset vault, its whole deposit-asset set) still deposit via
30
+ * `vaultDeposit`; only tokens OUTSIDE that set go through `swapRouterDeposit`.
20
31
  *
21
32
  * Lowercase comparison is required when checking — use
22
- * {@link vaultUsesSwapRouter} rather than reading this set directly.
33
+ * {@link isSwapRouterEligible} rather than reading this set directly.
34
+ */
35
+ export declare const SWAP_ROUTER_ELIGIBLE_VAULTS: ReadonlySet<string>;
36
+ /**
37
+ * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS}, and the semantics
38
+ * changed: this set no longer drives `vaultDeposit` auto-routing (that branch
39
+ * was removed) — it now only marks vaults whose UI may offer the swap-router
40
+ * deposit surface. Kept as an alias for one release; migrate to the new name.
23
41
  */
24
42
  export declare const VAULTS_USING_SWAP_ROUTER: ReadonlySet<string>;
25
43
  /**
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SWAP_ROUTER_DEX_AGGREGATOR = exports.SWAP_ROUTER_WRAPPED_NATIVE = exports.SWAP_ROUTER_MAX_SWAPS = exports.ORIGIN_CODES = exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ADDRESSES = void 0;
3
+ exports.SWAP_ROUTER_DEX_AGGREGATOR = exports.SWAP_ROUTER_WRAPPED_NATIVE = exports.SWAP_ROUTER_MAX_SWAPS = exports.ORIGIN_CODES = exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ELIGIBLE_VAULTS = exports.SWAP_ROUTER_ADDRESSES = void 0;
4
4
  /**
5
5
  * Address of the `SwapRouter` periphery contract on each supported chain.
6
6
  *
@@ -13,26 +13,42 @@ exports.SWAP_ROUTER_ADDRESSES = {
13
13
  1: '0xAC771209FF2b71EECfF6E85a9AD01db8Ff2618B0',
14
14
  };
15
15
  /**
16
- * Vault addresses registered on a `SwapRouter` via `enableVault`. The
17
- * presence of a vault here is the signal to route its deposits through the
18
- * SwapRouter rather than the legacy adapter path.
16
+ * Vaults whose UI **may offer the any-token SwapRouter deposit surface**
17
+ * i.e. the SwapRouter is `enableVault`-ed for them on-chain.
19
18
  *
20
- * Entries mirror the on-chain `vaultInfo[addr].referenceAsset != 0` state of
21
- * the `SwapRouter` deployment. Verify against the deployed contract before
22
- * adding a new entry — a vault that is not registered on-chain will revert
23
- * with `InvalidVault` at deposit time.
19
+ * This is *eligibility metadata only*. It is consumed by:
20
+ * - the app UI, to decide whether to render the (flag-gated) swap-router
21
+ * deposit surface for a vault; and
22
+ * - {@link swapRouterDeposit}, optionally, as a fail-fast eligibility check.
23
+ *
24
+ * It is deliberately **NOT** read by {@link vaultDeposit}: `vaultDeposit` is the
25
+ * native/multiasset/adapter path and never routes through the SwapRouter. That
26
+ * separation is what stops a natively-accepted asset from being silently
27
+ * swapped — the regression that implicit auto-routing caused. Any-token swap
28
+ * deposits are the explicit, opt-in job of {@link swapRouterDeposit}.
29
+ *
30
+ * Membership requires the vault to be registered on-chain
31
+ * (`vaultInfo[addr].referenceAsset != 0`) — an unregistered vault reverts with
32
+ * `InvalidVault` at deposit time. A listed vault's natively-accepted assets
33
+ * (for a multi-asset vault, its whole deposit-asset set) still deposit via
34
+ * `vaultDeposit`; only tokens OUTSIDE that set go through `swapRouterDeposit`.
24
35
  *
25
36
  * Lowercase comparison is required when checking — use
26
- * {@link vaultUsesSwapRouter} rather than reading this set directly.
37
+ * {@link isSwapRouterEligible} rather than reading this set directly.
27
38
  */
28
- exports.VAULTS_USING_SWAP_ROUTER = new Set([
29
- // Upshift Core USDC ERC-4626 vault, reference asset USDC. Enabled on
30
- // the mainnet SwapRouter at vaultType=1 (VAULT_TYPE_ERC4626).
31
- '0xe9b725010a9e419412ed67d0fa5f3a5f40159d32',
32
- // Sentora USD — Tokenized Vault V2, reference asset USDC. Enabled on the
33
- // mainnet SwapRouter at vaultType=2 (VAULT_TYPE_TOKENIZED_VAULT_V2).
39
+ exports.SWAP_ROUTER_ELIGIBLE_VAULTS = new Set([
40
+ // Sentora USDnative multi-asset Tokenized Vault V2 (reference asset
41
+ // USDC). Its native assets (USDC/RLUSD/PYUSD/USDT) deposit via vaultDeposit;
42
+ // the swap-router surface adds deposits of tokens outside that set.
34
43
  '0x74ad2f789ed583dbd141bbdafc673fe1f033718b',
35
44
  ]);
45
+ /**
46
+ * @deprecated Renamed to {@link SWAP_ROUTER_ELIGIBLE_VAULTS}, and the semantics
47
+ * changed: this set no longer drives `vaultDeposit` auto-routing (that branch
48
+ * was removed) — it now only marks vaults whose UI may offer the swap-router
49
+ * deposit surface. Kept as an alias for one release; migrate to the new name.
50
+ */
51
+ exports.VAULTS_USING_SWAP_ROUTER = exports.SWAP_ROUTER_ELIGIBLE_VAULTS;
36
52
  /**
37
53
  * 32-byte origin codes registered on the `SwapRouter` via `addOrigin`.
38
54
  * Drives origin/referral-fee accrual. The on-chain admin must register a
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Is this error a wallet/user rejection of a transaction or signature request?
3
+ *
4
+ * Detects ethers v6's `ACTION_REJECTED` code, the EIP-1193 `4001`
5
+ * ("User rejected the request") code (top-level or nested), and the common
6
+ * human-readable phrasings as a fallback for providers that omit a code.
7
+ *
8
+ * @param error - The caught value, of unknown type.
9
+ * @returns `true` when the failure was the user declining in their wallet.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * try { await vault.deposit(...); }
14
+ * catch (e) {
15
+ * if (isUserRejectionError(e)) return; // user cancelled — not an error
16
+ * throw e;
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function isUserRejectionError(error: unknown): boolean;
21
+ /**
22
+ * Is this error a routine on-chain read revert rather than a real failure?
23
+ *
24
+ * Reading a function a contract doesn't implement, or an address that holds no
25
+ * (or incompatible) bytecode, reverts — a normal outcome when the SDK probes
26
+ * heterogeneous vaults. Matches ethers' `CALL_EXCEPTION` code and the
27
+ * message variants emitted by ethers and viem (`missing revert data`,
28
+ * `execution reverted`, `call revert exception`, and the bare `reverted`
29
+ * phrasing such as `the contract function "totalAssets" reverted`).
30
+ *
31
+ * Scope note: callers apply this on **read** paths only. A reverted *write*
32
+ * (a tx that failed on-chain) is a genuine error and is intentionally not
33
+ * demoted by this predicate's use in `write.actions`.
34
+ *
35
+ * @param error - The caught value, of unknown type.
36
+ * @returns `true` when the failure is an expected/benign contract revert.
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * try { return await vaultContract.maxDepositAmount(); }
41
+ * catch (e) {
42
+ * logChainError('maxDeposit', e, isExpectedRevertError(e));
43
+ * throw e;
44
+ * }
45
+ * ```
46
+ */
47
+ export declare function isExpectedRevertError(error: unknown): boolean;
48
+ /**
49
+ * Log a caught chain error at the severity its category warrants, without
50
+ * swallowing it. When `isBenign` is `true` the failure is recorded as a `warn`
51
+ * (a Sentry breadcrumb that rides along with the next real issue, not a billed
52
+ * standalone issue); otherwise it is logged at `error` (a Sentry issue). The
53
+ * caller is still responsible for re-throwing — this only routes telemetry.
54
+ *
55
+ * Pass the benign decision explicitly (via {@link isUserRejectionError} or
56
+ * {@link isExpectedRevertError}) so the call site documents *why* the demotion
57
+ * is safe and each path opts into only the category that applies to it.
58
+ *
59
+ * @param tag - Low-cardinality call-site label (e.g. `'deposit'`), used as the
60
+ * Sentry breadcrumb/issue grouping key.
61
+ * @param error - The caught value, of unknown type.
62
+ * @param isBenign - `true` to demote to `warn`; `false` to keep at `error`.
63
+ * @param context - Optional structured context attached to the log entry. It is
64
+ * sanitized by the logger before transport.
65
+ */
66
+ export declare function logChainError(tag: string, error: unknown, isBenign: boolean, context?: Record<string, unknown>): void;