@augustdigital/sdk 9.10.1 → 9.12.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 (45) hide show
  1. package/README.md +8 -6
  2. package/lib/adapters/evm/index.d.ts +11 -3
  3. package/lib/adapters/evm/index.js +11 -3
  4. package/lib/adapters/solana/constants.d.ts +12 -4
  5. package/lib/adapters/solana/constants.js +8 -3
  6. package/lib/adapters/solana/getters.d.ts +5 -0
  7. package/lib/adapters/solana/getters.js +35 -1
  8. package/lib/adapters/solana/idl/vault-idl.d.ts +334 -7
  9. package/lib/adapters/solana/idl/vault-idl.js +600 -59
  10. package/lib/adapters/solana/idl/withdrawal-queue-idl.d.ts +790 -0
  11. package/lib/adapters/solana/idl/withdrawal-queue-idl.js +1868 -0
  12. package/lib/adapters/solana/index.d.ts +108 -10
  13. package/lib/adapters/solana/index.js +137 -12
  14. package/lib/adapters/solana/pricing.d.ts +11 -0
  15. package/lib/adapters/solana/pricing.js +24 -8
  16. package/lib/adapters/solana/queue.actions.d.ts +98 -0
  17. package/lib/adapters/solana/queue.actions.js +488 -0
  18. package/lib/adapters/solana/token-reads.d.ts +108 -0
  19. package/lib/adapters/solana/token-reads.js +145 -0
  20. package/lib/adapters/solana/types.d.ts +200 -1
  21. package/lib/adapters/solana/utils.d.ts +16 -0
  22. package/lib/adapters/solana/utils.js +41 -4
  23. package/lib/adapters/solana/vault.actions.d.ts +17 -0
  24. package/lib/adapters/solana/vault.actions.js +14 -125
  25. package/lib/adapters/solana/withdrawal-queue.d.ts +125 -0
  26. package/lib/adapters/solana/withdrawal-queue.js +301 -0
  27. package/lib/core/analytics/method-taxonomy.js +2 -0
  28. package/lib/core/analytics/version.d.ts +1 -1
  29. package/lib/core/analytics/version.js +1 -1
  30. package/lib/core/helpers/swap-router.d.ts +17 -0
  31. package/lib/core/helpers/swap-router.js +44 -0
  32. package/lib/main.d.ts +16 -0
  33. package/lib/main.js +16 -0
  34. package/lib/modules/vaults/getters.d.ts +2 -2
  35. package/lib/modules/vaults/getters.js +103 -3
  36. package/lib/modules/vaults/main.d.ts +12 -0
  37. package/lib/modules/vaults/main.js +17 -1
  38. package/lib/modules/vaults/types.d.ts +14 -1
  39. package/lib/modules/vaults/write.actions.d.ts +27 -17
  40. package/lib/modules/vaults/write.actions.js +45 -16
  41. package/lib/sdk.d.ts +2420 -1734
  42. package/lib/types/vaults.d.ts +47 -1
  43. package/lib/types/vaults.js +5 -0
  44. package/lib/types/webserver.d.ts +8 -0
  45. package/package.json +1 -1
@@ -10,6 +10,7 @@ exports.getOriginInfo = getOriginInfo;
10
10
  exports.readOriginInfo = readOriginInfo;
11
11
  exports.readSwapRouterVaultInfo = readSwapRouterVaultInfo;
12
12
  exports.readSwapRouterTokenWhitelisted = readSwapRouterTokenWhitelisted;
13
+ exports.readSwapRouterPaused = readSwapRouterPaused;
13
14
  exports.getSwapRouterWhitelistedTokens = getSwapRouterWhitelistedTokens;
14
15
  exports.getSwapRouterEligibleVaults = getSwapRouterEligibleVaults;
15
16
  const ethers_1 = require("ethers");
@@ -332,6 +333,49 @@ async function readSwapRouterTokenWhitelisted(runner, chainId, token) {
332
333
  cache_1.CACHE.set(cacheKey, whitelisted, { ttl: SWAP_ROUTER_ORIGIN_INFO_TTL_MS });
333
334
  return whitelisted;
334
335
  }
336
+ /**
337
+ * Cache TTL for a SwapRouter's pause state (15 seconds). Far shorter than the
338
+ * 5-minute TTL of the other router reads: the owner pauses the router to stop
339
+ * deposits during an incident, so a pause must reach the deposit-route
340
+ * resolver within seconds. Long enough that the resolver and the router write
341
+ * it hands off to share one `isPaused()` read.
342
+ */
343
+ const SWAP_ROUTER_PAUSED_TTL_MS = 15 * 1000;
344
+ /**
345
+ * Read whether a chain's `SwapRouter` is paused (`isPaused()`), cached for 15
346
+ * seconds. Every router entry point (`deposit`, `swapAndDeposit`,
347
+ * `depositNativeToken`) reverts with `ContractIsPaused` while the router is
348
+ * paused, so callers check this before routing a deposit or sending an
349
+ * approval to the router.
350
+ *
351
+ * @param runner - Contract runner (provider or signer) used for the read.
352
+ * @param chainId - EVM chain ID.
353
+ * @returns `true` while the router is paused; `false` when it is not, or on a
354
+ * chain with no SwapRouter (no RPC).
355
+ * @throws When the `isPaused()` read fails. Callers wrap it in
356
+ * {@link AugustSDKError}.
357
+ * @worstCaseRpcCalls 1 — one `isPaused()` call; none on a cache hit.
358
+ * @internal
359
+ */
360
+ async function readSwapRouterPaused(runner, chainId) {
361
+ const router = getSwapRouterAddress(chainId);
362
+ if (!router)
363
+ return false;
364
+ const cacheKey = `swap-router-paused-${chainId}-${router.toLowerCase()}`;
365
+ const cached = await (0, cache_1.getSafeCache)(cacheKey);
366
+ if (cached !== null)
367
+ return cached;
368
+ const contract = (0, web3_1.createContract)({
369
+ address: router,
370
+ provider: runner,
371
+ abi: abis_1.ABI_SWAP_ROUTER,
372
+ });
373
+ if (!contract)
374
+ return false;
375
+ const paused = (await contract.isPaused()) === true;
376
+ cache_1.CACHE.set(cacheKey, paused, { ttl: SWAP_ROUTER_PAUSED_TTL_MS });
377
+ return paused;
378
+ }
335
379
  /** Cache TTL for a chain's resolved SwapRouter token allowlist (5 minutes). */
