@perena/vault-sdk 1.0.55 → 1.0.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -20
- package/dist/browser/nest.d.mts +4 -0
- package/dist/browser/nest.mjs +17 -8
- package/dist/index.d.ts +5270 -4203
- package/dist/index.js +7614 -4867
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -370,6 +370,33 @@ and pass the data fields into the generated CPI method. For example,
|
|
|
370
370
|
`addressSeeds`, it corresponds to `execute_deposit`; with seeds, the builder
|
|
371
371
|
selects `execute_deposit_fee_exempt`.
|
|
372
372
|
|
|
373
|
+
For regular and instant tranche withdrawals, use `getCpiPlan(txArgs)` to resolve
|
|
374
|
+
liquidity and split the requested shares across external positions:
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
const cpis = await client.tx.executeWithdraw.getCpiPlan({
|
|
378
|
+
user: programAuthority,
|
|
379
|
+
vault,
|
|
380
|
+
assetMint,
|
|
381
|
+
shareMint,
|
|
382
|
+
shareAmount: 500_000n,
|
|
383
|
+
addressSeeds,
|
|
384
|
+
});
|
|
385
|
+
// Invoke each entry in order within the same transaction.
|
|
386
|
+
for (const { accounts, data, remainingAccounts, lookupTables } of cpis) {
|
|
387
|
+
// Pass accounts, data, and remainingAccounts to your Rust CPI integration.
|
|
388
|
+
// Include lookupTables in the outer transaction and allow enough compute.
|
|
389
|
+
}
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
`executeTrancheWithdraw.getCpiPlan(...)` has the same behavior for junior and
|
|
393
|
+
senior redemptions. `getIxArgs(txArgs)` returns the resolved arguments for each
|
|
394
|
+
leg; `getIxs(txArgs)` returns serialized vault instructions without ATA creation
|
|
395
|
+
or compute-budget instructions. `getTx(txArgs)` adds those transaction setup
|
|
396
|
+
instructions and combines lookup tables. The synchronous `getIxData(ixArgs)` and
|
|
397
|
+
`getIxAccounts(ixArgs)` helpers describe a single resolved leg; they do not fetch
|
|
398
|
+
balances or split it.
|
|
399
|
+
|
|
373
400
|
### Fee-exempt program integrations
|
|
374
401
|
|
|
375
402
|
The deposit, withdrawal, tranche deposit, tranche withdrawal, and queued junior
|
|
@@ -560,23 +587,26 @@ const plan = await client.tx.executeWithdraw.getTx({
|
|
|
560
587
|
await client.sendTransaction(payer, plan);
|
|
561
588
|
```
|
|
562
589
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
590
|
+
Regular and instant tranche withdrawal builders first count the live vault ATA
|
|
591
|
+
balance, then visit external liquidity slots in index order. Capacity is bounded
|
|
592
|
+
by the vault's deposit and the bank/reserve's available cash, so borrowed
|
|
593
|
+
liquidity is not counted. Kamino capacity also respects withdrawal caps, queued
|
|
594
|
+
redemptions, and cToken rounding. Automatic routing supports supply-only
|
|
595
|
+
Marginfi and Kamino positions.
|
|
596
|
+
|
|
597
|
+
If local cash plus slot 0 cannot fund the redemption, the builder splits the
|
|
598
|
+
requested shares into sequential withdrawal instructions, continuing with slot
|
|
599
|
+
1 and later slots until funded. It accounts for fees and integer rounding after
|
|
600
|
+
each burn, skips empty positions, and rejects the whole plan if aggregate
|
|
601
|
+
liquidity is insufficient. Splitting can slightly change rounding compared with
|
|
602
|
+
a single burn. The instructions belong in one atomic transaction.
|
|
603
|
+
|
|
604
|
+
The builder adds protocol lookup tables and one compute-budget instruction.
|
|
605
|
+
Additional `lookupTables` may be needed for large routes. Solana transaction
|
|
606
|
+
size and compute limits still apply. Capacity is a build-time snapshot; simulate
|
|
607
|
+
before sending and rebuild if balances change. `skipExternalLiquidity: true`
|
|
608
|
+
requires enough local cash, while `externalLiquiditySource: 1` pins routing to
|
|
609
|
+
slot 1 instead of scanning all positions.
|
|
580
610
|
|
|
581
611
|
To supply the external route explicitly instead of relying on auto-detection,
|
|
582
612
|
pass `externalWithdrawIxRefs`, `externalWithdrawAccounts`, and optionally
|
|
@@ -673,9 +703,51 @@ const signature = await client.sendTransaction(payer, plan);
|
|
|
673
703
|
|
|
674
704
|
### Versioned transactions (lookup tables)
|
|
675
705
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
706
|
+
All vault transaction builders include the vault-specific LUT from
|
|
707
|
+
`VAULT_LOOKUP_TABLES` when configured, alongside protocol/caller lookup tables.
|
|
708
|
+
Multi-vault operations include both vaults' tables. `sendTransaction` and
|
|
709
|
+
`simulateTransaction` use v0 messages when the plan contains lookup tables;
|
|
710
|
+
they also apply vault mappings to manually assembled vault instructions.
|
|
711
|
+
|
|
712
|
+
Create or update a vault's table from the repository root:
|
|
713
|
+
|
|
714
|
+
```bash
|
|
715
|
+
pnpm vault-lut prod --vault-id 0 --dry-run
|
|
716
|
+
pnpm vault-lut prod --vault-id 0
|
|
717
|
+
pnpm build:vault-sdk
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
The script defaults to `~/.config/solana/hw-manager-prod.json` as LUT authority
|
|
721
|
+
and rent payer; `--keypair PATH` selects another signer. This signer owns the
|
|
722
|
+
LUT, independently of vault roles. It discovers an existing table for this
|
|
723
|
+
authority/vault or uses the saved mapping, creates a table if absent, and adds
|
|
724
|
+
only missing addresses in batches of 20. It gathers vault PDAs, holding/share
|
|
725
|
+
mints and ATAs, Marginfi withdrawal/health accounts, and Kamino
|
|
726
|
+
obligation/reserve/oracle/farm accounts, including an empty SOL/BTC position.
|
|
727
|
+
`--user KEY` adds user ATAs; `--accounts A,B,...` adds explicit addresses.
|
|
728
|
+
|
|
729
|
+
The mapping is saved in `src/vaultLookupTables.json` as soon as the table is
|
|
730
|
+
created, so an interrupted extension resumes on the next run. Commit this file
|
|
731
|
+
and rebuild/publish the SDK for downstream consumers. Tables are limited to 256
|
|
732
|
+
addresses; setup fails before extension if the table lacks room. Newly added
|
|
733
|
+
entries must be active in a later slot; the CLI waits for that slot.
|
|
734
|
+
|
|
735
|
+
Applications can supply a mapping immediately without waiting for a new SDK
|
|
736
|
+
release:
|
|
737
|
+
|
|
738
|
+
```typescript
|
|
739
|
+
const { client } = createVaultClient("prod", {
|
|
740
|
+
keypair: payer,
|
|
741
|
+
vaultLookupTables: { [vault]: vaultLutAddress },
|
|
742
|
+
});
|
|
743
|
+
const plan = await client.tx.executeWithdraw.getTx(withdrawArgs);
|
|
744
|
+
await client.sendTransaction(payer, plan);
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
Withdrawal `getCpiPlan(...)` and `getIxArgs(...)` also return the vault LUT.
|
|
748
|
+
Single raw `getIx(...)` instructions have no LUT field: use
|
|
749
|
+
`getVaultLookupTables(vault)` or `withVaultLookupTables(plan, programId)` when
|
|
750
|
+
composing outside `VaultClient`. For a custom sender:
|
|
679
751
|
|
|
680
752
|
```typescript
|
|
681
753
|
import { fromKitInstruction, sendVersionedTransaction } from "common";
|
|
@@ -837,3 +909,46 @@ See [`scripts/README.md`](scripts/README.md) for the full command list.
|
|
|
837
909
|
- Public keys use `@solana/kit` `Address` strings in builder args.
|
|
838
910
|
- Convert from web3.js: `fromWeb3Pk(keypair.publicKey)` (from `common`).
|
|
839
911
|
- Amounts in `TxArgs` are `bigint` base units unless noted otherwise.
|
|
912
|
+
|
|
913
|
+
## External liquidity allocation (1.0.57)
|
|
914
|
+
|
|
915
|
+
`ExternalLiquidityIntegrityService` powers the
|
|
916
|
+
`backend-services/vault-external-liquidity` Lambda. For USDC with both protocols
|
|
917
|
+
registered, it targets **35% Marginfi / 65% Kamino SOL/BTC**, excluding the local
|
|
918
|
+
vault buffer. An external rebalance fires outside **30–40% Marginfi / 60–70%
|
|
919
|
+
Kamino** and restores 35/65. Exactly on a boundary remains inside the band.
|
|
920
|
+
`marginfiWeightBps` (default `3500`) and `externalWeightBandBps` (default `500`)
|
|
921
|
+
configure the target and absolute percentage-point tolerance.
|
|
922
|
+
|
|
923
|
+
The existing buffer remains: local USDC worth 1.5% of total vault TVL, or 0.5%
|
|
924
|
+
of each other supported holding, with a 20%-of-target buffer band. Buffer
|
|
925
|
+
replenishment takes priority. A buffer adjustment also distributes remaining
|
|
926
|
+
external funds toward the target weights. Single-protocol holdings continue to
|
|
927
|
+
use that protocol; both initialized, registered positions are required for the
|
|
928
|
+
USDC split. Other configured stablecoins continue to use Marginfi.
|
|
929
|
+
|
|
930
|
+
Allocation uses each live position's supplied balance, including accrued value,
|
|
931
|
+
and the actual vault token balance. Withdrawal capacity also checks bank/reserve
|
|
932
|
+
cash, Kamino withdrawal caps and queued redemptions. Utilization can limit a
|
|
933
|
+
rebalance to a partial transfer; subsequent runs retry if weights remain outside
|
|
934
|
+
the band. Each
|
|
935
|
+
mint's withdrawals and deposits share one atomic transaction and use the vault's
|
|
936
|
+
configured LUT. If a destination rejects a deposit, the whole transaction fails
|
|
937
|
+
and is reported for retry. No transfer is left half-completed.
|
|
938
|
+
|
|
939
|
+
Kamino deposits use `buildKaminoDepositInteraction` and the appended
|
|
940
|
+
`KLEND_DEPOSIT_AND_COLLATERALIZE_V2` CPI. The vault validates the registered
|
|
941
|
+
obligation, vault-owned source ATA, reserve, market, token programs, farms and
|
|
942
|
+
absence of borrowing. Only the hardware manager can deposit. **Upgrade the vault
|
|
943
|
+
program with this CPI support before deploying the Lambda with SDK 1.0.57.**
|
|
944
|
+
Publish the SDK and then rebuild/deploy the backend consumer; changing the local
|
|
945
|
+
package version alone does not update a running Lambda.
|
|
946
|
+
|
|
947
|
+
```sh
|
|
948
|
+
# Simulate all eligible vaults; no transactions are submitted.
|
|
949
|
+
pnpm run-external-liquidity-service prod --dry-run
|
|
950
|
+
|
|
951
|
+
# Explicitly supply the default allocation policy.
|
|
952
|
+
pnpm run-external-liquidity-service prod --dry-run \
|
|
953
|
+
--marginfi-weight-bps 3500 --external-weight-band-bps 500
|
|
954
|
+
```
|
package/dist/browser/nest.d.mts
CHANGED
|
@@ -155,6 +155,8 @@ interface PreparedSquadsTransaction {
|
|
|
155
155
|
transactionIndex: bigint;
|
|
156
156
|
proposalPda: PublicKey;
|
|
157
157
|
vaultTransactionPda: PublicKey;
|
|
158
|
+
/** Failed inner-instruction simulation explicitly allowed by the caller. */
|
|
159
|
+
executionSimulationError?: SquadsProposalExecutionSimulationError;
|
|
158
160
|
}
|
|
159
161
|
type PreparedVaultTransaction = PreparedDirectTransaction | PreparedSquadsTransaction;
|
|
160
162
|
type SquadsSimulationTransactionError = NonNullable<SimulatedTransactionResponse["err"]>;
|
|
@@ -209,6 +211,8 @@ declare function prepareVaultTransaction(args: {
|
|
|
209
211
|
squadsRoutes?: readonly SquadsWalletRouteConfig[];
|
|
210
212
|
/** Skip execution simulation when proposing a transaction that depends on future funding. */
|
|
211
213
|
skipSimulation?: boolean;
|
|
214
|
+
/** Still prepare the proposal if its inner instructions fail simulation; return the failure for display. */
|
|
215
|
+
allowExecutionSimulationFailure?: boolean;
|
|
212
216
|
addressLookupTableAccounts?: AddressLookupTableAccount[];
|
|
213
217
|
/** Temporary signer keys used only in account metas, replaced by Squads PDAs. */
|
|
214
218
|
ephemeralSignerKeys?: readonly PublicKey[];
|
package/dist/browser/nest.mjs
CHANGED
|
@@ -746,14 +746,22 @@ async function prepareVaultTransaction(args) {
|
|
|
746
746
|
);
|
|
747
747
|
}
|
|
748
748
|
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
749
|
+
let executionSimulationError;
|
|
749
750
|
if (!args.skipSimulation) {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
751
|
+
try {
|
|
752
|
+
await simulateSquadsProposalExecution({
|
|
753
|
+
connection,
|
|
754
|
+
feePayer: proposer,
|
|
755
|
+
instructions: instructions2,
|
|
756
|
+
recentBlockhash: blockhash,
|
|
757
|
+
addressLookupTableAccounts: args.addressLookupTableAccounts
|
|
758
|
+
});
|
|
759
|
+
} catch (error) {
|
|
760
|
+
if (!args.allowExecutionSimulationFailure || !(error instanceof SquadsProposalExecutionSimulationError)) {
|
|
761
|
+
throw error;
|
|
762
|
+
}
|
|
763
|
+
executionSimulationError = error;
|
|
764
|
+
}
|
|
757
765
|
}
|
|
758
766
|
const transactionMessage = new TransactionMessage4({
|
|
759
767
|
payerKey: route.vaultPda,
|
|
@@ -794,7 +802,8 @@ async function prepareVaultTransaction(args) {
|
|
|
794
802
|
vaultIndex: route.vaultIndex,
|
|
795
803
|
transactionIndex,
|
|
796
804
|
proposalPda,
|
|
797
|
-
vaultTransactionPda
|
|
805
|
+
vaultTransactionPda,
|
|
806
|
+
...executionSimulationError ? { executionSimulationError } : {}
|
|
798
807
|
};
|
|
799
808
|
}
|
|
800
809
|
|