@elmntl/jlpd-sdk 0.13.4 → 0.13.6
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/dist/jlpd-strategy/hedge-derived.d.ts +25 -32
- package/dist/jlpd-strategy/hedge-derived.js +46 -48
- package/dist/jlpd-strategy/hedge-instructions.d.ts +5 -8
- package/dist/jlpd-strategy/hedge-instructions.js +34 -16
- package/dist/jlpd-strategy/hedge-state.d.ts +6 -7
- package/dist/jlpd-strategy/hedge-state.js +8 -3
- package/dist/jlpd-strategy/settle-yield.d.ts +4 -4
- package/dist/jlpd-strategy/settle-yield.js +3 -3
- package/dist/p-stv-core/accounts.d.ts +18 -2
- package/dist/p-stv-core/accounts.js +27 -2
- package/dist/p-stv-core/constants.d.ts +55 -0
- package/dist/p-stv-core/constants.js +58 -2
- package/dist/p-stv-core/events.js +53 -15
- package/dist/p-stv-core/instructions.d.ts +32 -1
- package/dist/p-stv-core/instructions.js +48 -2
- package/dist/p-stv-core/types.d.ts +74 -1
- package/package.json +1 -1
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* `hedge-state.ts` that answers the same questions the on-chain guards answer:
|
|
6
6
|
* - per-slot LTV, valued on that slot's OWN pinned Fluid oracle (matches `hedge_borrow`'s /
|
|
7
7
|
* `hedge_withdraw_collateral`'s post-op guard basis exactly — see `fluid-view.ts`)
|
|
8
|
-
* - pledged collateral
|
|
9
|
-
* - swap-churn budget remaining (`maxSwapNotionalPerSettle - swapNotionalSinceSettle`)
|
|
8
|
+
* - each slot's pledged collateral vs its `HedgeState.maxPledgedBps` share of total controlled JLP
|
|
10
9
|
*/
|
|
11
10
|
import { PublicKey } from "@solana/web3.js";
|
|
12
11
|
import type { SolanaConnection } from "../common/connection";
|
|
@@ -27,13 +26,13 @@ export declare function resolveDebtManifestAta(state: HedgeState, debtMint: Publ
|
|
|
27
26
|
/** Sum already-decoded per-slot collateral (pure, never throws — for read-only dashboards). */
|
|
28
27
|
export declare function sumPledgedCollateral(perSlotCollateralJlp: bigint[]): bigint;
|
|
29
28
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* before
|
|
34
|
-
*
|
|
29
|
+
* Mirror of `check_pledged_bps`: for each slot i, `collateral_i * 10000 <= maxPledgedBps[i] *
|
|
30
|
+
* (vaultJlpFree + Σ pledged)`. `perSlotCollateralJlp` is indexed BY SLOT (0 for a disabled/absent
|
|
31
|
+
* slot). Returns total pledged; throws on the first slot over its bps share. For DRIVER preflight
|
|
32
|
+
* (reject before a tx that would revert); dashboards should use `sumPledgedCollateral` instead so an
|
|
33
|
+
* (unexpected) over-cap reading still renders.
|
|
35
34
|
*/
|
|
36
|
-
export declare function
|
|
35
|
+
export declare function checkPledgedBps(perSlotCollateralJlp: bigint[], maxPledgedBps: number[], vaultJlpFree: bigint): bigint;
|
|
37
36
|
/**
|
|
38
37
|
* `hedge_repay` repay-all sentinel (u64::MAX) — the only mode that guarantees `debt == 0`.
|
|
39
38
|
* Fund the debt ATA to the on-chain budget (ceiled reading + 0.1% + 2 units) and crank the
|
|
@@ -70,18 +69,6 @@ export declare function isPartialRepayAcceptable(xNative: bigint, netRawDebt: bi
|
|
|
70
69
|
* use the repay-all sentinel instead).
|
|
71
70
|
*/
|
|
72
71
|
export declare function maxPartialRepayNative(netRawDebt: bigint, debtDecimals: number, borrowExPrice: bigint): bigint;
|
|
73
|
-
/**
|
|
74
|
-
* Swap-churn budget remaining before the next `settle_yield` resets the accumulator — mirrors
|
|
75
|
-
* `HedgeState.maxSwapNotionalPerSettle - HedgeState.swapNotionalSinceSettle` (USD, 6-dec),
|
|
76
|
-
* floored at 0 (the accumulator should never on-chain exceed the cap, but this stays
|
|
77
|
-
* fail-safe against a stale/racing read).
|
|
78
|
-
*/
|
|
79
|
-
export declare function churnBudgetRemainingUsd(state: Pick<HedgeState, "maxSwapNotionalPerSettle" | "swapNotionalSinceSettle">): bigint;
|
|
80
|
-
/**
|
|
81
|
-
* `HedgeState.maxPledgedCollateralJlp` as a bigint — headroom convenience: pass the result of
|
|
82
|
-
* `sumAndCheckPledgedCollateral`'s successful total (or a raw sum) to get remaining pledge room.
|
|
83
|
-
*/
|
|
84
|
-
export declare function pledgeHeadroomJlp(state: Pick<HedgeState, "maxPledgedCollateralJlp">, totalPledgedJlp: bigint): bigint;
|
|
85
72
|
/** One enabled `HedgeState.positions` slot's derived valuation. */
|
|
86
73
|
export interface HedgeSlotDerived {
|
|
87
74
|
slotIndex: number;
|
|
@@ -109,27 +96,33 @@ export declare function fetchHedgeSlotDerived(connection: SolanaConnection, stat
|
|
|
109
96
|
*/
|
|
110
97
|
export declare function fetchAllHedgeSlotsDerived(connection: SolanaConnection, state: HedgeState): Promise<HedgeSlotDerived[]>;
|
|
111
98
|
/**
|
|
112
|
-
* Portfolio-level hedge exposure: total pledged JLP collateral
|
|
113
|
-
* `HedgeState.
|
|
114
|
-
* keyed by the debt mint's base58 — different debt mints are never summed together, since
|
|
99
|
+
* Portfolio-level hedge exposure: total pledged JLP collateral, each slot's pledged SHARE of total
|
|
100
|
+
* controlled JLP (bps, vs `HedgeState.maxPledgedBps`), and per-debt-mint net debt exposure (native
|
|
101
|
+
* units, keyed by the debt mint's base58 — different debt mints are never summed together, since
|
|
115
102
|
* they are different tokens).
|
|
116
103
|
*/
|
|
117
104
|
export interface HedgeExposure {
|
|
118
105
|
/** Σ `collateralJlpNative` across every enabled slot. */
|
|
119
106
|
totalPledgedCollateralJlp: bigint;
|
|
120
|
-
/**
|
|
121
|
-
|
|
107
|
+
/** Per-slot (indexed by slot) pledged share of total controlled JLP (free vault JLP + Σ pledged), bps. */
|
|
108
|
+
pledgedShareBps: number[];
|
|
122
109
|
/**
|
|
123
|
-
*
|
|
124
|
-
* the on-chain guard (`hedge_supply_collateral`
|
|
125
|
-
*
|
|
110
|
+
* True if any slot's share exceeds its `HedgeState.maxPledgedBps[i]` — should never be true given
|
|
111
|
+
* the on-chain admission guard (`hedge_supply_collateral` rejects it every supply), but surfaced
|
|
112
|
+
* rather than thrown so a stale/racing read still renders on a dashboard.
|
|
126
113
|
*/
|
|
127
114
|
pledgeCapExceeded: boolean;
|
|
128
115
|
/** Per-debt-mint (base58) → summed native debt across every slot borrowing that mint. */
|
|
129
116
|
debtByMint: Record<string, bigint>;
|
|
130
|
-
/** Swap-churn budget remaining (USD, 6-dec). */
|
|
131
|
-
churnBudgetRemainingUsd: bigint;
|
|
132
117
|
slots: HedgeSlotDerived[];
|
|
133
118
|
}
|
|
134
|
-
/**
|
|
135
|
-
|
|
119
|
+
/**
|
|
120
|
+
* Compute portfolio-level hedge exposure. `vaultJlpFree` is the config-owned vault JLP ATA balance
|
|
121
|
+
* (base units) — the free-JLP term of the pledge-cap denominator; fetch it alongside the state.
|
|
122
|
+
*
|
|
123
|
+
* NOTE: this reads each position's stored collateral WITHOUT applying the Fluid
|
|
124
|
+
* liquidation-staleness gate (`requireFluidPositionLiquidationCurrent`), so during a
|
|
125
|
+
* liquidation-stale window a slot's collateral (and thus `pledgedShareBps` / `pledgeCapExceeded`)
|
|
126
|
+
* can be phantom. Best-effort for dashboards; the on-chain guards are authoritative.
|
|
127
|
+
*/
|
|
128
|
+
export declare function fetchHedgeExposure(connection: SolanaConnection, state: HedgeState, vaultJlpFree: bigint): Promise<HedgeExposure>;
|
|
@@ -6,22 +6,19 @@
|
|
|
6
6
|
* `hedge-state.ts` that answers the same questions the on-chain guards answer:
|
|
7
7
|
* - per-slot LTV, valued on that slot's OWN pinned Fluid oracle (matches `hedge_borrow`'s /
|
|
8
8
|
* `hedge_withdraw_collateral`'s post-op guard basis exactly — see `fluid-view.ts`)
|
|
9
|
-
* - pledged collateral
|
|
10
|
-
* - swap-churn budget remaining (`maxSwapNotionalPerSettle - swapNotionalSinceSettle`)
|
|
9
|
+
* - each slot's pledged collateral vs its `HedgeState.maxPledgedBps` share of total controlled JLP
|
|
11
10
|
*/
|
|
12
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
12
|
exports.FLUID_MIN_OPERATE_NATIVE = exports.REPAY_ALL_SENTINEL = void 0;
|
|
14
13
|
exports.debtMintDecimals = debtMintDecimals;
|
|
15
14
|
exports.resolveDebtManifestAta = resolveDebtManifestAta;
|
|
16
15
|
exports.sumPledgedCollateral = sumPledgedCollateral;
|
|
17
|
-
exports.
|
|
16
|
+
exports.checkPledgedBps = checkPledgedBps;
|
|
18
17
|
exports.clampRepayAmount = clampRepayAmount;
|
|
19
18
|
exports.fluidMinDebtRaw = fluidMinDebtRaw;
|
|
20
19
|
exports.fluidPartialRepayCreditRaw = fluidPartialRepayCreditRaw;
|
|
21
20
|
exports.isPartialRepayAcceptable = isPartialRepayAcceptable;
|
|
22
21
|
exports.maxPartialRepayNative = maxPartialRepayNative;
|
|
23
|
-
exports.churnBudgetRemainingUsd = churnBudgetRemainingUsd;
|
|
24
|
-
exports.pledgeHeadroomJlp = pledgeHeadroomJlp;
|
|
25
22
|
exports.fetchHedgeSlotDerived = fetchHedgeSlotDerived;
|
|
26
23
|
exports.fetchAllHedgeSlotsDerived = fetchAllHedgeSlotsDerived;
|
|
27
24
|
exports.fetchHedgeExposure = fetchHedgeExposure;
|
|
@@ -73,18 +70,33 @@ function sumPledgedCollateral(perSlotCollateralJlp) {
|
|
|
73
70
|
return total;
|
|
74
71
|
}
|
|
75
72
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* before
|
|
80
|
-
*
|
|
73
|
+
* Mirror of `check_pledged_bps`: for each slot i, `collateral_i * 10000 <= maxPledgedBps[i] *
|
|
74
|
+
* (vaultJlpFree + Σ pledged)`. `perSlotCollateralJlp` is indexed BY SLOT (0 for a disabled/absent
|
|
75
|
+
* slot). Returns total pledged; throws on the first slot over its bps share. For DRIVER preflight
|
|
76
|
+
* (reject before a tx that would revert); dashboards should use `sumPledgedCollateral` instead so an
|
|
77
|
+
* (unexpected) over-cap reading still renders.
|
|
81
78
|
*/
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
79
|
+
function checkPledgedBps(perSlotCollateralJlp, maxPledgedBps, vaultJlpFree) {
|
|
80
|
+
// Mirror the program's fixed [_; MAX_HEDGE_POSITIONS] arrays: validate EVERY slot's bps, so a
|
|
81
|
+
// short array can't skip an out-of-range later entry the way the on-chain check never would.
|
|
82
|
+
if (perSlotCollateralJlp.length !== constants_1.MAX_HEDGE_POSITIONS ||
|
|
83
|
+
maxPledgedBps.length !== constants_1.MAX_HEDGE_POSITIONS) {
|
|
84
|
+
throw new Error(`checkPledgedBps: expected ${constants_1.MAX_HEDGE_POSITIONS} slot entries, got ` +
|
|
85
|
+
`collateral=${perSlotCollateralJlp.length} bps=${maxPledgedBps.length}`);
|
|
86
86
|
}
|
|
87
|
-
|
|
87
|
+
const totalPledged = sumPledgedCollateral(perSlotCollateralJlp);
|
|
88
|
+
const totalControlled = vaultJlpFree + totalPledged;
|
|
89
|
+
for (let i = 0; i < perSlotCollateralJlp.length; i++) {
|
|
90
|
+
const bps = maxPledgedBps[i] ?? 0;
|
|
91
|
+
if (!Number.isInteger(bps) || bps < 0 || bps > 10000) {
|
|
92
|
+
throw new Error(`checkPledgedBps: maxPledgedBps[${i}] out of range: ${bps}`);
|
|
93
|
+
}
|
|
94
|
+
if (perSlotCollateralJlp[i] * 10000n > BigInt(bps) * totalControlled) {
|
|
95
|
+
throw new Error(`checkPledgedBps: slot ${i} pledged ${perSlotCollateralJlp[i]} exceeds ${bps}bps of ` +
|
|
96
|
+
`controlled JLP ${totalControlled}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return totalPledged;
|
|
88
100
|
}
|
|
89
101
|
/**
|
|
90
102
|
* `hedge_repay` repay-all sentinel (u64::MAX) — the only mode that guarantees `debt == 0`.
|
|
@@ -164,27 +176,6 @@ function maxPartialRepayNative(netRawDebt, debtDecimals, borrowExPrice) {
|
|
|
164
176
|
}
|
|
165
177
|
return x >= exports.FLUID_MIN_OPERATE_NATIVE ? x : 0n;
|
|
166
178
|
}
|
|
167
|
-
/**
|
|
168
|
-
* Swap-churn budget remaining before the next `settle_yield` resets the accumulator — mirrors
|
|
169
|
-
* `HedgeState.maxSwapNotionalPerSettle - HedgeState.swapNotionalSinceSettle` (USD, 6-dec),
|
|
170
|
-
* floored at 0 (the accumulator should never on-chain exceed the cap, but this stays
|
|
171
|
-
* fail-safe against a stale/racing read).
|
|
172
|
-
*/
|
|
173
|
-
function churnBudgetRemainingUsd(state) {
|
|
174
|
-
const max = BigInt(state.maxSwapNotionalPerSettle.toString());
|
|
175
|
-
const since = BigInt(state.swapNotionalSinceSettle.toString());
|
|
176
|
-
const remaining = max - since;
|
|
177
|
-
return remaining > 0n ? remaining : 0n;
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* `HedgeState.maxPledgedCollateralJlp` as a bigint — headroom convenience: pass the result of
|
|
181
|
-
* `sumAndCheckPledgedCollateral`'s successful total (or a raw sum) to get remaining pledge room.
|
|
182
|
-
*/
|
|
183
|
-
function pledgeHeadroomJlp(state, totalPledgedJlp) {
|
|
184
|
-
const cap = BigInt(state.maxPledgedCollateralJlp.toString());
|
|
185
|
-
const headroom = cap - totalPledgedJlp;
|
|
186
|
-
return headroom > 0n ? headroom : 0n;
|
|
187
|
-
}
|
|
188
179
|
/**
|
|
189
180
|
* Fetch + value ONE `HedgeState.positions[slotIndex]` slot — the async convenience wrapper
|
|
190
181
|
* matching `hedge_borrow`'s / `hedge_withdraw_collateral`'s post-op LTV guard basis exactly
|
|
@@ -210,22 +201,29 @@ async function fetchAllHedgeSlotsDerived(connection, state) {
|
|
|
210
201
|
const results = await Promise.all(state.positions.map((slot, slotIndex) => (0, hedge_state_1.isHedgePositionSlotDisabled)(slot) ? Promise.resolve(null) : fetchHedgeSlotDerived(connection, state, slotIndex)));
|
|
211
202
|
return results.filter((r) => r !== null);
|
|
212
203
|
}
|
|
213
|
-
/**
|
|
214
|
-
|
|
204
|
+
/**
|
|
205
|
+
* Compute portfolio-level hedge exposure. `vaultJlpFree` is the config-owned vault JLP ATA balance
|
|
206
|
+
* (base units) — the free-JLP term of the pledge-cap denominator; fetch it alongside the state.
|
|
207
|
+
*
|
|
208
|
+
* NOTE: this reads each position's stored collateral WITHOUT applying the Fluid
|
|
209
|
+
* liquidation-staleness gate (`requireFluidPositionLiquidationCurrent`), so during a
|
|
210
|
+
* liquidation-stale window a slot's collateral (and thus `pledgedShareBps` / `pledgeCapExceeded`)
|
|
211
|
+
* can be phantom. Best-effort for dashboards; the on-chain guards are authoritative.
|
|
212
|
+
*/
|
|
213
|
+
async function fetchHedgeExposure(connection, state, vaultJlpFree) {
|
|
215
214
|
const slots = await fetchAllHedgeSlotsDerived(connection, state);
|
|
216
|
-
|
|
217
|
-
const
|
|
215
|
+
// Per-slot collateral indexed BY SLOT (0 for disabled) so it aligns with maxPledgedBps.
|
|
216
|
+
const perSlot = state.positions.map(() => 0n);
|
|
217
|
+
for (const s of slots)
|
|
218
|
+
perSlot[s.slotIndex] = s.collateralJlpNative;
|
|
219
|
+
const totalPledgedCollateralJlp = sumPledgedCollateral(perSlot);
|
|
220
|
+
const totalControlled = vaultJlpFree + totalPledgedCollateralJlp;
|
|
221
|
+
const pledgedShareBps = perSlot.map((c) => totalControlled > 0n ? Number((c * 10000n) / totalControlled) : 0);
|
|
222
|
+
const pledgeCapExceeded = perSlot.some((c, i) => c * 10000n > BigInt(state.maxPledgedBps[i] ?? 0) * totalControlled);
|
|
218
223
|
const debtByMint = {};
|
|
219
224
|
for (const s of slots) {
|
|
220
225
|
const key = s.slot.debtMint.toBase58();
|
|
221
226
|
debtByMint[key] = (debtByMint[key] ?? 0n) + s.debtNative;
|
|
222
227
|
}
|
|
223
|
-
return {
|
|
224
|
-
totalPledgedCollateralJlp,
|
|
225
|
-
pledgeHeadroomJlp: cap - totalPledgedCollateralJlp > 0n ? cap - totalPledgedCollateralJlp : 0n,
|
|
226
|
-
pledgeCapExceeded: totalPledgedCollateralJlp > cap,
|
|
227
|
-
debtByMint,
|
|
228
|
-
churnBudgetRemainingUsd: churnBudgetRemainingUsd(state),
|
|
229
|
-
slots,
|
|
230
|
-
};
|
|
228
|
+
return { totalPledgedCollateralJlp, pledgedShareBps, pledgeCapExceeded, debtByMint, slots };
|
|
231
229
|
}
|
|
@@ -52,10 +52,6 @@ export interface CreateHedgeRepayIxArgs extends HedgeOpAccounts {
|
|
|
52
52
|
/** Debt-mint-native amount REQUESTED to repay — must satisfy the on-chain acceptance predicate
|
|
53
53
|
* (no clamping), or the repay-all sentinel. */
|
|
54
54
|
amount: bigint | BN;
|
|
55
|
-
/** The position's canonical Fluid Tick — `deriveFluidTickPda(vaultId, position.tick)` /
|
|
56
|
-
* `settleTickPdaForPosition(position)` from a fresh position read. The program validates it
|
|
57
|
-
* and rejects a liquidation-stale position outright. */
|
|
58
|
-
fluidTick: PublicKey;
|
|
59
55
|
}
|
|
60
56
|
/** Build the on-chain `hedge_repay` instruction. */
|
|
61
57
|
export declare function createHedgeRepayIx(args: CreateHedgeRepayIxArgs, programId?: PublicKey): TransactionInstruction;
|
|
@@ -188,10 +184,11 @@ export interface InitOrUpdateHedgeStateArgs {
|
|
|
188
184
|
jlWbtcLending?: PublicKey | null;
|
|
189
185
|
/** wETH Earn `lending` rate-source account. `null`/omitted = unchanged. */
|
|
190
186
|
jlWethLending?: PublicKey | null;
|
|
191
|
-
/**
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Per-slot pledged-collateral cap, bps of total controlled JLP, one entry per positions slot
|
|
189
|
+
* (each 0..=10000, Σ 0..=10000). `null`/omitted = unchanged (init: [0,0,0,0] = fail-closed).
|
|
190
|
+
*/
|
|
191
|
+
maxPledgedBps?: number[] | null;
|
|
195
192
|
/** Pair-native per-position LTV cap, bps (0..=`MAX_HEDGE_LTV_BPS`). `null`/omitted = unchanged (init: 0). */
|
|
196
193
|
maxLtvBps?: number | null;
|
|
197
194
|
/** Hedge master switch. `null`/omitted = unchanged (init: false). */
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.HedgeManifestRole = void 0;
|
|
7
4
|
exports.createHedgeSupplyCollateralIx = createHedgeSupplyCollateralIx;
|
|
@@ -12,7 +9,6 @@ exports.createHedgeSwapIx = createHedgeSwapIx;
|
|
|
12
9
|
exports.createInitOrUpdateHedgeStateIx = createInitOrUpdateHedgeStateIx;
|
|
13
10
|
const web3_js_1 = require("@solana/web3.js");
|
|
14
11
|
const spl_token_1 = require("@solana/spl-token");
|
|
15
|
-
const bn_js_1 = __importDefault(require("bn.js"));
|
|
16
12
|
const buffer_1 = require("../common/buffer");
|
|
17
13
|
const constants_1 = require("./constants");
|
|
18
14
|
function toBigIntAmount(v) {
|
|
@@ -67,11 +63,7 @@ function createHedgeBorrowIx(args, programId = constants_1.PROGRAM_ID) {
|
|
|
67
63
|
/** Build the on-chain `hedge_repay` instruction. */
|
|
68
64
|
function createHedgeRepayIx(args, programId = constants_1.PROGRAM_ID) {
|
|
69
65
|
const data = serializeSlotIndexAmountParams(constants_1.IX_HEDGE_REPAY, args.slotIndex, args.amount);
|
|
70
|
-
|
|
71
|
-
// The Accounts struct inserts fluid_tick between vault_state (index 11) and
|
|
72
|
-
// jup_lend_borrow_program — mirror it exactly.
|
|
73
|
-
keys.splice(12, 0, { pubkey: args.fluidTick, isSigner: false, isWritable: false });
|
|
74
|
-
return new web3_js_1.TransactionInstruction({ keys, programId, data });
|
|
66
|
+
return new web3_js_1.TransactionInstruction({ keys: buildHedgeOpKeys(args), programId, data });
|
|
75
67
|
}
|
|
76
68
|
/** Build the on-chain `hedge_withdraw_collateral` instruction. */
|
|
77
69
|
function createHedgeWithdrawCollateralIx(args, programId = constants_1.PROGRAM_ID) {
|
|
@@ -96,7 +88,7 @@ function createHedgeWithdrawCollateralIx(args, programId = constants_1.PROGRAM_I
|
|
|
96
88
|
// 0. manager [signer]
|
|
97
89
|
// 1. config [] JLPD Config PDA (read-only — this ix never writes it)
|
|
98
90
|
// 2. manager_role [] ManagerRole PDA
|
|
99
|
-
// 3. hedge_state [
|
|
91
|
+
// 3. hedge_state [] HedgeState PDA (read-only — this ix never writes it)
|
|
100
92
|
// 4. src_ata [writable] == manifest_role_ata(hedge_state, params.src_role)
|
|
101
93
|
// 5. dst_ata [writable] == manifest_role_ata(hedge_state, params.dst_role)
|
|
102
94
|
// 6. price_oracle_src [] Doves oracle for src_role, if Doves-priced; else unused
|
|
@@ -164,7 +156,7 @@ function createHedgeSwapIx(args, programId = constants_1.PROGRAM_ID) {
|
|
|
164
156
|
{ pubkey: manager, isSigner: true, isWritable: false },
|
|
165
157
|
{ pubkey: config, isSigner: false, isWritable: false },
|
|
166
158
|
{ pubkey: managerRole, isSigner: false, isWritable: false },
|
|
167
|
-
{ pubkey: hedgeState, isSigner: false, isWritable:
|
|
159
|
+
{ pubkey: hedgeState, isSigner: false, isWritable: false },
|
|
168
160
|
{ pubkey: srcAta, isSigner: false, isWritable: true },
|
|
169
161
|
{ pubkey: dstAta, isSigner: false, isWritable: true },
|
|
170
162
|
{ pubkey: priceOracleSrc, isSigner: false, isWritable: false },
|
|
@@ -210,8 +202,7 @@ function createHedgeSwapIx(args, programId = constants_1.PROGRAM_ID) {
|
|
|
210
202
|
// jl_jupusd / jl_wbtc / jl_weth: Option<Pubkey> (3) — Earn fToken ATAs
|
|
211
203
|
// jl_jupusd_mint / jl_wbtc_mint / jl_weth_mint: Option<Pubkey> (3) — admin-set fToken mints
|
|
212
204
|
// jl_jupusd_lending / jl_wbtc_lending / jl_weth_lending: Option<Pubkey> (3) — Earn rate sources
|
|
213
|
-
//
|
|
214
|
-
// max_swap_notional_per_settle: Option<u64>
|
|
205
|
+
// max_pledged_bps: Option<[u16; MAX_HEDGE_POSITIONS(4)]>
|
|
215
206
|
// max_ltv_bps: Option<u16>
|
|
216
207
|
// enabled: Option<bool>
|
|
217
208
|
// ---------------------------------------------------------------------------
|
|
@@ -244,6 +235,33 @@ function writeOptionalBool(parts, value) {
|
|
|
244
235
|
parts.push(0x00);
|
|
245
236
|
}
|
|
246
237
|
}
|
|
238
|
+
/** Serialize `Option<[u16; n]>` — 1-byte tag, then n u16 LE if `Some` (a fixed-size Rust array, no
|
|
239
|
+
* length prefix). Mirrors the program's `validate_max_pledged_bps`: throws if the array is the
|
|
240
|
+
* wrong length, an entry exceeds 10000 (100%), or the entries sum above 10000 — so a bad governance
|
|
241
|
+
* proposal fails locally instead of on-chain. */
|
|
242
|
+
function writeOptionalU16Array(parts, value, n) {
|
|
243
|
+
if (value == null) {
|
|
244
|
+
parts.push(0x00);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (value.length !== n) {
|
|
248
|
+
throw new RangeError(`maxPledgedBps must have exactly ${n} entries, got ${value.length}`);
|
|
249
|
+
}
|
|
250
|
+
let sum = 0;
|
|
251
|
+
for (const v of value) {
|
|
252
|
+
if (!Number.isInteger(v) || v < 0 || v > 10000) {
|
|
253
|
+
throw new RangeError(`maxPledgedBps entry must be an integer in 0..=10000, got: ${v}`);
|
|
254
|
+
}
|
|
255
|
+
sum += v;
|
|
256
|
+
}
|
|
257
|
+
if (sum > 10000) {
|
|
258
|
+
throw new RangeError(`maxPledgedBps entries sum to ${sum}, exceeds 10000 (100%)`);
|
|
259
|
+
}
|
|
260
|
+
parts.push(0x01);
|
|
261
|
+
for (const v of value) {
|
|
262
|
+
parts.push(v & 0xff, (v >> 8) & 0xff);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
247
265
|
/**
|
|
248
266
|
* Build the on-chain `init_or_update_hedge_state` instruction (provisions/updates the singleton
|
|
249
267
|
* `HedgeState` PDA). See this section's module doc comment above for the full account list and
|
|
@@ -282,9 +300,9 @@ function createInitOrUpdateHedgeStateIx(args, programId = constants_1.PROGRAM_ID
|
|
|
282
300
|
(0, buffer_1.writeOptionalPubkey)(parts, args.jlJupusdLending ?? null);
|
|
283
301
|
(0, buffer_1.writeOptionalPubkey)(parts, args.jlWbtcLending ?? null);
|
|
284
302
|
(0, buffer_1.writeOptionalPubkey)(parts, args.jlWethLending ?? null);
|
|
285
|
-
// Guards.
|
|
286
|
-
|
|
287
|
-
(
|
|
303
|
+
// Guards. max_pledged_bps: Option<[u16; MAX_HEDGE_POSITIONS]> (1-byte tag + 4*u16 LE if Some),
|
|
304
|
+
// then max_ltv_bps: Option<u16>, then enabled: Option<bool>.
|
|
305
|
+
writeOptionalU16Array(parts, args.maxPledgedBps ?? null, constants_1.MAX_HEDGE_POSITIONS);
|
|
288
306
|
(0, buffer_1.writeOptionalU16)(parts, args.maxLtvBps ?? null);
|
|
289
307
|
writeOptionalBool(parts, args.enabled ?? null);
|
|
290
308
|
const data = Buffer.from(parts);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { PublicKey } from "@solana/web3.js";
|
|
2
|
-
import BN from "bn.js";
|
|
3
2
|
import type { SolanaConnection } from "../common/connection";
|
|
4
3
|
/**
|
|
5
4
|
* One Fluid borrow position: the position NFT, that vault's pinned
|
|
@@ -55,12 +54,12 @@ export interface HedgeState {
|
|
|
55
54
|
jlWbtcLending: PublicKey;
|
|
56
55
|
/** Canonical `lending` account for the wETH pool (disabled until `jlWethMint` is set). */
|
|
57
56
|
jlWethLending: PublicKey;
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Per-slot pledged-collateral cap, bps of total controlled JLP (one entry per positions slot,
|
|
59
|
+
* each 0..=10000). Lives in the reserved tail at bytes [1120..1128]. Replaces the removed absolute
|
|
60
|
+
* pledge cap + the swap-churn cap/accumulator (bytes [1088..1112] are now reserved, unread).
|
|
61
|
+
*/
|
|
62
|
+
maxPledgedBps: number[];
|
|
64
63
|
/** Liquidation-probability cap in basis points, valued on each position's own pinned Fluid oracle. */
|
|
65
64
|
maxLtvBps: number;
|
|
66
65
|
/** Hedge switch bitfield; bit 0 (`HEDGE_FLAG_ENABLED`) is the master switch. */
|
|
@@ -84,9 +84,14 @@ function deserializeHedgeState(data) {
|
|
|
84
84
|
jlJupusdLending: (0, buffer_1.readPubkey)(data, afterPositions + 352),
|
|
85
85
|
jlWbtcLending: (0, buffer_1.readPubkey)(data, afterPositions + 384),
|
|
86
86
|
jlWethLending: (0, buffer_1.readPubkey)(data, afterPositions + 416),
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
// bytes [1088..1112] (afterPositions + 448..472) are reserved (removed guards), unread.
|
|
88
|
+
// max_pledged_bps: [u16; 4] in the reserved tail at byte 1120 (afterPositions + 480).
|
|
89
|
+
maxPledgedBps: [
|
|
90
|
+
(0, buffer_1.readU16)(data, afterPositions + 480),
|
|
91
|
+
(0, buffer_1.readU16)(data, afterPositions + 482),
|
|
92
|
+
(0, buffer_1.readU16)(data, afterPositions + 484),
|
|
93
|
+
(0, buffer_1.readU16)(data, afterPositions + 486),
|
|
94
|
+
],
|
|
90
95
|
maxLtvBps: (0, buffer_1.readU16)(data, afterPositions + 472),
|
|
91
96
|
flags: (0, buffer_1.readU16)(data, afterPositions + 474),
|
|
92
97
|
version: (0, buffer_1.readU8)(data, afterPositions + 476),
|
|
@@ -8,10 +8,10 @@ export interface CreateSettleYieldIxArgs {
|
|
|
8
8
|
tokenProgram?: PublicKey;
|
|
9
9
|
programId?: PublicKey;
|
|
10
10
|
/**
|
|
11
|
-
* Hedge block accounts (position/vault_state
|
|
12
|
-
* plus the manifest + earn block), appended after the 15 fixed accounts
|
|
13
|
-
* BEFORE `custodyAccounts`. Defaults to `[]` -- for now callers pass
|
|
14
|
-
* while the hedge is disabled.
|
|
11
|
+
* Hedge block accounts (position/vault_state/tick triples per enabled hedge
|
|
12
|
+
* slot, plus the manifest + earn block), appended after the 15 fixed accounts
|
|
13
|
+
* and BEFORE `custodyAccounts`. Defaults to `[]` -- for now callers pass
|
|
14
|
+
* nothing while the hedge is disabled.
|
|
15
15
|
*/
|
|
16
16
|
hedgeAccounts?: AccountMeta[];
|
|
17
17
|
/**
|
|
@@ -17,7 +17,7 @@ const ata_1 = require("../common/ata");
|
|
|
17
17
|
* Accounts (15 total):
|
|
18
18
|
* 0: config (JlpdConfig PDA)
|
|
19
19
|
* 1: manager_role (ManagerRole PDA)
|
|
20
|
-
* 2: hedge_state (HedgeState PDA,
|
|
20
|
+
* 2: hedge_state (HedgeState PDA, read-only)
|
|
21
21
|
* 3: vault_jlp_ata (JLP ATA owned by config)
|
|
22
22
|
* 4: stv_0 (BTC strategy_state, mut)
|
|
23
23
|
* 5: stv_1 (ETH strategy_state, mut)
|
|
@@ -31,7 +31,7 @@ const ata_1 = require("../common/ata");
|
|
|
31
31
|
* 13: jlp_mint_account
|
|
32
32
|
* 14: manager (signer)
|
|
33
33
|
* 15+: remaining_accounts, in this EXACT order:
|
|
34
|
-
* [0 ..
|
|
34
|
+
* [0 .. 3*enabled_hedge_slots) -- (position, vault_state, tick) triples per
|
|
35
35
|
* ENABLED hedge slot, then the manifest + earn block (one account per
|
|
36
36
|
* non-default hedge manifest slot). Empty while the hedge is disabled.
|
|
37
37
|
* [.. remainder) -- the JLP pool custody accounts, in pool `custodies`
|
|
@@ -46,7 +46,7 @@ function buildRawSettleYieldIx(args, programId = constants_1.PROGRAM_ID) {
|
|
|
46
46
|
const keys = [
|
|
47
47
|
{ pubkey: config, isSigner: false, isWritable: true },
|
|
48
48
|
{ pubkey: managerRole, isSigner: false, isWritable: false },
|
|
49
|
-
{ pubkey: hedgeState, isSigner: false, isWritable:
|
|
49
|
+
{ pubkey: hedgeState, isSigner: false, isWritable: false },
|
|
50
50
|
{ pubkey: vaultJlpAta, isSigner: false, isWritable: false },
|
|
51
51
|
{ pubkey: stv0, isSigner: false, isWritable: true },
|
|
52
52
|
{ pubkey: stv1, isSigner: false, isWritable: true },
|
|
@@ -99,11 +99,17 @@ export declare function warmAdminEffective(stv: Stv): PublicKey;
|
|
|
99
99
|
* [ 92.. 96] claimAvailableAfter u32 (unix seconds)
|
|
100
100
|
* [ 96.. 97] bump u8
|
|
101
101
|
* [ 97.. 98] version u8
|
|
102
|
-
* [ 98.. 99] requestFlags u8 (bit0 WR_FLAG_MIGRATE
|
|
102
|
+
* [ 98.. 99] requestFlags u8 (mask 0x0F: bit0 WR_FLAG_MIGRATE,
|
|
103
|
+
* bit1 WR_FLAG_FROZEN, bit2
|
|
104
|
+
* WR_FLAG_RECIPIENT_USER_OK, bit3
|
|
105
|
+
* WR_FLAG_RECIPIENT_COLD_OK)
|
|
103
106
|
* [ 99..104] _padding [u8; 5]
|
|
104
107
|
* [104..112] destVaultId u64 (migrate: dest STV vault_id; withdraw: 0)
|
|
105
108
|
* [112..120] minDestShares u64 (migrate: slippage floor; withdraw: 0)
|
|
106
|
-
* [120..
|
|
109
|
+
* [120..152] claimRecipient Pubkey (withdrawal-freeze co-signed
|
|
110
|
+
* redirect target; [0;32] = pay
|
|
111
|
+
* `user`, today's default)
|
|
112
|
+
* [152..168] _reserved [u8; 16]
|
|
107
113
|
*/
|
|
108
114
|
export declare function deserializeWithdrawRequest(data: Buffer): WithdrawRequest;
|
|
109
115
|
/**
|
|
@@ -111,6 +117,16 @@ export declare function deserializeWithdrawRequest(data: Buffer): WithdrawReques
|
|
|
111
117
|
* Returns `"migrate"` when WR_FLAG_MIGRATE (0x01) is set, else `"withdraw"`.
|
|
112
118
|
*/
|
|
113
119
|
export declare function withdrawRequestKind(wr: WithdrawRequest): "withdraw" | "migrate";
|
|
120
|
+
/** True if `WR_FLAG_FROZEN` is set on `requestFlags`. Mirrors `WithdrawRequest::is_frozen`. */
|
|
121
|
+
export declare function isWithdrawRequestFrozen(wr: WithdrawRequest): boolean;
|
|
122
|
+
/**
|
|
123
|
+
* A redirect is ARMED iff `claimRecipient` is nonzero AND both the user's and
|
|
124
|
+
* cold's approval bits are set on the same stored value. Mirrors the on-chain
|
|
125
|
+
* `WithdrawRequest::is_redirect_armed()` (state/withdraw_request.rs) exactly —
|
|
126
|
+
* when armed, `execute_claim` pays the canonical `ATA(claimRecipient, baseMint)`
|
|
127
|
+
* instead of `user`.
|
|
128
|
+
*/
|
|
129
|
+
export declare function isRedirectArmed(wr: WithdrawRequest): boolean;
|
|
114
130
|
/**
|
|
115
131
|
* DelayedDepositRequest — per-(STV, user, epoch) pending deposit. Total 152 bytes.
|
|
116
132
|
*
|
|
@@ -5,6 +5,8 @@ exports.deserializeStv = deserializeStv;
|
|
|
5
5
|
exports.warmAdminEffective = warmAdminEffective;
|
|
6
6
|
exports.deserializeWithdrawRequest = deserializeWithdrawRequest;
|
|
7
7
|
exports.withdrawRequestKind = withdrawRequestKind;
|
|
8
|
+
exports.isWithdrawRequestFrozen = isWithdrawRequestFrozen;
|
|
9
|
+
exports.isRedirectArmed = isRedirectArmed;
|
|
8
10
|
exports.deserializeDelayedDepositRequest = deserializeDelayedDepositRequest;
|
|
9
11
|
exports.deserializeManagerRole = deserializeManagerRole;
|
|
10
12
|
exports.fetchGlobalConfig = fetchGlobalConfig;
|
|
@@ -209,11 +211,17 @@ function warmAdminEffective(stv) {
|
|
|
209
211
|
* [ 92.. 96] claimAvailableAfter u32 (unix seconds)
|
|
210
212
|
* [ 96.. 97] bump u8
|
|
211
213
|
* [ 97.. 98] version u8
|
|
212
|
-
* [ 98.. 99] requestFlags u8 (bit0 WR_FLAG_MIGRATE
|
|
214
|
+
* [ 98.. 99] requestFlags u8 (mask 0x0F: bit0 WR_FLAG_MIGRATE,
|
|
215
|
+
* bit1 WR_FLAG_FROZEN, bit2
|
|
216
|
+
* WR_FLAG_RECIPIENT_USER_OK, bit3
|
|
217
|
+
* WR_FLAG_RECIPIENT_COLD_OK)
|
|
213
218
|
* [ 99..104] _padding [u8; 5]
|
|
214
219
|
* [104..112] destVaultId u64 (migrate: dest STV vault_id; withdraw: 0)
|
|
215
220
|
* [112..120] minDestShares u64 (migrate: slippage floor; withdraw: 0)
|
|
216
|
-
* [120..
|
|
221
|
+
* [120..152] claimRecipient Pubkey (withdrawal-freeze co-signed
|
|
222
|
+
* redirect target; [0;32] = pay
|
|
223
|
+
* `user`, today's default)
|
|
224
|
+
* [152..168] _reserved [u8; 16]
|
|
217
225
|
*/
|
|
218
226
|
function deserializeWithdrawRequest(data) {
|
|
219
227
|
if (data.length < constants_1.WITHDRAW_REQUEST_SIZE) {
|
|
@@ -236,6 +244,7 @@ function deserializeWithdrawRequest(data) {
|
|
|
236
244
|
requestFlags: (0, buffer_1.readU8)(data, 98),
|
|
237
245
|
destVaultId: (0, buffer_1.readU64)(data, 104),
|
|
238
246
|
minDestShares: (0, buffer_1.readU64)(data, 112),
|
|
247
|
+
claimRecipient: (0, buffer_1.readPubkey)(data, 120),
|
|
239
248
|
};
|
|
240
249
|
}
|
|
241
250
|
/**
|
|
@@ -245,6 +254,22 @@ function deserializeWithdrawRequest(data) {
|
|
|
245
254
|
function withdrawRequestKind(wr) {
|
|
246
255
|
return (wr.requestFlags & 0x01) !== 0 ? "migrate" : "withdraw";
|
|
247
256
|
}
|
|
257
|
+
/** True if `WR_FLAG_FROZEN` is set on `requestFlags`. Mirrors `WithdrawRequest::is_frozen`. */
|
|
258
|
+
function isWithdrawRequestFrozen(wr) {
|
|
259
|
+
return (wr.requestFlags & constants_1.WR_FLAG_FROZEN) !== 0;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* A redirect is ARMED iff `claimRecipient` is nonzero AND both the user's and
|
|
263
|
+
* cold's approval bits are set on the same stored value. Mirrors the on-chain
|
|
264
|
+
* `WithdrawRequest::is_redirect_armed()` (state/withdraw_request.rs) exactly —
|
|
265
|
+
* when armed, `execute_claim` pays the canonical `ATA(claimRecipient, baseMint)`
|
|
266
|
+
* instead of `user`.
|
|
267
|
+
*/
|
|
268
|
+
function isRedirectArmed(wr) {
|
|
269
|
+
return (!wr.claimRecipient.equals(web3_js_1.PublicKey.default) &&
|
|
270
|
+
(wr.requestFlags & constants_1.WR_FLAG_RECIPIENT_USER_OK) !== 0 &&
|
|
271
|
+
(wr.requestFlags & constants_1.WR_FLAG_RECIPIENT_COLD_OK) !== 0);
|
|
272
|
+
}
|
|
248
273
|
/**
|
|
249
274
|
* DelayedDepositRequest — per-(STV, user, epoch) pending deposit. Total 152 bytes.
|
|
250
275
|
*
|
|
@@ -42,6 +42,25 @@ export declare const IX_ACCEPT_VAULT_ADMIN = 20;
|
|
|
42
42
|
* silently freezing a vault. See docs/spec-warm-admin-guardrails.md §4.3.
|
|
43
43
|
*/
|
|
44
44
|
export declare const IX_TRIP_CIRCUIT_BREAKER = 21;
|
|
45
|
+
/**
|
|
46
|
+
* freeze_withdraw_request (disc 0x16 = 22) — incident-response freeze on a
|
|
47
|
+
* single WithdrawRequest. OR-auth: the WR's own `user` (self-freeze) OR a
|
|
48
|
+
* valid manager for the STV. FIXED 4-account ABI (see
|
|
49
|
+
* `createFreezeWithdrawRequestIx`) — pause-exempt.
|
|
50
|
+
*/
|
|
51
|
+
export declare const IX_FREEZE_WITHDRAW_REQUEST = 22;
|
|
52
|
+
/**
|
|
53
|
+
* unfreeze_withdraw_request (disc 0x17 = 23) — clears `WR_FLAG_FROZEN`.
|
|
54
|
+
* `stv.coldAdmin` may always; `stv.warmAdminEffective()` may only when the
|
|
55
|
+
* redirect is ARMED. Pause-exempt.
|
|
56
|
+
*/
|
|
57
|
+
export declare const IX_UNFREEZE_WITHDRAW_REQUEST = 23;
|
|
58
|
+
/**
|
|
59
|
+
* set_claim_recipient (disc 0x18 = 24) — the 2-of-2 COLD-LOCK redirect.
|
|
60
|
+
* Signer is the WR's `user` OR `stv.coldAdmin` (never warm). WR must be
|
|
61
|
+
* frozen. Pause-exempt.
|
|
62
|
+
*/
|
|
63
|
+
export declare const IX_SET_CLAIM_RECIPIENT = 24;
|
|
45
64
|
export declare const EVT_CONFIG_INITIALIZED = 0;
|
|
46
65
|
export declare const EVT_CONFIG_UPDATED = 1;
|
|
47
66
|
export declare const EVT_STV_CREATED = 2;
|
|
@@ -91,6 +110,31 @@ export declare const EVT_CIRCUIT_BREAKER_TRIPPED = 27;
|
|
|
91
110
|
export declare const TRIP_AUTHORITY_KIND_COLD = 0;
|
|
92
111
|
export declare const TRIP_AUTHORITY_KIND_WARM = 1;
|
|
93
112
|
export declare const TRIP_AUTHORITY_KIND_MANAGER = 2;
|
|
113
|
+
/**
|
|
114
|
+
* WithdrawRequestFrozen — emitted by freeze_withdraw_request (disc 22).
|
|
115
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), authority(32), authorityKind(1).
|
|
116
|
+
*/
|
|
117
|
+
export declare const EVT_WITHDRAW_REQUEST_FROZEN = 28;
|
|
118
|
+
/**
|
|
119
|
+
* WithdrawRequestUnfrozen — emitted by unfreeze_withdraw_request (disc 23).
|
|
120
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), authority(32).
|
|
121
|
+
*/
|
|
122
|
+
export declare const EVT_WITHDRAW_REQUEST_UNFROZEN = 29;
|
|
123
|
+
/**
|
|
124
|
+
* ClaimRecipientSet — emitted by set_claim_recipient (disc 24).
|
|
125
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), recipient(32), approverKind(1), armed(1).
|
|
126
|
+
*/
|
|
127
|
+
export declare const EVT_CLAIM_RECIPIENT_SET = 30;
|
|
128
|
+
/**
|
|
129
|
+
* freeze_withdraw_request / WithdrawRequestFrozenEvent authorityKind values.
|
|
130
|
+
*/
|
|
131
|
+
export declare const FREEZE_AUTHORITY_KIND_USER = 0;
|
|
132
|
+
export declare const FREEZE_AUTHORITY_KIND_MANAGER = 1;
|
|
133
|
+
/**
|
|
134
|
+
* set_claim_recipient / ClaimRecipientSetEvent approverKind values.
|
|
135
|
+
*/
|
|
136
|
+
export declare const RECIPIENT_APPROVER_KIND_USER = 0;
|
|
137
|
+
export declare const RECIPIENT_APPROVER_KIND_COLD = 1;
|
|
94
138
|
export declare const FLAG_PAUSED = 1;
|
|
95
139
|
export declare const FLAG_DEPOSITS_DISABLED = 2;
|
|
96
140
|
export declare const FLAG_WITHDRAWALS_DISABLED = 4;
|
|
@@ -131,6 +175,17 @@ export declare const FEE_CAP_BPS = 9900;
|
|
|
131
175
|
export declare const MAX_FEE_BPS = 1000;
|
|
132
176
|
/** WithdrawRequest.request_flags bit 0: 0 = withdraw, 1 = migrate. */
|
|
133
177
|
export declare const WR_FLAG_MIGRATE = 1;
|
|
178
|
+
/**
|
|
179
|
+
* WithdrawRequest.request_flags bit 1: the WR is frozen (incident response).
|
|
180
|
+
* Blocks payout in execute_claim unless a redirect is ARMED (exit-only).
|
|
181
|
+
*/
|
|
182
|
+
export declare const WR_FLAG_FROZEN = 2;
|
|
183
|
+
/** WithdrawRequest.request_flags bit 2: the WR's `user` approved `claimRecipient`. */
|
|
184
|
+
export declare const WR_FLAG_RECIPIENT_USER_OK = 4;
|
|
185
|
+
/** WithdrawRequest.request_flags bit 3: `stv.coldAdmin` approved `claimRecipient`. */
|
|
186
|
+
export declare const WR_FLAG_RECIPIENT_COLD_OK = 8;
|
|
187
|
+
/** All bits outside this mask are reserved and must be zero. */
|
|
188
|
+
export declare const WR_VALID_FLAGS_MASK = 15;
|
|
134
189
|
export declare const GLOBAL_CONFIG_SIZE = 56;
|
|
135
190
|
export declare const STV_SIZE = 664;
|
|
136
191
|
export declare const WITHDRAW_REQUEST_SIZE = 168;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
3
|
+
exports.EVT_FEES_SETTLED = exports.EVT_EPOCH_ADVANCED = exports.EVT_EPOCH_PROCESSED = exports.EVT_WITHDRAWN_FROM_STRATEGY = exports.EVT_DEPOSITED_TO_STRATEGY = exports.EVT_WITHDRAW_CLAIMED = exports.EVT_WITHDRAW_REQUEST_INCREASED = exports.EVT_WITHDRAW_REQUESTED = exports.EVT_DEPOSITED = exports.EVT_STV_UPDATED = exports.EVT_STV_CREATED = exports.EVT_CONFIG_UPDATED = exports.EVT_CONFIG_INITIALIZED = exports.IX_SET_CLAIM_RECIPIENT = exports.IX_UNFREEZE_WITHDRAW_REQUEST = exports.IX_FREEZE_WITHDRAW_REQUEST = exports.IX_TRIP_CIRCUIT_BREAKER = exports.IX_ACCEPT_VAULT_ADMIN = exports.IX_SEED_STV = exports.IX_INSTANT_WITHDRAW = exports.IX_MIGRATE_CANCEL = exports.IX_PROCESS_DELAYED_DEPOSIT = exports.IX_MIGRATE_EXECUTE = exports.IX_MIGRATE_REQUEST = exports.IX_MIGRATE_LEND = exports.IX_OVERRIDE_CLAIM_WITHDRAW = exports.IX_REMOVE_MANAGER = exports.IX_ADD_MANAGER = exports.IX_CLOSE_STV = exports.IX_WITHDRAW_FROM_STRATEGY = exports.IX_DEPOSIT_TO_STRATEGY = exports.IX_PROCESS_EPOCH = exports.IX_CLAIM_WITHDRAW = exports.IX_REQUEST_WITHDRAW = exports.IX_DEPOSIT = exports.IX_INIT_OR_UPDATE_STV = exports.IX_INIT_OR_UPDATE_CONFIG = exports.DISC_MANAGER_ROLE = exports.DISC_DELAYED_DEPOSIT_REQUEST = exports.DISC_WITHDRAW_REQUEST = exports.DISC_STV = exports.DISC_GLOBAL_CONFIG = exports.MANAGER_SEED = exports.DELAYED_DEPOSIT_SEED = exports.MIGRATE_REQUEST_SEED = exports.WITHDRAW_REQUEST_SEED = exports.EV_MINT_SEED = exports.STV_SEED = exports.CONFIG_SEED = exports.PROGRAM_ID = void 0;
|
|
4
|
+
exports.GLOBAL_CONFIG_SIZE = exports.WR_VALID_FLAGS_MASK = exports.WR_FLAG_RECIPIENT_COLD_OK = exports.WR_FLAG_RECIPIENT_USER_OK = exports.WR_FLAG_FROZEN = exports.WR_FLAG_MIGRATE = exports.MAX_FEE_BPS = exports.FEE_CAP_BPS = exports.MAX_STRATEGIES = exports.MAX_CHILD_VAULTS = exports.STALENESS_THRESHOLD = exports.BPS_DENOMINATOR = exports.PPS_DECIMALS = exports.CFG_FLAG_GLOBAL_PAUSED = exports.FLAG_SEEDED = exports.FLAG_BYPASS_MIGRATE_DST_WAITOUT = exports.FLAG_BYPASS_MIGRATE_SRC_WAITOUT = exports.FLAG_DELAYED_DEPOSIT = exports.FLAG_DEPOSIT_FEE_ON_MIGRATE = exports.FLAG_WITHDRAWAL_FEE_ON_MIGRATE = exports.FLAG_BYPASS_WITHDRAW_LIMIT = exports.FLAG_ALLOCATOR = exports.FLAG_REBALANCE_DISABLED = exports.FLAG_WITHDRAWALS_DISABLED = exports.FLAG_DEPOSITS_DISABLED = exports.FLAG_PAUSED = exports.RECIPIENT_APPROVER_KIND_COLD = exports.RECIPIENT_APPROVER_KIND_USER = exports.FREEZE_AUTHORITY_KIND_MANAGER = exports.FREEZE_AUTHORITY_KIND_USER = exports.EVT_CLAIM_RECIPIENT_SET = exports.EVT_WITHDRAW_REQUEST_UNFROZEN = exports.EVT_WITHDRAW_REQUEST_FROZEN = exports.TRIP_AUTHORITY_KIND_MANAGER = exports.TRIP_AUTHORITY_KIND_WARM = exports.TRIP_AUTHORITY_KIND_COLD = exports.EVT_CIRCUIT_BREAKER_TRIPPED = exports.EVT_WARM_ADMIN_SET = exports.EVT_ADMIN_ROTATION_ACCEPTED = exports.EVT_ADMIN_ROTATION_STARTED = exports.EVT_STV_SEEDED = exports.EVT_INSTANT_WITHDRAWN = exports.EVT_DELAYED_DEPOSIT_PROCESSED = exports.EVT_MIGRATE_EXECUTED = exports.EVT_MIGRATE_REQUESTED = exports.EVT_LEND_MIGRATED = exports.EVT_WITHDRAW_OVERRIDE_CLAIMED = exports.EVT_MANAGER_REMOVED = exports.EVT_MANAGER_ADDED = exports.EVT_STV_CLOSED = void 0;
|
|
5
|
+
exports.MANAGER_ROLE_SIZE = exports.DELAYED_DEPOSIT_REQUEST_SIZE = exports.WITHDRAW_REQUEST_SIZE = exports.STV_SIZE = void 0;
|
|
5
6
|
const web3_js_1 = require("@solana/web3.js");
|
|
6
7
|
// ---------------------------------------------------------------------------
|
|
7
8
|
// Program ID
|
|
@@ -68,6 +69,25 @@ exports.IX_ACCEPT_VAULT_ADMIN = 20;
|
|
|
68
69
|
* silently freezing a vault. See docs/spec-warm-admin-guardrails.md §4.3.
|
|
69
70
|
*/
|
|
70
71
|
exports.IX_TRIP_CIRCUIT_BREAKER = 21;
|
|
72
|
+
/**
|
|
73
|
+
* freeze_withdraw_request (disc 0x16 = 22) — incident-response freeze on a
|
|
74
|
+
* single WithdrawRequest. OR-auth: the WR's own `user` (self-freeze) OR a
|
|
75
|
+
* valid manager for the STV. FIXED 4-account ABI (see
|
|
76
|
+
* `createFreezeWithdrawRequestIx`) — pause-exempt.
|
|
77
|
+
*/
|
|
78
|
+
exports.IX_FREEZE_WITHDRAW_REQUEST = 22;
|
|
79
|
+
/**
|
|
80
|
+
* unfreeze_withdraw_request (disc 0x17 = 23) — clears `WR_FLAG_FROZEN`.
|
|
81
|
+
* `stv.coldAdmin` may always; `stv.warmAdminEffective()` may only when the
|
|
82
|
+
* redirect is ARMED. Pause-exempt.
|
|
83
|
+
*/
|
|
84
|
+
exports.IX_UNFREEZE_WITHDRAW_REQUEST = 23;
|
|
85
|
+
/**
|
|
86
|
+
* set_claim_recipient (disc 0x18 = 24) — the 2-of-2 COLD-LOCK redirect.
|
|
87
|
+
* Signer is the WR's `user` OR `stv.coldAdmin` (never warm). WR must be
|
|
88
|
+
* frozen. Pause-exempt.
|
|
89
|
+
*/
|
|
90
|
+
exports.IX_SET_CLAIM_RECIPIENT = 24;
|
|
71
91
|
// ---------------------------------------------------------------------------
|
|
72
92
|
// Event Discriminators (1-byte)
|
|
73
93
|
// ---------------------------------------------------------------------------
|
|
@@ -120,6 +140,31 @@ exports.EVT_CIRCUIT_BREAKER_TRIPPED = 27;
|
|
|
120
140
|
exports.TRIP_AUTHORITY_KIND_COLD = 0;
|
|
121
141
|
exports.TRIP_AUTHORITY_KIND_WARM = 1;
|
|
122
142
|
exports.TRIP_AUTHORITY_KIND_MANAGER = 2;
|
|
143
|
+
/**
|
|
144
|
+
* WithdrawRequestFrozen — emitted by freeze_withdraw_request (disc 22).
|
|
145
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), authority(32), authorityKind(1).
|
|
146
|
+
*/
|
|
147
|
+
exports.EVT_WITHDRAW_REQUEST_FROZEN = 28;
|
|
148
|
+
/**
|
|
149
|
+
* WithdrawRequestUnfrozen — emitted by unfreeze_withdraw_request (disc 23).
|
|
150
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), authority(32).
|
|
151
|
+
*/
|
|
152
|
+
exports.EVT_WITHDRAW_REQUEST_UNFROZEN = 29;
|
|
153
|
+
/**
|
|
154
|
+
* ClaimRecipientSet — emitted by set_claim_recipient (disc 24).
|
|
155
|
+
* Fields: wr(32), stv(32), user(32), epochId(4), recipient(32), approverKind(1), armed(1).
|
|
156
|
+
*/
|
|
157
|
+
exports.EVT_CLAIM_RECIPIENT_SET = 30;
|
|
158
|
+
/**
|
|
159
|
+
* freeze_withdraw_request / WithdrawRequestFrozenEvent authorityKind values.
|
|
160
|
+
*/
|
|
161
|
+
exports.FREEZE_AUTHORITY_KIND_USER = 0;
|
|
162
|
+
exports.FREEZE_AUTHORITY_KIND_MANAGER = 1;
|
|
163
|
+
/**
|
|
164
|
+
* set_claim_recipient / ClaimRecipientSetEvent approverKind values.
|
|
165
|
+
*/
|
|
166
|
+
exports.RECIPIENT_APPROVER_KIND_USER = 0;
|
|
167
|
+
exports.RECIPIENT_APPROVER_KIND_COLD = 1;
|
|
123
168
|
// ---------------------------------------------------------------------------
|
|
124
169
|
// Vault Flags
|
|
125
170
|
// ---------------------------------------------------------------------------
|
|
@@ -171,6 +216,17 @@ exports.FEE_CAP_BPS = 9900;
|
|
|
171
216
|
exports.MAX_FEE_BPS = 1000;
|
|
172
217
|
/** WithdrawRequest.request_flags bit 0: 0 = withdraw, 1 = migrate. */
|
|
173
218
|
exports.WR_FLAG_MIGRATE = 0x01;
|
|
219
|
+
/**
|
|
220
|
+
* WithdrawRequest.request_flags bit 1: the WR is frozen (incident response).
|
|
221
|
+
* Blocks payout in execute_claim unless a redirect is ARMED (exit-only).
|
|
222
|
+
*/
|
|
223
|
+
exports.WR_FLAG_FROZEN = 0x02;
|
|
224
|
+
/** WithdrawRequest.request_flags bit 2: the WR's `user` approved `claimRecipient`. */
|
|
225
|
+
exports.WR_FLAG_RECIPIENT_USER_OK = 0x04;
|
|
226
|
+
/** WithdrawRequest.request_flags bit 3: `stv.coldAdmin` approved `claimRecipient`. */
|
|
227
|
+
exports.WR_FLAG_RECIPIENT_COLD_OK = 0x08;
|
|
228
|
+
/** All bits outside this mask are reserved and must be zero. */
|
|
229
|
+
exports.WR_VALID_FLAGS_MASK = 0x0f;
|
|
174
230
|
// ---------------------------------------------------------------------------
|
|
175
231
|
// Account Sizes
|
|
176
232
|
// ---------------------------------------------------------------------------
|
|
@@ -59,12 +59,14 @@ function parseEventsFromLogs(logs, programId = constants_1.PROGRAM_ID) {
|
|
|
59
59
|
* [41..49] amount | [49..57] sharesMinted | [57..65] depositFeeShares |
|
|
60
60
|
* [65..73] pps
|
|
61
61
|
* WithdrawRequested [0..1] disc | [1..9] vaultId | [9..41] user |
|
|
62
|
-
* [41..49] shares | [49..53] epochId
|
|
62
|
+
* [41..49] shares | [49..53] epochId | [53..85] wr
|
|
63
63
|
* WithdrawRequestIncreased [0..1] disc | [1..9] vaultId | [9..41] user |
|
|
64
64
|
* [41..49] additionalShares | [49..57] totalShares |
|
|
65
|
-
* [57..61] epochId
|
|
65
|
+
* [57..61] epochId | [61..93] wr
|
|
66
66
|
* WithdrawClaimed [0..1] disc | [1..9] vaultId | [9..41] user |
|
|
67
|
-
* [41..49] shares | [49..57] baseAmount | [57..
|
|
67
|
+
* [41..49] shares | [49..57] baseAmount | [57..65] withdrawalFeeBase |
|
|
68
|
+
* [65..69] epochId | [69..101] wr | [101..133] recipient |
|
|
69
|
+
* [133..165] destination
|
|
68
70
|
* DepositedToStrategy [0..1] disc | [1..9] vaultId | [9..41] strategy |
|
|
69
71
|
* [41..49] amount | [49..57] sharesReceived
|
|
70
72
|
* WithdrawnFromStrategy [0..1] disc | [1..9] vaultId | [9..41] strategy |
|
|
@@ -117,21 +119,28 @@ function parseEventBuffer(data) {
|
|
|
117
119
|
depositFeeShares: (0, buffer_1.readU64)(data, 57), pps: (0, buffer_1.readU64)(data, 65),
|
|
118
120
|
} : null;
|
|
119
121
|
case constants_1.EVT_WITHDRAW_REQUESTED:
|
|
120
|
-
|
|
122
|
+
// Rust: vault_id(8), user(32), shares(8), epoch_id(4), wr(32) — wr appended (withdrawal-freeze feature).
|
|
123
|
+
return data.length >= 85 ? {
|
|
121
124
|
name: "WithdrawRequested", vaultId: (0, buffer_1.readU64)(data, 1), user: (0, buffer_1.readPubkey)(data, 9),
|
|
122
|
-
shares: (0, buffer_1.readU64)(data, 41), epochId: (0, buffer_1.readU32)(data, 49),
|
|
125
|
+
shares: (0, buffer_1.readU64)(data, 41), epochId: (0, buffer_1.readU32)(data, 49), wr: (0, buffer_1.readPubkey)(data, 53),
|
|
123
126
|
} : null;
|
|
124
127
|
case constants_1.EVT_WITHDRAW_REQUEST_INCREASED:
|
|
125
|
-
|
|
128
|
+
// Rust: vault_id(8), user(32), additional_shares(8), total_shares(8), epoch_id(4), wr(32) — wr appended.
|
|
129
|
+
return data.length >= 93 ? {
|
|
126
130
|
name: "WithdrawRequestIncreased", vaultId: (0, buffer_1.readU64)(data, 1), user: (0, buffer_1.readPubkey)(data, 9),
|
|
127
131
|
additionalShares: (0, buffer_1.readU64)(data, 41), totalShares: (0, buffer_1.readU64)(data, 49), epochId: (0, buffer_1.readU32)(data, 57),
|
|
132
|
+
wr: (0, buffer_1.readPubkey)(data, 61),
|
|
128
133
|
} : null;
|
|
129
134
|
case constants_1.EVT_WITHDRAW_CLAIMED:
|
|
130
|
-
// Rust: vault_id(8), user(32), shares(8), net_base(8), withdrawal_fee_base(8), epoch_id(4)
|
|
131
|
-
|
|
135
|
+
// Rust: vault_id(8), user(32), shares(8), net_base(8), withdrawal_fee_base(8), epoch_id(4),
|
|
136
|
+
// wr(32), recipient(32), destination(32) — wr/recipient/destination appended
|
|
137
|
+
// (withdrawal-freeze feature). recipient/destination equal user/vaultAta
|
|
138
|
+
// unless the redirect was armed at claim time.
|
|
139
|
+
return data.length >= 165 ? {
|
|
132
140
|
name: "WithdrawClaimed", vaultId: (0, buffer_1.readU64)(data, 1), user: (0, buffer_1.readPubkey)(data, 9),
|
|
133
141
|
shares: (0, buffer_1.readU64)(data, 41), baseAmount: (0, buffer_1.readU64)(data, 49),
|
|
134
142
|
withdrawalFeeBase: (0, buffer_1.readU64)(data, 57), epochId: (0, buffer_1.readU32)(data, 65),
|
|
143
|
+
wr: (0, buffer_1.readPubkey)(data, 69), recipient: (0, buffer_1.readPubkey)(data, 101), destination: (0, buffer_1.readPubkey)(data, 133),
|
|
135
144
|
} : null;
|
|
136
145
|
case constants_1.EVT_DEPOSITED_TO_STRATEGY:
|
|
137
146
|
return data.length >= 57 ? {
|
|
@@ -172,12 +181,15 @@ function parseEventBuffer(data) {
|
|
|
172
181
|
} : null;
|
|
173
182
|
case constants_1.EVT_WITHDRAW_OVERRIDE_CLAIMED:
|
|
174
183
|
// Rust: vault_id(8), manager(32), user(32), shares(8), net_base(8),
|
|
175
|
-
// withdrawal_fee_base(8), epoch_id(4), daily_withdrawn(8), daily_limit(8)
|
|
176
|
-
|
|
184
|
+
// withdrawal_fee_base(8), epoch_id(4), daily_withdrawn(8), daily_limit(8),
|
|
185
|
+
// wr(32), recipient(32), destination(32) — wr/recipient/destination
|
|
186
|
+
// appended (withdrawal-freeze feature).
|
|
187
|
+
return data.length >= 213 ? {
|
|
177
188
|
name: "WithdrawOverrideClaimed", vaultId: (0, buffer_1.readU64)(data, 1), manager: (0, buffer_1.readPubkey)(data, 9),
|
|
178
189
|
user: (0, buffer_1.readPubkey)(data, 41), shares: (0, buffer_1.readU64)(data, 73), baseAmount: (0, buffer_1.readU64)(data, 81),
|
|
179
190
|
withdrawalFeeBase: (0, buffer_1.readU64)(data, 89), epochId: (0, buffer_1.readU32)(data, 97),
|
|
180
191
|
dailyWithdrawnBase: (0, buffer_1.readU64)(data, 101), dailyLimit: (0, buffer_1.readU64)(data, 109),
|
|
192
|
+
wr: (0, buffer_1.readPubkey)(data, 117), recipient: (0, buffer_1.readPubkey)(data, 149), destination: (0, buffer_1.readPubkey)(data, 181),
|
|
181
193
|
} : null;
|
|
182
194
|
case constants_1.EVT_LEND_MIGRATED:
|
|
183
195
|
return data.length >= 89 ? {
|
|
@@ -185,19 +197,21 @@ function parseEventBuffer(data) {
|
|
|
185
197
|
newLendProgram: (0, buffer_1.readPubkey)(data, 41), sharesWithdrawn: (0, buffer_1.readU64)(data, 73), baseMigrated: (0, buffer_1.readU64)(data, 81),
|
|
186
198
|
} : null;
|
|
187
199
|
case constants_1.EVT_MIGRATE_REQUESTED:
|
|
188
|
-
// Rust: src_vault_id(8), dest_vault_id(8), user(32), shares(8), epoch_id(4)
|
|
189
|
-
return data.length >=
|
|
200
|
+
// Rust: src_vault_id(8), dest_vault_id(8), user(32), shares(8), epoch_id(4), wr(32) — wr appended.
|
|
201
|
+
return data.length >= 93 ? {
|
|
190
202
|
name: "MigrateRequested", srcVaultId: (0, buffer_1.readU64)(data, 1), destVaultId: (0, buffer_1.readU64)(data, 9),
|
|
191
203
|
user: (0, buffer_1.readPubkey)(data, 17), shares: (0, buffer_1.readU64)(data, 49), epochId: (0, buffer_1.readU32)(data, 57),
|
|
204
|
+
wr: (0, buffer_1.readPubkey)(data, 61),
|
|
192
205
|
} : null;
|
|
193
206
|
case constants_1.EVT_MIGRATE_EXECUTED:
|
|
194
207
|
// Rust: src_vault_id(8), dst_vault_id(8), user(32), shares_burned(8), base_moved(8),
|
|
195
|
-
// withdrawal_fee_base(8), deposit_fee_base(8), user_dest_shares(8), epoch_id(4)
|
|
196
|
-
|
|
208
|
+
// withdrawal_fee_base(8), deposit_fee_base(8), user_dest_shares(8), epoch_id(4),
|
|
209
|
+
// wr(32) — wr appended.
|
|
210
|
+
return data.length >= 125 ? {
|
|
197
211
|
name: "MigrateExecuted", srcVaultId: (0, buffer_1.readU64)(data, 1), destVaultId: (0, buffer_1.readU64)(data, 9),
|
|
198
212
|
user: (0, buffer_1.readPubkey)(data, 17), sharesBurned: (0, buffer_1.readU64)(data, 49), baseMoved: (0, buffer_1.readU64)(data, 57),
|
|
199
213
|
withdrawalFeeBase: (0, buffer_1.readU64)(data, 65), depositFeeBase: (0, buffer_1.readU64)(data, 73),
|
|
200
|
-
userDestShares: (0, buffer_1.readU64)(data, 81), epochId: (0, buffer_1.readU32)(data, 89),
|
|
214
|
+
userDestShares: (0, buffer_1.readU64)(data, 81), epochId: (0, buffer_1.readU32)(data, 89), wr: (0, buffer_1.readPubkey)(data, 93),
|
|
201
215
|
} : null;
|
|
202
216
|
case constants_1.EVT_DELAYED_DEPOSIT_PROCESSED:
|
|
203
217
|
return data.length >= 77 ? {
|
|
@@ -240,6 +254,30 @@ function parseEventBuffer(data) {
|
|
|
240
254
|
name: "CircuitBreakerTripped", vaultId: (0, buffer_1.readU64)(data, 1), trippedBy: (0, buffer_1.readPubkey)(data, 9),
|
|
241
255
|
authorityKind: data[41],
|
|
242
256
|
} : null;
|
|
257
|
+
case constants_1.EVT_WITHDRAW_REQUEST_FROZEN:
|
|
258
|
+
// Rust: wr(32), stv(32), user(32), epoch_id(4), authority(32), authority_kind(1)
|
|
259
|
+
// → total payload 134 bytes. authorityKind: 0=user, 1=manager
|
|
260
|
+
// (FREEZE_AUTHORITY_KIND_* in constants.ts).
|
|
261
|
+
return data.length >= 134 ? {
|
|
262
|
+
name: "WithdrawRequestFrozen", wr: (0, buffer_1.readPubkey)(data, 1), stv: (0, buffer_1.readPubkey)(data, 33),
|
|
263
|
+
user: (0, buffer_1.readPubkey)(data, 65), epochId: (0, buffer_1.readU32)(data, 97), authority: (0, buffer_1.readPubkey)(data, 101),
|
|
264
|
+
authorityKind: data[133],
|
|
265
|
+
} : null;
|
|
266
|
+
case constants_1.EVT_WITHDRAW_REQUEST_UNFROZEN:
|
|
267
|
+
// Rust: wr(32), stv(32), user(32), epoch_id(4), authority(32) → total payload 133 bytes.
|
|
268
|
+
return data.length >= 133 ? {
|
|
269
|
+
name: "WithdrawRequestUnfrozen", wr: (0, buffer_1.readPubkey)(data, 1), stv: (0, buffer_1.readPubkey)(data, 33),
|
|
270
|
+
user: (0, buffer_1.readPubkey)(data, 65), epochId: (0, buffer_1.readU32)(data, 97), authority: (0, buffer_1.readPubkey)(data, 101),
|
|
271
|
+
} : null;
|
|
272
|
+
case constants_1.EVT_CLAIM_RECIPIENT_SET:
|
|
273
|
+
// Rust: wr(32), stv(32), user(32), epoch_id(4), recipient(32), approver_kind(1), armed(1)
|
|
274
|
+
// → total payload 135 bytes. approverKind: 0=user, 1=cold
|
|
275
|
+
// (RECIPIENT_APPROVER_KIND_* in constants.ts).
|
|
276
|
+
return data.length >= 135 ? {
|
|
277
|
+
name: "ClaimRecipientSet", wr: (0, buffer_1.readPubkey)(data, 1), stv: (0, buffer_1.readPubkey)(data, 33),
|
|
278
|
+
user: (0, buffer_1.readPubkey)(data, 65), epochId: (0, buffer_1.readU32)(data, 97), recipient: (0, buffer_1.readPubkey)(data, 101),
|
|
279
|
+
approverKind: data[133], armed: data[134] !== 0,
|
|
280
|
+
} : null;
|
|
243
281
|
default:
|
|
244
282
|
return null;
|
|
245
283
|
}
|
|
@@ -216,7 +216,7 @@ export interface OverrideClaimWithdrawArgs {
|
|
|
216
216
|
authority: PublicKey;
|
|
217
217
|
/** GlobalConfig PDA — checked for CFG_FLAG_GLOBAL_PAUSED */
|
|
218
218
|
config: PublicKey;
|
|
219
|
-
/** WithdrawRequest owner.
|
|
219
|
+
/** WithdrawRequest owner. Signer — MUST be distinct from `authority` (the on-chain handler rejects authority == user). */
|
|
220
220
|
user: PublicKey;
|
|
221
221
|
stv: PublicKey;
|
|
222
222
|
withdrawRequest: PublicKey;
|
|
@@ -635,3 +635,34 @@ export interface TripCircuitBreakerArgs {
|
|
|
635
635
|
managerRole?: PublicKey;
|
|
636
636
|
}
|
|
637
637
|
export declare function createTripCircuitBreakerIx(args: TripCircuitBreakerArgs, programId?: PublicKey): TransactionInstruction;
|
|
638
|
+
export interface FreezeWithdrawRequestArgs {
|
|
639
|
+
/** Self-freeze: the WR's own `user`. Manager path: any valid manager for the STV. */
|
|
640
|
+
authority: PublicKey;
|
|
641
|
+
stv: PublicKey;
|
|
642
|
+
withdrawRequest: PublicKey;
|
|
643
|
+
/**
|
|
644
|
+
* ManagerRole PDA for (stv, authority). ALWAYS required on the wire (FIXED
|
|
645
|
+
* 4-account ABI) — the handler destructures exactly 4 accounts regardless
|
|
646
|
+
* of path. Pass a real ManagerRole PDA when `authority` is a manager;
|
|
647
|
+
* pass any account (e.g. `findStvManagerRolePda(stv, authority)`) as an
|
|
648
|
+
* unread placeholder when self-freezing (`authority === wr.user`).
|
|
649
|
+
*/
|
|
650
|
+
managerRole: PublicKey;
|
|
651
|
+
}
|
|
652
|
+
export declare function createFreezeWithdrawRequestIx(args: FreezeWithdrawRequestArgs, programId?: PublicKey): TransactionInstruction;
|
|
653
|
+
export interface UnfreezeWithdrawRequestArgs {
|
|
654
|
+
/** stv.coldAdmin (always) or stv.warmAdminEffective() (only when the redirect is armed). */
|
|
655
|
+
authority: PublicKey;
|
|
656
|
+
stv: PublicKey;
|
|
657
|
+
withdrawRequest: PublicKey;
|
|
658
|
+
}
|
|
659
|
+
export declare function createUnfreezeWithdrawRequestIx(args: UnfreezeWithdrawRequestArgs, programId?: PublicKey): TransactionInstruction;
|
|
660
|
+
export interface SetClaimRecipientArgs {
|
|
661
|
+
/** wr.user OR stv.coldAdmin. Never warm — see module doc. */
|
|
662
|
+
authority: PublicKey;
|
|
663
|
+
stv: PublicKey;
|
|
664
|
+
withdrawRequest: PublicKey;
|
|
665
|
+
/** Recipient to propose/approve. `PublicKey.default` resets (cold-only). */
|
|
666
|
+
recipient: PublicKey;
|
|
667
|
+
}
|
|
668
|
+
export declare function createSetClaimRecipientIx(args: SetClaimRecipientArgs, programId?: PublicKey): TransactionInstruction;
|
|
@@ -24,6 +24,9 @@ exports.createInstantWithdrawIx = createInstantWithdrawIx;
|
|
|
24
24
|
exports.createSeedStvIx = createSeedStvIx;
|
|
25
25
|
exports.createAcceptVaultAdminIx = createAcceptVaultAdminIx;
|
|
26
26
|
exports.createTripCircuitBreakerIx = createTripCircuitBreakerIx;
|
|
27
|
+
exports.createFreezeWithdrawRequestIx = createFreezeWithdrawRequestIx;
|
|
28
|
+
exports.createUnfreezeWithdrawRequestIx = createUnfreezeWithdrawRequestIx;
|
|
29
|
+
exports.createSetClaimRecipientIx = createSetClaimRecipientIx;
|
|
27
30
|
const web3_js_1 = require("@solana/web3.js");
|
|
28
31
|
const spl_token_1 = require("@solana/spl-token");
|
|
29
32
|
const buffer_1 = require("../common/buffer");
|
|
@@ -217,13 +220,15 @@ function createOverrideClaimWithdrawIx(args, programId = constants_1.PROGRAM_ID)
|
|
|
217
220
|
const { authority, config, user, stv, withdrawRequest, vaultAta, userBaseAta, feeReceiverBaseAta, baseMint, tokenProgram, remainingAccounts = [], autoUnrouteCount = 0, protocolAumCount = 0, } = args;
|
|
218
221
|
// Data: auto_unroute_count(1) + protocol_aum_count(1) — protocol_aum_count is data[1],
|
|
219
222
|
// so always serialize both bytes (handler reads data[0]/data[1]). Data layout
|
|
220
|
-
// is unchanged by warm-admin-guardrails — only the
|
|
223
|
+
// is unchanged by warm-admin-guardrails / withdrawal-freeze — only the
|
|
224
|
+
// account list (and user's signer flag) changed.
|
|
221
225
|
const data = Buffer.from([constants_1.IX_OVERRIDE_CLAIM_WITHDRAW, autoUnrouteCount & 0xff, protocolAumCount & 0xff]);
|
|
222
226
|
return new web3_js_1.TransactionInstruction({
|
|
223
227
|
keys: [
|
|
224
228
|
{ pubkey: authority, isSigner: true, isWritable: false },
|
|
225
229
|
{ pubkey: config, isSigner: false, isWritable: false },
|
|
226
|
-
|
|
230
|
+
// user is now a required signer, distinct from authority — see module doc.
|
|
231
|
+
{ pubkey: user, isSigner: true, isWritable: true },
|
|
227
232
|
{ pubkey: stv, isSigner: false, isWritable: true },
|
|
228
233
|
{ pubkey: withdrawRequest, isSigner: false, isWritable: true },
|
|
229
234
|
{ pubkey: vaultAta, isSigner: false, isWritable: true },
|
|
@@ -668,3 +673,44 @@ function createTripCircuitBreakerIx(args, programId = constants_1.PROGRAM_ID) {
|
|
|
668
673
|
data: Buffer.from([constants_1.IX_TRIP_CIRCUIT_BREAKER]),
|
|
669
674
|
});
|
|
670
675
|
}
|
|
676
|
+
function createFreezeWithdrawRequestIx(args, programId = constants_1.PROGRAM_ID) {
|
|
677
|
+
const { authority, stv, withdrawRequest, managerRole } = args;
|
|
678
|
+
return new web3_js_1.TransactionInstruction({
|
|
679
|
+
keys: [
|
|
680
|
+
{ pubkey: authority, isSigner: true, isWritable: false },
|
|
681
|
+
{ pubkey: stv, isSigner: false, isWritable: false },
|
|
682
|
+
{ pubkey: withdrawRequest, isSigner: false, isWritable: true },
|
|
683
|
+
{ pubkey: managerRole, isSigner: false, isWritable: false },
|
|
684
|
+
],
|
|
685
|
+
programId,
|
|
686
|
+
data: Buffer.from([constants_1.IX_FREEZE_WITHDRAW_REQUEST]),
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
function createUnfreezeWithdrawRequestIx(args, programId = constants_1.PROGRAM_ID) {
|
|
690
|
+
const { authority, stv, withdrawRequest } = args;
|
|
691
|
+
return new web3_js_1.TransactionInstruction({
|
|
692
|
+
keys: [
|
|
693
|
+
{ pubkey: authority, isSigner: true, isWritable: false },
|
|
694
|
+
{ pubkey: stv, isSigner: false, isWritable: false },
|
|
695
|
+
{ pubkey: withdrawRequest, isSigner: false, isWritable: true },
|
|
696
|
+
],
|
|
697
|
+
programId,
|
|
698
|
+
data: Buffer.from([constants_1.IX_UNFREEZE_WITHDRAW_REQUEST]),
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
function createSetClaimRecipientIx(args, programId = constants_1.PROGRAM_ID) {
|
|
702
|
+
const { authority, stv, withdrawRequest, recipient } = args;
|
|
703
|
+
const data = Buffer.concat([
|
|
704
|
+
Buffer.from([constants_1.IX_SET_CLAIM_RECIPIENT]),
|
|
705
|
+
recipient.toBuffer(),
|
|
706
|
+
]);
|
|
707
|
+
return new web3_js_1.TransactionInstruction({
|
|
708
|
+
keys: [
|
|
709
|
+
{ pubkey: authority, isSigner: true, isWritable: false },
|
|
710
|
+
{ pubkey: stv, isSigner: false, isWritable: false },
|
|
711
|
+
{ pubkey: withdrawRequest, isSigner: false, isWritable: true },
|
|
712
|
+
],
|
|
713
|
+
programId,
|
|
714
|
+
data,
|
|
715
|
+
});
|
|
716
|
+
}
|
|
@@ -125,6 +125,14 @@ export interface WithdrawRequest {
|
|
|
125
125
|
destVaultId: BN;
|
|
126
126
|
/** Migrate kind: minimum dest shares (slippage protection). Withdraw kind: 0. */
|
|
127
127
|
minDestShares: BN;
|
|
128
|
+
/**
|
|
129
|
+
* Incident-response redirect target for `execute_claim` payout (offset 120).
|
|
130
|
+
* `PublicKey.default` (`[0;32]`, the deployed zero state) = pay `user`,
|
|
131
|
+
* exactly today's behavior. A redirect is ARMED iff this is nonzero AND both
|
|
132
|
+
* `WR_FLAG_RECIPIENT_USER_OK` and `WR_FLAG_RECIPIENT_COLD_OK` are set on
|
|
133
|
+
* `requestFlags` — see `isRedirectArmed` (accounts.ts).
|
|
134
|
+
*/
|
|
135
|
+
claimRecipient: PublicKey;
|
|
128
136
|
}
|
|
129
137
|
export interface DelayedDepositRequest {
|
|
130
138
|
stv: PublicKey;
|
|
@@ -183,6 +191,8 @@ export interface WithdrawRequestedEvent {
|
|
|
183
191
|
user: PublicKey;
|
|
184
192
|
shares: BN;
|
|
185
193
|
epochId: number;
|
|
194
|
+
/** WithdrawRequest PDA (appended field, withdrawal-freeze feature). */
|
|
195
|
+
wr: PublicKey;
|
|
186
196
|
}
|
|
187
197
|
export interface WithdrawRequestIncreasedEvent {
|
|
188
198
|
name: "WithdrawRequestIncreased";
|
|
@@ -191,6 +201,8 @@ export interface WithdrawRequestIncreasedEvent {
|
|
|
191
201
|
additionalShares: BN;
|
|
192
202
|
totalShares: BN;
|
|
193
203
|
epochId: number;
|
|
204
|
+
/** WithdrawRequest PDA (appended field, withdrawal-freeze feature). */
|
|
205
|
+
wr: PublicKey;
|
|
194
206
|
}
|
|
195
207
|
export interface WithdrawClaimedEvent {
|
|
196
208
|
name: "WithdrawClaimed";
|
|
@@ -200,6 +212,15 @@ export interface WithdrawClaimedEvent {
|
|
|
200
212
|
baseAmount: BN;
|
|
201
213
|
withdrawalFeeBase: BN;
|
|
202
214
|
epochId: number;
|
|
215
|
+
/** WithdrawRequest PDA (appended field, withdrawal-freeze feature). */
|
|
216
|
+
wr: PublicKey;
|
|
217
|
+
/**
|
|
218
|
+
* Payout target: `user` unless the redirect was ARMED at claim time, in
|
|
219
|
+
* which case this is the stored `claimRecipient`.
|
|
220
|
+
*/
|
|
221
|
+
recipient: PublicKey;
|
|
222
|
+
/** ATA the payout was actually sent to: `ATA(recipient, baseMint)`. */
|
|
223
|
+
destination: PublicKey;
|
|
203
224
|
}
|
|
204
225
|
export interface DepositedToStrategyEvent {
|
|
205
226
|
name: "DepositedToStrategy";
|
|
@@ -268,6 +289,15 @@ export interface WithdrawOverrideClaimedEvent {
|
|
|
268
289
|
epochId: number;
|
|
269
290
|
dailyWithdrawnBase: BN;
|
|
270
291
|
dailyLimit: BN;
|
|
292
|
+
/** WithdrawRequest PDA (appended field, withdrawal-freeze feature). */
|
|
293
|
+
wr: PublicKey;
|
|
294
|
+
/**
|
|
295
|
+
* Payout target: `user` unless the redirect was ARMED at claim time, in
|
|
296
|
+
* which case this is the stored `claimRecipient`.
|
|
297
|
+
*/
|
|
298
|
+
recipient: PublicKey;
|
|
299
|
+
/** ATA the payout was actually sent to: `ATA(recipient, baseMint)`. */
|
|
300
|
+
destination: PublicKey;
|
|
271
301
|
}
|
|
272
302
|
export interface LendMigratedEvent {
|
|
273
303
|
name: "LendMigrated";
|
|
@@ -284,6 +314,8 @@ export interface MigrateRequestedEvent {
|
|
|
284
314
|
user: PublicKey;
|
|
285
315
|
shares: BN;
|
|
286
316
|
epochId: number;
|
|
317
|
+
/** WithdrawRequest (migrate-kind) PDA (appended field, withdrawal-freeze feature). */
|
|
318
|
+
wr: PublicKey;
|
|
287
319
|
}
|
|
288
320
|
export interface MigrateExecutedEvent {
|
|
289
321
|
name: "MigrateExecuted";
|
|
@@ -296,6 +328,8 @@ export interface MigrateExecutedEvent {
|
|
|
296
328
|
depositFeeBase: BN;
|
|
297
329
|
userDestShares: BN;
|
|
298
330
|
epochId: number;
|
|
331
|
+
/** WithdrawRequest (migrate-kind) PDA (appended field, withdrawal-freeze feature). */
|
|
332
|
+
wr: PublicKey;
|
|
299
333
|
}
|
|
300
334
|
export interface DelayedDepositProcessedEvent {
|
|
301
335
|
name: "DelayedDepositProcessed";
|
|
@@ -358,4 +392,43 @@ export interface CircuitBreakerTrippedEvent {
|
|
|
358
392
|
trippedBy: PublicKey;
|
|
359
393
|
authorityKind: number;
|
|
360
394
|
}
|
|
361
|
-
|
|
395
|
+
/**
|
|
396
|
+
* Emitted by `freeze_withdraw_request` (disc 22).
|
|
397
|
+
* `authorityKind`: 0 = user (self-freeze), 1 = manager
|
|
398
|
+
* (see `FREEZE_AUTHORITY_KIND_*` in constants.ts).
|
|
399
|
+
*/
|
|
400
|
+
export interface WithdrawRequestFrozenEvent {
|
|
401
|
+
name: "WithdrawRequestFrozen";
|
|
402
|
+
wr: PublicKey;
|
|
403
|
+
stv: PublicKey;
|
|
404
|
+
user: PublicKey;
|
|
405
|
+
epochId: number;
|
|
406
|
+
authority: PublicKey;
|
|
407
|
+
authorityKind: number;
|
|
408
|
+
}
|
|
409
|
+
/** Emitted by `unfreeze_withdraw_request` (disc 23). */
|
|
410
|
+
export interface WithdrawRequestUnfrozenEvent {
|
|
411
|
+
name: "WithdrawRequestUnfrozen";
|
|
412
|
+
wr: PublicKey;
|
|
413
|
+
stv: PublicKey;
|
|
414
|
+
user: PublicKey;
|
|
415
|
+
epochId: number;
|
|
416
|
+
authority: PublicKey;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Emitted by `set_claim_recipient` (disc 24).
|
|
420
|
+
* `approverKind`: 0 = user, 1 = cold (see `RECIPIENT_APPROVER_KIND_*` in
|
|
421
|
+
* constants.ts). `armed` mirrors `WithdrawRequest.isRedirectArmed()` as of
|
|
422
|
+
* this call.
|
|
423
|
+
*/
|
|
424
|
+
export interface ClaimRecipientSetEvent {
|
|
425
|
+
name: "ClaimRecipientSet";
|
|
426
|
+
wr: PublicKey;
|
|
427
|
+
stv: PublicKey;
|
|
428
|
+
user: PublicKey;
|
|
429
|
+
epochId: number;
|
|
430
|
+
recipient: PublicKey;
|
|
431
|
+
approverKind: number;
|
|
432
|
+
armed: boolean;
|
|
433
|
+
}
|
|
434
|
+
export type StvEvent = ConfigInitializedEvent | ConfigUpdatedEvent | StvCreatedEvent | StvUpdatedEvent | DepositedEvent | WithdrawRequestedEvent | WithdrawRequestIncreasedEvent | WithdrawClaimedEvent | DepositedToStrategyEvent | WithdrawnFromStrategyEvent | EpochProcessedEvent | EpochAdvancedEvent | FeesSettledEvent | StvClosedEvent | ManagerAddedEvent | ManagerRemovedEvent | WithdrawOverrideClaimedEvent | LendMigratedEvent | MigrateRequestedEvent | MigrateExecutedEvent | DelayedDepositProcessedEvent | InstantWithdrawnEvent | StvSeededEvent | AdminRotationStartedEvent | AdminRotationAcceptedEvent | WarmAdminSetEvent | CircuitBreakerTrippedEvent | WithdrawRequestFrozenEvent | WithdrawRequestUnfrozenEvent | ClaimRecipientSetEvent;
|
package/package.json
CHANGED