336
380
  const SWAP_ROUTER_WHITELIST_TTL_MS = 5 * 60 * 1000;
337
381
  /**
package/lib/main.d.ts CHANGED
@@ -206,8 +206,24 @@ export declare class AugustSDK extends AugustBase {
206
206
  }): Promise<number>;
207
207
  /**
208
208
  * Get redemption requests that are ready to be claimed.
209
+ *
210
+ * For a Solana vault, `wallet` is the holder's base58 address and the result
211
+ * lists their withdrawal-queue requests: waiting (`AWAITING_COOLDOWN`) and
212
+ * past-window (`EXPIRED`, cancel-only) ones in `availableRedemptions`, and
213
+ * claimable ones (`READY_TO_CLAIM`) in `pendingRedemptions`, each with
214
+ * `estimatedAssets`, the net payout at the current share price. Without a
215
+ * Solana wallet, or for a vault with no queue, both lists are empty. Solana
216
+ * RPC: the vault state, one `getAccountInfo` for the queue, and, when it
217
+ * exists, one `getProgramAccounts` and one `getMultipleAccountsInfo` (the
218
+ * vault state, share mint and payout accounts, read together).
219
+ *
209
220
  * @param props - Vault address, chain ID, and optional wallet filter
210
221
  * @returns Array of available redemption requests with amounts and timestamps
222
+ * @example
223
+ * ```ts
224
+ * const { availableRedemptions, pendingRedemptions } =
225
+ * await sdk.getVaultAvailableRedemptions({ vault: solanaVault, wallet: holder });
226
+ * ```
211
227
  */
