@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
@@ -8,7 +8,7 @@ import * as SolanaGetters from './getters';
8
8
  import * as SolanaActions from './vault.actions';
9
9
  import type { AnchorProvider, web3 } from '@coral-xyz/anchor';
10
10
  import { type Commitment, Connection, PublicKey, type Transaction } from '@solana/web3.js';
11
- import type { ISolanaDepositOptions, ISolanaNetwork, ISolanaRedeemOptions, ISolanaRpcEndpoint } from './types';
11
+ import type { ISolanaCancelRedeemRequestParams, ISolanaDepositOptions, ISolanaNetwork, ISolanaRedeemOptions, ISolanaRequestRedeemParams, ISolanaRpcEndpoint } from './types';
12
12
  import type { SendTransactionOptions } from '@solana/wallet-adapter-base';
13
13
  export declare const Solana: {
14
14
  utils: {
@@ -79,12 +79,14 @@ export declare const Solana: {
79
79
  programIds: {
80
80
  devnet: {
81
81
  vault: string;
82
+ withdrawalQueue: string;
82
83
  };
83
84
  "mainnet-beta": {
84
85
  vault: string;
85
86
  };
86
87
  localnet: {
87
88
  vault: string;
89
+ withdrawalQueue: string;
88
90
  };
89
91
  };
90
92
  getVaultMints: ({ vaultProgramId, vaultAddress, connection, idl, }: {
@@ -150,16 +152,22 @@ declare class SolanaAdapter {
150
152
  * default (its embedded `address` is a build stamp, not network-aware), so
151
153
  * forwarding it on devnet never silently targets the mainnet program.
152
154
  *
155
+ * An IDL whose `metadata.name` is `august_withdrawal_queue` resolves against
156
+ * the withdrawal queue program's network default instead of the vault's.
157
+ *
153
158
  * @param programIdl - Anchor IDL to bind. Defaults to the SDK's bundled
154
159
  * `august_vault` IDL. A custom IDL's `address` is honoured when it differs
155
- * from the bundled build stamp.
160
+ * from the program's canonical id (the build stamp every bundled copy of
161
+ * the vault or queue IDL carries).
156
162
  * @param programId - Base58 program id that overrides both the IDL's address
157
163
  * and the network default. Use this to target a non-canonical deployment.
158
164
  * @returns An Anchor `Program` for the resolved program id. No RPC is made —
159
165
  * construction is offline.
160
166
  * @throws {@link AugustValidationError} if no program id can be resolved
161
- * because this adapter's network has no canonical deployment (e.g.
162
- * `testnet`) and neither `programId` nor a custom IDL address was supplied.
167
+ * because the program has no canonical deployment on this adapter's network
168
+ * (neither program on `testnet`; the withdrawal queue not yet on
169
+ * `mainnet-beta`) and neither `programId` nor a custom IDL address was
170
+ * supplied.
163
171
  *
164
172
  * @example
165
173
  * ```ts
@@ -257,18 +265,108 @@ declare class SolanaAdapter {
257
265
  * @param options - Slippage protection. By default the SDK quotes the net payout these shares should return
258
266
  * from the vault's current state and passes that quote, lowered by 50 bps,
259
267
  * as the floor to the program's checked instruction. See {@link ISolanaRedeemOptions}.
268
+ *
269
+ * **On a vault with a withdrawal queue**, holders cannot redeem directly:
270
+ * request with {@link SolanaAdapter.vaultRequestRedeem}, then claim here with
271
+ * `options.request` once the cooldown has run. The claim settles at the share
272
+ * price of that moment, net of the withdrawal fee, held to the floor set at
273
+ * request time, and pays the request's recipient; `redeemShares` and
274
+ * `vaultAddress` are then ignored, and `slippageBps` / `minAssetsOut` must
275
+ * be left unset. Without `request`, a
276
+ * queued vault is refused before signing.
277
+ * @returns The confirmed transaction's signature.
278
+ * @throws {@link AugustValidationError} for bad input, for a queued vault
279
+ * without `options.request`, or for a request the wallet cannot claim yet.
280
+ * @example
281
+ * ```ts
282
+ * // A vault with a withdrawal queue: claim a ready request.
283
+ * const { pendingRedemptions } = await sdk.getVaultAvailableRedemptions({ vault, wallet });
284
+ * await sdk.solana.vaultRedeem(programId, vaultIdl, wallet, 0n, undefined, undefined, {
285
+ * request: pendingRedemptions[0].id,
286
+ * });
287
+ * ```
260
288
  */
261
289
  vaultRedeem(vaultProgramId: PublicKey | string, idl: any, publicKey: PublicKey | string, redeemShares: number | bigint, sendTransaction?: (transaction: Transaction | web3.VersionedTransaction, connection: Connection, options?: SendTransactionOptions) => Promise<web3.TransactionSignature>, vaultAddress?: PublicKey | string, options?: ISolanaRedeemOptions): Promise<any>;
290
+ /**
291
+ * Request a withdrawal from a Solana vault that has a withdrawal queue.
292
+ *
293
+ * With a queue attached, a vault's shares cannot be redeemed directly: the
294
+ * holder escrows them in a request, waits out the queue's cooldown, then
295
+ * claims with {@link SolanaAdapter.vaultRedeem} and `options.request`, or
296
+ * anyone the request permits (a keeper, by default) claims for them. The
297
+ * payout is priced when the request is claimed, not now, but never below the
298
+ * floor set here: by default the current net quote lowered by 50 bps, so a
299
+ * fee rise or mark-down in between makes the claim fail rather than pay
300
+ * less. A pending request
301
+ * can be cancelled at any time with
302
+ * {@link SolanaAdapter.vaultCancelRedeemRequest}, which returns the shares.
303
+ *
304
+ * Signs through the provider's wallet and submits one transaction, which
305
+ * also creates the recipient's deposit-token account when it has none. The
306
+ * holder pays the request account's rent, refunded when it is claimed or
307
+ * cancelled, plus rent for any account created. Use
308
+ * `getVaultAvailableRedemptions` to list requests and see when they can be
309
+ * claimed.
310
+ *
311
+ * RPC: three to four reads, then the send.
312
+ *
313
+ * @param params - Vault, wallet, shares, and optional recipient, finalizer,
314
+ * request id and floor. See {@link ISolanaRequestRedeemParams}.
315
+ * @returns The signature, the request's address (pass it as `request` to
316
+ * claim or cancel) and its id.
317
+ * @throws {@link AugustValidationError} for bad input, a vault without an
318
+ * attached queue, a frozen account or too few shares, before signing.
319
+ * @throws {@link AugustSDKError} when the transaction fails.
320
+ * @example
321
+ * ```ts
322
+ * const { request } = await sdk.solana.vaultRequestRedeem({
323
+ * vault: vaultStateAddress,
324
+ * wallet: wallet.publicKey,
325
+ * amount: 10, // shares, UI units
326
+ * });
327
+ * // ...once the cooldown has run:
328
+ * await sdk.solana.vaultRedeem(programId, vaultIdl, wallet.publicKey, 0n, undefined, undefined, { request });
329
+ * ```
330
+ */
331
+ vaultRequestRedeem(params: ISolanaRequestRedeemParams): Promise<import("./types").ISolanaRequestRedeemResult>;
332
+ /**
333
+ * Cancel a pending withdrawal request, returning its shares to the holder.
334
+ *
335
+ * Allowed at any time while the request exists: during the cooldown, after
336
+ * it, past the fulfillment window, and while the vault is paused. Only the
337
+ * holder who made the request may cancel it. Signs through the provider's
338
+ * wallet; the request's rent is refunded to the holder.
339
+ *
340
+ * RPC: three reads, then the send.
341
+ *
342
+ * @param params - The holder and the request address. See
343
+ * {@link ISolanaCancelRedeemRequestParams}.
344
+ * @returns The confirmed transaction's signature.
345
+ * @throws {@link AugustValidationError} for a missing request, or one this
346
+ * wallet did not make, before signing.
347
+ * @throws {@link AugustSDKError} when the transaction fails.
348
+ * @example
349
+ * ```ts
350
+ * await sdk.solana.vaultCancelRedeemRequest({ wallet: wallet.publicKey, request });
351
+ * ```
352
+ */
353
+ vaultCancelRedeemRequest(params: ISolanaCancelRedeemRequestParams): Promise<string>;
262
354
  /**
263
355
  * Canonical program id for a program type on this adapter's network.
264
356
  *
265
- * @param type - Program to look up. Only `'vault'` (august_vault) exists today.
357
+ * @param type - Program to look up: `'vault'` (august_vault) or
358
+ * `'withdrawalQueue'` (august_withdrawal_queue).
266
359
  * @returns The base58 program id.
267
- * @throws {@link AugustValidationError} if the canonical program is not
268
- * deployed on this adapter's network (e.g. `testnet`). Previously an
269
- * unmapped network threw a bare `TypeError`.
360
+ * @throws {@link AugustValidationError} if `type` is not one of the two
361
+ * program types, or the program is not deployed on this adapter's network:
362
+ * neither program on `testnet`, and `'withdrawalQueue'` not yet on
363
+ * `mainnet-beta`.
364
+ * @example
365
+ * ```ts
366
+ * const queueProgram = adapter.getProgramId('withdrawalQueue');
367
+ * ```
270
368
  */
271
- getProgramId(type: 'vault'): string;
369
+ getProgramId(type: 'vault' | 'withdrawalQueue'): string;
272
370
  }
273
- export type { ISolanaDepositOptions, ISolanaRedeemOptions } from './types';
371
+ export type { ISolanaCancelRedeemRequestParams, ISolanaDepositOptions, ISolanaRedeemOptions, ISolanaRequestRedeemParams, ISolanaRequestRedeemResult, } from './types';
274
372
  export default SolanaAdapter;
@@ -45,6 +45,7 @@ const SolanaActions = __importStar(require("./vault.actions"));
45
45
  const web3_js_1 = require("@solana/web3.js");
46
46
  const utils_1 = require("./utils");
47
47
  const vault_actions_1 = require("./vault.actions");
48
+ const queue_actions_1 = require("./queue.actions");
48
49
  const constants_1 = require("./constants");
49
50
  const core_1 = require("../../core");
50
51
  exports.Solana = {
@@ -137,16 +138,22 @@ class SolanaAdapter {
137
138
  * default (its embedded `address` is a build stamp, not network-aware), so
138
139
  * forwarding it on devnet never silently targets the mainnet program.
139
140
  *
141
+ * An IDL whose `metadata.name` is `august_withdrawal_queue` resolves against
142
+ * the withdrawal queue program's network default instead of the vault's.
143
+ *
140
144
  * @param programIdl - Anchor IDL to bind. Defaults to the SDK's bundled
141
145
  * `august_vault` IDL. A custom IDL's `address` is honoured when it differs
142
- * from the bundled build stamp.
146
+ * from the program's canonical id (the build stamp every bundled copy of
147
+ * the vault or queue IDL carries).
143
148
  * @param programId - Base58 program id that overrides both the IDL's address
144
149
  * and the network default. Use this to target a non-canonical deployment.
145
150
  * @returns An Anchor `Program` for the resolved program id. No RPC is made —
146
151
  * construction is offline.
147
152
  * @throws {@link AugustValidationError} if no program id can be resolved
148
- * because this adapter's network has no canonical deployment (e.g.
149
- * `testnet`) and neither `programId` nor a custom IDL address was supplied.
153
+ * because the program has no canonical deployment on this adapter's network
154
+ * (neither program on `testnet`; the withdrawal queue not yet on
155
+ * `mainnet-beta`) and neither `programId` nor a custom IDL address was
156
+ * supplied.
150
157
  *
151
158
  * @example
152
159
  * ```ts
@@ -299,8 +306,42 @@ class SolanaAdapter {
299
306
  * @param options - Slippage protection. By default the SDK quotes the net payout these shares should return
300
307
  * from the vault's current state and passes that quote, lowered by 50 bps,
301
308
  * as the floor to the program's checked instruction. See {@link ISolanaRedeemOptions}.
309
+ *
310
+ * **On a vault with a withdrawal queue**, holders cannot redeem directly:
311
+ * request with {@link SolanaAdapter.vaultRequestRedeem}, then claim here with
312
+ * `options.request` once the cooldown has run. The claim settles at the share
313
+ * price of that moment, net of the withdrawal fee, held to the floor set at
314
+ * request time, and pays the request's recipient; `redeemShares` and
315
+ * `vaultAddress` are then ignored, and `slippageBps` / `minAssetsOut` must
316
+ * be left unset. Without `request`, a
317
+ * queued vault is refused before signing.
318
+ * @returns The confirmed transaction's signature.
319
+ * @throws {@link AugustValidationError} for bad input, for a queued vault
320
+ * without `options.request`, or for a request the wallet cannot claim yet.
321
+ * @example
322
+ * ```ts
323
+ * // A vault with a withdrawal queue: claim a ready request.
324
+ * const { pendingRedemptions } = await sdk.getVaultAvailableRedemptions({ vault, wallet });
325
+ * await sdk.solana.vaultRedeem(programId, vaultIdl, wallet, 0n, undefined, undefined, {
326
+ * request: pendingRedemptions[0].id,
327
+ * });
328
+ * ```
302
329
  */
303
330
  async vaultRedeem(vaultProgramId, idl, publicKey, redeemShares, sendTransaction, vaultAddress, options) {
331
+ if (options?.request !== undefined) {
332
+ if (options.slippageBps !== undefined ||
333
+ options.minAssetsOut !== undefined) {
334
+ throw new core_1.AugustValidationError('INVALID_INPUT', 'vaultRedeem: a withdrawal-queue claim is held to the floor set when the request was made, not one passed here; leave `slippageBps` and `minAssetsOut` unset when passing `request`.');
335
+ }
336
+ return await (0, queue_actions_1.handleSolanaClaimRedeem)({
337
+ provider: this._provider,
338
+ connection: this._connection,
339
+ vaultProgramId: new web3_js_1.PublicKey(vaultProgramId),
340
+ queueProgramId: new web3_js_1.PublicKey(this.getProgramId('withdrawalQueue')),
341
+ wallet: publicKey,
342
+ request: options.request,
343
+ });
344
+ }
304
345
  return await (0, vault_actions_1.handleSolanaRedeem)({
305
346
  network: this._network,
306
347
  provider: this._provider,
@@ -314,22 +355,106 @@ class SolanaAdapter {
314
355
  options,
315
356
  });
316
357
  }
358
+ /**
359
+ * Request a withdrawal from a Solana vault that has a withdrawal queue.
360
+ *
361
+ * With a queue attached, a vault's shares cannot be redeemed directly: the
362
+ * holder escrows them in a request, waits out the queue's cooldown, then
363
+ * claims with {@link SolanaAdapter.vaultRedeem} and `options.request`, or
364
+ * anyone the request permits (a keeper, by default) claims for them. The
365
+ * payout is priced when the request is claimed, not now, but never below the
366
+ * floor set here: by default the current net quote lowered by 50 bps, so a
367
+ * fee rise or mark-down in between makes the claim fail rather than pay
368
+ * less. A pending request
369
+ * can be cancelled at any time with
370
+ * {@link SolanaAdapter.vaultCancelRedeemRequest}, which returns the shares.
371
+ *
372
+ * Signs through the provider's wallet and submits one transaction, which
373
+ * also creates the recipient's deposit-token account when it has none. The
374
+ * holder pays the request account's rent, refunded when it is claimed or
375
+ * cancelled, plus rent for any account created. Use
376
+ * `getVaultAvailableRedemptions` to list requests and see when they can be
377
+ * claimed.
378
+ *
379
+ * RPC: three to four reads, then the send.
380
+ *
381
+ * @param params - Vault, wallet, shares, and optional recipient, finalizer,
382
+ * request id and floor. See {@link ISolanaRequestRedeemParams}.
383
+ * @returns The signature, the request's address (pass it as `request` to
384
+ * claim or cancel) and its id.
385
+ * @throws {@link AugustValidationError} for bad input, a vault without an
386
+ * attached queue, a frozen account or too few shares, before signing.
387
+ * @throws {@link AugustSDKError} when the transaction fails.
388
+ * @example
389
+ * ```ts
390
+ * const { request } = await sdk.solana.vaultRequestRedeem({
391
+ * vault: vaultStateAddress,
392
+ * wallet: wallet.publicKey,
393
+ * amount: 10, // shares, UI units
394
+ * });
395
+ * // ...once the cooldown has run:
396
+ * await sdk.solana.vaultRedeem(programId, vaultIdl, wallet.publicKey, 0n, undefined, undefined, { request });
397
+ * ```
398
+ */
399
+ async vaultRequestRedeem(params) {
400
+ return await (0, queue_actions_1.handleSolanaRequestRedeem)({
401
+ provider: this._provider,
402
+ connection: this._connection,
403
+ queueProgramId: new web3_js_1.PublicKey(this.getProgramId('withdrawalQueue')),
404
+ params,
405
+ });
406
+ }
407
+ /**
408
+ * Cancel a pending withdrawal request, returning its shares to the holder.
409
+ *
410
+ * Allowed at any time while the request exists: during the cooldown, after
411
+ * it, past the fulfillment window, and while the vault is paused. Only the
412
+ * holder who made the request may cancel it. Signs through the provider's
413
+ * wallet; the request's rent is refunded to the holder.
414
+ *
415
+ * RPC: three reads, then the send.
416
+ *
417
+ * @param params - The holder and the request address. See
418
+ * {@link ISolanaCancelRedeemRequestParams}.
419
+ * @returns The confirmed transaction's signature.
420
+ * @throws {@link AugustValidationError} for a missing request, or one this
421
+ * wallet did not make, before signing.
422
+ * @throws {@link AugustSDKError} when the transaction fails.
423
+ * @example
424
+ * ```ts
425
+ * await sdk.solana.vaultCancelRedeemRequest({ wallet: wallet.publicKey, request });
426
+ * ```
427
+ */
428
+ async vaultCancelRedeemRequest(params) {
429
+ return await (0, queue_actions_1.handleSolanaCancelRedeemRequest)({
430
+ provider: this._provider,
431
+ connection: this._connection,
432
+ queueProgramId: new web3_js_1.PublicKey(this.getProgramId('withdrawalQueue')),
433
+ params,
434
+ });
435
+ }
317
436
  /**
318
437
  * Canonical program id for a program type on this adapter's network.
319
438
  *
320
- * @param type - Program to look up. Only `'vault'` (august_vault) exists today.
439
+ * @param type - Program to look up: `'vault'` (august_vault) or
440
+ * `'withdrawalQueue'` (august_withdrawal_queue).
321
441
  * @returns The base58 program id.
322
- * @throws {@link AugustValidationError} if the canonical program is not
323
- * deployed on this adapter's network (e.g. `testnet`). Previously an
324
- * unmapped network threw a bare `TypeError`.
442
+ * @throws {@link AugustValidationError} if `type` is not one of the two
443
+ * program types, or the program is not deployed on this adapter's network:
444
+ * neither program on `testnet`, and `'withdrawalQueue'` not yet on
445
+ * `mainnet-beta`.
446
+ * @example
447
+ * ```ts
448
+ * const queueProgram = adapter.getProgramId('withdrawalQueue');
449
+ * ```
325
450
  */
326
451
  getProgramId(type) {
327
- const deployment = (0, constants_1.getDeployedProgramIds)(this._network);
328
- if (!deployment) {
329
- throw new core_1.AugustValidationError('INVALID_INPUT', `No canonical august_vault deployment for Solana network '${this._network}'. ` +
330
- `Deployed networks: ${Object.keys(constants_1.programIds).join(', ')}.`);
452
+ (0, utils_1.assertSolanaProgramType)(type);
453
+ const programId = (0, constants_1.getDeployedProgramIds)(this._network)?.[type];
454
+ if (!programId) {
455
+ throw new core_1.AugustValidationError('INVALID_INPUT', (0, utils_1.undeployedProgramMessage)(type, this._network));
331
456
  }
332
- return deployment[type];
457
+ return programId;
333
458
  }
334
459
  }
335
460
  exports.default = SolanaAdapter;
@@ -59,6 +59,11 @@ export declare function totalAssetsOf(state: {
59
59
  localAum?: unknown;
60
60
  deployedAum?: unknown;
61
61
  }): bigint;
62
+ /**
63
+ * Whether the vault has a share price. Mirrors `SharePriceUndefined`:
64
+ * outstanding shares against no assets has no price in either direction.
65
+ */
66
+ export declare function hasSharePrice(supply: bigint, totalAssets: bigint): boolean;
62
67
  /**
63
68
  * Shares minted for depositing `amount` base units.
64
69
  *
@@ -101,6 +106,12 @@ export declare function assetsForRedeem(input: {
101
106
  * @param feePpm - `VaultState.withdrawalFee`, parts per million.
102
107
  */
103
108
  export declare function withdrawalFee(assets: bigint, feePpm: bigint): bigint;
109
+ /**
110
+ * Refuse a `slippageBps` that is not an integer in `0 .. 10_000`.
111
+ *
112
+ * @throws AugustValidationError when it is out of range or not an integer.
113
+ */
114
+ export declare function validateSlippageBps(slippageBps: number): void;
104
115
  /**
105
116
  * Lower `expected` by `slippageBps` basis points, rounding down.
106
117
  *
@@ -33,9 +33,11 @@ exports.DEFAULT_SLIPPAGE_BPS = exports.DEFAULT_SHARE_OFFSET = void 0;
33
33
  exports.toBigInt = toBigInt;
34
34
  exports.resolveShareOffset = resolveShareOffset;
35
35
  exports.totalAssetsOf = totalAssetsOf;
36
+ exports.hasSharePrice = hasSharePrice;
36
37
  exports.sharesForDeposit = sharesForDeposit;
37
38
  exports.assetsForRedeem = assetsForRedeem;
38
39
  exports.withdrawalFee = withdrawalFee;
40
+ exports.validateSlippageBps = validateSlippageBps;
39
41
  exports.applySlippage = applySlippage;
40
42
  exports.quoteDepositFloor = quoteDepositFloor;
41
43
  exports.quoteRedeemFloor = quoteRedeemFloor;
@@ -93,10 +95,16 @@ function totalAssetsOf(state) {
93
95
  return (toBigInt(state.localAum, 'localAum') +
94
96
  toBigInt(state.deployedAum, 'deployedAum'));
95
97
  }
98
+ /**
99
+ * Whether the vault has a share price. Mirrors `SharePriceUndefined`:
100
+ * outstanding shares against no assets has no price in either direction.
101
+ */
102
+ function hasSharePrice(supply, totalAssets) {
103
+ return totalAssets !== 0n || supply === 0n;
104
+ }
96
105
  function requireSharePrice(supply, totalAssets) {
97
- // Mirrors `SharePriceUndefined`: outstanding shares against no assets has no
98
- // price in either direction, and the program would refuse the instruction.
99
- if (totalAssets === 0n && supply > 0n) {
106
+ // The program would refuse the instruction.
107
+ if (!hasSharePrice(supply, totalAssets)) {
100
108
  throw new core_1.AugustValidationError('INVALID_INPUT', 'This vault holds no assets while shares are outstanding, so it has no share price; deposits and redemptions are refused until the operator recapitalises it.');
101
109
  }
102
110
  }
@@ -151,18 +159,26 @@ function withdrawalFee(assets, feePpm) {
151
159
  return (assets * feePpm + FEE_RATE_DENOMINATOR - 1n) / FEE_RATE_DENOMINATOR;
152
160
  }
153
161
  /**
154
- * Lower `expected` by `slippageBps` basis points, rounding down.
162
+ * Refuse a `slippageBps` that is not an integer in `0 .. 10_000`.
155
163
  *
156
- * @param expected - The quoted output in raw base units.
157
- * @param slippageBps - Integer basis points, `0` to `10_000`.
158
- * @throws AugustValidationError when `slippageBps` is out of range or not an integer.
164
+ * @throws AugustValidationError when it is out of range or not an integer.
159
165
  */
160
- function applySlippage(expected, slippageBps) {
166
+ function validateSlippageBps(slippageBps) {
161
167
  if (!Number.isInteger(slippageBps) ||
162
168
  slippageBps < 0 ||
163
169
  slippageBps > Number(BPS_DENOMINATOR)) {
164
170
  throw new core_1.AugustValidationError('INVALID_INPUT', `slippageBps must be an integer between 0 and 10000, got ${slippageBps}.`);
165
171
  }
172
+ }
173
+ /**
174
+ * Lower `expected` by `slippageBps` basis points, rounding down.
175
+ *
176
+ * @param expected - The quoted output in raw base units.
177
+ * @param slippageBps - Integer basis points, `0` to `10_000`.
178
+ * @throws AugustValidationError when `slippageBps` is out of range or not an integer.
179
+ */
180
+ function applySlippage(expected, slippageBps) {
181
+ validateSlippageBps(slippageBps);
166
182
  return (expected * (BPS_DENOMINATOR - BigInt(slippageBps))) / BPS_DENOMINATOR;
167
183
  }
168
184
  /**
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Write paths for the august_withdrawal_queue program: request a withdrawal,
3
+ * claim (finalize) a ready one, cancel a pending one.
4
+ *
5
+ * Built like the vault's deposit and redeem handlers (`vault.actions.ts`):
6
+ * every check the SDK can make runs before the wallet is asked to sign, every
7
+ * account the transaction needs is created inside it with an idempotent
8
+ * instruction, and failures surface as `AugustValidationError` (bad input or
9
+ * state the caller can fix) or `AugustSDKError` (the transaction failed, with
10
+ * the program's reason and the numeric code).
11
+ */
12
+ import { type AnchorProvider } from '@coral-xyz/anchor';
13
+ import { type Connection, PublicKey } from '@solana/web3.js';
14
+ import type { ISolanaCancelRedeemRequestParams, ISolanaRequestRedeemParams, ISolanaRequestRedeemResult } from './types';
15
+ /** The sentence to append for a queue error the caller can act on, else empty. */
16
+ export declare function queueHint(e: unknown): string;
17
+ /** The request PDA: `["withdrawal_request", queue, owner, request_id as u64 LE]`. */
18
+ export declare function deriveWithdrawalRequestPda(queue: PublicKey, owner: PublicKey, requestId: bigint, queueProgramId: PublicKey): PublicKey;
19
+ /**
20
+ * Escrow shares in a withdrawal request on a vault with a queue attached.
21
+ *
22
+ * Reads the vault state and queue in one call, checks the gate points at the
23
+ * queue, and submits `request_withdrawal` from the holder's share account. The
24
+ * recipient's deposit-token account is created in the same transaction when it
25
+ * has none. Unless `minAssetsOut` is given, the request's floor is the current
26
+ * net quote lowered by `slippageBps`, the floor `vaultRedeem` would use.
27
+ *
28
+ * RPC: one `getMultipleAccountsInfo` (vault state and queue), one
29
+ * `getAccountInfo` for the share mint (decimals for a UI `amount`, supply for
30
+ * the default floor) unless `amount` is raw and `minAssetsOut` is given, one
31
+ * `getParsedTokenAccountsByOwner` for the share account, and one more read for
32
+ * the payout account (the holder's, or another recipient's ATA, which may be
33
+ * off-curve), then the send.
34
+ *
35
+ * @returns The signature, the new request's address and its id.
36
+ * @throws AugustValidationError for bad input, a vault without an attached
37
+ * queue, a frozen account or too few shares, all before signing.
38
+ * @throws AugustSDKError when the transaction fails.
39
+ */
40
+ export declare function handleSolanaRequestRedeem({ provider, connection, queueProgramId, params, }: {
41
+ provider: AnchorProvider;
42
+ connection: Connection;
43
+ queueProgramId: PublicKey;
44
+ params: ISolanaRequestRedeemParams;
45
+ }): Promise<ISolanaRequestRedeemResult>;
46
+ /**
47
+ * Claim a request whose cooldown has run: `finalize_withdrawal`, which redeems
48
+ * the escrowed shares through the vault and pays the request's recipient.
49
+ *
50
+ * Anyone the request permits may claim it: the holder always, and anyone else
51
+ * unless it names a finalizer, in which case only that key. It is refused here,
52
+ * before signing, when the caller is not permitted, the cooldown has not run,
53
+ * or the window has closed; the wall clock stands in for the chain's, so at the
54
+ * boundary the program may still disagree by a slot. The vault's fee-recipient
55
+ * account is created in the same transaction when it has none, and so is the
56
+ * request's payout account when it is the holder's own ATA and has been closed
57
+ * since; any other closed or a frozen payout account is refused before
58
+ * signing, since the claim could only fail.
59
+ *
60
+ * RPC: three reads in turn, each address coming from the account before it
61
+ * (the request, its queue, then the queue's vault together with the payout
62
+ * account), then the send.
63
+ *
64
+ * @throws AugustValidationError for a missing request or one the caller cannot
65
+ * claim yet, before signing.
66
+ * @throws AugustSDKError when the transaction fails, e.g. `NotEnoughLiquidity`
67
+ * while the vault's reserve is deployed; the request stays pending.
68
+ */
69
+ export declare function handleSolanaClaimRedeem({ provider, connection, vaultProgramId, queueProgramId, wallet, request: requestAddress, nowSeconds, }: {
70
+ provider: AnchorProvider;
71
+ connection: Connection;
72
+ vaultProgramId: PublicKey;
73
+ queueProgramId: PublicKey;
74
+ wallet: PublicKey | string;
75
+ request: PublicKey | string;
76
+ /** Unix seconds to check eligibility against; defaults to now. */
77
+ nowSeconds?: number;
78
+ }): Promise<string>;
79
+ /**
80
+ * Cancel a pending request: `cancel_withdrawal` returns its shares to the
81
+ * holder's share account (created in the same transaction when they closed
82
+ * theirs) and closes the request, refunding its rent. Allowed at any time
83
+ * while the request exists, cooldown or not, expired or not, paused or not.
84
+ *
85
+ * RPC: two reads in turn (the request, then its queue), one
86
+ * `getParsedTokenAccountsByOwner`, then the send.
87
+ *
88
+ * @returns The confirmed transaction's signature.
89
+ * @throws AugustValidationError for a missing request or one `wallet` did not
90
+ * make, before signing.
91
+ * @throws AugustSDKError when the transaction fails.
92
+ */
93
+ export declare function handleSolanaCancelRedeemRequest({ provider, connection, queueProgramId, params, }: {
94
+ provider: AnchorProvider;
95
+ connection: Connection;
96
+ queueProgramId: PublicKey;
97
+ params: ISolanaCancelRedeemRequestParams;
98
+ }): Promise<string>;