@perena/vault-sdk 1.0.66 → 1.0.68

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 (4) hide show
  1. package/README.md +104 -1
  2. package/dist/index.d.ts +754 -29
  3. package/dist/index.js +2972 -1892
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -663,6 +663,109 @@ const plan = await client.tx.executeTrancheDeposit.getTx({
663
663
  await client.sendTransaction(payer, plan);
664
664
  ```
665
665
 
666
+ ### Example: async regular-share redemption
667
+
668
+ Regular shares default to synchronous redemption. The curator can set
669
+ `redemptionMode: { asyncOnly: {} }` through `setVaultConfig` (or restore
670
+ `{ synchronous: {} }`). Configure `fulfiller` using the existing role timelock
671
+ before processing requests. Async-only mode blocks direct regular withdrawals,
672
+ including fee-exempt/external variants, and regular-to-tranche share swaps.
673
+ Junior and senior tranche redemption policies are unchanged.
674
+
675
+ ```typescript
676
+ await client.sendTransaction(curator, await client.tx.setVaultConfig.getTx({
677
+ curator: fromWeb3Pk(curator.publicKey),
678
+ vault,
679
+ redemptionMode: { asyncOnly: {} },
680
+ }));
681
+
682
+ await client.sendTransaction(user, await client.tx.requestAsyncWithdraw.getTx({
683
+ user: fromWeb3Pk(user.publicKey),
684
+ vault,
685
+ assetMint,
686
+ queueId: 0,
687
+ shareAmount: 100_000n,
688
+ }));
689
+
690
+ const pending = await client.account.fetchPendingRedemptionQueues(vault);
691
+ // Optional second argument restricts the results to one owner.
692
+
693
+ // Optional: the HW manager locks the current net output-token payout once.
694
+ await client.sendTransaction(hwManager, await client.tx.priceAsyncWithdraw.getTx({
695
+ hwManager: fromWeb3Pk(hwManager.publicKey),
696
+ vault,
697
+ withdrawalQueue: pending[0].publicKey,
698
+ }));
699
+
700
+ await client.sendTransaction(fulfiller, await client.tx.fulfillAsyncWithdraw.getTx({
701
+ signer: fromWeb3Pk(fulfiller.publicKey),
702
+ owner: fromWeb3Pk(user.publicKey),
703
+ vault,
704
+ assetMint,
705
+ queueId: 0,
706
+ }));
707
+ ```
708
+
709
+ Requests escrow shares without changing supply or NAV. Only the configured
710
+ fulfiller can settle regular requests, with no minimum settlement delay.
711
+ Unpriced requests use current NAV, asset prices, and burn fees. The HW manager
712
+ can price a request once, recording `request.outputAmount` in output-token
713
+ atomic units, `pricedTs`, and `feeShareAmount`. A positive `pricedTs` marks a
714
+ locked quote, even when its payout is zero. Pricing uses fresh oracle state and
715
+ regular-share backing (excluding tranches), applies the owner's fee exemption,
716
+ and does not require liquidity, burn shares, reserve assets, or change NAV.
717
+ Repricing is rejected.
718
+
719
+ Priced requests settle the recorded net tokens and fee shares. NAV is debited
720
+ by the locked tokens' value at the current output asset price, so settlement
721
+ still requires fresh oracle state. Current withdrawal limits apply to both
722
+ paths. Settlement is all-or-nothing,
723
+ burns the requested shares, pays the owner's asset ATA, returns surplus escrow
724
+ shares, and refunds queue/escrow rent to the original payer. The builder creates
725
+ missing owner ATAs and resolves the recorded rent payer. Settlement uses the
726
+ vault's local token balance first and pulls only the net payout's shortfall from
727
+ external liquidity. The builder reads the queue fresh and compares its locked
728
+ payout (or a current quote when unpriced) against the live local balance.
729
+ When local funds cover the payout, it omits external
730
+ CPI accounts and lookups. Otherwise it prepares the same single-source external
731
+ resolution as junior queue fulfillment. Explicit CPI refs remain caller-controlled.
732
+ Insufficient combined liquidity leaves the request pending. If liquidity or
733
+ pricing changes after building a local-only transaction, rebuild it to resolve
734
+ any newly required external accounts; the fulfiller does this on its next run.
735
+
736
+ Both share classes share the existing `VaultWithdrawalQueue` layout and the
737
+ 256 queue IDs per owner/vault. `fetchAllWithdrawalQueues` supports vault, owner,
738
+ and input-mint filters; `fetchPendingRedemptionQueues` selects regular shares.
739
+ `WithdrawalQueueService` routes by input mint, so previously accepted requests
740
+ remain fulfillable after switching back to synchronous mode. Service snapshots
741
+ include nullable `outputAmount` and `pricedTs`; fulfillment always refreshes
742
+ the queue before building its instruction.
743
+
744
+ Only the request owner can cancel a regular-share request, and only when chain
745
+ time is **strictly more than 30 days** after `requestTs`, whether priced or
746
+ unpriced. `cancelAsyncWithdraw.getTx({ user, vault, queueId })` recreates a
747
+ missing owner share ATA, returns all escrow shares (including surplus), and
748
+ refunds queue/escrow rent to the recorded payer without charging redemption fees.
749
+ The legacy `cancelJuniorTrancheWithdraw` route enforces the same delay for
750
+ regular shares; junior queue cancellation retains its existing behavior.
751
+
752
+ The curator console's **Redemptions** tab shows pending regular-share requests,
753
+ their locked payouts and pricing timestamps, and owner cancellation eligibility.
754
+ **Price all unpriced** packs instructions up to the transaction size limit and
755
+ uses the HW-manager wallet's `signAllTransactions` where supported. Each request
756
+ is priced when its transaction executes; separate transactions are not a single
757
+ atomic snapshot. Failed batches remain pending and can be refreshed and retried.
758
+
759
+ The redemption mode occupies an existing zeroed vault padding byte, preserving
760
+ account size and offsets. Pricing fields reuse three words of queue padding:
761
+ existing queues decode as unpriced, and queue accounts remain 296 bytes including
762
+ the discriminator. No account migration is needed. Deploy the updated program
763
+ and publish a new SDK release, then update and rebuild the backend fulfiller
764
+ with that release (including its package lock) before enabling manager pricing.
765
+ SDK 1.0.67 predates the pricing fields and cannot reliably prepare liquidity
766
+ accounts for a locked payout. Existing config payloads that omit the trailing
767
+ mode option remain valid.
768
+
666
769
  ### Example: junior withdrawal queue
667
770
 
668
771
  ```typescript
@@ -875,7 +978,7 @@ Argument shapes for each builder: [`src/client/builders/args.ts`](src/client/bui
875
978
  For recurring backend work, prefer the services layer over reimplementing
876
979
  discovery logic in your app:
877
980
 
878
- - **`WithdrawalQueueService`** — scan and fulfill eligible junior withdrawal
981
+ - **`WithdrawalQueueService`** — scan and fulfill regular and eligible junior withdrawal
879
982
  queues (`src/services/withdrawalQueueService.ts`)
880
983
  - **`OracleService`** — consensus oracle / asset price updates
881
984
  (`src/services/oracleService.ts`)