@perena/vault-sdk 1.0.28 → 1.0.29
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 +20 -3
- package/dist/index.d.ts +429 -31
- package/dist/index.js +759 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -150,7 +150,7 @@ var require_compat = __commonJS({
|
|
|
150
150
|
exports2.toWeb3PublicKey = toWeb3PublicKey;
|
|
151
151
|
exports2.asWeb3PublicKey = asWeb3PublicKey2;
|
|
152
152
|
exports2.toKitInstruction = toKitInstruction30;
|
|
153
|
-
exports2.fromKitInstruction =
|
|
153
|
+
exports2.fromKitInstruction = fromKitInstruction3;
|
|
154
154
|
var kit_1 = require("@solana/kit");
|
|
155
155
|
var web3_js_1 = require("@solana/web3.js");
|
|
156
156
|
function fromWeb3PublicKey(pubkey) {
|
|
@@ -175,7 +175,7 @@ var require_compat = __commonJS({
|
|
|
175
175
|
}))
|
|
176
176
|
};
|
|
177
177
|
}
|
|
178
|
-
function
|
|
178
|
+
function fromKitInstruction3(ix) {
|
|
179
179
|
return new web3_js_1.TransactionInstruction({
|
|
180
180
|
programId: toWeb3PublicKey(ix.programAddress),
|
|
181
181
|
keys: (ix.accounts ?? []).map((account) => ({
|
|
@@ -342,7 +342,7 @@ var require_refs = __commonJS({
|
|
|
342
342
|
"use strict";
|
|
343
343
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
344
344
|
exports2.createMultiCpiRefs = createMultiCpiRefs;
|
|
345
|
-
exports2.createCpiRefs =
|
|
345
|
+
exports2.createCpiRefs = createCpiRefs4;
|
|
346
346
|
var kit_1 = require("@solana/kit");
|
|
347
347
|
var roles_1 = require_roles();
|
|
348
348
|
var accounts_1 = require_accounts();
|
|
@@ -478,7 +478,7 @@ var require_refs = __commonJS({
|
|
|
478
478
|
lookupTables: collectLookupTables(allCpis)
|
|
479
479
|
};
|
|
480
480
|
}
|
|
481
|
-
function
|
|
481
|
+
function createCpiRefs4(cpis, options) {
|
|
482
482
|
const accountLists = toCpiAccountLists(cpis);
|
|
483
483
|
const { pool, poolIndex } = buildPool(accountLists, options);
|
|
484
484
|
const trackedIndices = resolveTrackedIndices(poolIndex, options?.trackAddresses);
|
|
@@ -592,11 +592,11 @@ var require_transaction = __commonJS({
|
|
|
592
592
|
"../common/dist/utils/transaction.js"(exports2) {
|
|
593
593
|
"use strict";
|
|
594
594
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
595
|
-
exports2.fetchLookupTables =
|
|
595
|
+
exports2.fetchLookupTables = fetchLookupTables3;
|
|
596
596
|
exports2.getSignatureStatus = getSignatureStatus;
|
|
597
597
|
exports2.sendVersionedTransaction = sendVersionedTransaction;
|
|
598
598
|
var web3_js_1 = require("@solana/web3.js");
|
|
599
|
-
async function
|
|
599
|
+
async function fetchLookupTables3(connection, lookupTables) {
|
|
600
600
|
const accounts2 = await Promise.all(lookupTables.map(async (lookupTable) => {
|
|
601
601
|
const response = await connection.getAddressLookupTable(new web3_js_1.PublicKey(lookupTable));
|
|
602
602
|
if (!response.value) {
|
|
@@ -613,7 +613,7 @@ var require_transaction = __commonJS({
|
|
|
613
613
|
}
|
|
614
614
|
async function sendVersionedTransaction({ connection, payer, instructions: instructions2, lookupTables }) {
|
|
615
615
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
616
|
-
const lookupTableAccounts = await
|
|
616
|
+
const lookupTableAccounts = await fetchLookupTables3(connection, lookupTables);
|
|
617
617
|
const message2 = new web3_js_1.TransactionMessage({
|
|
618
618
|
payerKey: payer.publicKey,
|
|
619
619
|
recentBlockhash: blockhash,
|
|
@@ -2921,7 +2921,7 @@ var require_client = __commonJS({
|
|
|
2921
2921
|
var extract_1 = require_extract();
|
|
2922
2922
|
var routePreInstructions_1 = require_routePreInstructions();
|
|
2923
2923
|
var constants_1 = require_constants4();
|
|
2924
|
-
var
|
|
2924
|
+
var JupiterSwapClient2 = class {
|
|
2925
2925
|
constructor(rpc, config = {}) {
|
|
2926
2926
|
this.rpc = rpc;
|
|
2927
2927
|
this.config = config;
|
|
@@ -3012,7 +3012,7 @@ var require_client = __commonJS({
|
|
|
3012
3012
|
};
|
|
3013
3013
|
}
|
|
3014
3014
|
};
|
|
3015
|
-
exports2.JupiterSwapClient =
|
|
3015
|
+
exports2.JupiterSwapClient = JupiterSwapClient2;
|
|
3016
3016
|
}
|
|
3017
3017
|
});
|
|
3018
3018
|
|
|
@@ -3232,6 +3232,7 @@ var require_dist4 = __commonJS({
|
|
|
3232
3232
|
var index_exports = {};
|
|
3233
3233
|
__export(index_exports, {
|
|
3234
3234
|
ASSET_DECIMALS: () => ASSET_DECIMALS,
|
|
3235
|
+
ASSET_REBALANCE_COOLDOWN_SECS: () => ASSET_REBALANCE_COOLDOWN_SECS,
|
|
3235
3236
|
AccountClient: () => AccountClient,
|
|
3236
3237
|
ActivateCircuitBreakerBuilder: () => ActivateCircuitBreakerBuilder,
|
|
3237
3238
|
CONSENSUS_ORACLE_VARIANT: () => CONSENSUS_ORACLE_VARIANT,
|
|
@@ -3242,15 +3243,20 @@ __export(index_exports, {
|
|
|
3242
3243
|
CreateAssetHoldingBuilder: () => CreateAssetHoldingBuilder,
|
|
3243
3244
|
CreateTrancheStateBuilder: () => CreateTrancheStateBuilder,
|
|
3244
3245
|
CreateVaultBuilder: () => CreateVaultBuilder,
|
|
3246
|
+
DEFAULT_CU_PRICE_MICRO_LAMPORTS: () => DEFAULT_CU_PRICE_MICRO_LAMPORTS,
|
|
3245
3247
|
DEFAULT_JUNIOR_EARLY_UNSTAKE_FEE_BPS: () => DEFAULT_JUNIOR_EARLY_UNSTAKE_FEE_BPS,
|
|
3246
3248
|
DEFAULT_JUNIOR_STANDARD_UNSTAKE_FEE_BPS: () => DEFAULT_JUNIOR_STANDARD_UNSTAKE_FEE_BPS,
|
|
3247
3249
|
DEFAULT_JUNIOR_WITHDRAWAL_LOCKUP_SECS: () => DEFAULT_JUNIOR_WITHDRAWAL_LOCKUP_SECS,
|
|
3248
3250
|
DEFAULT_MAX_ACCEPTABLE_APY_BPS: () => DEFAULT_MAX_ACCEPTABLE_APY_BPS,
|
|
3251
|
+
DEFAULT_MAX_ACCOUNTS: () => DEFAULT_MAX_ACCOUNTS,
|
|
3249
3252
|
DEFAULT_MIN_AMOUNT_UI: () => DEFAULT_MIN_AMOUNT_UI,
|
|
3250
3253
|
DEFAULT_ORACLE_STALENESS_THRESHOLD_SECS: () => DEFAULT_ORACLE_STALENESS_THRESHOLD_SECS,
|
|
3251
3254
|
DEFAULT_PRICE_ORACLE_ACCOUNT: () => DEFAULT_PRICE_ORACLE_ACCOUNT,
|
|
3252
3255
|
DEFAULT_PRICE_STALENESS_SECS: () => DEFAULT_PRICE_STALENESS_SECS,
|
|
3253
3256
|
DEFAULT_PRICE_STALENESS_THRESHOLD_SECS: () => DEFAULT_PRICE_STALENESS_THRESHOLD_SECS,
|
|
3257
|
+
DEFAULT_REBALANCE_BAND_BPS: () => DEFAULT_REBALANCE_BAND_BPS,
|
|
3258
|
+
DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
|
|
3259
|
+
DEFAULT_TARGET_LOCAL_BPS: () => DEFAULT_TARGET_LOCAL_BPS,
|
|
3254
3260
|
DEFAULT_VAULT_ID: () => DEFAULT_VAULT_ID,
|
|
3255
3261
|
DisableCircuitBreakerBuilder: () => DisableCircuitBreakerBuilder,
|
|
3256
3262
|
EXTERNAL_POSITION_SAMPLES: () => EXTERNAL_POSITION_SAMPLES,
|
|
@@ -3264,6 +3270,9 @@ __export(index_exports, {
|
|
|
3264
3270
|
FEE_VAULT_CACHE_CATEGORY: () => FEE_VAULT_CACHE_CATEGORY,
|
|
3265
3271
|
FulfillJuniorTrancheWithdrawBuilder: () => FulfillJuniorTrancheWithdrawBuilder,
|
|
3266
3272
|
IDL: () => IDL,
|
|
3273
|
+
IDLE_RESERVE_FLOOR_BPS: () => IDLE_RESERVE_FLOOR_BPS,
|
|
3274
|
+
IDLE_RESERVE_TARGET_BPS: () => IDLE_RESERVE_TARGET_BPS,
|
|
3275
|
+
IdleLiquidityService: () => IdleLiquidityService,
|
|
3267
3276
|
InitializeVaultRolesBuilder: () => InitializeVaultRolesBuilder,
|
|
3268
3277
|
JupiterBalanceSource: () => JupiterBalanceSource,
|
|
3269
3278
|
JupiterPriceSource: () => JupiterPriceSource,
|
|
@@ -3377,6 +3386,7 @@ __export(index_exports, {
|
|
|
3377
3386
|
mintTokensTo: () => mintTokensTo,
|
|
3378
3387
|
mostFrequent: () => mostFrequent,
|
|
3379
3388
|
parseExternalLiquidityRefs: () => parseExternalLiquidityRefs,
|
|
3389
|
+
planRebalance: () => planRebalance,
|
|
3380
3390
|
prepareVaultTransaction: () => prepareVaultTransaction,
|
|
3381
3391
|
priceInAccountingUnit: () => priceInAccountingUnit,
|
|
3382
3392
|
readI64LE: () => readI64LE,
|
|
@@ -14326,6 +14336,106 @@ var IDL = {
|
|
|
14326
14336
|
]
|
|
14327
14337
|
}
|
|
14328
14338
|
},
|
|
14339
|
+
{
|
|
14340
|
+
"name": "RollingRebalanceLimit",
|
|
14341
|
+
"docs": [
|
|
14342
|
+
"Rolling-window cap on rebalance (Jupiter swap) throughput, expressed as a",
|
|
14343
|
+
"share of current TVL rather than a fixed amount.",
|
|
14344
|
+
"",
|
|
14345
|
+
"Sibling of [`super::withdrawal_limits::RollingWithdrawalLimit`]: same",
|
|
14346
|
+
"window-slide-then-charge mechanics, but the ceiling is recomputed from live",
|
|
14347
|
+
"TVL on every call, so the cap tracks the vault as it grows or shrinks",
|
|
14348
|
+
"instead of going stale at whatever amount the curator last set.",
|
|
14349
|
+
"",
|
|
14350
|
+
"Both swap directions charge the same window \u2014 the cap bounds total value",
|
|
14351
|
+
"routed through Jupiter per window, regardless of which asset is sold."
|
|
14352
|
+
],
|
|
14353
|
+
"serialization": "bytemuck",
|
|
14354
|
+
"repr": {
|
|
14355
|
+
"kind": "c"
|
|
14356
|
+
},
|
|
14357
|
+
"type": {
|
|
14358
|
+
"kind": "struct",
|
|
14359
|
+
"fields": [
|
|
14360
|
+
{
|
|
14361
|
+
"name": "window_start_ts",
|
|
14362
|
+
"docs": [
|
|
14363
|
+
"Unix timestamp the current window opened."
|
|
14364
|
+
],
|
|
14365
|
+
"type": "i64"
|
|
14366
|
+
},
|
|
14367
|
+
{
|
|
14368
|
+
"name": "window_duration_seconds",
|
|
14369
|
+
"docs": [
|
|
14370
|
+
"Window length, in seconds (e.g. 3_600 for an hourly limit)."
|
|
14371
|
+
],
|
|
14372
|
+
"type": "u64"
|
|
14373
|
+
},
|
|
14374
|
+
{
|
|
14375
|
+
"name": "value_in_window",
|
|
14376
|
+
"docs": [
|
|
14377
|
+
"Value rebalanced inside the current window, in the vault's accounting",
|
|
14378
|
+
"unit."
|
|
14379
|
+
],
|
|
14380
|
+
"type": "u64"
|
|
14381
|
+
},
|
|
14382
|
+
{
|
|
14383
|
+
"name": "window_limit_bps",
|
|
14384
|
+
"docs": [
|
|
14385
|
+
"Cap as a share of TVL, in bps. `0` disables the limit."
|
|
14386
|
+
],
|
|
14387
|
+
"type": "u16"
|
|
14388
|
+
},
|
|
14389
|
+
{
|
|
14390
|
+
"name": "_padding1",
|
|
14391
|
+
"type": {
|
|
14392
|
+
"array": [
|
|
14393
|
+
"u8",
|
|
14394
|
+
6
|
|
14395
|
+
]
|
|
14396
|
+
}
|
|
14397
|
+
},
|
|
14398
|
+
{
|
|
14399
|
+
"name": "_padding2",
|
|
14400
|
+
"type": {
|
|
14401
|
+
"array": [
|
|
14402
|
+
"u64",
|
|
14403
|
+
4
|
|
14404
|
+
]
|
|
14405
|
+
}
|
|
14406
|
+
}
|
|
14407
|
+
]
|
|
14408
|
+
}
|
|
14409
|
+
},
|
|
14410
|
+
{
|
|
14411
|
+
"name": "RollingRebalanceLimitConfig",
|
|
14412
|
+
"docs": [
|
|
14413
|
+
"Rolling rebalance-limit config applied via [`SetVaultConfigArgs`].",
|
|
14414
|
+
"",
|
|
14415
|
+
"The cap is a share of TVL rather than a fixed amount, so it stays",
|
|
14416
|
+
"meaningful as the vault grows. Both fields must be zero (disable the cap)",
|
|
14417
|
+
"or both non-zero (enable it)."
|
|
14418
|
+
],
|
|
14419
|
+
"type": {
|
|
14420
|
+
"kind": "struct",
|
|
14421
|
+
"fields": [
|
|
14422
|
+
{
|
|
14423
|
+
"name": "window_limit_bps",
|
|
14424
|
+
"docs": [
|
|
14425
|
+
"Max share of TVL rebalanced inside one window, in bps (`0` disables)."
|
|
14426
|
+
],
|
|
14427
|
+
"type": "u16"
|
|
14428
|
+
},
|
|
14429
|
+
{
|
|
14430
|
+
"name": "window_duration_seconds",
|
|
14431
|
+
"docs": [
|
|
14432
|
+
"Window length in seconds (`0` only valid when `window_limit_bps` is `0`)."
|
|
14433
|
+
],
|
|
14434
|
+
"type": "u64"
|
|
14435
|
+
}
|
|
14436
|
+
]
|
|
14437
|
+
}
|
|
14438
|
+
},
|
|
14329
14439
|
{
|
|
14330
14440
|
"name": "SetAssetPriceOracleArgs",
|
|
14331
14441
|
"type": {
|
|
@@ -14511,6 +14621,20 @@ var IDL = {
|
|
|
14511
14621
|
}
|
|
14512
14622
|
}
|
|
14513
14623
|
}
|
|
14624
|
+
},
|
|
14625
|
+
{
|
|
14626
|
+
"name": "rebalance_limit",
|
|
14627
|
+
"docs": [
|
|
14628
|
+
"Rolling cap on rebalance (Jupiter swap) throughput. `None` leaves",
|
|
14629
|
+
"unchanged."
|
|
14630
|
+
],
|
|
14631
|
+
"type": {
|
|
14632
|
+
"option": {
|
|
14633
|
+
"defined": {
|
|
14634
|
+
"name": "RollingRebalanceLimitConfig"
|
|
14635
|
+
}
|
|
14636
|
+
}
|
|
14637
|
+
}
|
|
14514
14638
|
}
|
|
14515
14639
|
]
|
|
14516
14640
|
}
|
|
@@ -15432,6 +15556,14 @@ var IDL = {
|
|
|
15432
15556
|
"name": "senior_fixed_apy_bps",
|
|
15433
15557
|
"type": "u16"
|
|
15434
15558
|
},
|
|
15559
|
+
{
|
|
15560
|
+
"name": "junior_floor_apy_bps",
|
|
15561
|
+
"docs": [
|
|
15562
|
+
"Floor APY for the junior tranche, in basis points. Zero disables the",
|
|
15563
|
+
"floor. Shortfalls are funded from the untranched sleeve, never senior."
|
|
15564
|
+
],
|
|
15565
|
+
"type": "u16"
|
|
15566
|
+
},
|
|
15435
15567
|
{
|
|
15436
15568
|
"name": "early_unstake_fee_bps",
|
|
15437
15569
|
"type": "u16"
|
|
@@ -16257,12 +16389,38 @@ var IDL = {
|
|
|
16257
16389
|
],
|
|
16258
16390
|
"type": "u64"
|
|
16259
16391
|
},
|
|
16392
|
+
{
|
|
16393
|
+
"name": "junior_floor_apy_bps",
|
|
16394
|
+
"docs": [
|
|
16395
|
+
"Curator-set floor APY for the junior tranche, in basis points. Zero",
|
|
16396
|
+
"disables the floor.",
|
|
16397
|
+
"",
|
|
16398
|
+
"When junior's realized growth falls short of this floor, the shortfall is",
|
|
16399
|
+
"topped up from the *untranched* (regular) sleeve's value, never from the",
|
|
16400
|
+
"senior tranche -- senior's fixed-APY entitlement is settled first and is",
|
|
16401
|
+
"untouched by the floor. The top-up is best-effort: it is capped by the",
|
|
16402
|
+
"untranched sleeve's available value, and any unpaid remainder stays",
|
|
16403
|
+
"outstanding against the durable junior anchor",
|
|
16404
|
+
"(`VaultTrancheState::junior_apy_anchor_share_price`) so it can be paid on",
|
|
16405
|
+
"a later settlement."
|
|
16406
|
+
],
|
|
16407
|
+
"type": "u16"
|
|
16408
|
+
},
|
|
16409
|
+
{
|
|
16410
|
+
"name": "_padding1",
|
|
16411
|
+
"type": {
|
|
16412
|
+
"array": [
|
|
16413
|
+
"u8",
|
|
16414
|
+
6
|
|
16415
|
+
]
|
|
16416
|
+
}
|
|
16417
|
+
},
|
|
16260
16418
|
{
|
|
16261
16419
|
"name": "_padding2",
|
|
16262
16420
|
"type": {
|
|
16263
16421
|
"array": [
|
|
16264
16422
|
"u64",
|
|
16265
|
-
|
|
16423
|
+
12
|
|
16266
16424
|
]
|
|
16267
16425
|
}
|
|
16268
16426
|
}
|
|
@@ -16340,12 +16498,28 @@ var IDL = {
|
|
|
16340
16498
|
],
|
|
16341
16499
|
"type": "i64"
|
|
16342
16500
|
},
|
|
16501
|
+
{
|
|
16502
|
+
"name": "junior_apy_anchor_share_price",
|
|
16503
|
+
"docs": [
|
|
16504
|
+
"Junior share price at the start of the current floor-APY regime. The",
|
|
16505
|
+
"anchor is durable across settlements so an unpaid floor shortfall stays",
|
|
16506
|
+
"outstanding and can be caught up later."
|
|
16507
|
+
],
|
|
16508
|
+
"type": "u64"
|
|
16509
|
+
},
|
|
16510
|
+
{
|
|
16511
|
+
"name": "junior_apy_anchor_ts",
|
|
16512
|
+
"docs": [
|
|
16513
|
+
"Unix timestamp when the junior floor-APY anchor was set."
|
|
16514
|
+
],
|
|
16515
|
+
"type": "i64"
|
|
16516
|
+
},
|
|
16343
16517
|
{
|
|
16344
16518
|
"name": "_padding2",
|
|
16345
16519
|
"type": {
|
|
16346
16520
|
"array": [
|
|
16347
16521
|
"u64",
|
|
16348
|
-
|
|
16522
|
+
27
|
|
16349
16523
|
]
|
|
16350
16524
|
}
|
|
16351
16525
|
}
|
|
@@ -16363,6 +16537,17 @@ var IDL = {
|
|
|
16363
16537
|
"option": "u16"
|
|
16364
16538
|
}
|
|
16365
16539
|
},
|
|
16540
|
+
{
|
|
16541
|
+
"name": "junior_floor_apy_bps",
|
|
16542
|
+
"docs": [
|
|
16543
|
+
"Floor APY for the junior tranche, in basis points. Zero disables the",
|
|
16544
|
+
"floor. Setting this starts a fresh regime: any shortfall accrued under",
|
|
16545
|
+
"the previous value is forfeited."
|
|
16546
|
+
],
|
|
16547
|
+
"type": {
|
|
16548
|
+
"option": "u16"
|
|
16549
|
+
}
|
|
16550
|
+
},
|
|
16366
16551
|
{
|
|
16367
16552
|
"name": "early_unstake_fee_bps",
|
|
16368
16553
|
"type": {
|
|
@@ -16645,12 +16830,25 @@ var IDL = {
|
|
|
16645
16830
|
],
|
|
16646
16831
|
"type": "u64"
|
|
16647
16832
|
},
|
|
16833
|
+
{
|
|
16834
|
+
"name": "rebalance_limit",
|
|
16835
|
+
"docs": [
|
|
16836
|
+
"Rolling cap on rebalance (Jupiter swap) throughput per window, as a",
|
|
16837
|
+
"share of TVL. Carved out of `_padding1`, so the account layout and size",
|
|
16838
|
+
"are unchanged and existing vaults decode it as disabled."
|
|
16839
|
+
],
|
|
16840
|
+
"type": {
|
|
16841
|
+
"defined": {
|
|
16842
|
+
"name": "RollingRebalanceLimit"
|
|
16843
|
+
}
|
|
16844
|
+
}
|
|
16845
|
+
},
|
|
16648
16846
|
{
|
|
16649
16847
|
"name": "_padding1",
|
|
16650
16848
|
"type": {
|
|
16651
16849
|
"array": [
|
|
16652
16850
|
"u64",
|
|
16653
|
-
|
|
16851
|
+
22
|
|
16654
16852
|
]
|
|
16655
16853
|
}
|
|
16656
16854
|
},
|
|
@@ -17789,6 +17987,7 @@ var CreateTrancheStateBuilder = class extends VaultBuilderBase {
|
|
|
17789
17987
|
async getIx(args) {
|
|
17790
17988
|
return this.program.methods.vaultCreateTrancheState({
|
|
17791
17989
|
seniorFixedApyBps: args.seniorFixedApyBps,
|
|
17990
|
+
juniorFloorApyBps: args.juniorFloorApyBps,
|
|
17792
17991
|
earlyUnstakeFeeBps: args.earlyUnstakeFeeBps,
|
|
17793
17992
|
standardUnstakeFeeBps: args.standardUnstakeFeeBps,
|
|
17794
17993
|
targetLockupDurationSecs: args.targetLockupDurationSecs,
|
|
@@ -17832,6 +18031,7 @@ var CreateTrancheStateBuilder = class extends VaultBuilderBase {
|
|
|
17832
18031
|
seniorShareMint: txArgs.seniorShareMint,
|
|
17833
18032
|
vaultOracle,
|
|
17834
18033
|
seniorFixedApyBps: txArgs.seniorFixedApyBps ?? 0,
|
|
18034
|
+
juniorFloorApyBps: txArgs.juniorFloorApyBps ?? 0,
|
|
17835
18035
|
earlyUnstakeFeeBps: txArgs.earlyUnstakeFeeBps ?? DEFAULT_JUNIOR_EARLY_UNSTAKE_FEE_BPS,
|
|
17836
18036
|
standardUnstakeFeeBps: txArgs.standardUnstakeFeeBps ?? DEFAULT_JUNIOR_STANDARD_UNSTAKE_FEE_BPS,
|
|
17837
18037
|
targetLockupDurationSecs: new import_core.BN(
|
|
@@ -17907,7 +18107,8 @@ function toAnchorSetVaultConfigArgs(args) {
|
|
|
17907
18107
|
lossesEnabled: args.lossesEnabled,
|
|
17908
18108
|
priceStalenessThresholdSecs: args.priceStalenessThresholdSecs,
|
|
17909
18109
|
userBurnLimit: args.userBurnLimit,
|
|
17910
|
-
managerPullLimit: args.managerPullLimit
|
|
18110
|
+
managerPullLimit: args.managerPullLimit,
|
|
18111
|
+
rebalanceLimit: args.rebalanceLimit
|
|
17911
18112
|
};
|
|
17912
18113
|
}
|
|
17913
18114
|
function toAnchorConsensusUpdates(updates) {
|
|
@@ -18115,6 +18316,12 @@ var SetVaultConfigBuilder = class extends VaultBuilderBase {
|
|
|
18115
18316
|
windowDurationSeconds: new import_core4.BN(
|
|
18116
18317
|
txArgs.managerPullLimit.windowDurationSeconds.toString()
|
|
18117
18318
|
)
|
|
18319
|
+
} : null,
|
|
18320
|
+
rebalanceLimit: txArgs.rebalanceLimit !== void 0 ? {
|
|
18321
|
+
windowLimitBps: txArgs.rebalanceLimit.windowLimitBps,
|
|
18322
|
+
windowDurationSeconds: new import_core4.BN(
|
|
18323
|
+
txArgs.rebalanceLimit.windowDurationSeconds.toString()
|
|
18324
|
+
)
|
|
18118
18325
|
} : null
|
|
18119
18326
|
}
|
|
18120
18327
|
};
|
|
@@ -19499,6 +19706,7 @@ var UpdateTrancheConfigBuilder = class extends VaultBuilderBase {
|
|
|
19499
19706
|
async getIx(args) {
|
|
19500
19707
|
return this.program.methods.vaultUpdateTrancheConfig({
|
|
19501
19708
|
seniorFixedApyBps: args.seniorFixedApyBps,
|
|
19709
|
+
juniorFloorApyBps: args.juniorFloorApyBps,
|
|
19502
19710
|
earlyUnstakeFeeBps: args.earlyUnstakeFeeBps,
|
|
19503
19711
|
standardUnstakeFeeBps: args.standardUnstakeFeeBps,
|
|
19504
19712
|
targetLockupDurationSecs: args.targetLockupDurationSecs,
|
|
@@ -19521,6 +19729,7 @@ var UpdateTrancheConfigBuilder = class extends VaultBuilderBase {
|
|
|
19521
19729
|
vaultTrancheState: txArgs.vaultTrancheState ?? vaultTrancheState,
|
|
19522
19730
|
vaultOracle: txArgs.vaultOracle ?? vaultOracle,
|
|
19523
19731
|
seniorFixedApyBps: txArgs.seniorFixedApyBps ?? null,
|
|
19732
|
+
juniorFloorApyBps: txArgs.juniorFloorApyBps ?? null,
|
|
19524
19733
|
earlyUnstakeFeeBps: txArgs.earlyUnstakeFeeBps ?? null,
|
|
19525
19734
|
standardUnstakeFeeBps: txArgs.standardUnstakeFeeBps ?? null,
|
|
19526
19735
|
targetLockupDurationSecs: txArgs.targetLockupDurationSecs === void 0 ? null : new import_core11.BN(txArgs.targetLockupDurationSecs.toString()),
|
|
@@ -21576,21 +21785,27 @@ function settleVault(args) {
|
|
|
21576
21785
|
args.grossNav,
|
|
21577
21786
|
args.nowTs
|
|
21578
21787
|
);
|
|
21788
|
+
const trancheValueBeforeFees = args.tranche.junior.value + args.tranche.senior.value;
|
|
21789
|
+
const juniorFees = settleShareClassPerformanceFee(
|
|
21790
|
+
args.tranche.junior,
|
|
21791
|
+
args.performanceFeeBps,
|
|
21792
|
+
args.protocolFeeBps
|
|
21793
|
+
);
|
|
21794
|
+
const juniorFloorTopup = applyJuniorFloorTopup(
|
|
21795
|
+
args.tranche,
|
|
21796
|
+
regularGrossValue,
|
|
21797
|
+
args.nowTs
|
|
21798
|
+
);
|
|
21579
21799
|
regularValue = settleFixedApyNav({
|
|
21580
21800
|
currentSharePrice: args.currentSharePrice,
|
|
21581
|
-
reportedNav: regularGrossValue,
|
|
21801
|
+
reportedNav: regularGrossValue - juniorFloorTopup,
|
|
21582
21802
|
nowTs: args.nowTs,
|
|
21583
21803
|
totalSupply: args.totalSupply,
|
|
21584
21804
|
fixedApyBps: args.fixedApyBps,
|
|
21585
21805
|
anchorSharePrice: args.apyAnchorSharePrice,
|
|
21586
21806
|
anchorTs: args.apyAnchorTs
|
|
21587
21807
|
});
|
|
21588
|
-
settledAccountingNav = regularValue +
|
|
21589
|
-
const juniorFees = settleShareClassPerformanceFee(
|
|
21590
|
-
args.tranche.junior,
|
|
21591
|
-
args.performanceFeeBps,
|
|
21592
|
-
args.protocolFeeBps
|
|
21593
|
-
);
|
|
21808
|
+
settledAccountingNav = regularValue + trancheValueBeforeFees + juniorFloorTopup;
|
|
21594
21809
|
const regularFees = settleRegularPerformanceFee(
|
|
21595
21810
|
regularValue,
|
|
21596
21811
|
args.totalSupply,
|
|
@@ -21711,6 +21926,31 @@ function seniorEntitlement(tranche, nowTs) {
|
|
|
21711
21926
|
);
|
|
21712
21927
|
return targetValue > tranche.senior.value ? targetValue - tranche.senior.value : 0n;
|
|
21713
21928
|
}
|
|
21929
|
+
function applyJuniorFloorTopup(tranche, availableRegularValue, nowTs) {
|
|
21930
|
+
if (tranche.juniorApyAnchorTs <= 0n) {
|
|
21931
|
+
tranche.juniorApyAnchorSharePrice = tranche.junior.sharePrice;
|
|
21932
|
+
tranche.juniorApyAnchorTs = tranche.lastSettledTs > 0n ? tranche.lastSettledTs : nowTs;
|
|
21933
|
+
}
|
|
21934
|
+
if (tranche.juniorFloorApyBps === 0 || tranche.juniorApyAnchorSharePrice === 0n || tranche.junior.totalSupply === 0n || tranche.juniorApyAnchorTs <= 0n || nowTs <= tranche.juniorApyAnchorTs) {
|
|
21935
|
+
return 0n;
|
|
21936
|
+
}
|
|
21937
|
+
const targetPrice = applyEffectiveApy(
|
|
21938
|
+
tranche.juniorApyAnchorSharePrice,
|
|
21939
|
+
tranche.juniorFloorApyBps,
|
|
21940
|
+
nowTs - tranche.juniorApyAnchorTs
|
|
21941
|
+
);
|
|
21942
|
+
const targetValue = mulDiv2(
|
|
21943
|
+
targetPrice,
|
|
21944
|
+
tranche.junior.totalSupply,
|
|
21945
|
+
DEFAULT_SHARE_PRICE
|
|
21946
|
+
);
|
|
21947
|
+
const shortfall = targetValue > tranche.junior.value ? targetValue - tranche.junior.value : 0n;
|
|
21948
|
+
const topup = shortfall < availableRegularValue ? shortfall : availableRegularValue;
|
|
21949
|
+
if (topup === 0n) return 0n;
|
|
21950
|
+
tranche.junior.value += topup;
|
|
21951
|
+
refreshShareClass(tranche.junior);
|
|
21952
|
+
return topup;
|
|
21953
|
+
}
|
|
21714
21954
|
function settleShareClassPerformanceFee(shareClass, performanceFeeBps, protocolFeeBps) {
|
|
21715
21955
|
refreshShareClass(shareClass);
|
|
21716
21956
|
const grossPrice = shareClass.sharePrice;
|
|
@@ -21931,9 +22171,12 @@ function decodeTrancheState(decoded, args, warnings, blockers) {
|
|
|
21931
22171
|
junior,
|
|
21932
22172
|
senior,
|
|
21933
22173
|
seniorFixedApyBps: number(decoded.config.seniorFixedApyBps),
|
|
22174
|
+
juniorFloorApyBps: number(decoded.config.juniorFloorApyBps),
|
|
21934
22175
|
lastSettledTs: bigint(decoded.lastSettledTs),
|
|
21935
22176
|
seniorApyAnchorSharePrice: bigint(decoded.seniorApyAnchorSharePrice),
|
|
21936
|
-
seniorApyAnchorTs: bigint(decoded.seniorApyAnchorTs)
|
|
22177
|
+
seniorApyAnchorTs: bigint(decoded.seniorApyAnchorTs),
|
|
22178
|
+
juniorApyAnchorSharePrice: bigint(decoded.juniorApyAnchorSharePrice),
|
|
22179
|
+
juniorApyAnchorTs: bigint(decoded.juniorApyAnchorTs)
|
|
21937
22180
|
};
|
|
21938
22181
|
}
|
|
21939
22182
|
function decodeShareClass(value) {
|
|
@@ -23427,6 +23670,9 @@ var import_web328 = require("@solana/web3.js");
|
|
|
23427
23670
|
var import_common50 = __toESM(require_dist());
|
|
23428
23671
|
var import_marginfi3 = __toESM(require_dist2());
|
|
23429
23672
|
var DEFAULT_MIN_AMOUNT_UI = 1;
|
|
23673
|
+
var DEFAULT_TARGET_LOCAL_BPS = 100;
|
|
23674
|
+
var DEFAULT_REBALANCE_BAND_BPS = 2e3;
|
|
23675
|
+
var BPS_DENOMINATOR3 = 10000n;
|
|
23430
23676
|
function toRawAmount(uiAmount, decimals) {
|
|
23431
23677
|
return BigInt(Math.floor(uiAmount * 10 ** decimals));
|
|
23432
23678
|
}
|
|
@@ -23463,26 +23709,50 @@ function pubkeyStr(value) {
|
|
|
23463
23709
|
function isZeroPubkey2(pk) {
|
|
23464
23710
|
return !pk || /^1+$/.test(pk) || pk === "11111111111111111111111111111111";
|
|
23465
23711
|
}
|
|
23712
|
+
function planRebalance(params) {
|
|
23713
|
+
const { localAmount, externalAmount, targetLocalBps, rebalanceBandBps, minRaw } = params;
|
|
23714
|
+
const total = localAmount + externalAmount;
|
|
23715
|
+
const targetLocal = total * BigInt(Math.round(targetLocalBps)) / BPS_DENOMINATOR3;
|
|
23716
|
+
const band = targetLocal * BigInt(Math.round(rebalanceBandBps)) / BPS_DENOMINATOR3;
|
|
23717
|
+
const threshold = band > minRaw ? band : minRaw;
|
|
23718
|
+
if (localAmount > targetLocal) {
|
|
23719
|
+
const amount2 = localAmount - targetLocal;
|
|
23720
|
+
if (amount2 < threshold) return null;
|
|
23721
|
+
return { direction: "deposit", amount: amount2, targetLocal };
|
|
23722
|
+
}
|
|
23723
|
+
const shortfall = targetLocal - localAmount;
|
|
23724
|
+
if (shortfall < threshold) return null;
|
|
23725
|
+
const amount = shortfall < externalAmount ? shortfall : externalAmount;
|
|
23726
|
+
if (amount < minRaw) return null;
|
|
23727
|
+
return { direction: "withdraw", amount, targetLocal };
|
|
23728
|
+
}
|
|
23466
23729
|
var ExternalLiquidityIntegrityService = class {
|
|
23467
23730
|
constructor(client) {
|
|
23468
23731
|
this.client = client;
|
|
23469
23732
|
}
|
|
23470
23733
|
/**
|
|
23471
|
-
* Scan all vaults and
|
|
23472
|
-
*
|
|
23734
|
+
* Scan all vaults and rebalance each holding toward its target local share.
|
|
23735
|
+
* Non-fatal per vault — errors are logged and counted.
|
|
23473
23736
|
*/
|
|
23474
23737
|
async runAll(hwManager, opts = {}) {
|
|
23475
23738
|
const log = opts.log ?? (() => {
|
|
23476
23739
|
});
|
|
23477
23740
|
const dryRun = opts.dryRun ?? false;
|
|
23478
23741
|
const minAmountUi = opts.minAmountUi ?? DEFAULT_MIN_AMOUNT_UI;
|
|
23479
|
-
|
|
23480
|
-
|
|
23742
|
+
const targetLocalBps = opts.targetLocalBps ?? DEFAULT_TARGET_LOCAL_BPS;
|
|
23743
|
+
const rebalanceBandBps = opts.rebalanceBandBps ?? DEFAULT_REBALANCE_BAND_BPS;
|
|
23744
|
+
if (dryRun) log("DRY RUN \u2014 rebalances will be simulated, not sent");
|
|
23745
|
+
log(`Minimum rebalance: ${minAmountUi} token(s) (~$${minAmountUi})`);
|
|
23746
|
+
log(`Target local share: ${targetLocalBps / 100}% of each holding`);
|
|
23747
|
+
log(
|
|
23748
|
+
`Rebalance band: ${rebalanceBandBps / 100}% of target (${targetLocalBps * (1 - rebalanceBandBps / 1e4) / 100}%\u2013${targetLocalBps * (1 + rebalanceBandBps / 1e4) / 100}% of holding)`
|
|
23749
|
+
);
|
|
23481
23750
|
const allVaults = await this.client.account.fetchAllVaults({ fresh: true });
|
|
23482
23751
|
log(`Discovered ${allVaults.length} vault(s) on-chain`);
|
|
23483
23752
|
const summary = {
|
|
23484
23753
|
vaultsProcessed: 0,
|
|
23485
23754
|
totalDeposited: 0,
|
|
23755
|
+
totalWithdrawn: 0,
|
|
23486
23756
|
totalSkipped: 0,
|
|
23487
23757
|
totalFailed: 0,
|
|
23488
23758
|
dryRun
|
|
@@ -23493,25 +23763,29 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23493
23763
|
vaultState,
|
|
23494
23764
|
hwManager,
|
|
23495
23765
|
log,
|
|
23496
|
-
{ dryRun, minAmountUi }
|
|
23766
|
+
{ dryRun, minAmountUi, targetLocalBps, rebalanceBandBps }
|
|
23497
23767
|
);
|
|
23498
23768
|
summary.vaultsProcessed++;
|
|
23499
23769
|
summary.totalDeposited += result.deposited;
|
|
23770
|
+
summary.totalWithdrawn += result.withdrawn;
|
|
23500
23771
|
summary.totalSkipped += result.skipped;
|
|
23501
23772
|
summary.totalFailed += result.failed;
|
|
23502
23773
|
}
|
|
23503
23774
|
return summary;
|
|
23504
23775
|
}
|
|
23505
23776
|
/**
|
|
23506
|
-
* Process a single vault: for each active external liquidity slot,
|
|
23507
|
-
*
|
|
23777
|
+
* Process a single vault: for each active external liquidity slot, move each
|
|
23778
|
+
* holding's balance toward the target local/external split.
|
|
23508
23779
|
*/
|
|
23509
23780
|
async processVault(vault, vaultState, hwManager, log, opts = {}) {
|
|
23510
23781
|
const dryRun = opts.dryRun ?? false;
|
|
23511
23782
|
const minAmountUi = opts.minAmountUi ?? DEFAULT_MIN_AMOUNT_UI;
|
|
23783
|
+
const targetLocalBps = opts.targetLocalBps ?? DEFAULT_TARGET_LOCAL_BPS;
|
|
23784
|
+
const rebalanceBandBps = opts.rebalanceBandBps ?? DEFAULT_REBALANCE_BAND_BPS;
|
|
23512
23785
|
const result = {
|
|
23513
23786
|
vault,
|
|
23514
23787
|
deposited: 0,
|
|
23788
|
+
withdrawn: 0,
|
|
23515
23789
|
skipped: 0,
|
|
23516
23790
|
failed: 0,
|
|
23517
23791
|
signatures: []
|
|
@@ -23541,24 +23815,33 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23541
23815
|
}
|
|
23542
23816
|
const holdings = vaultState.holdings.filter((h) => {
|
|
23543
23817
|
const mint = pubkeyStr(h.mint);
|
|
23544
|
-
|
|
23818
|
+
if (isZeroPubkey2(mint)) return false;
|
|
23819
|
+
return toBigInt3(h.localAmount) > 0n || toBigInt3(h.externalAmount) > 0n;
|
|
23545
23820
|
});
|
|
23546
23821
|
if (holdings.length === 0) {
|
|
23547
|
-
log(`Vault ${vault} slot ${slot.index}: no
|
|
23822
|
+
log(`Vault ${vault} slot ${slot.index}: no balance to rebalance`);
|
|
23548
23823
|
result.skipped++;
|
|
23549
23824
|
continue;
|
|
23550
23825
|
}
|
|
23551
23826
|
for (const holding of holdings) {
|
|
23552
23827
|
const mintAddress = (0, import_kit15.address)(pubkeyStr(holding.mint));
|
|
23553
23828
|
const localAmount = toBigInt3(holding.localAmount);
|
|
23829
|
+
const externalAmount = toBigInt3(holding.externalAmount);
|
|
23554
23830
|
const decimals = Number(holding.decimals ?? 0);
|
|
23555
23831
|
const minRaw = toRawAmount(minAmountUi, decimals);
|
|
23556
|
-
|
|
23832
|
+
const plan = planRebalance({
|
|
23833
|
+
localAmount,
|
|
23834
|
+
externalAmount,
|
|
23835
|
+
targetLocalBps,
|
|
23836
|
+
rebalanceBandBps,
|
|
23837
|
+
minRaw
|
|
23838
|
+
});
|
|
23839
|
+
if (!plan) {
|
|
23557
23840
|
log(
|
|
23558
|
-
`Vault ${vault} slot ${slot.index}: mint ${mintAddress}
|
|
23559
|
-
|
|
23841
|
+
`Vault ${vault} slot ${slot.index}: mint ${mintAddress} within band (local ${formatUi(localAmount, decimals)}, external ${formatUi(
|
|
23842
|
+
externalAmount,
|
|
23560
23843
|
decimals
|
|
23561
|
-
)}
|
|
23844
|
+
)}) \u2014 skipping`
|
|
23562
23845
|
);
|
|
23563
23846
|
result.skipped++;
|
|
23564
23847
|
continue;
|
|
@@ -23572,31 +23855,36 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23572
23855
|
continue;
|
|
23573
23856
|
}
|
|
23574
23857
|
log(
|
|
23575
|
-
`Vault ${vault} slot ${slot.index}: ${dryRun ? "simulating
|
|
23858
|
+
`Vault ${vault} slot ${slot.index}: ${dryRun ? "simulating " : ""}${plan.direction} of ${formatUi(plan.amount, decimals)} ${mintAddress} (local ${formatUi(localAmount, decimals)} \u2192 target ${formatUi(
|
|
23859
|
+
plan.targetLocal,
|
|
23860
|
+
decimals
|
|
23861
|
+
)})`
|
|
23576
23862
|
);
|
|
23577
23863
|
try {
|
|
23578
|
-
const outcome = await this.
|
|
23864
|
+
const outcome = await this.rebalanceMarginfi({
|
|
23579
23865
|
vault,
|
|
23580
23866
|
vaultPk,
|
|
23581
23867
|
hwManager,
|
|
23582
23868
|
hwManagerAddress,
|
|
23583
23869
|
slot,
|
|
23584
23870
|
mintAddress,
|
|
23585
|
-
|
|
23871
|
+
direction: plan.direction,
|
|
23872
|
+
amount: plan.amount,
|
|
23586
23873
|
marginfiAccounts,
|
|
23587
23874
|
dryRun,
|
|
23588
23875
|
log
|
|
23589
23876
|
});
|
|
23590
23877
|
if (outcome.signature) {
|
|
23591
23878
|
log(
|
|
23592
|
-
`Vault ${vault} slot ${slot.index}:
|
|
23879
|
+
`Vault ${vault} slot ${slot.index}: ${plan.direction} tx ${outcome.signature}`
|
|
23593
23880
|
);
|
|
23594
23881
|
result.signatures.push(outcome.signature);
|
|
23595
23882
|
}
|
|
23596
|
-
result.deposited++;
|
|
23883
|
+
if (plan.direction === "deposit") result.deposited++;
|
|
23884
|
+
else result.withdrawn++;
|
|
23597
23885
|
} catch (err) {
|
|
23598
23886
|
log(
|
|
23599
|
-
`Vault ${vault} slot ${slot.index}:
|
|
23887
|
+
`Vault ${vault} slot ${slot.index}: ${plan.direction} failed \u2014 ${err.message}`
|
|
23600
23888
|
);
|
|
23601
23889
|
result.failed++;
|
|
23602
23890
|
}
|
|
@@ -23604,48 +23892,60 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23604
23892
|
}
|
|
23605
23893
|
return result;
|
|
23606
23894
|
}
|
|
23607
|
-
|
|
23895
|
+
/**
|
|
23896
|
+
* Move `amount` of `mintAddress` between the vault's own token account and
|
|
23897
|
+
* its Marginfi position, in `direction`, through `protocol_interaction`.
|
|
23898
|
+
*/
|
|
23899
|
+
async rebalanceMarginfi(params) {
|
|
23608
23900
|
const {
|
|
23609
23901
|
vault,
|
|
23610
23902
|
hwManager,
|
|
23611
23903
|
hwManagerAddress,
|
|
23612
23904
|
slot,
|
|
23613
23905
|
mintAddress,
|
|
23906
|
+
direction,
|
|
23614
23907
|
amount,
|
|
23615
23908
|
marginfiAccounts,
|
|
23616
23909
|
dryRun = false,
|
|
23617
23910
|
log = () => {
|
|
23618
23911
|
}
|
|
23619
23912
|
} = params;
|
|
23620
|
-
const marginfiClient = new import_marginfi3.CpiClient(
|
|
23913
|
+
const marginfiClient = new import_marginfi3.CpiClient({
|
|
23914
|
+
accounts: marginfiAccounts
|
|
23915
|
+
});
|
|
23621
23916
|
const { getAtaAddress: getAtaAddress16 } = await Promise.resolve().then(() => __toESM(require_dist()));
|
|
23622
|
-
const
|
|
23917
|
+
const vaultAta = getAtaAddress16(
|
|
23623
23918
|
mintAddress,
|
|
23624
23919
|
vault,
|
|
23625
23920
|
marginfiAccounts.tokenProgram,
|
|
23626
23921
|
true
|
|
23627
23922
|
);
|
|
23628
|
-
const
|
|
23629
|
-
marginfiClient.deposit_cpi({
|
|
23923
|
+
const cpiRefs = (0, import_common50.createCpiRefs)([
|
|
23924
|
+
direction === "deposit" ? marginfiClient.deposit_cpi({
|
|
23630
23925
|
marginfiAccount: slot.userAccount,
|
|
23631
23926
|
authority: vault,
|
|
23632
|
-
signerTokenAccount,
|
|
23927
|
+
signerTokenAccount: vaultAta,
|
|
23928
|
+
amount
|
|
23929
|
+
}) : marginfiClient.withdraw_cpi({
|
|
23930
|
+
marginfiAccount: slot.userAccount,
|
|
23931
|
+
authority: vault,
|
|
23932
|
+
destinationTokenAccount: vaultAta,
|
|
23633
23933
|
amount
|
|
23634
23934
|
})
|
|
23635
23935
|
]);
|
|
23636
23936
|
const ix = await this.client.tx.protocolInteraction.getIx({
|
|
23637
23937
|
hwManager: hwManagerAddress,
|
|
23638
23938
|
vault,
|
|
23639
|
-
refs:
|
|
23939
|
+
refs: cpiRefs.refs,
|
|
23640
23940
|
externalLiquidityIndex: slot.index,
|
|
23641
23941
|
affectedAssetMint: mintAddress,
|
|
23642
|
-
affectedVaultAta:
|
|
23942
|
+
affectedVaultAta: vaultAta,
|
|
23643
23943
|
affectedTokenProgram: marginfiAccounts.tokenProgram,
|
|
23644
|
-
accounts:
|
|
23944
|
+
accounts: cpiRefs.accounts
|
|
23645
23945
|
});
|
|
23646
23946
|
const plan = {
|
|
23647
23947
|
instructions: [ix],
|
|
23648
|
-
...
|
|
23948
|
+
...cpiRefs.lookupTables?.length ? { lookupTables: cpiRefs.lookupTables } : {}
|
|
23649
23949
|
};
|
|
23650
23950
|
if (dryRun) {
|
|
23651
23951
|
const sim = await this.client.simulateTransaction(hwManager, plan);
|
|
@@ -23653,9 +23953,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23653
23953
|
log(` | ${line}`);
|
|
23654
23954
|
}
|
|
23655
23955
|
if (sim.err) {
|
|
23656
|
-
throw new Error(
|
|
23657
|
-
`simulation failed: ${JSON.stringify(sim.err)}`
|
|
23658
|
-
);
|
|
23956
|
+
throw new Error(`simulation failed: ${JSON.stringify(sim.err)}`);
|
|
23659
23957
|
}
|
|
23660
23958
|
log(
|
|
23661
23959
|
`Vault ${vault} slot ${slot.index}: simulation OK (${sim.unitsConsumed ?? "?"} CU)`
|
|
@@ -23665,9 +23963,408 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23665
23963
|
return { signature: await this.client.sendTransaction(hwManager, plan) };
|
|
23666
23964
|
}
|
|
23667
23965
|
};
|
|
23966
|
+
|
|
23967
|
+
// src/services/idleLiquidityService.ts
|
|
23968
|
+
var import_kit16 = require("@solana/kit");
|
|
23969
|
+
var import_spl_token19 = require("@solana/spl-token");
|
|
23970
|
+
var import_web329 = require("@solana/web3.js");
|
|
23971
|
+
var import_common51 = __toESM(require_dist());
|
|
23972
|
+
var import_jupiter3 = __toESM(require_dist3());
|
|
23973
|
+
var IDLE_RESERVE_FLOOR_BPS = 400;
|
|
23974
|
+
var IDLE_RESERVE_TARGET_BPS = 500;
|
|
23975
|
+
var DEFAULT_SLIPPAGE_BPS = 30;
|
|
23976
|
+
var DEFAULT_CU_PRICE_MICRO_LAMPORTS = 1e4;
|
|
23977
|
+
var DEFAULT_MAX_ACCOUNTS = 20;
|
|
23978
|
+
var COMPUTE_UNIT_LIMIT = 12e5;
|
|
23979
|
+
var ASSET_REBALANCE_COOLDOWN_SECS = 60;
|
|
23980
|
+
function toBigInt4(value) {
|
|
23981
|
+
if (typeof value === "bigint") return value;
|
|
23982
|
+
if (value !== null && value !== void 0) return BigInt(String(value));
|
|
23983
|
+
return 0n;
|
|
23984
|
+
}
|
|
23985
|
+
function pubkeyStr2(value) {
|
|
23986
|
+
if (typeof value === "string") return value;
|
|
23987
|
+
if (value && typeof value.toBase58 === "function") {
|
|
23988
|
+
return value.toBase58();
|
|
23989
|
+
}
|
|
23990
|
+
return String(value);
|
|
23991
|
+
}
|
|
23992
|
+
function coerceBool4(value) {
|
|
23993
|
+
if (typeof value === "boolean") return value;
|
|
23994
|
+
if (typeof value === "number") return value !== 0;
|
|
23995
|
+
const inner = value?.[0];
|
|
23996
|
+
if (typeof inner === "number") return inner !== 0;
|
|
23997
|
+
return false;
|
|
23998
|
+
}
|
|
23999
|
+
function formatUi2(raw, decimals) {
|
|
24000
|
+
return (Number(raw) / 10 ** decimals).toFixed(Math.min(decimals, 6));
|
|
24001
|
+
}
|
|
24002
|
+
function readHolding(raw) {
|
|
24003
|
+
const h = raw;
|
|
24004
|
+
return {
|
|
24005
|
+
mint: pubkeyStr2(h.mint),
|
|
24006
|
+
price: toBigInt4(h.price),
|
|
24007
|
+
decimals: Number(h.decimals ?? 0),
|
|
24008
|
+
localAmount: toBigInt4(h.localAmount),
|
|
24009
|
+
externalAmount: toBigInt4(h.externalAmount),
|
|
24010
|
+
lastUpdateTs: Number(toBigInt4(h.lastUpdateTs)),
|
|
24011
|
+
lastRebalanceTs: Number(toBigInt4(h.lastRebalanceTs))
|
|
24012
|
+
};
|
|
24013
|
+
}
|
|
24014
|
+
function findHolding2(vaultState, mint) {
|
|
24015
|
+
const holdings = vaultState.holdings ?? [];
|
|
24016
|
+
return holdings.map(readHolding).find((h) => h.mint === mint);
|
|
24017
|
+
}
|
|
24018
|
+
function holdingValue2(holding, amount) {
|
|
24019
|
+
return amount * holding.price / 10n ** BigInt(holding.decimals);
|
|
24020
|
+
}
|
|
24021
|
+
var IdleLiquidityService = class {
|
|
24022
|
+
constructor(client) {
|
|
24023
|
+
this.client = client;
|
|
24024
|
+
}
|
|
24025
|
+
/** Current unix time in seconds (override in tests). */
|
|
24026
|
+
now() {
|
|
24027
|
+
return Math.floor(Date.now() / 1e3);
|
|
24028
|
+
}
|
|
24029
|
+
/**
|
|
24030
|
+
* Top up the vault's idle USDC reserve if it has fallen below the floor.
|
|
24031
|
+
* Never throws for an expected no-op — inspect `status` on the result.
|
|
24032
|
+
*/
|
|
24033
|
+
async run(vault, hwManager, opts = {}) {
|
|
24034
|
+
const log = opts.log ?? (() => {
|
|
24035
|
+
});
|
|
24036
|
+
const vaultState = await this.client.account.fetchVault(vault, {
|
|
24037
|
+
fresh: true
|
|
24038
|
+
});
|
|
24039
|
+
const registeredHwManager = pubkeyStr2(
|
|
24040
|
+
vaultState.roles.hwManager
|
|
24041
|
+
);
|
|
24042
|
+
if (registeredHwManager !== hwManager.publicKey.toBase58()) {
|
|
24043
|
+
throw new Error(
|
|
24044
|
+
`Signer ${hwManager.publicKey.toBase58()} is not the vault hw_manager ${registeredHwManager}`
|
|
24045
|
+
);
|
|
24046
|
+
}
|
|
24047
|
+
const assessment = this.assess(vault, vaultState, log);
|
|
24048
|
+
if (assessment.result) return assessment.result;
|
|
24049
|
+
const { usdc, pst, base } = assessment;
|
|
24050
|
+
const pstInput = this.sizePstInput(base.shortfallUsdc, usdc, pst);
|
|
24051
|
+
if (pstInput === 0n) {
|
|
24052
|
+
const reason = "top-up rounds to zero PST";
|
|
24053
|
+
return { ...base, status: "above-floor", reason };
|
|
24054
|
+
}
|
|
24055
|
+
const cap = opts.maxPstInput !== void 0 && opts.maxPstInput < pst.localAmount ? opts.maxPstInput : pst.localAmount;
|
|
24056
|
+
if (pstInput > cap) {
|
|
24057
|
+
const reason = `top-up needs ${formatUi2(
|
|
24058
|
+
pstInput,
|
|
24059
|
+
pst.decimals
|
|
24060
|
+
)} PST but only ${formatUi2(cap, pst.decimals)} is available`;
|
|
24061
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24062
|
+
return { ...base, status: "insufficient-pst", reason };
|
|
24063
|
+
}
|
|
24064
|
+
const jupiter = new import_jupiter3.JupiterSwapClient(
|
|
24065
|
+
(0, import_kit16.createSolanaRpc)(this.client.provider.connection.rpcEndpoint)
|
|
24066
|
+
);
|
|
24067
|
+
let quote;
|
|
24068
|
+
try {
|
|
24069
|
+
quote = await jupiter.getQuote({
|
|
24070
|
+
inputMint: import_common51.PST_MINT,
|
|
24071
|
+
outputMint: import_common51.USDC_MINT,
|
|
24072
|
+
amount: pstInput,
|
|
24073
|
+
slippageBps: opts.slippageBps ?? DEFAULT_SLIPPAGE_BPS,
|
|
24074
|
+
maxAccounts: DEFAULT_MAX_ACCOUNTS
|
|
24075
|
+
});
|
|
24076
|
+
} catch (err) {
|
|
24077
|
+
log(`Vault ${vault}: Jupiter quote failed \u2014 ${err.message}`);
|
|
24078
|
+
return { ...base, status: "failed", reason: err.message };
|
|
24079
|
+
}
|
|
24080
|
+
log(
|
|
24081
|
+
`Vault ${vault}: swapping ${formatUi2(
|
|
24082
|
+
quote.inputAmount,
|
|
24083
|
+
pst.decimals
|
|
24084
|
+
)} PST -> ${formatUi2(
|
|
24085
|
+
quote.outputAmount,
|
|
24086
|
+
usdc.decimals
|
|
24087
|
+
)} USDC (price impact ${quote.priceImpactPct})`
|
|
24088
|
+
);
|
|
24089
|
+
try {
|
|
24090
|
+
const outcome = await this.executeSwap({
|
|
24091
|
+
vault,
|
|
24092
|
+
vaultState,
|
|
24093
|
+
hwManager,
|
|
24094
|
+
jupiter,
|
|
24095
|
+
quote,
|
|
24096
|
+
cuPriceMicroLamports: opts.cuPriceMicroLamports ?? DEFAULT_CU_PRICE_MICRO_LAMPORTS,
|
|
24097
|
+
dryRun: opts.dryRun ?? false,
|
|
24098
|
+
log
|
|
24099
|
+
});
|
|
24100
|
+
return {
|
|
24101
|
+
...base,
|
|
24102
|
+
status: outcome.signature ? "swapped" : "simulated",
|
|
24103
|
+
reason: outcome.signature ? `swapped in ${outcome.signature}` : "dry run \u2014 simulation succeeded, nothing submitted",
|
|
24104
|
+
pstSpent: quote.inputAmount,
|
|
24105
|
+
usdcReceived: quote.outputAmount,
|
|
24106
|
+
...outcome.signature ? { signature: outcome.signature } : {}
|
|
24107
|
+
};
|
|
24108
|
+
} catch (err) {
|
|
24109
|
+
log(`Vault ${vault}: swap failed \u2014 ${err.message}`);
|
|
24110
|
+
return { ...base, status: "failed", reason: err.message };
|
|
24111
|
+
}
|
|
24112
|
+
}
|
|
24113
|
+
// ── Assessment ──────────────────────────────────────────────────────────
|
|
24114
|
+
/**
|
|
24115
|
+
* Decide whether a top-up is warranted. Returns either a terminal `result`
|
|
24116
|
+
* (nothing to do) or the holdings and sizing needed to build the swap.
|
|
24117
|
+
*/
|
|
24118
|
+
assess(vault, vaultState, log) {
|
|
24119
|
+
const tvl = toBigInt4(
|
|
24120
|
+
vaultState.accounting?.tvl
|
|
24121
|
+
);
|
|
24122
|
+
const empty = {
|
|
24123
|
+
vault,
|
|
24124
|
+
tvl,
|
|
24125
|
+
idleValue: 0n,
|
|
24126
|
+
idleBps: 0,
|
|
24127
|
+
shortfallUsdc: 0n,
|
|
24128
|
+
pstSpent: 0n,
|
|
24129
|
+
usdcReceived: 0n
|
|
24130
|
+
};
|
|
24131
|
+
if (tvl === 0n) {
|
|
24132
|
+
const reason = "vault TVL is zero";
|
|
24133
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24134
|
+
return { result: { ...empty, status: "no-tvl", reason } };
|
|
24135
|
+
}
|
|
24136
|
+
const usdc = findHolding2(vaultState, import_common51.USDC_MINT);
|
|
24137
|
+
const pst = findHolding2(vaultState, import_common51.PST_MINT);
|
|
24138
|
+
if (!usdc || !pst) {
|
|
24139
|
+
const reason = `vault has no ${usdc ? "PST" : "USDC"} holding`;
|
|
24140
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24141
|
+
return { result: { ...empty, status: "missing-holding", reason } };
|
|
24142
|
+
}
|
|
24143
|
+
const stalenessThreshold = this.stalenessThresholdSecs(vaultState);
|
|
24144
|
+
const now = this.now();
|
|
24145
|
+
for (const [name, holding] of [
|
|
24146
|
+
["USDC", usdc],
|
|
24147
|
+
["PST", pst]
|
|
24148
|
+
]) {
|
|
24149
|
+
if (holding.price === 0n) {
|
|
24150
|
+
const reason = `${name} holding has no price set`;
|
|
24151
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24152
|
+
return { result: { ...empty, status: "stale-price", reason } };
|
|
24153
|
+
}
|
|
24154
|
+
if (now - holding.lastUpdateTs > stalenessThreshold) {
|
|
24155
|
+
const reason = `${name} holding price is stale (last update ${holding.lastUpdateTs})`;
|
|
24156
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24157
|
+
return { result: { ...empty, status: "stale-price", reason } };
|
|
24158
|
+
}
|
|
24159
|
+
}
|
|
24160
|
+
const idleAmount = usdc.localAmount + usdc.externalAmount;
|
|
24161
|
+
const idleValue = holdingValue2(usdc, idleAmount);
|
|
24162
|
+
const idleBps = Number(idleValue * 10000n / tvl);
|
|
24163
|
+
const base = { ...empty, idleValue, idleBps };
|
|
24164
|
+
log(
|
|
24165
|
+
`Vault ${vault}: idle USDC ${formatUi2(
|
|
24166
|
+
idleAmount,
|
|
24167
|
+
usdc.decimals
|
|
24168
|
+
)} = ${idleBps}bps of TVL (floor ${IDLE_RESERVE_FLOOR_BPS}bps, target ${IDLE_RESERVE_TARGET_BPS}bps)`
|
|
24169
|
+
);
|
|
24170
|
+
if (idleBps >= IDLE_RESERVE_FLOOR_BPS) {
|
|
24171
|
+
const reason = `idle USDC ${idleBps}bps is at or above the ${IDLE_RESERVE_FLOOR_BPS}bps floor`;
|
|
24172
|
+
return { result: { ...base, status: "above-floor", reason } };
|
|
24173
|
+
}
|
|
24174
|
+
for (const [name, holding] of [
|
|
24175
|
+
["USDC", usdc],
|
|
24176
|
+
["PST", pst]
|
|
24177
|
+
]) {
|
|
24178
|
+
if (holding.lastRebalanceTs !== 0 && now < holding.lastRebalanceTs + ASSET_REBALANCE_COOLDOWN_SECS) {
|
|
24179
|
+
const reason = `${name} holding is in its rebalance cooldown until ${holding.lastRebalanceTs + ASSET_REBALANCE_COOLDOWN_SECS}`;
|
|
24180
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24181
|
+
return { result: { ...base, status: "rebalance-cooldown", reason } };
|
|
24182
|
+
}
|
|
24183
|
+
}
|
|
24184
|
+
const targetValue = tvl * BigInt(IDLE_RESERVE_TARGET_BPS) / 10000n;
|
|
24185
|
+
let shortfallValue = targetValue - idleValue;
|
|
24186
|
+
const allowance = this.remainingRebalanceAllowance(vaultState, tvl, now);
|
|
24187
|
+
if (allowance !== void 0 && allowance < shortfallValue) {
|
|
24188
|
+
if (allowance === 0n) {
|
|
24189
|
+
const reason = "rolling rebalance limit is exhausted for this window";
|
|
24190
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24191
|
+
return { result: { ...base, status: "rebalance-limit", reason } };
|
|
24192
|
+
}
|
|
24193
|
+
log(
|
|
24194
|
+
`Vault ${vault}: rolling rebalance limit caps this run at ${allowance} of ${shortfallValue} accounting units`
|
|
24195
|
+
);
|
|
24196
|
+
shortfallValue = allowance;
|
|
24197
|
+
}
|
|
24198
|
+
const shortfallUsdc = shortfallValue * 10n ** BigInt(usdc.decimals) / usdc.price;
|
|
24199
|
+
if (shortfallUsdc <= 0n) {
|
|
24200
|
+
const reason = "computed shortfall rounds to zero";
|
|
24201
|
+
return { result: { ...base, status: "above-floor", reason } };
|
|
24202
|
+
}
|
|
24203
|
+
if (pst.localAmount === 0n) {
|
|
24204
|
+
const reason = "vault holds no local PST";
|
|
24205
|
+
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
24206
|
+
return {
|
|
24207
|
+
result: { ...base, shortfallUsdc, status: "insufficient-pst", reason }
|
|
24208
|
+
};
|
|
24209
|
+
}
|
|
24210
|
+
return { usdc, pst, base: { ...base, shortfallUsdc } };
|
|
24211
|
+
}
|
|
24212
|
+
/**
|
|
24213
|
+
* Value still chargeable against the vault's rolling rebalance window, in
|
|
24214
|
+
* accounting units. `undefined` when the cap is disabled (unlimited).
|
|
24215
|
+
*/
|
|
24216
|
+
remainingRebalanceAllowance(vaultState, tvl, now) {
|
|
24217
|
+
const limit = vaultState.accounting?.rebalanceLimit;
|
|
24218
|
+
const bps = Number(toBigInt4(limit?.windowLimitBps));
|
|
24219
|
+
if (!limit || bps === 0) return void 0;
|
|
24220
|
+
const windowStartTs = Number(toBigInt4(limit.windowStartTs));
|
|
24221
|
+
const windowDuration = Number(toBigInt4(limit.windowDurationSeconds));
|
|
24222
|
+
const consumed = windowStartTs === 0 || now >= windowStartTs + windowDuration ? 0n : toBigInt4(limit.valueInWindow);
|
|
24223
|
+
const ceiling = tvl * BigInt(bps) / 10000n;
|
|
24224
|
+
return ceiling > consumed ? ceiling - consumed : 0n;
|
|
24225
|
+
}
|
|
24226
|
+
/**
|
|
24227
|
+
* PST input that buys `shortfallUsdc` at the holdings' recorded prices.
|
|
24228
|
+
* Both prices share the vault's accounting unit, so this is a straight
|
|
24229
|
+
* value conversion; slippage is absorbed by landing slightly under target.
|
|
24230
|
+
*/
|
|
24231
|
+
sizePstInput(shortfallUsdc, usdc, pst) {
|
|
24232
|
+
const shortfallValue = holdingValue2(usdc, shortfallUsdc);
|
|
24233
|
+
return shortfallValue * 10n ** BigInt(pst.decimals) / pst.price;
|
|
24234
|
+
}
|
|
24235
|
+
stalenessThresholdSecs(vaultState) {
|
|
24236
|
+
const configured = Number(
|
|
24237
|
+
toBigInt4(
|
|
24238
|
+
vaultState.config?.priceStalenessThresholdSecs
|
|
24239
|
+
)
|
|
24240
|
+
);
|
|
24241
|
+
return configured > 0 ? configured : DEFAULT_PRICE_STALENESS_THRESHOLD_SECS;
|
|
24242
|
+
}
|
|
24243
|
+
// ── Execution ───────────────────────────────────────────────────────────
|
|
24244
|
+
/**
|
|
24245
|
+
* Token program owning a mint. Read from the chain rather than from the
|
|
24246
|
+
* holding's enum so a Token-2022 mint can never be passed to the classic
|
|
24247
|
+
* program (and vice versa).
|
|
24248
|
+
*/
|
|
24249
|
+
async mintTokenProgram(mint) {
|
|
24250
|
+
const account = await this.client.provider.connection.getAccountInfo(
|
|
24251
|
+
new import_web329.PublicKey(mint),
|
|
24252
|
+
"confirmed"
|
|
24253
|
+
);
|
|
24254
|
+
if (!account) throw new Error(`Mint account not found: ${mint}`);
|
|
24255
|
+
if (!account.owner.equals(import_spl_token19.TOKEN_PROGRAM_ID) && !account.owner.equals(import_spl_token19.TOKEN_2022_PROGRAM_ID)) {
|
|
24256
|
+
throw new Error(
|
|
24257
|
+
`Unsupported token program ${account.owner.toBase58()} for mint ${mint}`
|
|
24258
|
+
);
|
|
24259
|
+
}
|
|
24260
|
+
return (0, import_common51.fromWeb3Pk)(account.owner);
|
|
24261
|
+
}
|
|
24262
|
+
/**
|
|
24263
|
+
* Build, simulate, and (unless `dryRun`) submit the `jupiter_swap`.
|
|
24264
|
+
*
|
|
24265
|
+
* Built as a versioned transaction here rather than through
|
|
24266
|
+
* `client.sendTransaction`, because a Jupiter route needs address lookup
|
|
24267
|
+
* tables and a raised compute-unit limit to fit.
|
|
24268
|
+
*/
|
|
24269
|
+
async executeSwap(params) {
|
|
24270
|
+
const {
|
|
24271
|
+
vault,
|
|
24272
|
+
vaultState,
|
|
24273
|
+
hwManager,
|
|
24274
|
+
jupiter,
|
|
24275
|
+
quote,
|
|
24276
|
+
cuPriceMicroLamports,
|
|
24277
|
+
dryRun,
|
|
24278
|
+
log
|
|
24279
|
+
} = params;
|
|
24280
|
+
const signer = (0, import_common51.fromWeb3Pk)(hwManager.publicKey);
|
|
24281
|
+
const [sourceTokenProgram, destinationTokenProgram] = await Promise.all([
|
|
24282
|
+
this.mintTokenProgram(import_common51.PST_MINT),
|
|
24283
|
+
this.mintTokenProgram(import_common51.USDC_MINT)
|
|
24284
|
+
]);
|
|
24285
|
+
const jupiterCpi = await jupiter.getSwapCpiData(quote, vault, {
|
|
24286
|
+
payer: signer
|
|
24287
|
+
});
|
|
24288
|
+
const { accounts: accounts2, refs, lookupTables } = (0, import_common51.createCpiRefs)([jupiterCpi]);
|
|
24289
|
+
const vaultTrancheState = coerceBool4(
|
|
24290
|
+
vaultState.tranchingEnabled
|
|
24291
|
+
) ? (await this.client.pda.deriveVaultTrancheStatePda(vault))[0] : void 0;
|
|
24292
|
+
const plan = await this.client.tx.jupiterSwap.getTx({
|
|
24293
|
+
hwManager: signer,
|
|
24294
|
+
vault,
|
|
24295
|
+
sourceMint: import_common51.PST_MINT,
|
|
24296
|
+
destinationMint: import_common51.USDC_MINT,
|
|
24297
|
+
refs,
|
|
24298
|
+
accounts: accounts2,
|
|
24299
|
+
sourceTokenProgram,
|
|
24300
|
+
destinationTokenProgram,
|
|
24301
|
+
vaultTrancheState,
|
|
24302
|
+
lookupTables
|
|
24303
|
+
});
|
|
24304
|
+
const connection = this.client.provider.connection;
|
|
24305
|
+
const instructions2 = [
|
|
24306
|
+
import_web329.ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNIT_LIMIT }),
|
|
24307
|
+
...cuPriceMicroLamports > 0 ? [
|
|
24308
|
+
import_web329.ComputeBudgetProgram.setComputeUnitPrice({
|
|
24309
|
+
microLamports: cuPriceMicroLamports
|
|
24310
|
+
})
|
|
24311
|
+
] : [],
|
|
24312
|
+
...(jupiterCpi.preInstructions ?? []).map(import_common51.fromKitInstruction),
|
|
24313
|
+
...plan.instructions.map(import_common51.fromKitInstruction)
|
|
24314
|
+
];
|
|
24315
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
24316
|
+
const lookupTableAccounts = await (0, import_common51.fetchLookupTables)(
|
|
24317
|
+
connection,
|
|
24318
|
+
plan.lookupTables ?? []
|
|
24319
|
+
);
|
|
24320
|
+
const message2 = new import_web329.TransactionMessage({
|
|
24321
|
+
payerKey: hwManager.publicKey,
|
|
24322
|
+
recentBlockhash: blockhash,
|
|
24323
|
+
instructions: instructions2
|
|
24324
|
+
}).compileToV0Message(lookupTableAccounts);
|
|
24325
|
+
const transaction = new import_web329.VersionedTransaction(message2);
|
|
24326
|
+
transaction.sign([hwManager]);
|
|
24327
|
+
const simulation = await connection.simulateTransaction(transaction, {
|
|
24328
|
+
sigVerify: true,
|
|
24329
|
+
commitment: "confirmed"
|
|
24330
|
+
});
|
|
24331
|
+
if (simulation.value.err) {
|
|
24332
|
+
for (const line of simulation.value.logs ?? []) log(` | ${line}`);
|
|
24333
|
+
throw new Error(
|
|
24334
|
+
`simulation failed: ${JSON.stringify(simulation.value.err)}`
|
|
24335
|
+
);
|
|
24336
|
+
}
|
|
24337
|
+
log(
|
|
24338
|
+
`Vault ${vault}: simulation OK (${simulation.value.unitsConsumed ?? "?"} CU)`
|
|
24339
|
+
);
|
|
24340
|
+
if (dryRun) {
|
|
24341
|
+
log(`Vault ${vault}: dry run \u2014 transaction NOT submitted`);
|
|
24342
|
+
return {};
|
|
24343
|
+
}
|
|
24344
|
+
const signature = await connection.sendRawTransaction(
|
|
24345
|
+
transaction.serialize(),
|
|
24346
|
+
{ skipPreflight: false, maxRetries: 5 }
|
|
24347
|
+
);
|
|
24348
|
+
const confirmation = await connection.confirmTransaction(
|
|
24349
|
+
{ signature, blockhash, lastValidBlockHeight },
|
|
24350
|
+
"confirmed"
|
|
24351
|
+
);
|
|
24352
|
+
if (confirmation.value.err) {
|
|
24353
|
+
throw new Error(
|
|
24354
|
+
`transaction ${signature} failed: ${JSON.stringify(
|
|
24355
|
+
confirmation.value.err
|
|
24356
|
+
)}`
|
|
24357
|
+
);
|
|
24358
|
+
}
|
|
24359
|
+
this.client.applyCacheInvalidations(plan);
|
|
24360
|
+
log(`Vault ${vault}: swap tx ${signature}`);
|
|
24361
|
+
return { signature };
|
|
24362
|
+
}
|
|
24363
|
+
};
|
|
23668
24364
|
// Annotate the CommonJS export names for ESM import in node:
|
|
23669
24365
|
0 && (module.exports = {
|
|
23670
24366
|
ASSET_DECIMALS,
|
|
24367
|
+
ASSET_REBALANCE_COOLDOWN_SECS,
|
|
23671
24368
|
AccountClient,
|
|
23672
24369
|
ActivateCircuitBreakerBuilder,
|
|
23673
24370
|
CONSENSUS_ORACLE_VARIANT,
|
|
@@ -23678,15 +24375,20 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23678
24375
|
CreateAssetHoldingBuilder,
|
|
23679
24376
|
CreateTrancheStateBuilder,
|
|
23680
24377
|
CreateVaultBuilder,
|
|
24378
|
+
DEFAULT_CU_PRICE_MICRO_LAMPORTS,
|
|
23681
24379
|
DEFAULT_JUNIOR_EARLY_UNSTAKE_FEE_BPS,
|
|
23682
24380
|
DEFAULT_JUNIOR_STANDARD_UNSTAKE_FEE_BPS,
|
|
23683
24381
|
DEFAULT_JUNIOR_WITHDRAWAL_LOCKUP_SECS,
|
|
23684
24382
|
DEFAULT_MAX_ACCEPTABLE_APY_BPS,
|
|
24383
|
+
DEFAULT_MAX_ACCOUNTS,
|
|
23685
24384
|
DEFAULT_MIN_AMOUNT_UI,
|
|
23686
24385
|
DEFAULT_ORACLE_STALENESS_THRESHOLD_SECS,
|
|
23687
24386
|
DEFAULT_PRICE_ORACLE_ACCOUNT,
|
|
23688
24387
|
DEFAULT_PRICE_STALENESS_SECS,
|
|
23689
24388
|
DEFAULT_PRICE_STALENESS_THRESHOLD_SECS,
|
|
24389
|
+
DEFAULT_REBALANCE_BAND_BPS,
|
|
24390
|
+
DEFAULT_SLIPPAGE_BPS,
|
|
24391
|
+
DEFAULT_TARGET_LOCAL_BPS,
|
|
23690
24392
|
DEFAULT_VAULT_ID,
|
|
23691
24393
|
DisableCircuitBreakerBuilder,
|
|
23692
24394
|
EXTERNAL_POSITION_SAMPLES,
|
|
@@ -23700,6 +24402,9 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23700
24402
|
FEE_VAULT_CACHE_CATEGORY,
|
|
23701
24403
|
FulfillJuniorTrancheWithdrawBuilder,
|
|
23702
24404
|
IDL,
|
|
24405
|
+
IDLE_RESERVE_FLOOR_BPS,
|
|
24406
|
+
IDLE_RESERVE_TARGET_BPS,
|
|
24407
|
+
IdleLiquidityService,
|
|
23703
24408
|
InitializeVaultRolesBuilder,
|
|
23704
24409
|
JupiterBalanceSource,
|
|
23705
24410
|
JupiterPriceSource,
|
|
@@ -23813,6 +24518,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
23813
24518
|
mintTokensTo,
|
|
23814
24519
|
mostFrequent,
|
|
23815
24520
|
parseExternalLiquidityRefs,
|
|
24521
|
+
planRebalance,
|
|
23816
24522
|
prepareVaultTransaction,
|
|
23817
24523
|
priceInAccountingUnit,
|
|
23818
24524
|
readI64LE,
|