212
228
  getVaultAvailableRedemptions(props: {
213
229
  vault: IAddress;
package/lib/main.js CHANGED
@@ -317,8 +317,24 @@ class AugustSDK extends core_1.AugustBase {
317
317
  }
318
318
  /**
319
319
  * Get redemption requests that are ready to be claimed.
320
+ *
321
+ * For a Solana vault, `wallet` is the holder's base58 address and the result
322
+ * lists their withdrawal-queue requests: waiting (`AWAITING_COOLDOWN`) and
323
+ * past-window (`EXPIRED`, cancel-only) ones in `availableRedemptions`, and
324
+ * claimable ones (`READY_TO_CLAIM`) in `pendingRedemptions`, each with
325
+ * `estimatedAssets`, the net payout at the current share price. Without a
326
+ * Solana wallet, or for a vault with no queue, both lists are empty. Solana
327
+ * RPC: the vault state, one `getAccountInfo` for the queue, and, when it
328
+ * exists, one `getProgramAccounts` and one `getMultipleAccountsInfo` (the
329
+ * vault state, share mint and payout accounts, read together).
330
+ *
320
331
  * @param props - Vault address, chain ID, and optional wallet filter
321
332
  * @returns Array of available redemption requests with amounts and timestamps
333
+ * @example
334
+ * ```ts
335
+ * const { availableRedemptions, pendingRedemptions } =
336
+ * await sdk.getVaultAvailableRedemptions({ vault: solanaVault, wallet: holder });
337
+ * ```
322
338
  */
323
339
  async getVaultAvailableRedemptions(props) {
324
340
  return await this.vaults.getVaultAvailableRedemptions(props);
@@ -1,4 +1,4 @@
1
- import { type IAddress, type IHistoricalTimeseriesPoint, type IHistoricalTimeseriesResponse, type INormalizedNumber, type ISubgraphReserveDeposit, type ISubgraphTransfer, type ISubgraphUserHistoryItem, type ITokenizedVault, type ISubgraphWithdrawProccessed, type IVault, type IVaultAllocations, type IVaultAnnualizedApy, type IVaultAvailableRedemption, type IVaultLoan, type IVaultPosition, type IVaultRedemptionHistoryItem, type IVaultSummary, type IVaultWithdrawals, type IVaultPendingRedemptions, type IActiveStakingPosition, type IVaultHistoricalParams, type IVaultUserLifetimePnl, type IVaultBorrowerHealthFactor, type IVaultPnl, type VaultAddress } from '../../types';
1
+ import { type IAddress, type IHistoricalTimeseriesPoint, type IHistoricalTimeseriesResponse, type INormalizedNumber, type ISubgraphReserveDeposit, type ISubgraphTransfer, type ISubgraphUserHistoryItem, type ITokenizedVault, type ISubgraphWithdrawProccessed, type ISubgraphWithdrawRequest, type IVault, type IVaultAllocations, type IVaultAnnualizedApy, type IVaultAvailableRedemption, type IVaultLoan, type IVaultPosition, type IVaultRedemptionHistoryItem, type IVaultSummary, type IVaultWithdrawals, type IVaultPendingRedemptions, type IActiveStakingPosition, type IVaultHistoricalParams, type IVaultUserLifetimePnl, type IVaultBorrowerHealthFactor, type IVaultPnl, type VaultAddress } from '../../types';
2
2
  import type { IVaultBaseOptions } from './types';
3
3
  /**
4
4
  * Vault Data Getters
@@ -98,7 +98,7 @@ export declare function getVaultAvailableRedemptions({ vault, wallet, options, p
98
98
  };
99
99
  }): Promise<{
100
100
  processedWithdrawals: ISubgraphWithdrawProccessed[];
101
- requestedWithdrawals: import("../../types").ISubgraphWithdrawRequest[];
101
+ requestedWithdrawals: ISubgraphWithdrawRequest[];
102
102
  availableRedemptions: IVaultAvailableRedemption[];
103
103
  pendingRedemptions: IVaultAvailableRedemption[];
104
104
  }>;
@@ -85,6 +85,8 @@ const debank_1 = require("../../services/debank");
85
85
  const utils_2 = require("../../adapters/solana/utils");
86
86
  const SolanaGetters = __importStar(require("../../adapters/solana/getters"));
87
87
  const SolanaConstants = __importStar(require("../../adapters/solana/constants"));
88
+ const withdrawal_queue_1 = require("../../adapters/solana/withdrawal-queue");
89
+ const web3_js_1 = require("@solana/web3.js");
88
90
  const StellarGetters = __importStar(require("../../adapters/stellar/getters"));
89
91
  const utils_3 = require("../../adapters/stellar/utils");
90
92
  const constants_1 = require("../../adapters/stellar/constants");
@@ -935,6 +937,51 @@ async function readLagDuration(vaultContract, vault, scope) {
935
937
  * an empty response to any *other* view still surfaces as an error.
936
938
  */
937
939
  const LAG_DURATION_SELECTOR = '0x24e86d67';
940
+ /**
941
+ * A Solana wallet's withdrawal-queue requests on one vault, for
942
+ * `getVaultPositions` and `getVaultAvailableRedemptions`. Empty when the vault
943
+ * has no queue, the wallet has no request, or the service cannot name the queue
944
+ * program (including where the queue is not deployed); a failed read is logged
945
+ * and reads as empty, like the balance reads beside it.
946
+ *
947
+ * RPC: see `getSolanaWithdrawalRedemptions` (one `getAccountInfo` for a vault
948
+ * with no queue; up to one more `getProgramAccounts` and one
949
+ * `getMultipleAccountsInfo`).
950
+ */
951
+ async function readSolanaRedemptions(input) {
952
+ const empty = {
953
+ availableRedemptions: [],
954
+ pendingRedemptions: [],
955
+ };
956
+ const { tokenizedVault, solanaService, vaultState } = input;
957
+ if (!vaultState.shareMint)
958
+ return empty;
959
+ try {
960
+ const queueProgramId = (0, withdrawal_queue_1.resolveQueueProgramId)(solanaService);
961
+ if (!queueProgramId)
962
+ return empty;
963
+ const metadata = tokenizedVault.solana_vault_metadata;
964
+ const programId = utils_2.SolanaUtils.resolveProgramId(String(tokenizedVault.address), metadata);
965
+ return await (0, withdrawal_queue_1.getSolanaWithdrawalRedemptions)({
966
+ connection: solanaService.connection,
967
+ queueProgramId,
968
+ vaultStateAddress: metadata?.vault_state_pda
969
+ ? new web3_js_1.PublicKey(metadata.vault_state_pda)
970
+ : utils_2.SolanaUtils.deriveVaultStatePda(programId),
971
+ shareMint: new web3_js_1.PublicKey(vaultState.shareMint),
972
+ owner: new web3_js_1.PublicKey(input.wallet),
973
+ vault: tokenizedVault.address,
974
+ depositDecimals: input.depositDecimals,
975
+ });
976
+ }
977
+ catch (error) {
978
+ core_1.Logger.log.warn('readSolanaRedemptions', 'Withdrawal requests read failed', {
979
+ vault: tokenizedVault.address,
980
+ error,
981
+ });
982
+ return empty;
983
+ }
984
+ }
938
985
  async function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }) {
939
986
  try {
940
987
  // Stellar vaults don't support on-chain redemptions yet
@@ -949,6 +996,41 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
949
996
  }),
950
997
  };
951
998
  }
999
+ // Solana: the wallet's withdrawal-queue requests. There is no processed
1000
+ // history to report, so the verbose lists are always empty.
1001
+ if (utils_2.SolanaUtils.isSolanaAddress(vault)) {
1002
+ const empty = {
1003
+ availableRedemptions: [],
1004
+ pendingRedemptions: [],
1005
+ ...(options.verbose && {
1006
+ processedWithdrawals: [],
1007
+ requestedWithdrawals: [],
1008
+ }),
1009
+ };
1010
+ const solanaService = options.solanaService;
1011
+ if (!wallet || !utils_2.SolanaUtils.isSolanaAddress(wallet) || !solanaService) {
1012
+ return empty;
1013
+ }
1014
+ const solanaVault = (await (0, core_1.fetchTokenizedVault)(vault, options?.headers, false, false))?.[0];
1015
+ if (!solanaVault)
1016
+ return empty;
1017
+ const vaultStateRes = await solanaService.getVaultState(utils_2.SolanaUtils.resolveProgramId(String(solanaVault.address), solanaVault.solana_vault_metadata), SolanaConstants.vaultIdl, solanaVault.solana_vault_metadata?.vault_state_pda ?? undefined);
1018
+ const vaultState = vaultStateRes?.vaultState;
1019
+ if (!vaultState)
1020
+ return empty;
1021
+ return {
1022
+ ...empty,
1023
+ ...(await readSolanaRedemptions({
1024
+ tokenizedVault: solanaVault,
1025
+ wallet,
1026
+ solanaService,
1027
+ vaultState,
1028
+ depositDecimals: vaultStateRes?.depositMintDecimals ??
1029
+ solanaVault.solana_vault_metadata?.deposit_token_decimals ??
1030
+ SolanaConstants.fallbackDecimals,
1031
+ })),
1032
+ };
1033
+ }
952
1034
  // setup
953
1035
  const provider = (0, core_1.createProvider)(options.rpcUrl);
954
1036
  const tokenizedVault = (await (0, core_1.fetchTokenizedVault)(vault, options?.headers, false, false))?.[0];
@@ -1435,6 +1517,10 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1435
1517
  const fallbackShareDecimals = v.solana_vault_metadata?.deposit_token_decimals ??
1436
1518
  SolanaConstants.fallbackDecimals;
1437
1519
  let balance = (0, core_1.toNormalizedBn)(0, fallbackShareDecimals);
1520
+ let redemptions = {
1521
+ availableRedemptions: [],
1522
+ pendingRedemptions: [],
1523
+ };
1438
1524
  // Defensive: without a Solana adapter we can't fetch on-chain
1439
1525
  // state. The outer filter in modules/vaults/main.ts already gates
1440
1526
  // on `this.solanaService`, so this is a belt-and-suspenders guard
@@ -1456,6 +1542,15 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1456
1542
  const decimals = raw.decimals ?? fallbackShareDecimals;
1457
1543
  balance = (0, core_1.toNormalizedBn)(BigInt(raw.amount), decimals);
1458
1544
  }
1545
+ if (vaultState) {
1546
+ redemptions = await readSolanaRedemptions({
1547
+ tokenizedVault: v,
1548
+ wallet: solanaWallet,
1549
+ solanaService: options.solanaService,
1550
+ vaultState,
1551
+ depositDecimals: vaultStateRes?.depositMintDecimals ?? fallbackShareDecimals,
1552
+ });
1553
+ }
1459
1554
  }
1460
1555
  return {
1461
1556
  // Mirror the Stellar branch — return the backend's `v.address`,
@@ -1464,9 +1559,14 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
1464
1559
  // not 0x-hex; the IAddress typing across non-EVM positions is a
1465
1560
  // known wart documented in IVaultPosition.
1466
1561
  vault: v.address,
1467
- status: renderStatus([], balance),
1468
- availableRedemptions: [],
1469
- pendingRedemptions: [],
1562
+ // Any queued request, waiting or claimable, marks the position
1563
+ // REDEEM; the shares it escrows are no longer in the wallet.
1564
+ status: renderStatus([
1565
+ ...redemptions.availableRedemptions,
1566
+ ...redemptions.pendingRedemptions,
1567
+ ], balance),
1568
+ availableRedemptions: redemptions.availableRedemptions,
1569
+ pendingRedemptions: redemptions.pendingRedemptions,
1470
1570
  redeemable: balance,
1471
1571
  walletBalance: balance,
1472
1572
  };
@@ -68,6 +68,8 @@ export declare class AugustVaults extends AugustBase {
68
68
  /**
69
69
  * Calculate total deposited across all tokenized vaults by summing latest_reported_tvl.
70
70
  * Uses the /tokenized_vault endpoint which returns latest_reported_tvl in USD.
71
+ * Wrapper vaults (non-null `underlying_vault_address`) are skipped: their
72
+ * deposits sit in the underlying vault as LP and are already counted there.
71
73
  * @param options Optional configuration for loading vaults
72
74
  * @returns Total deposited amount in USD (sum of all latest_reported_tvl values)
73
75
  */
@@ -160,7 +162,17 @@ export declare class AugustVaults extends AugustBase {
160
162
  nDays?: number;
161
163
  }): Promise<import("../../types").IHistoricalTimeseriesResponse>;
162
164
  /**
165
+ * A wallet's redemption requests on one vault, split into
166
+ * `availableRedemptions` and `pendingRedemptions`. EVM, Stellar and Solana
167
+ * vault addresses are accepted; see `AugustSDK.getVaultAvailableRedemptions`
168
+ * for what each list holds on Solana.
163
169
  *
170
+ * @param props - `vault`, the vault address; `chainId`, the EVM chain whose
171
+ * RPC to use (the active network when omitted); `wallet`, the holder,
172
+ * required for Solana, where it is base58; `verbose`, to also return the
173
+ * processed and requested withdrawal lists (always empty for Solana).
174
+ * @returns `{ availableRedemptions, pendingRedemptions }`, plus the verbose lists.
175
+ * @throws Error when unauthorized, or when `vault` is missing or not an address.
164
176
  */
165
177
  getVaultAvailableRedemptions({ vault, chainId, wallet, verbose, }: {
166
178
  vault: IAddress;
@@ -339,6 +339,8 @@ class AugustVaults extends core_1.AugustBase {
339
339
  /**
340
340
  * Calculate total deposited across all tokenized vaults by summing latest_reported_tvl.
341
341
  * Uses the /tokenized_vault endpoint which returns latest_reported_tvl in USD.
342
+ * Wrapper vaults (non-null `underlying_vault_address`) are skipped: their
343
+ * deposits sit in the underlying vault as LP and are already counted there.
342
344
  * @param options Optional configuration for loading vaults
343
345
  * @returns Total deposited amount in USD (sum of all latest_reported_tvl values)
344
346
  */
@@ -348,6 +350,8 @@ class AugustVaults extends core_1.AugustBase {
348
350
  allVaults.forEach((vault) => {
349
351
  if (vaults_2.TVL_EXCLUDED_VAULTS.has(vault.address?.toLowerCase()))
350
352
  return;
353
+ if (vault.underlying_vault_address)
354
+ return;
351
355
  if (vault.latest_reported_tvl !== null &&
352
356
  vault.latest_reported_tvl !== undefined) {
353
357
  total += vault.latest_reported_tvl;
@@ -591,14 +595,26 @@ class AugustVaults extends core_1.AugustBase {
591
595
  });
592
596
  }
593
597
  /**
598
+ * A wallet's redemption requests on one vault, split into
599
+ * `availableRedemptions` and `pendingRedemptions`. EVM, Stellar and Solana
600
+ * vault addresses are accepted; see `AugustSDK.getVaultAvailableRedemptions`
601
+ * for what each list holds on Solana.
594
602
  *
603
+ * @param props - `vault`, the vault address; `chainId`, the EVM chain whose
604
+ * RPC to use (the active network when omitted); `wallet`, the holder,
605
+ * required for Solana, where it is base58; `verbose`, to also return the
606
+ * processed and requested withdrawal lists (always empty for Solana).
607
+ * @returns `{ availableRedemptions, pendingRedemptions }`, plus the verbose lists.
608
+ * @throws Error when unauthorized, or when `vault` is missing or not an address.
595
609
  */
596
610
  async getVaultAvailableRedemptions({ vault, chainId, wallet, verbose, }) {
597
611
  if (!this.authorized)
598
612
  throw new Error('Not authorized.');
599
613
  if (!vault)
600
614
  throw new Error('Vault input parameter is undefined.');
601
- if (!(0, ethers_1.isAddress)(vault) && !(0, utils_2.isStellarAddress)(vault))
615
+ if (!(0, ethers_1.isAddress)(vault) &&
616
+ !(0, utils_2.isStellarAddress)(vault) &&
617
+ !utils_1.SolanaUtils.isSolanaAddress(vault))
602
618
  throw new Error(`Vault input parameter is not an address: ${String(vault)}`);
603
619
  return await (0, getters_1.getVaultAvailableRedemptions)({
604
620
  vault,
@@ -1,5 +1,5 @@
1
1
  import type { Connection } from '@solana/web3.js';
2
- import type { IAddress, IEnv, IStellarNetwork, IWSMonitorHeaders } from '../../types';
2
+ import type { IAddress, IEnv, ISolanaNetwork, IStellarNetwork, IWSMonitorHeaders } from '../../types';
3
3
  /**
4
4
  * Structural interface for the Solana adapter surface used by vault operations.
5
5
  * Avoids importing the concrete SolanaAdapter class to prevent circular dependencies.
@@ -29,6 +29,19 @@ export interface ISolanaService {
29
29
  amount: string;
30
30
  decimals: number | null;
31
31
  }>;
32
+ /**
33
+ * Canonical program id for this service's network, as
34
+ * `SolanaAdapter.getProgramId`. Optional so a hand-built service keeps
35
+ * working: without it the withdrawal-queue reads are skipped, and vaults and
36
+ * positions come back without queue data.
37
+ */
38
+ getProgramId?: (type: 'vault' | 'withdrawalQueue') => string;
39
+ /**
40
+ * This service's network, as `SolanaAdapter.network`. When present, the
41
+ * withdrawal-queue reads look the queue program up in `programIds` directly
42
+ * instead of calling `getProgramId`.
43
+ */
44
+ network?: ISolanaNetwork;
32
45
  }
33
46
  /**
34
47
  * Base configuration for vault operations.
@@ -172,8 +172,11 @@ export type ApproveResult =
172
172
  /**
173
173
  * Why {@link getDepositRoute} kept a deposit on the vault's native path.
174
174
  * `no-origin-code` is what every SDK without `attribution.originCode` gets.
175
+ * `router-paused` means the SwapRouter's owner paused it: the deposit goes
176
+ * straight to the vault, even under `attribution.strictOrigin`, until the
177
+ * router is unpaused.
175
178
  */
176
- export type DepositRouteReason = 'no-origin-code' | 'no-router' | 'chain-not-supported' | 'permit' | 'native-token' | 'adapter' | 'vault-not-registered' | 'asset-not-accepted' | 'router-token-not-whitelisted' | 'origin-not-registered';
179
+ export type DepositRouteReason = 'no-origin-code' | 'no-router' | 'chain-not-supported' | 'permit' | 'native-token' | 'adapter' | 'vault-not-registered' | 'asset-not-accepted' | 'router-token-not-whitelisted' | 'router-paused' | 'origin-not-registered';
177
180
  /** A deposit's route — the SwapRouter or the vault's native path — and the address to approve. */
178
181
  export type IDepositRoute = {
179
182
  /**
@@ -199,23 +202,25 @@ export type IGetDepositRouteOptions = Pick<IContractWriteOptions, 'target' | 'de
199
202
  * Ethereum mainnet ({@link ORIGIN_ATTRIBUTION_CHAINS}) and has a SwapRouter,
200
203
  * the vault is registered on it, the vault accepts the asset directly (its
201
204
  * reference asset, or a Tokenized Vault V2 whitelisted asset — deposited
202
- * as-is, never swapped), the router whitelists the asset, the deposit is not a
203
- * permit, native-token or adapter deposit, and the code is registered.
204
- * Otherwise it is `native` with a `reason`.
205
+ * as-is, never swapped), the router whitelists the asset, the router is not
206
+ * paused, the deposit is not a permit, native-token or adapter deposit, and
207
+ * the code is registered. Otherwise it is `native` with a `reason`. A paused
208
+ * router gives `router-paused` even under `attribution.strictOrigin`.
205
209
  *
206
210
  * @param signer - ethers `Signer` / `Wallet` used for the reads.
207
211
  * @param options - {@link IGetDepositRouteOptions}; `depositAsset` defaults
208
212
  * to the vault's underlying.
209
213
  * @returns {@link IDepositRoute}.
210
214
  * @throws AugustValidationError on an invalid `target`, or an unregistered
211
- * code under `attribution.strictOrigin`.
215
+ * code under `attribution.strictOrigin` while the router is not paused.
212
216
  * @throws AugustSDKError when a backend, vault or router read fails.
213
- * @worstCaseRpcCalls 7 — the backend vault row, `asset()`, the router's
217
+ * @worstCaseRpcCalls 8 — the backend vault row, `asset()`, the router's
214
218
  * `vaultInfo`, the vault's `assetsWhitelistAddress()` and
215
219
  * `getWhitelistedAssets()` (Tokenized Vault V2 non-reference asset only),
216
- * the router's `whitelistedTokens(asset)`, and the router's `origins`. The
217
- * router reads and `getWhitelistedAssets()` are cached for 5 minutes. No
218
- * router read without a code or off Ethereum mainnet.
220
+ * the router's `whitelistedTokens(asset)`, `isPaused()` and `origins`. The
221
+ * router reads and `getWhitelistedAssets()` are cached for 5 minutes, except
222
+ * `isPaused()` (15 seconds). No router read without a code or off Ethereum
223
+ * mainnet.
219
224
  * @example
220
225
  * ```ts
221
226
  * const route = await augustSdk.evm.getDepositRoute({ target: vault, depositAsset: usdt });
@@ -555,7 +560,8 @@ export declare function rwaRedeemAsset(signer: Signer | Wallet, options: IRwaRed
555
560
  * addresses, empty/oversized swap arrays, or an origin code not registered on
556
561
  * the router (a per-call code, or the instance code under
557
562
  * `attribution.strictOrigin`), before any approval.
558
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
563
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
564
+ * any approval), or on unrecoverable contract or RPC failure.
559
565
  *
560
566
  * @example
561
567
  * ```ts
@@ -598,7 +604,8 @@ export declare function swapAndDeposit(signer: Signer | Wallet, options: ISwapAn
598
604
  * per-call code, or the instance code under `attribution.strictOrigin`),
599
605
  * before any approval; with code `ACCOUNT_NOT_FUNDED` when the account cannot
600
606
  * cover gas.
601
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
607
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
608
+ * any approval), or on unrecoverable contract or RPC failure.
602
609
  */
603
610
  export declare function depositViaSwapRouter(signer: Signer | Wallet, options: ISwapRouterDirectDepositOptions): Promise<string>;
604
611
  /**
@@ -626,7 +633,8 @@ export declare function depositViaSwapRouter(signer: Signer | Wallet, options: I
626
633
  * per-call code, or the instance code under `attribution.strictOrigin`),
627
634
  * before any approval; with code `ACCOUNT_NOT_FUNDED` when the account cannot
628
635
  * cover gas.
629
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
636
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
637
+ * any approval), or on unrecoverable contract or RPC failure.
630
638
  */
631
639
  export declare function depositNativeViaSwapRouter(signer: Signer | Wallet, options: ISwapRouterNativeDepositOptions): Promise<string>;
632
640
  /**
@@ -724,14 +732,16 @@ export declare function isNativeSwapRouterDepositSupported(chainId: number, vaul
724
732
  * not registered on the router (a per-call code, or the instance code under
725
733
  * `attribution.strictOrigin`), before any approval; with code
726
734
  * `ACCOUNT_NOT_FUNDED` when the account cannot cover gas.
727
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
728
- * @worstCaseRpcCalls 10 on the swap path into a Tokenized Vault V2 —
735
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
736
+ * any approval), or on unrecoverable contract or RPC failure.
737
+ * @worstCaseRpcCalls 11 on the swap path into a Tokenized Vault V2 —
729
738
  * tokenized-vault metadata, reference asset + decimals, deposit-token
730
739
  * decimals, the router's `vaultInfo` and `whitelistedTokens`, the vault's
731
740
  * `assetsWhitelistAddress()` and `getWhitelistedAssets()`, the quote, the
732
- * origin code's `origins` (none for the zero sentinel), and the allowance
733
- * read. The router reads and `getWhitelistedAssets()` are cached for 5
734
- * minutes.
741
+ * router's `isPaused()`, the origin code's `origins` (none for the zero
742
+ * sentinel), and the allowance read. The router reads and
743
+ * `getWhitelistedAssets()` are cached for 5 minutes, except `isPaused()`
744
+ * (15 seconds).
735
745
  * @example
736
746
  * ```ts
737
747
  * // USDT deposited into a USDC-reference vault → swapped to USDC en route.
@@ -515,6 +515,12 @@ async function resolveDepositRoute(signer, args) {
515
515
  if (!(await (0, core_1.readSwapRouterTokenWhitelisted)(signer, chainId, actualDepositAsset))) {
516
516
  return native('router-token-not-whitelisted');
517
517
  }
518
+ // After the cached registration gates, so only a deposit that would
519
+ // otherwise route pays the short-TTL read; before the origin check, so a
520
+ // paused router falls back to native instead of throwing under strictOrigin.
521
+ if (await (0, core_1.readSwapRouterPaused)(signer, chainId)) {
522
+ return native('router-paused');
523
+ }
518
524
  if (!(await (0, core_1.readOriginInfo)(chainId, originCode, () => signer)).registered) {
519
525
  if ((0, core_1.isStrictOrigin)()) {
520
526
  throw new core_1.AugustValidationError('INVALID_INPUT', `attribution.originCode is not registered on the SwapRouter for chain ${chainId} and attribution.strictOrigin is set. Register it with addOrigin, or unset strictOrigin to fall back to a native deposit.`, { context: { chainId, target } });
@@ -534,23 +540,25 @@ async function resolveDepositRoute(signer, args) {
534
540
  * Ethereum mainnet ({@link ORIGIN_ATTRIBUTION_CHAINS}) and has a SwapRouter,
535
541
  * the vault is registered on it, the vault accepts the asset directly (its
536
542
  * reference asset, or a Tokenized Vault V2 whitelisted asset — deposited
537
- * as-is, never swapped), the router whitelists the asset, the deposit is not a
538
- * permit, native-token or adapter deposit, and the code is registered.
539
- * Otherwise it is `native` with a `reason`.
543
+ * as-is, never swapped), the router whitelists the asset, the router is not
544
+ * paused, the deposit is not a permit, native-token or adapter deposit, and
545
+ * the code is registered. Otherwise it is `native` with a `reason`. A paused
546
+ * router gives `router-paused` even under `attribution.strictOrigin`.
540
547
  *
541
548
  * @param signer - ethers `Signer` / `Wallet` used for the reads.
542
549
  * @param options - {@link IGetDepositRouteOptions}; `depositAsset` defaults
543
550
  * to the vault's underlying.
544
551
  * @returns {@link IDepositRoute}.
545
552
  * @throws AugustValidationError on an invalid `target`, or an unregistered
546
- * code under `attribution.strictOrigin`.
553
+ * code under `attribution.strictOrigin` while the router is not paused.
547
554
  * @throws AugustSDKError when a backend, vault or router read fails.
548
- * @worstCaseRpcCalls 7 — the backend vault row, `asset()`, the router's
555
+ * @worstCaseRpcCalls 8 — the backend vault row, `asset()`, the router's
549
556
  * `vaultInfo`, the vault's `assetsWhitelistAddress()` and
550
557
  * `getWhitelistedAssets()` (Tokenized Vault V2 non-reference asset only),
551
- * the router's `whitelistedTokens(asset)`, and the router's `origins`. The
552
- * router reads and `getWhitelistedAssets()` are cached for 5 minutes. No
553
- * router read without a code or off Ethereum mainnet.
558
+ * the router's `whitelistedTokens(asset)`, `isPaused()` and `origins`. The
559
+ * router reads and `getWhitelistedAssets()` are cached for 5 minutes, except
560
+ * `isPaused()` (15 seconds). No router read without a code or off Ethereum
561
+ * mainnet.
554
562
  * @example
555
563
  * ```ts
556
564
  * const route = await augustSdk.evm.getDepositRoute({ target: vault, depositAsset: usdt });
@@ -1752,6 +1760,19 @@ async function resolveRouterOriginCode(signer, operation, chainId, vault, provid
1752
1760
  trackOriginAttribution({ via: 'native', spender: null, reason: 'origin-not-registered' }, { chainId, target: vault }, operation);
1753
1761
  return core_1.ORIGIN_CODES.default;
1754
1762
  }
1763
+ /**
1764
+ * Throw before any approval when the chain's SwapRouter is paused. Every
1765
+ * router entry point reverts with `ContractIsPaused` while it is paused, so an
1766
+ * approval sent first would only cost the user gas. Unlike `vaultDeposit`,
1767
+ * these methods have no native path to fall back to: the caller asked for the
1768
+ * router.
1769
+ * @internal
1770
+ */
1771
+ async function assertSwapRouterNotPaused(signer, operation, chainId, vault) {
1772
+ if (!(await (0, core_1.readSwapRouterPaused)(signer, chainId)))
1773
+ return;
1774
+ throw new core_1.AugustSDKError('UNKNOWN', `${operation}: the SwapRouter on chain ${chainId} is paused and rejects every deposit. Deposit into the vault directly with vaultDeposit, or retry once the router is unpaused.`, { context: { chainId, vault, reason: 'router-paused' } });
1775
+ }
1755
1776
  /** @internal */
1756
1777
  function resolveSwapRouterOrThrow(chainId) {
1757
1778
  const router = (0, core_1.getSwapRouterAddress)(chainId);
@@ -1848,7 +1869,8 @@ async function resolveSignerEOA(signer, callerContext) {
1848
1869
  * addresses, empty/oversized swap arrays, or an origin code not registered on
1849
1870
  * the router (a per-call code, or the instance code under
1850
1871
  * `attribution.strictOrigin`), before any approval.
1851
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
1872
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
1873
+ * any approval), or on unrecoverable contract or RPC failure.
1852
1874
  *
1853
1875
  * @example
1854
1876
  * ```ts
@@ -1887,6 +1909,7 @@ async function swapAndDeposit(signer, options) {
1887
1909
  const routerAddress = resolveSwapRouterOrThrow(chainId);
1888
1910
  let tx;
1889
1911
  try {
1912
+ await assertSwapRouterNotPaused(signer, 'swapAndDeposit', chainId, vault);
1890
1913
  const origin = await resolveRouterOriginCode(signer, 'swapAndDeposit', chainId, vault, originCode);
1891
1914
  const eoa = await resolveSignerEOA(signer, 'swapAndDeposit');
1892
1915
  for (const [tokenIn, totalIn] of totalInputPerToken(swaps)) {
@@ -1923,7 +1946,8 @@ async function swapAndDeposit(signer, options) {
1923
1946
  * per-call code, or the instance code under `attribution.strictOrigin`),
1924
1947
  * before any approval; with code `ACCOUNT_NOT_FUNDED` when the account cannot
1925
1948
  * cover gas.
1926
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
1949
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
1950
+ * any approval), or on unrecoverable contract or RPC failure.
1927
1951
  */
1928
1952
  async function depositViaSwapRouter(signer, options) {
1929
1953
  const { chainId, vault, receiver, asset, amount, originCode, wait } = options;
@@ -1939,6 +1963,7 @@ async function depositViaSwapRouter(signer, options) {
1939
1963
  const routerAddress = resolveSwapRouterOrThrow(chainId);
1940
1964
  let tx;
1941
1965
  try {
1966
+ await assertSwapRouterNotPaused(signer, 'depositViaSwapRouter', chainId, vault);
1942
1967
  const origin = await resolveRouterOriginCode(signer, 'depositViaSwapRouter', chainId, vault, originCode);
1943
1968
  const eoa = await resolveSignerEOA(signer, 'depositViaSwapRouter');
1944
1969
  await ensureAllowance(signer, asset, eoa, routerAddress, amount);
@@ -1984,7 +2009,8 @@ async function depositViaSwapRouter(signer, options) {
1984
2009
  * per-call code, or the instance code under `attribution.strictOrigin`),
1985
2010
  * before any approval; with code `ACCOUNT_NOT_FUNDED` when the account cannot
1986
2011
  * cover gas.
1987
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
2012
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
2013
+ * any approval), or on unrecoverable contract or RPC failure.
1988
2014
  */
1989
2015
  async function depositNativeViaSwapRouter(signer, options) {
1990
2016
  const { chainId, vault, receiver, amount, originCode, wait } = options;
@@ -1999,6 +2025,7 @@ async function depositNativeViaSwapRouter(signer, options) {
1999
2025
  const routerAddress = resolveSwapRouterOrThrow(chainId);
2000
2026
  let tx;
2001
2027
  try {
2028
+ await assertSwapRouterNotPaused(signer, 'depositNativeViaSwapRouter', chainId, vault);
2002
2029
  const origin = await resolveRouterOriginCode(signer, 'depositNativeViaSwapRouter', chainId, vault, originCode);
2003
2030
  const routerContract = (0, core_1.createContract)({
2004
2031
  address: routerAddress,
@@ -2141,14 +2168,16 @@ async function isNativeSwapRouterDepositSupported(chainId, vault, options) {
2141
2168
  * not registered on the router (a per-call code, or the instance code under
2142
2169
  * `attribution.strictOrigin`), before any approval; with code
2143
2170
  * `ACCOUNT_NOT_FUNDED` when the account cannot cover gas.
2144
- * @throws {@link AugustSDKError} on unrecoverable contract or RPC failure.
2145
- * @worstCaseRpcCalls 10 on the swap path into a Tokenized Vault V2 —
2171
+ * @throws {@link AugustSDKError} while the SwapRouter is paused (checked before
2172
+ * any approval), or on unrecoverable contract or RPC failure.
2173
+ * @worstCaseRpcCalls 11 on the swap path into a Tokenized Vault V2 —
2146
2174
  * tokenized-vault metadata, reference asset + decimals, deposit-token
2147
2175
  * decimals, the router's `vaultInfo` and `whitelistedTokens`, the vault's
2148
2176
  * `assetsWhitelistAddress()` and `getWhitelistedAssets()`, the quote, the
2149
- * origin code's `origins` (none for the zero sentinel), and the allowance
2150
- * read. The router reads and `getWhitelistedAssets()` are cached for 5
2151
- * minutes.
2177
+ * router's `isPaused()`, the origin code's `origins` (none for the zero
2178
+ * sentinel), and the allowance read. The router reads and
2179
+ * `getWhitelistedAssets()` are cached for 5 minutes, except `isPaused()`
2180
+ * (15 seconds).
2152
2181
  * @example
2153
2182
  * ```ts
2154
2183
  * // USDT deposited into a USDC-reference vault → swapped to USDC en route.