@perena/vault-sdk 1.0.48 → 1.0.50
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 +4 -3
- package/dist/browser/nest.d.mts +26 -1
- package/dist/browser/nest.mjs +195 -17
- package/dist/index.d.ts +109 -16
- package/dist/index.js +805 -294
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -149,7 +149,7 @@ var require_compat = __commonJS({
|
|
|
149
149
|
exports2.fromWeb3PublicKey = fromWeb3PublicKey;
|
|
150
150
|
exports2.toWeb3PublicKey = toWeb3PublicKey;
|
|
151
151
|
exports2.asWeb3PublicKey = asWeb3PublicKey2;
|
|
152
|
-
exports2.toKitInstruction =
|
|
152
|
+
exports2.toKitInstruction = toKitInstruction36;
|
|
153
153
|
exports2.fromKitInstruction = fromKitInstruction3;
|
|
154
154
|
var kit_1 = require("@solana/kit");
|
|
155
155
|
var web3_js_1 = require("@solana/web3.js");
|
|
@@ -165,7 +165,7 @@ var require_compat = __commonJS({
|
|
|
165
165
|
exports2.toAddress = fromWeb3PublicKey;
|
|
166
166
|
exports2.fromWeb3Pk = fromWeb3PublicKey;
|
|
167
167
|
exports2.toWeb3Pk = toWeb3PublicKey;
|
|
168
|
-
function
|
|
168
|
+
function toKitInstruction36(ix) {
|
|
169
169
|
return {
|
|
170
170
|
programAddress: ix.programId.toBase58(),
|
|
171
171
|
data: new Uint8Array(ix.data),
|
|
@@ -253,9 +253,9 @@ var require_meta = __commonJS({
|
|
|
253
253
|
exports2.toCustomAccountMeta = toCustomAccountMeta;
|
|
254
254
|
exports2.toCustomAccountMetaFromWeb3AccountMeta = toCustomAccountMetaFromWeb3AccountMeta;
|
|
255
255
|
var roles_1 = require_roles();
|
|
256
|
-
function toCustomAccountMeta(
|
|
256
|
+
function toCustomAccountMeta(address15, isWritable, requiredAtaDetails, isSigner) {
|
|
257
257
|
const role = (0, roles_1.getAccountRole)(isWritable ?? false, isSigner ?? false);
|
|
258
|
-
return { address:
|
|
258
|
+
return { address: address15, role, isRequiredAta: requiredAtaDetails };
|
|
259
259
|
}
|
|
260
260
|
function toCustomAccountMetaFromWeb3AccountMeta(web3AccountMeta) {
|
|
261
261
|
return toCustomAccountMeta(web3AccountMeta.pubkey.toBase58(), web3AccountMeta.isWritable, void 0, web3AccountMeta.isSigner);
|
|
@@ -1236,8 +1236,8 @@ var require_cpiClient = __commonJS({
|
|
|
1236
1236
|
var kit_1 = require("@solana/kit");
|
|
1237
1237
|
var common_1 = require_dist();
|
|
1238
1238
|
var constants_1 = require_constants3();
|
|
1239
|
-
function account(
|
|
1240
|
-
return { address:
|
|
1239
|
+
function account(address15, role) {
|
|
1240
|
+
return { address: address15, role };
|
|
1241
1241
|
}
|
|
1242
1242
|
function requiredAddress(value, label) {
|
|
1243
1243
|
if (!value) {
|
|
@@ -1326,7 +1326,7 @@ var require_cpiClient = __commonJS({
|
|
|
1326
1326
|
});
|
|
1327
1327
|
const bankAndOracleRemainingAccounts = [
|
|
1328
1328
|
account(this.accounts.bank, kit_1.AccountRole.READONLY),
|
|
1329
|
-
...this.accounts.oracleAccounts.map((
|
|
1329
|
+
...this.accounts.oracleAccounts.map((address15) => account(address15, kit_1.AccountRole.READONLY))
|
|
1330
1330
|
];
|
|
1331
1331
|
return {
|
|
1332
1332
|
cpiType: params.cpiType ?? common_1.CpiTypes.MARGINFI_WITHDRAW,
|
|
@@ -1479,6 +1479,140 @@ var require_dist2 = __commonJS({
|
|
|
1479
1479
|
}
|
|
1480
1480
|
});
|
|
1481
1481
|
|
|
1482
|
+
// ../nest/dist/priceApi.js
|
|
1483
|
+
var require_priceApi = __commonJS({
|
|
1484
|
+
"../nest/dist/priceApi.js"(exports2) {
|
|
1485
|
+
"use strict";
|
|
1486
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1487
|
+
exports2.NEST_API_BASE_URL = void 0;
|
|
1488
|
+
exports2.fetchNestVaultSharePrice = fetchNestVaultSharePrice2;
|
|
1489
|
+
exports2.NEST_API_BASE_URL = "https://api.nest.credit/v1";
|
|
1490
|
+
async function fetchNestVaultSharePrice2(vaultSlug, opts = {}) {
|
|
1491
|
+
const baseUrl = (opts.baseUrl ?? exports2.NEST_API_BASE_URL).replace(/\/$/, "");
|
|
1492
|
+
const response = await (opts.fetchFn ?? fetch)(`${baseUrl}/vaults/${encodeURIComponent(vaultSlug)}/price`);
|
|
1493
|
+
if (!response.ok) {
|
|
1494
|
+
throw new Error(`Nest price API request failed: ${response.status} ${response.statusText}`);
|
|
1495
|
+
}
|
|
1496
|
+
const body = await response.json();
|
|
1497
|
+
const price = [body.data?.interpolatedPrice, body.data?.price].map(Number).find((candidate) => Number.isFinite(candidate) && candidate > 0);
|
|
1498
|
+
if (price === void 0) {
|
|
1499
|
+
throw new Error("Nest price API returned no positive share price");
|
|
1500
|
+
}
|
|
1501
|
+
return price;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
});
|
|
1505
|
+
|
|
1506
|
+
// ../nest/dist/redemptionApi.js
|
|
1507
|
+
var require_redemptionApi = __commonJS({
|
|
1508
|
+
"../nest/dist/redemptionApi.js"(exports2) {
|
|
1509
|
+
"use strict";
|
|
1510
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1511
|
+
exports2.NestApiError = void 0;
|
|
1512
|
+
exports2.assertNestShareAmount = assertNestShareAmount;
|
|
1513
|
+
exports2.fetchNestRedemptionTransaction = fetchNestRedemptionTransaction2;
|
|
1514
|
+
exports2.fetchNestRedemptionQuote = fetchNestRedemptionQuote2;
|
|
1515
|
+
exports2.fetchNestRedemptionStatus = fetchNestRedemptionStatus2;
|
|
1516
|
+
var priceApi_1 = require_priceApi();
|
|
1517
|
+
var NestApiError2 = class extends Error {
|
|
1518
|
+
constructor(status, message2) {
|
|
1519
|
+
super(`Nest API (${status}): ${message2}`);
|
|
1520
|
+
this.status = status;
|
|
1521
|
+
this.name = "NestApiError";
|
|
1522
|
+
}
|
|
1523
|
+
};
|
|
1524
|
+
exports2.NestApiError = NestApiError2;
|
|
1525
|
+
function assertNestShareAmount(amount) {
|
|
1526
|
+
if (typeof amount !== "bigint" || amount <= 0n || amount > 0xffffffffffffffffn) {
|
|
1527
|
+
throw new Error("Nest share amount must be a positive u64 bigint in base units");
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
async function request(path2, options, body) {
|
|
1531
|
+
const response = await (options.fetchFn ?? fetch)(`${(options.baseUrl ?? priceApi_1.NEST_API_BASE_URL).replace(/\/$/, "")}${path2}`, {
|
|
1532
|
+
method: body ? "POST" : "GET",
|
|
1533
|
+
headers: body ? { "Content-Type": "application/json" } : void 0,
|
|
1534
|
+
body: body ? JSON.stringify(body) : void 0,
|
|
1535
|
+
signal: options.signal
|
|
1536
|
+
});
|
|
1537
|
+
const payload = await response.json().catch(() => null);
|
|
1538
|
+
if (!response.ok) {
|
|
1539
|
+
throw new NestApiError2(response.status, typeof payload?.error === "string" ? payload.error : response.statusText);
|
|
1540
|
+
}
|
|
1541
|
+
if (!payload || typeof payload !== "object" || !payload.data) {
|
|
1542
|
+
throw new Error("Nest API returned an invalid response");
|
|
1543
|
+
}
|
|
1544
|
+
return payload.data;
|
|
1545
|
+
}
|
|
1546
|
+
async function fetchNestRedemptionTransaction2(args, options = {}) {
|
|
1547
|
+
assertNestShareAmount(args.rawAmountNestToken);
|
|
1548
|
+
const data = await request("/solana/nest/async-redeem/request/build-tx", options, {
|
|
1549
|
+
...args,
|
|
1550
|
+
rawAmountNestToken: args.rawAmountNestToken.toString(),
|
|
1551
|
+
// Squads must sign both the token authority and LayerZero fee payer at execution.
|
|
1552
|
+
feePayer: args.owner
|
|
1553
|
+
});
|
|
1554
|
+
if (typeof data.txBase64 !== "string" || !data.txBase64.length) {
|
|
1555
|
+
throw new Error("Nest API returned no transaction");
|
|
1556
|
+
}
|
|
1557
|
+
return data.txBase64;
|
|
1558
|
+
}
|
|
1559
|
+
async function fetchNestRedemptionQuote2(args, options = {}) {
|
|
1560
|
+
assertNestShareAmount(args.rawAmountNestToken);
|
|
1561
|
+
const data = await request("/solana/nest/async-redeem/quote", options, {
|
|
1562
|
+
...args,
|
|
1563
|
+
rawAmountNestToken: args.rawAmountNestToken.toString()
|
|
1564
|
+
});
|
|
1565
|
+
if (data.nestVaultSlug !== args.nestVaultSlug || data.redemptionAsset !== "USDC" || data.shareAmount !== args.rawAmountNestToken.toString() || !Number.isInteger(data.shareDecimals) || data.shareDecimals < 0 || data.shareDecimals > 18 || data.redemptionDecimals !== 6 || typeof data.redemptionAmount !== "string" || typeof data.feeAmount !== "string" || !/^\d+$/.test(data.redemptionAmount) || !/^\d+$/.test(data.feeAmount)) {
|
|
1566
|
+
throw new Error("Nest API returned an invalid redemption quote");
|
|
1567
|
+
}
|
|
1568
|
+
return data;
|
|
1569
|
+
}
|
|
1570
|
+
async function fetchNestRedemptionStatus2(signature, options = {}) {
|
|
1571
|
+
if (!/^[1-9A-HJ-NP-Za-km-z]{64,88}$/.test(signature)) {
|
|
1572
|
+
throw new Error("Enter a Solana withdrawal execution signature");
|
|
1573
|
+
}
|
|
1574
|
+
let data;
|
|
1575
|
+
try {
|
|
1576
|
+
data = await request(`/solana/redeem-status/${encodeURIComponent(signature)}`, options);
|
|
1577
|
+
} catch (error) {
|
|
1578
|
+
if (error instanceof NestApiError2 && error.status === 404)
|
|
1579
|
+
return null;
|
|
1580
|
+
throw error;
|
|
1581
|
+
}
|
|
1582
|
+
if (data.solanaBurnSignature !== signature || typeof data.solanaWallet !== "string" || typeof data.overallStatus !== "string" || !["solanaBurn", "plumeProcessing", "cctpAttestation", "solanaClaim"].every((key) => typeof data.steps?.[key]?.status === "string")) {
|
|
1583
|
+
throw new Error("Nest API returned an invalid redemption status");
|
|
1584
|
+
}
|
|
1585
|
+
return data;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
|
|
1590
|
+
// ../nest/dist/index.js
|
|
1591
|
+
var require_dist3 = __commonJS({
|
|
1592
|
+
"../nest/dist/index.js"(exports2) {
|
|
1593
|
+
"use strict";
|
|
1594
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
1595
|
+
if (k2 === void 0) k2 = k;
|
|
1596
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1597
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1598
|
+
desc = { enumerable: true, get: function() {
|
|
1599
|
+
return m[k];
|
|
1600
|
+
} };
|
|
1601
|
+
}
|
|
1602
|
+
Object.defineProperty(o, k2, desc);
|
|
1603
|
+
}) : (function(o, m, k, k2) {
|
|
1604
|
+
if (k2 === void 0) k2 = k;
|
|
1605
|
+
o[k2] = m[k];
|
|
1606
|
+
}));
|
|
1607
|
+
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
1608
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
1609
|
+
};
|
|
1610
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
1611
|
+
__exportStar(require_priceApi(), exports2);
|
|
1612
|
+
__exportStar(require_redemptionApi(), exports2);
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
|
|
1482
1616
|
// ../../node_modules/.pnpm/@jup-ag+api@6.0.48/node_modules/@jup-ag/api/dist/index.mjs
|
|
1483
1617
|
var dist_exports = {};
|
|
1484
1618
|
__export(dist_exports, {
|
|
@@ -2844,12 +2978,12 @@ var require_routePreInstructions = __commonJS({
|
|
|
2844
2978
|
if (existingAta.value) {
|
|
2845
2979
|
continue;
|
|
2846
2980
|
}
|
|
2847
|
-
instructions2.push(
|
|
2981
|
+
instructions2.push(toKitInstruction36((0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(new web3_js_1.PublicKey(payer), new web3_js_1.PublicKey(ata), new web3_js_1.PublicKey(user), new web3_js_1.PublicKey(mint), new web3_js_1.PublicKey(tokenProgram), spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID)));
|
|
2848
2982
|
postSuccessCacheInvalidations.push({ address: ata });
|
|
2849
2983
|
}
|
|
2850
2984
|
return { instructions: instructions2, postSuccessCacheInvalidations };
|
|
2851
2985
|
}
|
|
2852
|
-
function
|
|
2986
|
+
function toKitInstruction36(ix) {
|
|
2853
2987
|
return {
|
|
2854
2988
|
programAddress: ix.programId.toBase58(),
|
|
2855
2989
|
accounts: ix.keys.map((account) => ({
|
|
@@ -2978,7 +3112,7 @@ var require_client = __commonJS({
|
|
|
2978
3112
|
});
|
|
2979
3113
|
|
|
2980
3114
|
// ../../node_modules/.pnpm/jupiter@file+typescript+jupiter_bufferutil@4.1.0_fastestsmallesttextencoderdecoder@1.0._929400004aea12c8b3c9bcc7c5a22ec9/node_modules/jupiter/dist/priceApi.js
|
|
2981
|
-
var
|
|
3115
|
+
var require_priceApi2 = __commonJS({
|
|
2982
3116
|
"../../node_modules/.pnpm/jupiter@file+typescript+jupiter_bufferutil@4.1.0_fastestsmallesttextencoderdecoder@1.0._929400004aea12c8b3c9bcc7c5a22ec9/node_modules/jupiter/dist/priceApi.js"(exports2) {
|
|
2983
3117
|
"use strict";
|
|
2984
3118
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -3109,7 +3243,7 @@ var require_types4 = __commonJS({
|
|
|
3109
3243
|
});
|
|
3110
3244
|
|
|
3111
3245
|
// ../../node_modules/.pnpm/jupiter@file+typescript+jupiter_bufferutil@4.1.0_fastestsmallesttextencoderdecoder@1.0._929400004aea12c8b3c9bcc7c5a22ec9/node_modules/jupiter/dist/index.js
|
|
3112
|
-
var
|
|
3246
|
+
var require_dist4 = __commonJS({
|
|
3113
3247
|
"../../node_modules/.pnpm/jupiter@file+typescript+jupiter_bufferutil@4.1.0_fastestsmallesttextencoderdecoder@1.0._929400004aea12c8b3c9bcc7c5a22ec9/node_modules/jupiter/dist/index.js"(exports2) {
|
|
3114
3248
|
"use strict";
|
|
3115
3249
|
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -3132,144 +3266,10 @@ var require_dist3 = __commonJS({
|
|
|
3132
3266
|
__exportStar(require_api(), exports2);
|
|
3133
3267
|
__exportStar(require_client(), exports2);
|
|
3134
3268
|
__exportStar(require_constants4(), exports2);
|
|
3135
|
-
__exportStar(require_priceApi(), exports2);
|
|
3136
|
-
__exportStar(require_routePreInstructions(), exports2);
|
|
3137
|
-
__exportStar(require_sizeExactInForMinOutput(), exports2);
|
|
3138
|
-
__exportStar(require_types4(), exports2);
|
|
3139
|
-
}
|
|
3140
|
-
});
|
|
3141
|
-
|
|
3142
|
-
// ../nest/dist/priceApi.js
|
|
3143
|
-
var require_priceApi2 = __commonJS({
|
|
3144
|
-
"../nest/dist/priceApi.js"(exports2) {
|
|
3145
|
-
"use strict";
|
|
3146
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3147
|
-
exports2.NEST_API_BASE_URL = void 0;
|
|
3148
|
-
exports2.fetchNestVaultSharePrice = fetchNestVaultSharePrice2;
|
|
3149
|
-
exports2.NEST_API_BASE_URL = "https://api.nest.credit/v1";
|
|
3150
|
-
async function fetchNestVaultSharePrice2(vaultSlug, opts = {}) {
|
|
3151
|
-
const baseUrl = (opts.baseUrl ?? exports2.NEST_API_BASE_URL).replace(/\/$/, "");
|
|
3152
|
-
const response = await (opts.fetchFn ?? fetch)(`${baseUrl}/vaults/${encodeURIComponent(vaultSlug)}/price`);
|
|
3153
|
-
if (!response.ok) {
|
|
3154
|
-
throw new Error(`Nest price API request failed: ${response.status} ${response.statusText}`);
|
|
3155
|
-
}
|
|
3156
|
-
const body = await response.json();
|
|
3157
|
-
const price = [body.data?.interpolatedPrice, body.data?.price].map(Number).find((candidate) => Number.isFinite(candidate) && candidate > 0);
|
|
3158
|
-
if (price === void 0) {
|
|
3159
|
-
throw new Error("Nest price API returned no positive share price");
|
|
3160
|
-
}
|
|
3161
|
-
return price;
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
});
|
|
3165
|
-
|
|
3166
|
-
// ../nest/dist/redemptionApi.js
|
|
3167
|
-
var require_redemptionApi = __commonJS({
|
|
3168
|
-
"../nest/dist/redemptionApi.js"(exports2) {
|
|
3169
|
-
"use strict";
|
|
3170
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3171
|
-
exports2.NestApiError = void 0;
|
|
3172
|
-
exports2.assertNestShareAmount = assertNestShareAmount;
|
|
3173
|
-
exports2.fetchNestRedemptionTransaction = fetchNestRedemptionTransaction2;
|
|
3174
|
-
exports2.fetchNestRedemptionQuote = fetchNestRedemptionQuote2;
|
|
3175
|
-
exports2.fetchNestRedemptionStatus = fetchNestRedemptionStatus2;
|
|
3176
|
-
var priceApi_1 = require_priceApi2();
|
|
3177
|
-
var NestApiError2 = class extends Error {
|
|
3178
|
-
constructor(status, message2) {
|
|
3179
|
-
super(`Nest API (${status}): ${message2}`);
|
|
3180
|
-
this.status = status;
|
|
3181
|
-
this.name = "NestApiError";
|
|
3182
|
-
}
|
|
3183
|
-
};
|
|
3184
|
-
exports2.NestApiError = NestApiError2;
|
|
3185
|
-
function assertNestShareAmount(amount) {
|
|
3186
|
-
if (typeof amount !== "bigint" || amount <= 0n || amount > 0xffffffffffffffffn) {
|
|
3187
|
-
throw new Error("Nest share amount must be a positive u64 bigint in base units");
|
|
3188
|
-
}
|
|
3189
|
-
}
|
|
3190
|
-
async function request(path2, options, body) {
|
|
3191
|
-
const response = await (options.fetchFn ?? fetch)(`${(options.baseUrl ?? priceApi_1.NEST_API_BASE_URL).replace(/\/$/, "")}${path2}`, {
|
|
3192
|
-
method: body ? "POST" : "GET",
|
|
3193
|
-
headers: body ? { "Content-Type": "application/json" } : void 0,
|
|
3194
|
-
body: body ? JSON.stringify(body) : void 0,
|
|
3195
|
-
signal: options.signal
|
|
3196
|
-
});
|
|
3197
|
-
const payload = await response.json().catch(() => null);
|
|
3198
|
-
if (!response.ok) {
|
|
3199
|
-
throw new NestApiError2(response.status, typeof payload?.error === "string" ? payload.error : response.statusText);
|
|
3200
|
-
}
|
|
3201
|
-
if (!payload || typeof payload !== "object" || !payload.data) {
|
|
3202
|
-
throw new Error("Nest API returned an invalid response");
|
|
3203
|
-
}
|
|
3204
|
-
return payload.data;
|
|
3205
|
-
}
|
|
3206
|
-
async function fetchNestRedemptionTransaction2(args, options = {}) {
|
|
3207
|
-
assertNestShareAmount(args.rawAmountNestToken);
|
|
3208
|
-
const data = await request("/solana/nest/async-redeem/request/build-tx", options, {
|
|
3209
|
-
...args,
|
|
3210
|
-
rawAmountNestToken: args.rawAmountNestToken.toString(),
|
|
3211
|
-
// Squads must sign both the token authority and LayerZero fee payer at execution.
|
|
3212
|
-
feePayer: args.owner
|
|
3213
|
-
});
|
|
3214
|
-
if (typeof data.txBase64 !== "string" || !data.txBase64.length) {
|
|
3215
|
-
throw new Error("Nest API returned no transaction");
|
|
3216
|
-
}
|
|
3217
|
-
return data.txBase64;
|
|
3218
|
-
}
|
|
3219
|
-
async function fetchNestRedemptionQuote2(args, options = {}) {
|
|
3220
|
-
assertNestShareAmount(args.rawAmountNestToken);
|
|
3221
|
-
const data = await request("/solana/nest/async-redeem/quote", options, {
|
|
3222
|
-
...args,
|
|
3223
|
-
rawAmountNestToken: args.rawAmountNestToken.toString()
|
|
3224
|
-
});
|
|
3225
|
-
if (data.nestVaultSlug !== args.nestVaultSlug || data.redemptionAsset !== "USDC" || data.shareAmount !== args.rawAmountNestToken.toString() || !Number.isInteger(data.shareDecimals) || data.shareDecimals < 0 || data.shareDecimals > 18 || data.redemptionDecimals !== 6 || typeof data.redemptionAmount !== "string" || typeof data.feeAmount !== "string" || !/^\d+$/.test(data.redemptionAmount) || !/^\d+$/.test(data.feeAmount)) {
|
|
3226
|
-
throw new Error("Nest API returned an invalid redemption quote");
|
|
3227
|
-
}
|
|
3228
|
-
return data;
|
|
3229
|
-
}
|
|
3230
|
-
async function fetchNestRedemptionStatus2(signature, options = {}) {
|
|
3231
|
-
if (!/^[1-9A-HJ-NP-Za-km-z]{64,88}$/.test(signature)) {
|
|
3232
|
-
throw new Error("Enter a Solana withdrawal execution signature");
|
|
3233
|
-
}
|
|
3234
|
-
let data;
|
|
3235
|
-
try {
|
|
3236
|
-
data = await request(`/solana/redeem-status/${encodeURIComponent(signature)}`, options);
|
|
3237
|
-
} catch (error) {
|
|
3238
|
-
if (error instanceof NestApiError2 && error.status === 404)
|
|
3239
|
-
return null;
|
|
3240
|
-
throw error;
|
|
3241
|
-
}
|
|
3242
|
-
if (data.solanaBurnSignature !== signature || typeof data.solanaWallet !== "string" || typeof data.overallStatus !== "string" || !["solanaBurn", "plumeProcessing", "cctpAttestation", "solanaClaim"].every((key) => typeof data.steps?.[key]?.status === "string")) {
|
|
3243
|
-
throw new Error("Nest API returned an invalid redemption status");
|
|
3244
|
-
}
|
|
3245
|
-
return data;
|
|
3246
|
-
}
|
|
3247
|
-
}
|
|
3248
|
-
});
|
|
3249
|
-
|
|
3250
|
-
// ../nest/dist/index.js
|
|
3251
|
-
var require_dist4 = __commonJS({
|
|
3252
|
-
"../nest/dist/index.js"(exports2) {
|
|
3253
|
-
"use strict";
|
|
3254
|
-
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
3255
|
-
if (k2 === void 0) k2 = k;
|
|
3256
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
3257
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
3258
|
-
desc = { enumerable: true, get: function() {
|
|
3259
|
-
return m[k];
|
|
3260
|
-
} };
|
|
3261
|
-
}
|
|
3262
|
-
Object.defineProperty(o, k2, desc);
|
|
3263
|
-
}) : (function(o, m, k, k2) {
|
|
3264
|
-
if (k2 === void 0) k2 = k;
|
|
3265
|
-
o[k2] = m[k];
|
|
3266
|
-
}));
|
|
3267
|
-
var __exportStar = exports2 && exports2.__exportStar || function(m, exports3) {
|
|
3268
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
3269
|
-
};
|
|
3270
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3271
3269
|
__exportStar(require_priceApi2(), exports2);
|
|
3272
|
-
__exportStar(
|
|
3270
|
+
__exportStar(require_routePreInstructions(), exports2);
|
|
3271
|
+
__exportStar(require_sizeExactInForMinOutput(), exports2);
|
|
3272
|
+
__exportStar(require_types4(), exports2);
|
|
3273
3273
|
}
|
|
3274
3274
|
});
|
|
3275
3275
|
|
|
@@ -3302,7 +3302,7 @@ __export(index_exports, {
|
|
|
3302
3302
|
DEFAULT_JUNIOR_WITHDRAWAL_LOCKUP_SECS: () => DEFAULT_JUNIOR_WITHDRAWAL_LOCKUP_SECS,
|
|
3303
3303
|
DEFAULT_MAX_ACCEPTABLE_APY_BPS: () => DEFAULT_MAX_ACCEPTABLE_APY_BPS,
|
|
3304
3304
|
DEFAULT_MAX_ACCOUNTS: () => DEFAULT_MAX_ACCOUNTS,
|
|
3305
|
-
DEFAULT_MINTS: () =>
|
|
3305
|
+
DEFAULT_MINTS: () => import_common62.DEFAULT_MINTS,
|
|
3306
3306
|
DEFAULT_MIN_AMOUNT_UI: () => DEFAULT_MIN_AMOUNT_UI,
|
|
3307
3307
|
DEFAULT_ORACLE_STALENESS_THRESHOLD_SECS: () => DEFAULT_ORACLE_STALENESS_THRESHOLD_SECS,
|
|
3308
3308
|
DEFAULT_PRICE_ORACLE_ACCOUNT: () => DEFAULT_PRICE_ORACLE_ACCOUNT,
|
|
@@ -3311,6 +3311,7 @@ __export(index_exports, {
|
|
|
3311
3311
|
DEFAULT_REBALANCE_BAND_BPS: () => DEFAULT_REBALANCE_BAND_BPS,
|
|
3312
3312
|
DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
|
|
3313
3313
|
DEFAULT_TARGET_LOCAL_BPS: () => DEFAULT_TARGET_LOCAL_BPS,
|
|
3314
|
+
DEFAULT_TARGET_LOCAL_USDC_TVL_BPS: () => DEFAULT_TARGET_LOCAL_USDC_TVL_BPS,
|
|
3314
3315
|
DEFAULT_VAULT_ID: () => DEFAULT_VAULT_ID,
|
|
3315
3316
|
DisableCircuitBreakerBuilder: () => DisableCircuitBreakerBuilder,
|
|
3316
3317
|
DistributeIncentiveBuilder: () => DistributeIncentiveBuilder,
|
|
@@ -3338,6 +3339,8 @@ __export(index_exports, {
|
|
|
3338
3339
|
LOCAL_PROTOCOL_ADMIN: () => LOCAL_PROTOCOL_ADMIN,
|
|
3339
3340
|
LargeBalanceChangeError: () => LargeBalanceChangeError,
|
|
3340
3341
|
LivePriceSource: () => LivePriceSource,
|
|
3342
|
+
MANAGER_WALLET_NAV_DROP_TRIGGER_BPS: () => MANAGER_WALLET_NAV_DROP_TRIGGER_BPS,
|
|
3343
|
+
MANAGER_WALLET_NAV_TOLERANCE_BPS: () => MANAGER_WALLET_NAV_TOLERANCE_BPS,
|
|
3341
3344
|
MAX_APY_ANCHOR_WINDOW_SECS: () => MAX_APY_ANCHOR_WINDOW_SECS,
|
|
3342
3345
|
MAX_BALANCE_CHANGE_BPS: () => MAX_BALANCE_CHANGE_BPS,
|
|
3343
3346
|
MAX_CONSENSUS_SIGNERS: () => MAX_CONSENSUS_SIGNERS,
|
|
@@ -3349,7 +3352,7 @@ __export(index_exports, {
|
|
|
3349
3352
|
ManagerRedepositAssetBuilder: () => ManagerRedepositAssetBuilder,
|
|
3350
3353
|
ManagerWithdrawAssetBuilder: () => ManagerWithdrawAssetBuilder,
|
|
3351
3354
|
MarginfiPositionProvider: () => MarginfiPositionProvider,
|
|
3352
|
-
MintRegistry: () =>
|
|
3355
|
+
MintRegistry: () => import_common62.MintRegistry,
|
|
3353
3356
|
MockYieldTracker: () => MockYieldTracker,
|
|
3354
3357
|
NEST_API_BASE_URL: () => import_nest2.NEST_API_BASE_URL,
|
|
3355
3358
|
NEST_RWA_SHARE_MINT: () => NEST_RWA_SHARE_MINT,
|
|
@@ -3370,6 +3373,7 @@ __export(index_exports, {
|
|
|
3370
3373
|
RemoveAssetHoldingBuilder: () => RemoveAssetHoldingBuilder,
|
|
3371
3374
|
ReportIncentiveV3Builder: () => ReportIncentiveV3Builder,
|
|
3372
3375
|
RequestJuniorTrancheWithdrawBuilder: () => RequestJuniorTrancheWithdrawBuilder,
|
|
3376
|
+
RpcManagerWalletBalanceSource: () => RpcManagerWalletBalanceSource,
|
|
3373
3377
|
SHARE_DECIMALS: () => SHARE_DECIMALS,
|
|
3374
3378
|
SYSTEM_PROGRAM: () => SYSTEM_PROGRAM,
|
|
3375
3379
|
SetAssetPriceOracleBuilder: () => SetAssetPriceOracleBuilder,
|
|
@@ -3409,6 +3413,7 @@ __export(index_exports, {
|
|
|
3409
3413
|
VaultClient: () => VaultClient,
|
|
3410
3414
|
VaultQuoteClient: () => VaultQuoteClient,
|
|
3411
3415
|
VaultReallocationBuilder: () => VaultReallocationBuilder,
|
|
3416
|
+
WITHDRAWABLE_RESERVE_FLOOR_BPS: () => WITHDRAWABLE_RESERVE_FLOOR_BPS,
|
|
3412
3417
|
WithdrawalQueueService: () => WithdrawalQueueService,
|
|
3413
3418
|
accountingUnitPriceToUsd: () => accountingUnitPriceToUsd,
|
|
3414
3419
|
addCashflowUpdate: () => addCashflowUpdate,
|
|
@@ -3418,8 +3423,10 @@ __export(index_exports, {
|
|
|
3418
3423
|
assertNoUnconfirmedYieldPayments: () => assertNoUnconfirmedYieldPayments,
|
|
3419
3424
|
buildHoldingUpdate: () => buildHoldingUpdate,
|
|
3420
3425
|
buildMarginfiWithdrawInteraction: () => buildMarginfiWithdrawInteraction,
|
|
3426
|
+
buildNestDepositRequest: () => buildNestDepositRequest,
|
|
3421
3427
|
buildNestWithdrawalRequest: () => buildNestWithdrawalRequest,
|
|
3422
3428
|
buildUpdates: () => buildUpdates,
|
|
3429
|
+
candidateGrossNav: () => candidateGrossNav,
|
|
3423
3430
|
coerceBool: () => coerceBool3,
|
|
3424
3431
|
collectSamples: () => collectSamples,
|
|
3425
3432
|
confirmYieldPayment: () => confirmYieldPayment,
|
|
@@ -3431,6 +3438,7 @@ __export(index_exports, {
|
|
|
3431
3438
|
createVaultClient: () => createVaultClient,
|
|
3432
3439
|
createYieldPayment: () => createYieldPayment,
|
|
3433
3440
|
dateToStr: () => dateToStr,
|
|
3441
|
+
decodeNestDepositRequest: () => decodeNestDepositRequest,
|
|
3434
3442
|
decodeNestWithdrawalRequest: () => decodeNestWithdrawalRequest,
|
|
3435
3443
|
decodePendingConsensusSigners: () => decodePendingConsensusSigners,
|
|
3436
3444
|
defaultKeypairPath: () => defaultKeypairPath,
|
|
@@ -3478,16 +3486,19 @@ __export(index_exports, {
|
|
|
3478
3486
|
loadKeypair: () => loadKeypair,
|
|
3479
3487
|
logProspectiveApy: () => logProspectiveApy,
|
|
3480
3488
|
makeProvider: () => makeProvider,
|
|
3489
|
+
managerReconciliationStateKey: () => managerReconciliationStateKey,
|
|
3481
3490
|
mintTokensTo: () => mintTokensTo,
|
|
3482
|
-
mints: () =>
|
|
3491
|
+
mints: () => import_common62.mints,
|
|
3483
3492
|
mostFrequent: () => mostFrequent,
|
|
3484
3493
|
parseExternalLiquidityRefs: () => parseExternalLiquidityRefs,
|
|
3485
3494
|
planRebalance: () => planRebalance,
|
|
3486
3495
|
prepareSquadsProposalUpload: () => prepareSquadsProposalUpload,
|
|
3487
3496
|
prepareVaultTransaction: () => prepareVaultTransaction,
|
|
3497
|
+
previousPhysicalNav: () => previousPhysicalNav,
|
|
3488
3498
|
priceInAccountingUnit: () => priceInAccountingUnit,
|
|
3489
3499
|
readI64LE: () => readI64LE,
|
|
3490
3500
|
readSplMintSupply: () => readSplMintSupply,
|
|
3501
|
+
reconcileManagerWalletBalances: () => reconcileManagerWalletBalances,
|
|
3491
3502
|
refreshLiveOraclePrices: () => refreshLiveOraclePrices,
|
|
3492
3503
|
resolveExternalWithdraw: () => resolveExternalWithdraw,
|
|
3493
3504
|
resolveKeypairPath: () => resolveKeypairPath,
|
|
@@ -17833,9 +17844,13 @@ async function simulateSquadsProposalExecution(args) {
|
|
|
17833
17844
|
return value;
|
|
17834
17845
|
}
|
|
17835
17846
|
async function prepareVaultTransaction(args) {
|
|
17836
|
-
const { connection, proposer
|
|
17847
|
+
const { connection, proposer } = args;
|
|
17848
|
+
let instructions2 = [...args.instructions];
|
|
17849
|
+
const ephemeralKeys = args.ephemeralSignerKeys ?? [];
|
|
17837
17850
|
const route = findSquadsWalletRoute(proposer, args.squadsRoutes ?? []);
|
|
17838
17851
|
if (!route) {
|
|
17852
|
+
if (ephemeralKeys.length)
|
|
17853
|
+
throw new Error("Ephemeral signers require a Squads route");
|
|
17839
17854
|
return {
|
|
17840
17855
|
kind: "direct",
|
|
17841
17856
|
transaction: new import_web324.Transaction().add(...instructions2),
|
|
@@ -17863,6 +17878,44 @@ async function prepareVaultTransaction(args) {
|
|
|
17863
17878
|
);
|
|
17864
17879
|
}
|
|
17865
17880
|
const transactionIndex = BigInt(multisig.transactionIndex.toString()) + 1n;
|
|
17881
|
+
if (ephemeralKeys.length > 255 || new Set(ephemeralKeys.map(String)).size !== ephemeralKeys.length) {
|
|
17882
|
+
throw new Error("Invalid Squads ephemeral signer keys");
|
|
17883
|
+
}
|
|
17884
|
+
const [transactionPda] = squads.getTransactionPda({
|
|
17885
|
+
multisigPda: route.multisigPda,
|
|
17886
|
+
index: transactionIndex
|
|
17887
|
+
});
|
|
17888
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
17889
|
+
ephemeralKeys.forEach((key, index) => {
|
|
17890
|
+
if (key.equals(proposer) || key.equals(route.vaultPda) || !instructions2.some(
|
|
17891
|
+
(ix) => ix.keys.some((meta) => meta.isSigner && meta.pubkey.equals(key))
|
|
17892
|
+
) || instructions2.some(
|
|
17893
|
+
(ix) => ix.programId.equals(key) || ix.data.includes(key.toBuffer())
|
|
17894
|
+
)) {
|
|
17895
|
+
throw new Error(
|
|
17896
|
+
"Ephemeral signer must be a separate account-meta signer, never embedded in instruction data"
|
|
17897
|
+
);
|
|
17898
|
+
}
|
|
17899
|
+
replacements.set(
|
|
17900
|
+
key.toBase58(),
|
|
17901
|
+
squads.getEphemeralSignerPda({
|
|
17902
|
+
transactionPda,
|
|
17903
|
+
ephemeralSignerIndex: index
|
|
17904
|
+
})[0]
|
|
17905
|
+
);
|
|
17906
|
+
});
|
|
17907
|
+
if (replacements.size) {
|
|
17908
|
+
instructions2 = instructions2.map(
|
|
17909
|
+
(ix) => new import_web324.TransactionInstruction({
|
|
17910
|
+
programId: ix.programId,
|
|
17911
|
+
data: ix.data,
|
|
17912
|
+
keys: ix.keys.map((meta) => ({
|
|
17913
|
+
...meta,
|
|
17914
|
+
pubkey: replacements.get(meta.pubkey.toBase58()) ?? meta.pubkey
|
|
17915
|
+
}))
|
|
17916
|
+
})
|
|
17917
|
+
);
|
|
17918
|
+
}
|
|
17866
17919
|
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
17867
17920
|
if (!args.skipSimulation) {
|
|
17868
17921
|
await simulateSquadsProposalExecution({
|
|
@@ -17883,7 +17936,7 @@ async function prepareVaultTransaction(args) {
|
|
|
17883
17936
|
transactionIndex,
|
|
17884
17937
|
creator: proposer,
|
|
17885
17938
|
vaultIndex: route.vaultIndex,
|
|
17886
|
-
ephemeralSigners:
|
|
17939
|
+
ephemeralSigners: ephemeralKeys.length,
|
|
17887
17940
|
transactionMessage,
|
|
17888
17941
|
addressLookupTableAccounts: args.addressLookupTableAccounts,
|
|
17889
17942
|
memo: route.memo
|
|
@@ -20498,15 +20551,199 @@ async function refreshLiveOraclePrices({
|
|
|
20498
20551
|
return results.some((result) => Boolean(result.signature));
|
|
20499
20552
|
}
|
|
20500
20553
|
|
|
20501
|
-
// src/services/consensusOracle/pipeline/
|
|
20554
|
+
// src/services/consensusOracle/pipeline/managerWalletReconciliation.ts
|
|
20502
20555
|
var import_common51 = __toESM(require_dist());
|
|
20556
|
+
|
|
20557
|
+
// src/services/consensusOracle/sources/nestPriceSource.ts
|
|
20558
|
+
var import_kit13 = require("@solana/kit");
|
|
20559
|
+
var import_nest = __toESM(require_dist3());
|
|
20560
|
+
var import_nest2 = __toESM(require_dist3());
|
|
20561
|
+
var NEST_VAULT_SLUG = "nest-perena-vault";
|
|
20562
|
+
var NEST_RWA_SHARE_MINT = (0, import_kit13.address)(
|
|
20563
|
+
"VyXKJnVhkSkB6KAozSZCiLQbuB1k1r6Nu4etNYVo5LJ"
|
|
20564
|
+
);
|
|
20565
|
+
async function fetchNestTokenPrice(nestVaultSlug = NEST_VAULT_SLUG, opts = {}) {
|
|
20566
|
+
return (0, import_nest.fetchNestVaultSharePrice)(nestVaultSlug, opts);
|
|
20567
|
+
}
|
|
20568
|
+
var NestPriceSource = class {
|
|
20569
|
+
constructor(opts = {}) {
|
|
20570
|
+
this.shareMint = opts.shareMint ?? NEST_RWA_SHARE_MINT;
|
|
20571
|
+
this.nestVaultSlug = opts.nestVaultSlug ?? NEST_VAULT_SLUG;
|
|
20572
|
+
this.options = { baseUrl: opts.baseUrl, fetchFn: opts.fetchFn };
|
|
20573
|
+
}
|
|
20574
|
+
async fetchUsdPrices(mints2) {
|
|
20575
|
+
if (!mints2.some((mint) => mint.toString() === this.shareMint.toString())) {
|
|
20576
|
+
return {};
|
|
20577
|
+
}
|
|
20578
|
+
return {
|
|
20579
|
+
[this.shareMint.toString()]: await (0, import_nest.fetchNestVaultSharePrice)(
|
|
20580
|
+
this.nestVaultSlug,
|
|
20581
|
+
this.options
|
|
20582
|
+
)
|
|
20583
|
+
};
|
|
20584
|
+
}
|
|
20585
|
+
};
|
|
20586
|
+
|
|
20587
|
+
// src/services/consensusOracle/pipeline/managerWalletReconciliation.ts
|
|
20588
|
+
var MANAGER_WALLET_NAV_DROP_TRIGGER_BPS = 10n;
|
|
20589
|
+
var MANAGER_WALLET_NAV_TOLERANCE_BPS = 5n;
|
|
20590
|
+
var BPS = 10000n;
|
|
20591
|
+
var U64_MAX = 0xffffffffffffffffn;
|
|
20592
|
+
function previousPhysicalNav(state) {
|
|
20593
|
+
const banked = toBigInt2(state.config.apy?.accruedApyBalance);
|
|
20594
|
+
return toBigInt2(state.accounting?.tvl) + (banked > 0n ? banked : 0n);
|
|
20595
|
+
}
|
|
20596
|
+
function candidateGrossNav(state, updates) {
|
|
20597
|
+
const byIndex = /* @__PURE__ */ new Map();
|
|
20598
|
+
for (const update of updates) {
|
|
20599
|
+
const holding = state.holdings[update.holdingIndex];
|
|
20600
|
+
if (!holding || (0, import_common51.fromWeb3Pk)(holding.mint) !== update.mint || holding.decimals !== update.decimals || byIndex.has(update.holdingIndex)) {
|
|
20601
|
+
throw new Error(`Invalid NAV update for holding #${update.holdingIndex}`);
|
|
20602
|
+
}
|
|
20603
|
+
byIndex.set(update.holdingIndex, update);
|
|
20604
|
+
}
|
|
20605
|
+
return state.holdings.reduce((nav, holding, index) => {
|
|
20606
|
+
if ((0, import_common51.fromWeb3Pk)(holding.mint) === SYSTEM_PROGRAM) return nav;
|
|
20607
|
+
const update = byIndex.get(index);
|
|
20608
|
+
const local = toBigInt2(holding.localAmount);
|
|
20609
|
+
const external = update?.externalAmount ?? toBigInt2(holding.externalAmount);
|
|
20610
|
+
if (local < 0n || external < 0n || local + external > U64_MAX) {
|
|
20611
|
+
throw new Error(`Invalid NAV amount for holding #${index}`);
|
|
20612
|
+
}
|
|
20613
|
+
if (local + external === 0n) return nav;
|
|
20614
|
+
const price = update && variantName2(holding.priceOracleType).toLowerCase() === CONSENSUS_ORACLE_VARIANT ? update.price : toBigInt2(holding.price);
|
|
20615
|
+
if (price <= 0n || !Number.isInteger(holding.decimals) || holding.decimals < 0 || holding.decimals > 18) {
|
|
20616
|
+
throw new Error(
|
|
20617
|
+
`Cannot value holding #${index} for manager reconciliation`
|
|
20618
|
+
);
|
|
20619
|
+
}
|
|
20620
|
+
const nextNav = nav + (local + external) * price / 10n ** BigInt(holding.decimals);
|
|
20621
|
+
if (nextNav > U64_MAX) throw new Error("Candidate NAV exceeds u64");
|
|
20622
|
+
return nextNav;
|
|
20623
|
+
}, 0n);
|
|
20624
|
+
}
|
|
20625
|
+
function retainPendingNestShares(state, updates) {
|
|
20626
|
+
return updates.map((update) => {
|
|
20627
|
+
if (update.mint !== NEST_RWA_SHARE_MINT) return update;
|
|
20628
|
+
const recorded = toBigInt2(
|
|
20629
|
+
state.holdings[update.holdingIndex]?.externalAmount
|
|
20630
|
+
);
|
|
20631
|
+
if (recorded <= update.externalAmount) return update;
|
|
20632
|
+
return {
|
|
20633
|
+
...update,
|
|
20634
|
+
pendingNestAmount: recorded - update.externalAmount,
|
|
20635
|
+
externalAmount: recorded
|
|
20636
|
+
};
|
|
20637
|
+
});
|
|
20638
|
+
}
|
|
20639
|
+
async function reconcileManagerWalletBalances({
|
|
20640
|
+
vault,
|
|
20641
|
+
vaultState,
|
|
20642
|
+
updates,
|
|
20643
|
+
source,
|
|
20644
|
+
log = () => {
|
|
20645
|
+
}
|
|
20646
|
+
}) {
|
|
20647
|
+
const previousNav = previousPhysicalNav(vaultState);
|
|
20648
|
+
if (updates.some(
|
|
20649
|
+
(update) => (update.managerWalletAmount ?? 0n) !== 0n || (update.pendingNestAmount ?? 0n) !== 0n
|
|
20650
|
+
)) {
|
|
20651
|
+
throw new Error("Manager reconciliation requires fresh source amounts");
|
|
20652
|
+
}
|
|
20653
|
+
const pendingUpdates = retainPendingNestShares(vaultState, updates);
|
|
20654
|
+
if (!source || previousNav <= 0n) {
|
|
20655
|
+
return {
|
|
20656
|
+
accepted: false,
|
|
20657
|
+
updates: pendingUpdates,
|
|
20658
|
+
previousNav,
|
|
20659
|
+
candidateNav: 0n
|
|
20660
|
+
};
|
|
20661
|
+
}
|
|
20662
|
+
const candidateNav = candidateGrossNav(vaultState, updates);
|
|
20663
|
+
const result = {
|
|
20664
|
+
accepted: false,
|
|
20665
|
+
updates: pendingUpdates,
|
|
20666
|
+
previousNav,
|
|
20667
|
+
candidateNav
|
|
20668
|
+
};
|
|
20669
|
+
if ((previousNav - candidateNav) * BPS < previousNav * MANAGER_WALLET_NAV_DROP_TRIGGER_BPS) {
|
|
20670
|
+
return result;
|
|
20671
|
+
}
|
|
20672
|
+
const baseUpdates = updates.filter(
|
|
20673
|
+
(update) => coerceBool3(vaultState.holdings[update.holdingIndex].isBase)
|
|
20674
|
+
);
|
|
20675
|
+
const mints2 = baseUpdates.map((update) => update.mint);
|
|
20676
|
+
if (mints2.length === 0) return result;
|
|
20677
|
+
if (new Set(mints2).size !== mints2.length) {
|
|
20678
|
+
throw new Error("Duplicate base mint in manager reconciliation");
|
|
20679
|
+
}
|
|
20680
|
+
if (vaultState.holdings.some(
|
|
20681
|
+
(holding) => coerceBool3(holding.isBase) && !mints2.includes((0, import_common51.fromWeb3Pk)(holding.mint))
|
|
20682
|
+
)) {
|
|
20683
|
+
throw new Error(
|
|
20684
|
+
"Cannot reconcile all vault base assets with oracle reports"
|
|
20685
|
+
);
|
|
20686
|
+
}
|
|
20687
|
+
const manager = (0, import_common51.fromWeb3Pk)(vaultState.roles.manager);
|
|
20688
|
+
if (manager === SYSTEM_PROGRAM || manager === vault) {
|
|
20689
|
+
throw new Error("Invalid manager wallet for NAV reconciliation");
|
|
20690
|
+
}
|
|
20691
|
+
log(
|
|
20692
|
+
`vault ${vault}: NAV ${candidateNav} is at least 0.1% below ${previousNav}; checking manager ${manager}`
|
|
20693
|
+
);
|
|
20694
|
+
const amounts = await source.fetchBalances(manager, mints2);
|
|
20695
|
+
const adjusted = updates.map((update) => {
|
|
20696
|
+
if (!mints2.includes(update.mint)) return update;
|
|
20697
|
+
const amount = amounts.get(update.mint) ?? 0n;
|
|
20698
|
+
if (typeof amount !== "bigint" || amount < 0n || amount > U64_MAX) {
|
|
20699
|
+
throw new Error(`Invalid manager base-asset balance for ${update.mint}`);
|
|
20700
|
+
}
|
|
20701
|
+
return {
|
|
20702
|
+
...update,
|
|
20703
|
+
managerWalletAmount: amount,
|
|
20704
|
+
externalAmount: update.externalAmount + amount
|
|
20705
|
+
};
|
|
20706
|
+
});
|
|
20707
|
+
const adjustedNav = candidateGrossNav(vaultState, adjusted);
|
|
20708
|
+
const delta = adjustedNav - previousNav;
|
|
20709
|
+
const absoluteDelta = delta < 0n ? -delta : delta;
|
|
20710
|
+
const accepted = adjustedNav > candidateNav && absoluteDelta * BPS <= previousNav * MANAGER_WALLET_NAV_TOLERANCE_BPS;
|
|
20711
|
+
log(
|
|
20712
|
+
`vault ${vault}: manager wallet ${accepted ? "accepted" : "rejected"}; adjusted NAV ${adjustedNav}, previous NAV ${previousNav}, allowed difference \xB10.05%`
|
|
20713
|
+
);
|
|
20714
|
+
return {
|
|
20715
|
+
accepted,
|
|
20716
|
+
updates: accepted ? adjusted : pendingUpdates,
|
|
20717
|
+
previousNav,
|
|
20718
|
+
candidateNav,
|
|
20719
|
+
adjustedNav
|
|
20720
|
+
};
|
|
20721
|
+
}
|
|
20722
|
+
function managerReconciliationStateKey(state) {
|
|
20723
|
+
return JSON.stringify({
|
|
20724
|
+
manager: (0, import_common51.fromWeb3Pk)(state.roles.manager),
|
|
20725
|
+
previousNav: previousPhysicalNav(state).toString(),
|
|
20726
|
+
holdings: state.holdings.map((holding) => [
|
|
20727
|
+
(0, import_common51.fromWeb3Pk)(holding.mint),
|
|
20728
|
+
holding.decimals,
|
|
20729
|
+
variantName2(holding.priceOracleType),
|
|
20730
|
+
coerceBool3(holding.isBase),
|
|
20731
|
+
toBigInt2(holding.localAmount).toString(),
|
|
20732
|
+
toBigInt2(holding.externalAmount).toString(),
|
|
20733
|
+
toBigInt2(holding.price).toString()
|
|
20734
|
+
])
|
|
20735
|
+
});
|
|
20736
|
+
}
|
|
20737
|
+
|
|
20738
|
+
// src/services/consensusOracle/pipeline/pricingInputs.ts
|
|
20739
|
+
var import_common52 = __toESM(require_dist());
|
|
20503
20740
|
async function gatherPricingInputs(deps, target, vaultState, reportableHoldings, log = () => {
|
|
20504
20741
|
}) {
|
|
20505
20742
|
const consensusMints = reportableHoldings.filter(
|
|
20506
20743
|
({ holding }) => variantName2(holding.priceOracleType).toLowerCase() === CONSENSUS_ORACLE_VARIANT
|
|
20507
|
-
).map(({ holding }) => (0,
|
|
20744
|
+
).map(({ holding }) => (0, import_common52.fromWeb3Pk)(holding.mint));
|
|
20508
20745
|
const baseHolding = vaultState.holdings.find((h) => coerceBool3(h.isBase));
|
|
20509
|
-
const baseMint = baseHolding ? (0,
|
|
20746
|
+
const baseMint = baseHolding ? (0, import_common52.fromWeb3Pk)(baseHolding.mint) : consensusMints[0];
|
|
20510
20747
|
if (!baseMint) {
|
|
20511
20748
|
throw new Error(`vault has no holdings \u2014 cannot determine base asset`);
|
|
20512
20749
|
}
|
|
@@ -20590,11 +20827,11 @@ function reconcilePositionSnapshots(snapshots, vault, log) {
|
|
|
20590
20827
|
}
|
|
20591
20828
|
|
|
20592
20829
|
// src/services/consensusOracle/pipeline/receiptMints.ts
|
|
20593
|
-
var
|
|
20830
|
+
var import_common53 = __toESM(require_dist());
|
|
20594
20831
|
async function fetchReceiptMints(client, vault, vaultState) {
|
|
20595
20832
|
const receiptMints = /* @__PURE__ */ new Set();
|
|
20596
20833
|
if (vaultState.mint) {
|
|
20597
|
-
receiptMints.add((0,
|
|
20834
|
+
receiptMints.add((0, import_common53.fromWeb3Pk)(vaultState.mint).toString());
|
|
20598
20835
|
}
|
|
20599
20836
|
if (!coerceBool3(vaultState.tranchingEnabled)) return receiptMints;
|
|
20600
20837
|
const trancheState = await client.account.fetchVaultTrancheStateForVault(
|
|
@@ -20602,19 +20839,19 @@ async function fetchReceiptMints(client, vault, vaultState) {
|
|
|
20602
20839
|
{ fresh: true }
|
|
20603
20840
|
);
|
|
20604
20841
|
receiptMints.add(
|
|
20605
|
-
(0,
|
|
20842
|
+
(0, import_common53.fromWeb3Pk)(trancheState.config.juniorMint).toString()
|
|
20606
20843
|
);
|
|
20607
20844
|
receiptMints.add(
|
|
20608
|
-
(0,
|
|
20845
|
+
(0, import_common53.fromWeb3Pk)(trancheState.config.seniorMint).toString()
|
|
20609
20846
|
);
|
|
20610
20847
|
return receiptMints;
|
|
20611
20848
|
}
|
|
20612
20849
|
|
|
20613
20850
|
// src/services/consensusOracle/pipeline/settlement.ts
|
|
20614
|
-
var
|
|
20851
|
+
var import_common55 = __toESM(require_dist());
|
|
20615
20852
|
|
|
20616
20853
|
// src/services/consensusOracle/pipeline/yieldAccounts.ts
|
|
20617
|
-
var
|
|
20854
|
+
var import_common54 = __toESM(require_dist());
|
|
20618
20855
|
async function assertNoUnconfirmedYieldPayments(yieldTracker, target) {
|
|
20619
20856
|
const accountNames = [
|
|
20620
20857
|
...new Set(
|
|
@@ -20656,7 +20893,7 @@ async function withDiscoveredYieldAccounts(yieldTracker, target, vaultState, exc
|
|
|
20656
20893
|
);
|
|
20657
20894
|
if (namesToAttach.length === 0) return target;
|
|
20658
20895
|
const baseHolding = vaultState.holdings.find((holding) => {
|
|
20659
|
-
const mint = (0,
|
|
20896
|
+
const mint = (0, import_common54.fromWeb3Pk)(holding.mint).toString();
|
|
20660
20897
|
return coerceBool3(holding.isBase) && !excludedMints.has(mint);
|
|
20661
20898
|
});
|
|
20662
20899
|
if (!baseHolding) {
|
|
@@ -20664,7 +20901,7 @@ async function withDiscoveredYieldAccounts(yieldTracker, target, vaultState, exc
|
|
|
20664
20901
|
`vault ${target.vault}: tagged yield accounts found but no base holding is available`
|
|
20665
20902
|
);
|
|
20666
20903
|
}
|
|
20667
|
-
const baseMint = (0,
|
|
20904
|
+
const baseMint = (0, import_common54.fromWeb3Pk)(baseHolding.mint);
|
|
20668
20905
|
const holdings = [...target.holdings ?? []];
|
|
20669
20906
|
const existingIndex = holdings.findIndex(
|
|
20670
20907
|
(holding) => holding.mint.toString() === baseMint.toString()
|
|
@@ -20697,13 +20934,14 @@ async function settleVault2({
|
|
|
20697
20934
|
updates,
|
|
20698
20935
|
vaultState,
|
|
20699
20936
|
nowSecs,
|
|
20700
|
-
log
|
|
20937
|
+
log,
|
|
20938
|
+
beforeSubmit
|
|
20701
20939
|
}) {
|
|
20702
20940
|
const vault = target.vault;
|
|
20703
20941
|
log(`vault ${vault}: submitting ${updates.length} consensus asset update(s)`);
|
|
20704
20942
|
for (const update of updates) {
|
|
20705
20943
|
log(
|
|
20706
|
-
` holding #${update.holdingIndex} ${update.mint}: price=${update.price} external_amount=${update.externalAmount} [lp=${update.lpAmount} tracked=${update.trackedValueAmount} principal=${update.trackedPrincipalAmount} yield=${update.yieldAmount}]`
|
|
20944
|
+
` holding #${update.holdingIndex} ${update.mint}: price=${update.price} external_amount=${update.externalAmount} [pendingNest=${update.pendingNestAmount ?? 0n} managerWallet=${update.managerWalletAmount ?? 0n} lp=${update.lpAmount} tracked=${update.trackedValueAmount} principal=${update.trackedPrincipalAmount} yield=${update.yieldAmount}]`
|
|
20707
20945
|
);
|
|
20708
20946
|
}
|
|
20709
20947
|
try {
|
|
@@ -20725,6 +20963,7 @@ async function settleVault2({
|
|
|
20725
20963
|
);
|
|
20726
20964
|
}
|
|
20727
20965
|
await assertNoUnconfirmedYieldPayments(yieldTracker, target);
|
|
20966
|
+
await beforeSubmit?.();
|
|
20728
20967
|
const updateSignature = await oracle.updateAssetConsensusPrice(
|
|
20729
20968
|
signer,
|
|
20730
20969
|
{
|
|
@@ -20765,7 +21004,7 @@ async function logProspectiveApy({
|
|
|
20765
21004
|
);
|
|
20766
21005
|
const prospectiveNav = vaultState.holdings.reduce(
|
|
20767
21006
|
(sum, holding, holdingIndex) => {
|
|
20768
|
-
const mint = (0,
|
|
21007
|
+
const mint = (0, import_common55.fromWeb3Pk)(holding.mint).toString();
|
|
20769
21008
|
if (mint === SYSTEM_PROGRAM) return sum;
|
|
20770
21009
|
const update = updatesByIndex.get(holdingIndex);
|
|
20771
21010
|
const localAmount = toBigInt2(holding.localAmount);
|
|
@@ -20821,7 +21060,7 @@ async function discoverVaultsForSigner(client, signer, opts = {}) {
|
|
|
20821
21060
|
}
|
|
20822
21061
|
|
|
20823
21062
|
// src/services/consensusOracle/sources/jupiterPriceSource.ts
|
|
20824
|
-
var import_jupiter = __toESM(
|
|
21063
|
+
var import_jupiter = __toESM(require_dist4());
|
|
20825
21064
|
var JupiterPriceSource = class {
|
|
20826
21065
|
constructor(opts = {}) {
|
|
20827
21066
|
this.opts = opts;
|
|
@@ -20831,36 +21070,6 @@ var JupiterPriceSource = class {
|
|
|
20831
21070
|
}
|
|
20832
21071
|
};
|
|
20833
21072
|
|
|
20834
|
-
// src/services/consensusOracle/sources/nestPriceSource.ts
|
|
20835
|
-
var import_kit13 = require("@solana/kit");
|
|
20836
|
-
var import_nest = __toESM(require_dist4());
|
|
20837
|
-
var import_nest2 = __toESM(require_dist4());
|
|
20838
|
-
var NEST_VAULT_SLUG = "nest-perena-vault";
|
|
20839
|
-
var NEST_RWA_SHARE_MINT = (0, import_kit13.address)(
|
|
20840
|
-
"VyXKJnVhkSkB6KAozSZCiLQbuB1k1r6Nu4etNYVo5LJ"
|
|
20841
|
-
);
|
|
20842
|
-
async function fetchNestTokenPrice(nestVaultSlug = NEST_VAULT_SLUG, opts = {}) {
|
|
20843
|
-
return (0, import_nest.fetchNestVaultSharePrice)(nestVaultSlug, opts);
|
|
20844
|
-
}
|
|
20845
|
-
var NestPriceSource = class {
|
|
20846
|
-
constructor(opts = {}) {
|
|
20847
|
-
this.shareMint = opts.shareMint ?? NEST_RWA_SHARE_MINT;
|
|
20848
|
-
this.nestVaultSlug = opts.nestVaultSlug ?? NEST_VAULT_SLUG;
|
|
20849
|
-
this.options = { baseUrl: opts.baseUrl, fetchFn: opts.fetchFn };
|
|
20850
|
-
}
|
|
20851
|
-
async fetchUsdPrices(mints2) {
|
|
20852
|
-
if (!mints2.some((mint) => mint.toString() === this.shareMint.toString())) {
|
|
20853
|
-
return {};
|
|
20854
|
-
}
|
|
20855
|
-
return {
|
|
20856
|
-
[this.shareMint.toString()]: await (0, import_nest.fetchNestVaultSharePrice)(
|
|
20857
|
-
this.nestVaultSlug,
|
|
20858
|
-
this.options
|
|
20859
|
-
)
|
|
20860
|
-
};
|
|
20861
|
-
}
|
|
20862
|
-
};
|
|
20863
|
-
|
|
20864
21073
|
// src/services/consensusOracle/sources/livePriceSource.ts
|
|
20865
21074
|
var LivePriceSource = class {
|
|
20866
21075
|
constructor(opts = {}) {
|
|
@@ -20882,6 +21091,59 @@ var LivePriceSource = class {
|
|
|
20882
21091
|
}
|
|
20883
21092
|
};
|
|
20884
21093
|
|
|
21094
|
+
// src/services/consensusOracle/sources/managerWalletBalanceSource.ts
|
|
21095
|
+
var import_web330 = require("@solana/web3.js");
|
|
21096
|
+
var import_spl_token20 = require("@solana/spl-token");
|
|
21097
|
+
var RpcManagerWalletBalanceSource = class {
|
|
21098
|
+
constructor(connection) {
|
|
21099
|
+
this.connection = connection;
|
|
21100
|
+
}
|
|
21101
|
+
async fetchBalances(manager, mints2) {
|
|
21102
|
+
const wanted = new Set(mints2);
|
|
21103
|
+
if (wanted.size === 0) return /* @__PURE__ */ new Map();
|
|
21104
|
+
const owner = new import_web330.PublicKey(manager);
|
|
21105
|
+
const programs = [import_spl_token20.TOKEN_PROGRAM_ID, import_spl_token20.TOKEN_2022_PROGRAM_ID];
|
|
21106
|
+
const responses = await Promise.all(
|
|
21107
|
+
programs.map(
|
|
21108
|
+
(programId) => this.connection.getParsedTokenAccountsByOwner(
|
|
21109
|
+
owner,
|
|
21110
|
+
{ programId },
|
|
21111
|
+
"confirmed"
|
|
21112
|
+
)
|
|
21113
|
+
)
|
|
21114
|
+
);
|
|
21115
|
+
const amounts = /* @__PURE__ */ new Map();
|
|
21116
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21117
|
+
for (let index = 0; index < responses.length; index += 1) {
|
|
21118
|
+
for (const { pubkey: pubkey2, account } of responses[index].value) {
|
|
21119
|
+
const data = account.data;
|
|
21120
|
+
if (!("parsed" in data) || data.parsed?.type !== "account") {
|
|
21121
|
+
throw new Error(`Unparsed manager token account ${pubkey2}`);
|
|
21122
|
+
}
|
|
21123
|
+
const info = data.parsed.info;
|
|
21124
|
+
if (!account.owner.equals(programs[index]) || info?.owner !== manager) {
|
|
21125
|
+
throw new Error(`Invalid manager token account owner ${pubkey2}`);
|
|
21126
|
+
}
|
|
21127
|
+
if (!wanted.has(info.mint)) continue;
|
|
21128
|
+
const key = pubkey2.toBase58();
|
|
21129
|
+
if (seen.has(key))
|
|
21130
|
+
throw new Error(`Duplicate manager token account ${key}`);
|
|
21131
|
+
seen.add(key);
|
|
21132
|
+
const raw = info.tokenAmount?.amount;
|
|
21133
|
+
if (typeof raw !== "string" || !/^\d+$/.test(raw)) {
|
|
21134
|
+
throw new Error(`Invalid manager token balance ${key}`);
|
|
21135
|
+
}
|
|
21136
|
+
const amount = BigInt(raw);
|
|
21137
|
+
if (amount > 0xffffffffffffffffn) {
|
|
21138
|
+
throw new Error(`Manager token balance exceeds u64: ${key}`);
|
|
21139
|
+
}
|
|
21140
|
+
amounts.set(info.mint, (amounts.get(info.mint) ?? 0n) + amount);
|
|
21141
|
+
}
|
|
21142
|
+
}
|
|
21143
|
+
return amounts;
|
|
21144
|
+
}
|
|
21145
|
+
};
|
|
21146
|
+
|
|
20885
21147
|
// src/services/consensusOracle/positions/externalPositions.ts
|
|
20886
21148
|
var ExternalPositionRegistry = class {
|
|
20887
21149
|
constructor(providers = [], log = () => {
|
|
@@ -20918,7 +21180,7 @@ var StaticPositionProvider = class {
|
|
|
20918
21180
|
|
|
20919
21181
|
// src/services/consensusOracle/positions/kaminoPositionProvider.ts
|
|
20920
21182
|
var import_kit14 = require("@solana/kit");
|
|
20921
|
-
var
|
|
21183
|
+
var import_web331 = require("@solana/web3.js");
|
|
20922
21184
|
var import_klend_sdk = require("@kamino-finance/klend-sdk");
|
|
20923
21185
|
async function readKaminoBalance(manager, vault, sharesHolder) {
|
|
20924
21186
|
const userShares = await manager.getUserSharesBalanceSingleVault(
|
|
@@ -20955,7 +21217,7 @@ var KaminoPositionProvider = class {
|
|
|
20955
21217
|
const amount = await readKaminoBalance(
|
|
20956
21218
|
manager,
|
|
20957
21219
|
kVault,
|
|
20958
|
-
new
|
|
21220
|
+
new import_web331.PublicKey(sharesHolder)
|
|
20959
21221
|
);
|
|
20960
21222
|
out.push({ mint: ref.mint, amount });
|
|
20961
21223
|
}
|
|
@@ -20964,7 +21226,7 @@ var KaminoPositionProvider = class {
|
|
|
20964
21226
|
};
|
|
20965
21227
|
|
|
20966
21228
|
// src/services/consensusOracle/positions/marginfiPositionProvider.ts
|
|
20967
|
-
var
|
|
21229
|
+
var import_web332 = require("@solana/web3.js");
|
|
20968
21230
|
var import_marginfi2 = __toESM(require_dist2());
|
|
20969
21231
|
var MarginfiPositionProvider = class {
|
|
20970
21232
|
constructor(connection, log = () => {
|
|
@@ -20975,8 +21237,8 @@ var MarginfiPositionProvider = class {
|
|
|
20975
21237
|
async positionsFor(ctx) {
|
|
20976
21238
|
const refs = ctx.refs.filter((r) => r.kind === "marginfi");
|
|
20977
21239
|
if (refs.length === 0) return [];
|
|
20978
|
-
const explicitBanks = refs.map((r) => r.marginfiBank).filter(Boolean).map((bank) => new
|
|
20979
|
-
const autoAccountPks = refs.filter((r) => !r.marginfiBank).map((r) => r.marginfiAccount).filter(Boolean).map((account) => new
|
|
21240
|
+
const explicitBanks = refs.map((r) => r.marginfiBank).filter(Boolean).map((bank) => new import_web332.PublicKey(bank));
|
|
21241
|
+
const autoAccountPks = refs.filter((r) => !r.marginfiBank).map((r) => r.marginfiAccount).filter(Boolean).map((account) => new import_web332.PublicKey(account));
|
|
20980
21242
|
const autoBanks = [];
|
|
20981
21243
|
for (const accountPk of autoAccountPks) {
|
|
20982
21244
|
try {
|
|
@@ -21005,14 +21267,14 @@ var MarginfiPositionProvider = class {
|
|
|
21005
21267
|
if (bank) {
|
|
21006
21268
|
const amount = await (0, import_marginfi2.readMarginfiBankBalance)(
|
|
21007
21269
|
client,
|
|
21008
|
-
new
|
|
21009
|
-
new
|
|
21270
|
+
new import_web332.PublicKey(account),
|
|
21271
|
+
new import_web332.PublicKey(bank)
|
|
21010
21272
|
);
|
|
21011
21273
|
out.push({ mint: ref.mint, amount });
|
|
21012
21274
|
} else {
|
|
21013
21275
|
const balances = await (0, import_marginfi2.readAllMarginfiBalances)(
|
|
21014
21276
|
client,
|
|
21015
|
-
new
|
|
21277
|
+
new import_web332.PublicKey(account)
|
|
21016
21278
|
);
|
|
21017
21279
|
for (const { mint, amount } of balances) {
|
|
21018
21280
|
out.push({ mint: mint.toBase58(), amount });
|
|
@@ -21219,6 +21481,7 @@ function createLiveConsensusOracleDeps(connection, opts = {}) {
|
|
|
21219
21481
|
});
|
|
21220
21482
|
const deps = {
|
|
21221
21483
|
priceSource: new LivePriceSource(),
|
|
21484
|
+
managerWalletBalances: new RpcManagerWalletBalanceSource(connection),
|
|
21222
21485
|
yieldTracker: {
|
|
21223
21486
|
async getAccountNamesForVault(vault) {
|
|
21224
21487
|
const accounts2 = await getAccounts();
|
|
@@ -21252,7 +21515,7 @@ function createLiveConsensusOracleDeps(connection, opts = {}) {
|
|
|
21252
21515
|
}
|
|
21253
21516
|
|
|
21254
21517
|
// src/services/consensusOracle/consensusOracleService.ts
|
|
21255
|
-
var
|
|
21518
|
+
var import_common56 = __toESM(require_dist());
|
|
21256
21519
|
var ConsensusOracleService = class {
|
|
21257
21520
|
constructor(client, deps) {
|
|
21258
21521
|
this.client = client;
|
|
@@ -21288,7 +21551,7 @@ var ConsensusOracleService = class {
|
|
|
21288
21551
|
receiptMints
|
|
21289
21552
|
);
|
|
21290
21553
|
const filteredCount = vaultState.holdings.filter(
|
|
21291
|
-
(holding) => receiptMints.has((0,
|
|
21554
|
+
(holding) => receiptMints.has((0, import_common56.fromWeb3Pk)(holding.mint).toString())
|
|
21292
21555
|
).length;
|
|
21293
21556
|
if (filteredCount > 0) {
|
|
21294
21557
|
log(
|
|
@@ -21318,18 +21581,35 @@ var ConsensusOracleService = class {
|
|
|
21318
21581
|
reportableHoldings,
|
|
21319
21582
|
log
|
|
21320
21583
|
);
|
|
21321
|
-
const
|
|
21584
|
+
const sourcedUpdates = await buildUpdates(
|
|
21322
21585
|
this.deps.yieldTracker,
|
|
21323
21586
|
reportableHoldings,
|
|
21324
21587
|
inputs
|
|
21325
21588
|
);
|
|
21326
|
-
|
|
21327
|
-
target.vault,
|
|
21589
|
+
const reconciliation = await reconcileManagerWalletBalances({
|
|
21590
|
+
vault: target.vault,
|
|
21328
21591
|
vaultState,
|
|
21329
|
-
updates,
|
|
21330
|
-
this.
|
|
21592
|
+
updates: sourcedUpdates,
|
|
21593
|
+
source: this.deps.managerWalletBalances,
|
|
21331
21594
|
log
|
|
21332
|
-
);
|
|
21595
|
+
});
|
|
21596
|
+
const updates = reconciliation.updates;
|
|
21597
|
+
const needsRevalidation = reconciliation.accepted || // A new withdrawal can be queued after the first vault read, too.
|
|
21598
|
+
updates.some((update) => update.mint === NEST_RWA_SHARE_MINT);
|
|
21599
|
+
const reconciliationStateKey = needsRevalidation ? managerReconciliationStateKey(vaultState) : void 0;
|
|
21600
|
+
if (!reconciliation.accepted) {
|
|
21601
|
+
assertNoLargeBalanceChanges(
|
|
21602
|
+
target.vault,
|
|
21603
|
+
vaultState,
|
|
21604
|
+
updates,
|
|
21605
|
+
this.nowSecs(),
|
|
21606
|
+
log
|
|
21607
|
+
);
|
|
21608
|
+
} else {
|
|
21609
|
+
log(
|
|
21610
|
+
`vault ${target.vault}: manager NAV reconciliation passed; allowing cross-asset external balance changes`
|
|
21611
|
+
);
|
|
21612
|
+
}
|
|
21333
21613
|
if (dryRun) {
|
|
21334
21614
|
log(`vault ${target.vault}: dry run, ${updates.length} holding(s)`);
|
|
21335
21615
|
try {
|
|
@@ -21369,7 +21649,29 @@ var ConsensusOracleService = class {
|
|
|
21369
21649
|
updates,
|
|
21370
21650
|
vaultState,
|
|
21371
21651
|
nowSecs: this.nowSecs(),
|
|
21372
|
-
log
|
|
21652
|
+
log,
|
|
21653
|
+
beforeSubmit: needsRevalidation ? async () => {
|
|
21654
|
+
const freshState = await this.fetchDecodedVault(target.vault);
|
|
21655
|
+
if (managerReconciliationStateKey(freshState) !== reconciliationStateKey) {
|
|
21656
|
+
throw new Error(
|
|
21657
|
+
"Vault changed during manager-wallet reconciliation; retry with fresh inputs"
|
|
21658
|
+
);
|
|
21659
|
+
}
|
|
21660
|
+
if (!reconciliation.accepted) return;
|
|
21661
|
+
const fresh = await reconcileManagerWalletBalances({
|
|
21662
|
+
vault: target.vault,
|
|
21663
|
+
vaultState: freshState,
|
|
21664
|
+
updates: sourcedUpdates,
|
|
21665
|
+
source: this.deps.managerWalletBalances
|
|
21666
|
+
});
|
|
21667
|
+
if (!fresh.accepted || fresh.updates.some(
|
|
21668
|
+
(update, index) => update.externalAmount !== updates[index].externalAmount
|
|
21669
|
+
)) {
|
|
21670
|
+
throw new Error(
|
|
21671
|
+
"Manager wallet changed during reconciliation; retry with fresh inputs"
|
|
21672
|
+
);
|
|
21673
|
+
}
|
|
21674
|
+
} : void 0
|
|
21373
21675
|
});
|
|
21374
21676
|
return {
|
|
21375
21677
|
vault: target.vault,
|
|
@@ -21469,11 +21771,12 @@ async function runLiveConsensusOracle(env, oracleSigner, opts = {}) {
|
|
|
21469
21771
|
|
|
21470
21772
|
// src/services/externalLiquidityIntegrityService.ts
|
|
21471
21773
|
var import_kit15 = require("@solana/kit");
|
|
21472
|
-
var
|
|
21473
|
-
var
|
|
21774
|
+
var import_web333 = require("@solana/web3.js");
|
|
21775
|
+
var import_common57 = __toESM(require_dist());
|
|
21474
21776
|
var import_marginfi3 = __toESM(require_dist2());
|
|
21475
21777
|
var DEFAULT_MIN_AMOUNT_UI = 1;
|
|
21476
21778
|
var DEFAULT_TARGET_LOCAL_BPS = 50;
|
|
21779
|
+
var DEFAULT_TARGET_LOCAL_USDC_TVL_BPS = 150;
|
|
21477
21780
|
var DEFAULT_REBALANCE_BAND_BPS = 2e3;
|
|
21478
21781
|
var BPS_DENOMINATOR4 = 10000n;
|
|
21479
21782
|
function toRawAmount(uiAmount, decimals) {
|
|
@@ -21492,7 +21795,7 @@ function parseActiveSlots(externalLiquidity) {
|
|
|
21492
21795
|
if (discriminant === 0) continue;
|
|
21493
21796
|
if (discriminant !== 1) continue;
|
|
21494
21797
|
const pubkeyBytes = new Uint8Array(data.slice(8, 40));
|
|
21495
|
-
const userAccount = (0,
|
|
21798
|
+
const userAccount = (0, import_common57.toAddress)(new import_web333.PublicKey(pubkeyBytes));
|
|
21496
21799
|
results.push({ index: i, source: "marginfi", userAccount });
|
|
21497
21800
|
}
|
|
21498
21801
|
return results;
|
|
@@ -21517,11 +21820,12 @@ function planRebalance(params) {
|
|
|
21517
21820
|
localAmount,
|
|
21518
21821
|
externalAmount,
|
|
21519
21822
|
targetLocalBps,
|
|
21823
|
+
targetLocalAmount,
|
|
21520
21824
|
rebalanceBandBps,
|
|
21521
21825
|
minRaw
|
|
21522
21826
|
} = params;
|
|
21523
21827
|
const total = localAmount + externalAmount;
|
|
21524
|
-
const targetLocal = total * BigInt(Math.round(targetLocalBps)) / BPS_DENOMINATOR4;
|
|
21828
|
+
const targetLocal = targetLocalAmount ?? total * BigInt(Math.round(targetLocalBps)) / BPS_DENOMINATOR4;
|
|
21525
21829
|
const band = targetLocal * BigInt(Math.round(rebalanceBandBps)) / BPS_DENOMINATOR4;
|
|
21526
21830
|
const threshold = band > minRaw ? band : minRaw;
|
|
21527
21831
|
if (localAmount > targetLocal) {
|
|
@@ -21549,6 +21853,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21549
21853
|
const dryRun = opts.dryRun ?? false;
|
|
21550
21854
|
const minAmountUi = opts.minAmountUi ?? DEFAULT_MIN_AMOUNT_UI;
|
|
21551
21855
|
const targetLocalBps = opts.targetLocalBps ?? DEFAULT_TARGET_LOCAL_BPS;
|
|
21856
|
+
const targetLocalUsdcTvlBps = opts.targetLocalUsdcTvlBps ?? DEFAULT_TARGET_LOCAL_USDC_TVL_BPS;
|
|
21552
21857
|
const rebalanceBandBps = opts.rebalanceBandBps ?? DEFAULT_REBALANCE_BAND_BPS;
|
|
21553
21858
|
if (dryRun) {
|
|
21554
21859
|
log(
|
|
@@ -21556,7 +21861,12 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21556
21861
|
);
|
|
21557
21862
|
}
|
|
21558
21863
|
log(`Minimum rebalance: ${minAmountUi} token(s) (~$${minAmountUi})`);
|
|
21559
|
-
log(
|
|
21864
|
+
log(
|
|
21865
|
+
`Target local USDC: ${targetLocalUsdcTvlBps / 100}% of total vault TVL`
|
|
21866
|
+
);
|
|
21867
|
+
log(
|
|
21868
|
+
`Target local share: ${targetLocalBps / 100}% of each non-USDC holding`
|
|
21869
|
+
);
|
|
21560
21870
|
log(
|
|
21561
21871
|
`Rebalance band: ${rebalanceBandBps / 100}% of target (${targetLocalBps * (1 - rebalanceBandBps / 1e4) / 100}%\u2013${targetLocalBps * (1 + rebalanceBandBps / 1e4) / 100}% of holding)`
|
|
21562
21872
|
);
|
|
@@ -21576,7 +21886,13 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21576
21886
|
vaultState,
|
|
21577
21887
|
hwManager,
|
|
21578
21888
|
log,
|
|
21579
|
-
{
|
|
21889
|
+
{
|
|
21890
|
+
dryRun,
|
|
21891
|
+
minAmountUi,
|
|
21892
|
+
targetLocalBps,
|
|
21893
|
+
targetLocalUsdcTvlBps,
|
|
21894
|
+
rebalanceBandBps
|
|
21895
|
+
}
|
|
21580
21896
|
);
|
|
21581
21897
|
summary.vaultsProcessed++;
|
|
21582
21898
|
summary.totalDeposited += result.deposited;
|
|
@@ -21594,6 +21910,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21594
21910
|
const dryRun = opts.dryRun ?? false;
|
|
21595
21911
|
const minAmountUi = opts.minAmountUi ?? DEFAULT_MIN_AMOUNT_UI;
|
|
21596
21912
|
const targetLocalBps = opts.targetLocalBps ?? DEFAULT_TARGET_LOCAL_BPS;
|
|
21913
|
+
const targetLocalUsdcTvlBps = opts.targetLocalUsdcTvlBps ?? DEFAULT_TARGET_LOCAL_USDC_TVL_BPS;
|
|
21597
21914
|
const rebalanceBandBps = opts.rebalanceBandBps ?? DEFAULT_REBALANCE_BAND_BPS;
|
|
21598
21915
|
const result = {
|
|
21599
21916
|
vault,
|
|
@@ -21608,8 +21925,8 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21608
21925
|
result.skipped++;
|
|
21609
21926
|
return result;
|
|
21610
21927
|
}
|
|
21611
|
-
const hwManagerAddress = (0,
|
|
21612
|
-
const vaultPk = new
|
|
21928
|
+
const hwManagerAddress = (0, import_common57.fromWeb3Pk)(hwManager.publicKey);
|
|
21929
|
+
const vaultPk = new import_web333.PublicKey(vault.toString());
|
|
21613
21930
|
const registeredHwManager = pubkeyStr(
|
|
21614
21931
|
vaultState.roles.hwManager
|
|
21615
21932
|
);
|
|
@@ -21642,10 +21959,27 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21642
21959
|
const externalAmount = toBigInt3(holding.externalAmount);
|
|
21643
21960
|
const decimals = Number(holding.decimals ?? 0);
|
|
21644
21961
|
const minRaw = toRawAmount(minAmountUi, decimals);
|
|
21962
|
+
let targetLocalAmount;
|
|
21963
|
+
if (mintAddress === import_common57.USDC_MINT) {
|
|
21964
|
+
const tvl = toBigInt3(vaultState.accounting.tvl);
|
|
21965
|
+
const price = toBigInt3(holding.price);
|
|
21966
|
+
const stalenessThreshold = Number(toBigInt3(vaultState.config.priceStalenessThresholdSecs)) || DEFAULT_PRICE_STALENESS_THRESHOLD_SECS;
|
|
21967
|
+
if (tvl <= 0n || price <= 0n || Math.floor(Date.now() / 1e3) - Number(toBigInt3(holding.lastUpdateTs)) > stalenessThreshold) {
|
|
21968
|
+
log(
|
|
21969
|
+
`Vault ${vault}: cannot size local USDC target without TVL and a fresh USDC price \u2014 skipping`
|
|
21970
|
+
);
|
|
21971
|
+
result.skipped++;
|
|
21972
|
+
continue;
|
|
21973
|
+
}
|
|
21974
|
+
const numerator = tvl * BigInt(Math.round(targetLocalUsdcTvlBps)) * 10n ** BigInt(decimals);
|
|
21975
|
+
const denominator = BPS_DENOMINATOR4 * price;
|
|
21976
|
+
targetLocalAmount = (numerator + denominator - 1n) / denominator;
|
|
21977
|
+
}
|
|
21645
21978
|
const plan = planRebalance({
|
|
21646
21979
|
localAmount,
|
|
21647
21980
|
externalAmount,
|
|
21648
21981
|
targetLocalBps,
|
|
21982
|
+
targetLocalAmount,
|
|
21649
21983
|
rebalanceBandBps,
|
|
21650
21984
|
minRaw
|
|
21651
21985
|
});
|
|
@@ -21736,7 +22070,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21736
22070
|
marginfiAccounts.tokenProgram,
|
|
21737
22071
|
true
|
|
21738
22072
|
);
|
|
21739
|
-
const cpiRefs = (0,
|
|
22073
|
+
const cpiRefs = (0, import_common57.createCpiRefs)([
|
|
21740
22074
|
direction === "deposit" ? marginfiClient.deposit_cpi({
|
|
21741
22075
|
marginfiAccount: slot.userAccount,
|
|
21742
22076
|
authority: vault,
|
|
@@ -21788,14 +22122,15 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
21788
22122
|
|
|
21789
22123
|
// src/services/idleLiquidityService.ts
|
|
21790
22124
|
var import_kit16 = require("@solana/kit");
|
|
21791
|
-
var
|
|
22125
|
+
var import_spl_token21 = require("@solana/spl-token");
|
|
21792
22126
|
var import_marginfi_client_v2 = require("@mrgnlabs/marginfi-client-v2");
|
|
21793
|
-
var
|
|
21794
|
-
var
|
|
21795
|
-
var import_jupiter2 = __toESM(
|
|
22127
|
+
var import_web334 = require("@solana/web3.js");
|
|
22128
|
+
var import_common58 = __toESM(require_dist());
|
|
22129
|
+
var import_jupiter2 = __toESM(require_dist4());
|
|
21796
22130
|
var import_marginfi4 = __toESM(require_dist2());
|
|
21797
22131
|
var IDLE_RESERVE_FLOOR_BPS = 400;
|
|
21798
22132
|
var IDLE_RESERVE_TARGET_BPS = 500;
|
|
22133
|
+
var WITHDRAWABLE_RESERVE_FLOOR_BPS = 150;
|
|
21799
22134
|
var DEFAULT_SLIPPAGE_BPS = 30;
|
|
21800
22135
|
var DEFAULT_CU_PRICE_MICRO_LAMPORTS = 1e4;
|
|
21801
22136
|
var DEFAULT_MAX_ACCOUNTS = 20;
|
|
@@ -21890,8 +22225,8 @@ var IdleLiquidityService = class {
|
|
|
21890
22225
|
let quote;
|
|
21891
22226
|
try {
|
|
21892
22227
|
quote = await jupiter.getQuote({
|
|
21893
|
-
inputMint:
|
|
21894
|
-
outputMint:
|
|
22228
|
+
inputMint: import_common58.PST_MINT,
|
|
22229
|
+
outputMint: import_common58.USDC_MINT,
|
|
21895
22230
|
amount: pstInput,
|
|
21896
22231
|
slippageBps: opts.slippageBps ?? DEFAULT_SLIPPAGE_BPS,
|
|
21897
22232
|
maxAccounts: DEFAULT_MAX_ACCOUNTS
|
|
@@ -21937,34 +22272,41 @@ var IdleLiquidityService = class {
|
|
|
21937
22272
|
/** Read only the two locations that constitute the idle USDC reserve. */
|
|
21938
22273
|
async fetchIdleUsdc(vault, vaultState) {
|
|
21939
22274
|
const connection = this.client.provider.connection;
|
|
21940
|
-
const vaultPk = new
|
|
21941
|
-
const usdcMint = new
|
|
21942
|
-
const ata = (0,
|
|
22275
|
+
const vaultPk = new import_web334.PublicKey(vault);
|
|
22276
|
+
const usdcMint = new import_web334.PublicKey(import_common58.USDC_MINT);
|
|
22277
|
+
const ata = (0, import_spl_token21.getAssociatedTokenAddressSync)(usdcMint, vaultPk, true);
|
|
21943
22278
|
const tokenInfo = await connection.getAccountInfo(ata, "confirmed");
|
|
21944
22279
|
let localAmount = 0n;
|
|
21945
22280
|
if (tokenInfo) {
|
|
21946
|
-
const tokenAccount = (0,
|
|
22281
|
+
const tokenAccount = (0, import_spl_token21.unpackAccount)(ata, tokenInfo, import_spl_token21.TOKEN_PROGRAM_ID);
|
|
21947
22282
|
if (!tokenAccount.mint.equals(usdcMint) || !tokenAccount.owner.equals(vaultPk) || !tokenAccount.isInitialized) {
|
|
21948
22283
|
throw new Error(`Invalid vault USDC token account: ${ata.toBase58()}`);
|
|
21949
22284
|
}
|
|
21950
22285
|
localAmount = tokenAccount.amount;
|
|
21951
22286
|
}
|
|
21952
|
-
const
|
|
21953
|
-
|
|
21954
|
-
|
|
22287
|
+
const slotIndex = vaultState.externalLiquidity.findIndex(
|
|
22288
|
+
(slot) => slot.data[0] === 1
|
|
22289
|
+
);
|
|
22290
|
+
if (slotIndex === -1) {
|
|
22291
|
+
return {
|
|
22292
|
+
localAmount,
|
|
22293
|
+
marginfiAmount: 0n,
|
|
22294
|
+
withdrawableMarginfiAmount: 0n,
|
|
22295
|
+
slotIndex
|
|
22296
|
+
};
|
|
21955
22297
|
}
|
|
21956
|
-
|
|
21957
|
-
if (data
|
|
21958
|
-
throw new Error(
|
|
22298
|
+
const data = vaultState.externalLiquidity[slotIndex].data;
|
|
22299
|
+
if (data.length < 40) {
|
|
22300
|
+
throw new Error(`Invalid Project0 external-liquidity slot ${slotIndex}`);
|
|
21959
22301
|
}
|
|
21960
|
-
const positionPk = new
|
|
22302
|
+
const positionPk = new import_web334.PublicKey(new Uint8Array(data.slice(8, 40)));
|
|
21961
22303
|
const positionInfo = await connection.getAccountInfo(
|
|
21962
22304
|
positionPk,
|
|
21963
22305
|
"confirmed"
|
|
21964
22306
|
);
|
|
21965
|
-
if (!positionInfo || !positionInfo.owner.equals(new
|
|
22307
|
+
if (!positionInfo || !positionInfo.owner.equals(new import_web334.PublicKey(import_marginfi4.MARGINFI_PROGRAM_ID))) {
|
|
21966
22308
|
throw new Error(
|
|
21967
|
-
`Invalid
|
|
22309
|
+
`Invalid Project0 slot-${slotIndex} account: ${positionPk.toBase58()}`
|
|
21968
22310
|
);
|
|
21969
22311
|
}
|
|
21970
22312
|
const marginfi = await (0, import_marginfi4.createMarginfiReadClient)(
|
|
@@ -21973,9 +22315,10 @@ var IdleLiquidityService = class {
|
|
|
21973
22315
|
);
|
|
21974
22316
|
const position = await import_marginfi_client_v2.MarginfiAccountWrapper.fetch(positionPk, marginfi);
|
|
21975
22317
|
if (!position.authority.equals(vaultPk)) {
|
|
21976
|
-
throw new Error(
|
|
22318
|
+
throw new Error(`Project0 slot-${slotIndex} authority is not the vault`);
|
|
21977
22319
|
}
|
|
21978
22320
|
let marginfiAmount = 0n;
|
|
22321
|
+
let withdrawableMarginfiAmount = 0n;
|
|
21979
22322
|
for (const balance of position.activeBalances) {
|
|
21980
22323
|
const bank = marginfi.getBankByPk(balance.bankPk);
|
|
21981
22324
|
if (!bank) {
|
|
@@ -21984,11 +22327,22 @@ var IdleLiquidityService = class {
|
|
|
21984
22327
|
);
|
|
21985
22328
|
}
|
|
21986
22329
|
if (!bank.mint.equals(usdcMint)) continue;
|
|
21987
|
-
|
|
22330
|
+
const deposited = BigInt(
|
|
21988
22331
|
balance.computeQuantity(bank).assets.toFixed(0, 1)
|
|
21989
22332
|
);
|
|
22333
|
+
const available = BigInt(
|
|
22334
|
+
bank.getTotalAssetQuantity().minus(bank.getTotalLiabilityQuantity()).toFixed(0, 1)
|
|
22335
|
+
);
|
|
22336
|
+
const bankLiquidity = available > 0n ? available : 0n;
|
|
22337
|
+
marginfiAmount += deposited;
|
|
22338
|
+
withdrawableMarginfiAmount += deposited < bankLiquidity ? deposited : bankLiquidity;
|
|
21990
22339
|
}
|
|
21991
|
-
return {
|
|
22340
|
+
return {
|
|
22341
|
+
localAmount,
|
|
22342
|
+
marginfiAmount,
|
|
22343
|
+
withdrawableMarginfiAmount,
|
|
22344
|
+
slotIndex
|
|
22345
|
+
};
|
|
21992
22346
|
}
|
|
21993
22347
|
/**
|
|
21994
22348
|
* Decide whether a top-up is warranted. Returns either a terminal `result`
|
|
@@ -22003,6 +22357,8 @@ var IdleLiquidityService = class {
|
|
|
22003
22357
|
tvl,
|
|
22004
22358
|
idleValue: 0n,
|
|
22005
22359
|
idleBps: 0,
|
|
22360
|
+
withdrawableValue: 0n,
|
|
22361
|
+
withdrawableBps: 0,
|
|
22006
22362
|
shortfallUsdc: 0n,
|
|
22007
22363
|
pstSpent: 0n,
|
|
22008
22364
|
usdcReceived: 0n
|
|
@@ -22012,8 +22368,8 @@ var IdleLiquidityService = class {
|
|
|
22012
22368
|
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
22013
22369
|
return { result: { ...empty, status: "no-tvl", reason } };
|
|
22014
22370
|
}
|
|
22015
|
-
const usdc = findHolding2(vaultState,
|
|
22016
|
-
const pst = findHolding2(vaultState,
|
|
22371
|
+
const usdc = findHolding2(vaultState, import_common58.USDC_MINT);
|
|
22372
|
+
const pst = findHolding2(vaultState, import_common58.PST_MINT);
|
|
22017
22373
|
if (!usdc || !pst) {
|
|
22018
22374
|
const reason = `vault has no ${usdc ? "PST" : "USDC"} holding`;
|
|
22019
22375
|
log(`Vault ${vault}: ${reason} \u2014 skipping`);
|
|
@@ -22047,7 +22403,16 @@ var IdleLiquidityService = class {
|
|
|
22047
22403
|
const idleAmount = balances.localAmount + balances.marginfiAmount;
|
|
22048
22404
|
const idleValue = holdingValue2(usdc, idleAmount);
|
|
22049
22405
|
const idleBps = Number(idleValue * 10000n / tvl);
|
|
22050
|
-
const
|
|
22406
|
+
const withdrawableAmount = balances.localAmount + balances.withdrawableMarginfiAmount;
|
|
22407
|
+
const withdrawableValue = holdingValue2(usdc, withdrawableAmount);
|
|
22408
|
+
const withdrawableBps = Number(withdrawableValue * 10000n / tvl);
|
|
22409
|
+
const base = {
|
|
22410
|
+
...empty,
|
|
22411
|
+
idleValue,
|
|
22412
|
+
idleBps,
|
|
22413
|
+
withdrawableValue,
|
|
22414
|
+
withdrawableBps
|
|
22415
|
+
};
|
|
22051
22416
|
log(
|
|
22052
22417
|
`Vault ${vault}: idle USDC ${formatUi2(
|
|
22053
22418
|
idleAmount,
|
|
@@ -22055,13 +22420,21 @@ var IdleLiquidityService = class {
|
|
|
22055
22420
|
)} (vault token account ${formatUi2(
|
|
22056
22421
|
balances.localAmount,
|
|
22057
22422
|
usdc.decimals
|
|
22058
|
-
)} +
|
|
22423
|
+
)} + Project0 slot ${balances.slotIndex} ${formatUi2(
|
|
22059
22424
|
balances.marginfiAmount,
|
|
22060
22425
|
usdc.decimals
|
|
22061
22426
|
)}) = ${idleBps}bps of TVL (floor ${IDLE_RESERVE_FLOOR_BPS}bps, target ${IDLE_RESERVE_TARGET_BPS}bps)`
|
|
22062
22427
|
);
|
|
22063
|
-
|
|
22064
|
-
|
|
22428
|
+
log(
|
|
22429
|
+
`Vault ${vault}: withdrawable USDC ${formatUi2(
|
|
22430
|
+
withdrawableAmount,
|
|
22431
|
+
usdc.decimals
|
|
22432
|
+
)} = ${withdrawableBps}bps of TVL (floor ${WITHDRAWABLE_RESERVE_FLOOR_BPS}bps)`
|
|
22433
|
+
);
|
|
22434
|
+
const idleBelowFloor = idleBps < IDLE_RESERVE_FLOOR_BPS;
|
|
22435
|
+
const withdrawableBelowFloor = withdrawableBps < WITHDRAWABLE_RESERVE_FLOOR_BPS;
|
|
22436
|
+
if (!idleBelowFloor && !withdrawableBelowFloor) {
|
|
22437
|
+
const reason = `idle USDC ${idleBps}bps and withdrawable USDC ${withdrawableBps}bps are at or above their floors`;
|
|
22065
22438
|
return { result: { ...base, status: "above-floor", reason } };
|
|
22066
22439
|
}
|
|
22067
22440
|
for (const [name, holding] of [
|
|
@@ -22074,8 +22447,11 @@ var IdleLiquidityService = class {
|
|
|
22074
22447
|
return { result: { ...base, status: "rebalance-cooldown", reason } };
|
|
22075
22448
|
}
|
|
22076
22449
|
}
|
|
22077
|
-
const targetValue = tvl * BigInt(IDLE_RESERVE_TARGET_BPS) / 10000n;
|
|
22078
|
-
|
|
22450
|
+
const targetValue = (tvl * BigInt(IDLE_RESERVE_TARGET_BPS) + 9999n) / 10000n;
|
|
22451
|
+
const withdrawableTargetValue = (tvl * BigInt(WITHDRAWABLE_RESERVE_FLOOR_BPS) + 9999n) / 10000n;
|
|
22452
|
+
const idleShortfall = idleBelowFloor ? targetValue - idleValue : 0n;
|
|
22453
|
+
const withdrawableShortfall = withdrawableBelowFloor ? withdrawableTargetValue - withdrawableValue : 0n;
|
|
22454
|
+
let shortfallValue = idleShortfall > withdrawableShortfall ? idleShortfall : withdrawableShortfall;
|
|
22079
22455
|
const allowance = this.remainingRebalanceAllowance(vaultState, tvl, now);
|
|
22080
22456
|
if (allowance !== void 0 && allowance < shortfallValue) {
|
|
22081
22457
|
if (allowance === 0n) {
|
|
@@ -22088,7 +22464,7 @@ var IdleLiquidityService = class {
|
|
|
22088
22464
|
);
|
|
22089
22465
|
shortfallValue = allowance;
|
|
22090
22466
|
}
|
|
22091
|
-
const shortfallUsdc = shortfallValue * 10n ** BigInt(usdc.decimals) / usdc.price;
|
|
22467
|
+
const shortfallUsdc = (shortfallValue * 10n ** BigInt(usdc.decimals) + usdc.price - 1n) / usdc.price;
|
|
22092
22468
|
if (shortfallUsdc <= 0n) {
|
|
22093
22469
|
const reason = "computed shortfall rounds to zero";
|
|
22094
22470
|
return { result: { ...base, status: "above-floor", reason } };
|
|
@@ -22141,16 +22517,16 @@ var IdleLiquidityService = class {
|
|
|
22141
22517
|
*/
|
|
22142
22518
|
async mintTokenProgram(mint) {
|
|
22143
22519
|
const account = await this.client.provider.connection.getAccountInfo(
|
|
22144
|
-
new
|
|
22520
|
+
new import_web334.PublicKey(mint),
|
|
22145
22521
|
"confirmed"
|
|
22146
22522
|
);
|
|
22147
22523
|
if (!account) throw new Error(`Mint account not found: ${mint}`);
|
|
22148
|
-
if (!account.owner.equals(
|
|
22524
|
+
if (!account.owner.equals(import_spl_token21.TOKEN_PROGRAM_ID) && !account.owner.equals(import_spl_token21.TOKEN_2022_PROGRAM_ID)) {
|
|
22149
22525
|
throw new Error(
|
|
22150
22526
|
`Unsupported token program ${account.owner.toBase58()} for mint ${mint}`
|
|
22151
22527
|
);
|
|
22152
22528
|
}
|
|
22153
|
-
return (0,
|
|
22529
|
+
return (0, import_common58.fromWeb3Pk)(account.owner);
|
|
22154
22530
|
}
|
|
22155
22531
|
/**
|
|
22156
22532
|
* Build, simulate, and (unless `dryRun`) submit the `jupiter_swap`.
|
|
@@ -22170,23 +22546,23 @@ var IdleLiquidityService = class {
|
|
|
22170
22546
|
dryRun,
|
|
22171
22547
|
log
|
|
22172
22548
|
} = params;
|
|
22173
|
-
const signer = (0,
|
|
22549
|
+
const signer = (0, import_common58.fromWeb3Pk)(hwManager.publicKey);
|
|
22174
22550
|
const [sourceTokenProgram, destinationTokenProgram] = await Promise.all([
|
|
22175
|
-
this.mintTokenProgram(
|
|
22176
|
-
this.mintTokenProgram(
|
|
22551
|
+
this.mintTokenProgram(import_common58.PST_MINT),
|
|
22552
|
+
this.mintTokenProgram(import_common58.USDC_MINT)
|
|
22177
22553
|
]);
|
|
22178
22554
|
const jupiterCpi = await jupiter.getSwapCpiData(quote, vault, {
|
|
22179
22555
|
payer: signer
|
|
22180
22556
|
});
|
|
22181
|
-
const { accounts: accounts2, refs, lookupTables } = (0,
|
|
22557
|
+
const { accounts: accounts2, refs, lookupTables } = (0, import_common58.createCpiRefs)([jupiterCpi]);
|
|
22182
22558
|
const vaultTrancheState = coerceBool4(
|
|
22183
22559
|
vaultState.tranchingEnabled
|
|
22184
22560
|
) ? (await this.client.pda.deriveVaultTrancheStatePda(vault))[0] : void 0;
|
|
22185
22561
|
const plan = await this.client.tx.jupiterSwap.getTx({
|
|
22186
22562
|
hwManager: signer,
|
|
22187
22563
|
vault,
|
|
22188
|
-
sourceMint:
|
|
22189
|
-
destinationMint:
|
|
22564
|
+
sourceMint: import_common58.PST_MINT,
|
|
22565
|
+
destinationMint: import_common58.USDC_MINT,
|
|
22190
22566
|
refs,
|
|
22191
22567
|
accounts: accounts2,
|
|
22192
22568
|
sourceTokenProgram,
|
|
@@ -22196,26 +22572,26 @@ var IdleLiquidityService = class {
|
|
|
22196
22572
|
});
|
|
22197
22573
|
const connection = this.client.provider.connection;
|
|
22198
22574
|
const instructions2 = [
|
|
22199
|
-
|
|
22575
|
+
import_web334.ComputeBudgetProgram.setComputeUnitLimit({ units: COMPUTE_UNIT_LIMIT }),
|
|
22200
22576
|
...cuPriceMicroLamports > 0 ? [
|
|
22201
|
-
|
|
22577
|
+
import_web334.ComputeBudgetProgram.setComputeUnitPrice({
|
|
22202
22578
|
microLamports: cuPriceMicroLamports
|
|
22203
22579
|
})
|
|
22204
22580
|
] : [],
|
|
22205
|
-
...(jupiterCpi.preInstructions ?? []).map(
|
|
22206
|
-
...plan.instructions.map(
|
|
22581
|
+
...(jupiterCpi.preInstructions ?? []).map(import_common58.fromKitInstruction),
|
|
22582
|
+
...plan.instructions.map(import_common58.fromKitInstruction)
|
|
22207
22583
|
];
|
|
22208
22584
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
22209
|
-
const lookupTableAccounts = await (0,
|
|
22585
|
+
const lookupTableAccounts = await (0, import_common58.fetchLookupTables)(
|
|
22210
22586
|
connection,
|
|
22211
22587
|
plan.lookupTables ?? []
|
|
22212
22588
|
);
|
|
22213
|
-
const message2 = new
|
|
22589
|
+
const message2 = new import_web334.TransactionMessage({
|
|
22214
22590
|
payerKey: hwManager.publicKey,
|
|
22215
22591
|
recentBlockhash: blockhash,
|
|
22216
22592
|
instructions: instructions2
|
|
22217
22593
|
}).compileToV0Message(lookupTableAccounts);
|
|
22218
|
-
const transaction = new
|
|
22594
|
+
const transaction = new import_web334.VersionedTransaction(message2);
|
|
22219
22595
|
transaction.sign([hwManager]);
|
|
22220
22596
|
if (!this.client.skipSimulation) {
|
|
22221
22597
|
const simulation = await connection.simulateTransaction(transaction, {
|
|
@@ -22261,9 +22637,9 @@ var IdleLiquidityService = class {
|
|
|
22261
22637
|
|
|
22262
22638
|
// src/services/timelockSettlementService.ts
|
|
22263
22639
|
var import_kit17 = require("@solana/kit");
|
|
22264
|
-
var
|
|
22265
|
-
var
|
|
22266
|
-
var ZERO_PUBKEY =
|
|
22640
|
+
var import_web335 = require("@solana/web3.js");
|
|
22641
|
+
var import_common59 = __toESM(require_dist());
|
|
22642
|
+
var ZERO_PUBKEY = import_web335.PublicKey.default.toBase58();
|
|
22267
22643
|
var CONSENSUS_SIGNER_CAPACITY = 4;
|
|
22268
22644
|
var CONSENSUS_ENTRY_OFFSET = 40;
|
|
22269
22645
|
var CONSENSUS_ENTRY_SIZE = 272;
|
|
@@ -22303,7 +22679,7 @@ function decodePendingConsensusSigners(data) {
|
|
|
22303
22679
|
const signers = [];
|
|
22304
22680
|
for (let i = 0; i < count; i += 1) {
|
|
22305
22681
|
const start = CONSENSUS_PENDING_OFFSET + i * 32;
|
|
22306
|
-
const signer = new
|
|
22682
|
+
const signer = new import_web335.PublicKey(bytes.slice(start, start + 32)).toBase58();
|
|
22307
22683
|
if (signer === ZERO_PUBKEY) {
|
|
22308
22684
|
throw new Error(`pending consensus signer ${i} is unset`);
|
|
22309
22685
|
}
|
|
@@ -22359,7 +22735,7 @@ var TimelockSettlementService = class {
|
|
|
22359
22735
|
});
|
|
22360
22736
|
const dryRun = opts.dryRun ?? false;
|
|
22361
22737
|
const now = opts.now ?? await this.chainTime();
|
|
22362
|
-
const fulfillerAddress = (0,
|
|
22738
|
+
const fulfillerAddress = (0, import_common59.fromWeb3Pk)(fulfiller.publicKey);
|
|
22363
22739
|
const allVaults = opts.vault ? [
|
|
22364
22740
|
{
|
|
22365
22741
|
publicKey: opts.vault,
|
|
@@ -22502,18 +22878,18 @@ var TimelockSettlementService = class {
|
|
|
22502
22878
|
|
|
22503
22879
|
// src/services/nestWithdrawalService.ts
|
|
22504
22880
|
var import_kit18 = require("@solana/kit");
|
|
22505
|
-
var
|
|
22506
|
-
var
|
|
22507
|
-
var
|
|
22508
|
-
var import_nest3 = __toESM(
|
|
22509
|
-
var import_nest4 = __toESM(
|
|
22510
|
-
var NestOftProgram = new
|
|
22881
|
+
var import_spl_token22 = require("@solana/spl-token");
|
|
22882
|
+
var import_web336 = require("@solana/web3.js");
|
|
22883
|
+
var import_common60 = __toESM(require_dist());
|
|
22884
|
+
var import_nest3 = __toESM(require_dist3());
|
|
22885
|
+
var import_nest4 = __toESM(require_dist3());
|
|
22886
|
+
var NestOftProgram = new import_web336.PublicKey(
|
|
22511
22887
|
"ChEfPd3RzLeYiRwp1K9evimmaFSd6DV1S4Mv5q5Aj1th"
|
|
22512
22888
|
);
|
|
22513
|
-
var NestOftStore = new
|
|
22889
|
+
var NestOftStore = new import_web336.PublicKey(
|
|
22514
22890
|
"k8mJj8Gyw2gFAqut21AFVUUZhxb4RVDMnb4PrSYiDhV"
|
|
22515
22891
|
);
|
|
22516
|
-
var UsdcMint = new
|
|
22892
|
+
var UsdcMint = new import_web336.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
22517
22893
|
var NestPerenaComposer = Buffer.from(
|
|
22518
22894
|
"000000000000000000000000908dcb5531691c2124c54e30bb645cf11647090d",
|
|
22519
22895
|
"hex"
|
|
@@ -22530,7 +22906,7 @@ async function buildNestWithdrawalRequest(args) {
|
|
|
22530
22906
|
return decodeNestWithdrawalRequest({ ...args, txBase64 });
|
|
22531
22907
|
}
|
|
22532
22908
|
async function decodeNestWithdrawalRequest(args) {
|
|
22533
|
-
const transaction =
|
|
22909
|
+
const transaction = import_web336.VersionedTransaction.deserialize(
|
|
22534
22910
|
Buffer.from(args.txBase64, "base64")
|
|
22535
22911
|
);
|
|
22536
22912
|
const message2 = transaction.message;
|
|
@@ -22551,19 +22927,19 @@ async function decodeNestWithdrawalRequest(args) {
|
|
|
22551
22927
|
return value;
|
|
22552
22928
|
})
|
|
22553
22929
|
);
|
|
22554
|
-
const decoded =
|
|
22930
|
+
const decoded = import_web336.TransactionMessage.decompile(message2, {
|
|
22555
22931
|
addressLookupTableAccounts: tables
|
|
22556
22932
|
});
|
|
22557
|
-
const nestMint = new
|
|
22558
|
-
const sourceAta = (0,
|
|
22559
|
-
const usdcAta = (0,
|
|
22933
|
+
const nestMint = new import_web336.PublicKey(NEST_RWA_SHARE_MINT);
|
|
22934
|
+
const sourceAta = (0, import_spl_token22.getAssociatedTokenAddressSync)(nestMint, args.owner, true);
|
|
22935
|
+
const usdcAta = (0, import_spl_token22.getAssociatedTokenAddressSync)(UsdcMint, args.owner, true);
|
|
22560
22936
|
const instructions2 = decoded.instructions.filter(
|
|
22561
|
-
(ix) => !ix.programId.equals(
|
|
22937
|
+
(ix) => !ix.programId.equals(import_web336.ComputeBudgetProgram.programId)
|
|
22562
22938
|
);
|
|
22563
22939
|
let sends = 0;
|
|
22564
22940
|
for (const ix of instructions2) {
|
|
22565
|
-
if (ix.programId.equals(
|
|
22566
|
-
if (ix.data.length !== 1 || ix.data[0] !== 1 || !ix.keys[0]?.pubkey.equals(args.owner) || !ix.keys[1]?.pubkey.equals(usdcAta) || !ix.keys[2]?.pubkey.equals(args.owner) || !ix.keys[3]?.pubkey.equals(UsdcMint) || !ix.keys[5]?.pubkey.equals(
|
|
22941
|
+
if (ix.programId.equals(import_spl_token22.ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
22942
|
+
if (ix.data.length !== 1 || ix.data[0] !== 1 || !ix.keys[0]?.pubkey.equals(args.owner) || !ix.keys[1]?.pubkey.equals(usdcAta) || !ix.keys[2]?.pubkey.equals(args.owner) || !ix.keys[3]?.pubkey.equals(UsdcMint) || !ix.keys[5]?.pubkey.equals(import_spl_token22.TOKEN_PROGRAM_ID)) {
|
|
22567
22943
|
throw new Error("Unexpected token account creation in Nest withdrawal");
|
|
22568
22944
|
}
|
|
22569
22945
|
continue;
|
|
@@ -22580,13 +22956,137 @@ async function decodeNestWithdrawalRequest(args) {
|
|
|
22580
22956
|
if (sends !== 1)
|
|
22581
22957
|
throw new Error("Nest withdrawal must contain exactly one OFT send");
|
|
22582
22958
|
return {
|
|
22583
|
-
instructions: instructions2.map(
|
|
22959
|
+
instructions: instructions2.map(import_common60.toKitInstruction),
|
|
22584
22960
|
lookupTables: tables.map((table) => (0, import_kit18.address)(table.key.toBase58()))
|
|
22585
22961
|
};
|
|
22586
22962
|
}
|
|
22587
22963
|
|
|
22964
|
+
// src/services/nestDepositService.ts
|
|
22965
|
+
var import_kit19 = require("@solana/kit");
|
|
22966
|
+
var import_spl_token23 = require("@solana/spl-token");
|
|
22967
|
+
var import_web337 = require("@solana/web3.js");
|
|
22968
|
+
var import_common61 = __toESM(require_dist());
|
|
22969
|
+
var import_nest5 = __toESM(require_dist3());
|
|
22970
|
+
var Usdc = new import_web337.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
|
|
22971
|
+
var Messenger = new import_web337.PublicKey("CCTPV2vPZJS2u2BBsUoscuikbYjnpFmbFsvVuJdgUMQe");
|
|
22972
|
+
var Transmitter = new import_web337.PublicKey(
|
|
22973
|
+
"CCTPV2Sm4AdWt5296sk4P66VBZ7bEhcARwFaaS9YPbeC"
|
|
22974
|
+
);
|
|
22975
|
+
var Router = Buffer.from(
|
|
22976
|
+
"0000000000000000000000007de01896d36bea9cf072ac64e41685418941d8be",
|
|
22977
|
+
"hex"
|
|
22978
|
+
);
|
|
22979
|
+
var Composer = Buffer.from("908dcb5531691c2124c54e30bb645cf11647090d", "hex");
|
|
22980
|
+
var BurnWithHook = Buffer.from([111, 245, 62, 131, 204, 108, 223, 155]);
|
|
22981
|
+
var PerenaAssetId = Buffer.from(
|
|
22982
|
+
"355750bed2d05a1eb92ab578335cc3ea6d572dd5f57a086088c68667f11e50d2",
|
|
22983
|
+
"hex"
|
|
22984
|
+
);
|
|
22985
|
+
var MintAndSend = Buffer.from("fe030ec4", "hex");
|
|
22986
|
+
async function buildNestDepositRequest(args) {
|
|
22987
|
+
if (args.rawAmountUsdc <= 0n || args.rawAmountUsdc > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
22988
|
+
throw new Error(
|
|
22989
|
+
"Nest deposit must be a positive, safely representable USDC base-unit amount"
|
|
22990
|
+
);
|
|
22991
|
+
}
|
|
22992
|
+
const options = args.apiOptions ?? {};
|
|
22993
|
+
const response = await (options.fetchFn ?? fetch)(
|
|
22994
|
+
`${(options.baseUrl ?? import_nest5.NEST_API_BASE_URL).replace(
|
|
22995
|
+
/\/$/,
|
|
22996
|
+
""
|
|
22997
|
+
)}/solana/nest/mint/build-tx`,
|
|
22998
|
+
{
|
|
22999
|
+
method: "POST",
|
|
23000
|
+
headers: { "Content-Type": "application/json" },
|
|
23001
|
+
signal: options.signal,
|
|
23002
|
+
body: JSON.stringify({
|
|
23003
|
+
rawAmountUsdc: Number(args.rawAmountUsdc),
|
|
23004
|
+
receiver: args.owner.toBase58(),
|
|
23005
|
+
nestVaultSlug: NEST_VAULT_SLUG,
|
|
23006
|
+
finality: "standard"
|
|
23007
|
+
})
|
|
23008
|
+
}
|
|
23009
|
+
);
|
|
23010
|
+
const payload = await response.json().catch(() => null);
|
|
23011
|
+
if (!response.ok)
|
|
23012
|
+
throw new Error(
|
|
23013
|
+
`Nest deposit API (${response.status}): ${typeof payload?.error === "string" ? payload.error : response.statusText}`
|
|
23014
|
+
);
|
|
23015
|
+
if (typeof payload?.data?.txBase64 !== "string")
|
|
23016
|
+
throw new Error("Nest API returned no deposit transaction");
|
|
23017
|
+
return decodeNestDepositRequest({ ...args, txBase64: payload.data.txBase64 });
|
|
23018
|
+
}
|
|
23019
|
+
async function decodeNestDepositRequest(args) {
|
|
23020
|
+
if (args.rawAmountUsdc <= 0n || args.rawAmountUsdc > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
23021
|
+
throw new Error(
|
|
23022
|
+
"Nest deposit must be a positive, safely representable USDC base-unit amount"
|
|
23023
|
+
);
|
|
23024
|
+
}
|
|
23025
|
+
const message2 = import_web337.VersionedTransaction.deserialize(
|
|
23026
|
+
Buffer.from(args.txBase64, "base64")
|
|
23027
|
+
).message;
|
|
23028
|
+
if (!message2.staticAccountKeys[0].equals(args.owner))
|
|
23029
|
+
throw new Error("Nest deposit payer must be the manager");
|
|
23030
|
+
const tables = await Promise.all(
|
|
23031
|
+
message2.addressTableLookups.map(async (lookup) => {
|
|
23032
|
+
const { value } = await args.connection.getAddressLookupTable(
|
|
23033
|
+
lookup.accountKey
|
|
23034
|
+
);
|
|
23035
|
+
if (!value)
|
|
23036
|
+
throw new Error(`Nest lookup table not found: ${lookup.accountKey}`);
|
|
23037
|
+
return value;
|
|
23038
|
+
})
|
|
23039
|
+
);
|
|
23040
|
+
const instructions2 = import_web337.TransactionMessage.decompile(message2, {
|
|
23041
|
+
addressLookupTableAccounts: tables
|
|
23042
|
+
}).instructions;
|
|
23043
|
+
const shareMint = new import_web337.PublicKey(NEST_RWA_SHARE_MINT);
|
|
23044
|
+
const shareAta = (0, import_spl_token23.getAssociatedTokenAddressSync)(shareMint, args.owner, true);
|
|
23045
|
+
const usdcAta = (0, import_spl_token23.getAssociatedTokenAddressSync)(Usdc, args.owner, true);
|
|
23046
|
+
let burn;
|
|
23047
|
+
for (const ix of instructions2) {
|
|
23048
|
+
if (ix.programId.equals(import_web337.ComputeBudgetProgram.programId)) continue;
|
|
23049
|
+
if (ix.programId.equals(import_spl_token23.ASSOCIATED_TOKEN_PROGRAM_ID)) {
|
|
23050
|
+
if (ix.data.length !== 1 || ix.data[0] !== 1 || !ix.keys[0]?.pubkey.equals(args.owner) || !ix.keys[1]?.pubkey.equals(shareAta) || !ix.keys[2]?.pubkey.equals(args.owner) || !ix.keys[3]?.pubkey.equals(shareMint) || !ix.keys[4]?.pubkey.equals(import_web337.SystemProgram.programId) || !ix.keys[5]?.pubkey.equals(import_spl_token23.TOKEN_PROGRAM_ID))
|
|
23051
|
+
throw new Error("Unexpected Nest deposit token account creation");
|
|
23052
|
+
continue;
|
|
23053
|
+
}
|
|
23054
|
+
const d = ix.data;
|
|
23055
|
+
const matches = (index, key) => ix.keys[index]?.pubkey.equals(key);
|
|
23056
|
+
if (burn || !ix.programId.equals(Messenger) || ix.keys.length !== 18 || d.length < 316 || !d.subarray(0, 8).equals(BurnWithHook) || d.readBigUInt64LE(8) !== args.rawAmountUsdc || d.readUInt32LE(16) !== 22 || !d.subarray(20, 52).equals(Router) || !d.subarray(52, 84).equals(Router) || d.readBigUInt64LE(84) !== 0n || d.readUInt32LE(92) !== 2e3 || d.readUInt32LE(96) !== d.length - 100 || !d.subarray(100, 120).equals(Composer) || !d.subarray(120, 124).equals(MintAndSend) || !d.subarray(124, 156).equals(PerenaAssetId) || BigInt(`0x${d.subarray(156, 188).toString("hex")}`) !== args.rawAmountUsdc || BigInt(`0x${d.subarray(188, 220).toString("hex")}`) !== 128n || !d.subarray(220, 252).equals(Buffer.concat([Buffer.alloc(12), Composer])) || BigInt(`0x${d.subarray(252, 284).toString("hex")}`) !== 30168n || !d.subarray(284, 316).equals(args.owner.toBuffer()) || !matches(0, args.owner) || !matches(3, usdcAta) || !matches(10, Usdc) || !matches(12, Transmitter) || !matches(13, Messenger) || !matches(14, import_spl_token23.TOKEN_PROGRAM_ID) || !matches(15, import_web337.SystemProgram.programId) || !matches(17, Messenger) || ![0, 1, 11].every((index) => ix.keys[index].isSigner) || ix.keys.some(
|
|
23057
|
+
(meta, index) => meta.isSigner && ![0, 1, 11].includes(index)
|
|
23058
|
+
)) {
|
|
23059
|
+
throw new Error(
|
|
23060
|
+
"Unexpected Nest deposit instruction, amount, or recipient"
|
|
23061
|
+
);
|
|
23062
|
+
}
|
|
23063
|
+
burn = ix;
|
|
23064
|
+
}
|
|
23065
|
+
if (!burn) throw new Error("Nest deposit must contain one CCTP burn");
|
|
23066
|
+
const eventKey = burn.keys[11].pubkey;
|
|
23067
|
+
if (eventKey.equals(args.owner) || burn.keys.some(
|
|
23068
|
+
(meta, index) => index !== 11 && meta.pubkey.equals(eventKey)
|
|
23069
|
+
)) {
|
|
23070
|
+
throw new Error("Nest deposit event signer must be a separate account");
|
|
23071
|
+
}
|
|
23072
|
+
burn.keys[1] = { pubkey: args.owner, isSigner: true, isWritable: true };
|
|
23073
|
+
return {
|
|
23074
|
+
instructions: [
|
|
23075
|
+
(0, import_spl_token23.createAssociatedTokenAccountIdempotentInstruction)(
|
|
23076
|
+
args.owner,
|
|
23077
|
+
shareAta,
|
|
23078
|
+
args.owner,
|
|
23079
|
+
shareMint
|
|
23080
|
+
),
|
|
23081
|
+
burn
|
|
23082
|
+
].map(import_common61.toKitInstruction),
|
|
23083
|
+
lookupTables: tables.map((table) => (0, import_kit19.address)(table.key.toBase58())),
|
|
23084
|
+
ephemeralSignerKeys: [eventKey]
|
|
23085
|
+
};
|
|
23086
|
+
}
|
|
23087
|
+
|
|
22588
23088
|
// src/index.ts
|
|
22589
|
-
var
|
|
23089
|
+
var import_common62 = __toESM(require_dist());
|
|
22590
23090
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22591
23091
|
0 && (module.exports = {
|
|
22592
23092
|
ASSET_DECIMALS,
|
|
@@ -22624,6 +23124,7 @@ var import_common60 = __toESM(require_dist());
|
|
|
22624
23124
|
DEFAULT_REBALANCE_BAND_BPS,
|
|
22625
23125
|
DEFAULT_SLIPPAGE_BPS,
|
|
22626
23126
|
DEFAULT_TARGET_LOCAL_BPS,
|
|
23127
|
+
DEFAULT_TARGET_LOCAL_USDC_TVL_BPS,
|
|
22627
23128
|
DEFAULT_VAULT_ID,
|
|
22628
23129
|
DisableCircuitBreakerBuilder,
|
|
22629
23130
|
DistributeIncentiveBuilder,
|
|
@@ -22651,6 +23152,8 @@ var import_common60 = __toESM(require_dist());
|
|
|
22651
23152
|
LOCAL_PROTOCOL_ADMIN,
|
|
22652
23153
|
LargeBalanceChangeError,
|
|
22653
23154
|
LivePriceSource,
|
|
23155
|
+
MANAGER_WALLET_NAV_DROP_TRIGGER_BPS,
|
|
23156
|
+
MANAGER_WALLET_NAV_TOLERANCE_BPS,
|
|
22654
23157
|
MAX_APY_ANCHOR_WINDOW_SECS,
|
|
22655
23158
|
MAX_BALANCE_CHANGE_BPS,
|
|
22656
23159
|
MAX_CONSENSUS_SIGNERS,
|
|
@@ -22683,6 +23186,7 @@ var import_common60 = __toESM(require_dist());
|
|
|
22683
23186
|
RemoveAssetHoldingBuilder,
|
|
22684
23187
|
ReportIncentiveV3Builder,
|
|
22685
23188
|
RequestJuniorTrancheWithdrawBuilder,
|
|
23189
|
+
RpcManagerWalletBalanceSource,
|
|
22686
23190
|
SHARE_DECIMALS,
|
|
22687
23191
|
SYSTEM_PROGRAM,
|
|
22688
23192
|
SetAssetPriceOracleBuilder,
|
|
@@ -22722,6 +23226,7 @@ var import_common60 = __toESM(require_dist());
|
|
|
22722
23226
|
VaultClient,
|
|
22723
23227
|
VaultQuoteClient,
|
|
22724
23228
|
VaultReallocationBuilder,
|
|
23229
|
+
WITHDRAWABLE_RESERVE_FLOOR_BPS,
|
|
22725
23230
|
WithdrawalQueueService,
|
|
22726
23231
|
accountingUnitPriceToUsd,
|
|
22727
23232
|
addCashflowUpdate,
|
|
@@ -22731,8 +23236,10 @@ var import_common60 = __toESM(require_dist());
|
|
|
22731
23236
|
assertNoUnconfirmedYieldPayments,
|
|
22732
23237
|
buildHoldingUpdate,
|
|
22733
23238
|
buildMarginfiWithdrawInteraction,
|
|
23239
|
+
buildNestDepositRequest,
|
|
22734
23240
|
buildNestWithdrawalRequest,
|
|
22735
23241
|
buildUpdates,
|
|
23242
|
+
candidateGrossNav,
|
|
22736
23243
|
coerceBool,
|
|
22737
23244
|
collectSamples,
|
|
22738
23245
|
confirmYieldPayment,
|
|
@@ -22744,6 +23251,7 @@ var import_common60 = __toESM(require_dist());
|
|
|
22744
23251
|
createVaultClient,
|
|
22745
23252
|
createYieldPayment,
|
|
22746
23253
|
dateToStr,
|
|
23254
|
+
decodeNestDepositRequest,
|
|
22747
23255
|
decodeNestWithdrawalRequest,
|
|
22748
23256
|
decodePendingConsensusSigners,
|
|
22749
23257
|
defaultKeypairPath,
|
|
@@ -22791,6 +23299,7 @@ var import_common60 = __toESM(require_dist());
|
|
|
22791
23299
|
loadKeypair,
|
|
22792
23300
|
logProspectiveApy,
|
|
22793
23301
|
makeProvider,
|
|
23302
|
+
managerReconciliationStateKey,
|
|
22794
23303
|
mintTokensTo,
|
|
22795
23304
|
mints,
|
|
22796
23305
|
mostFrequent,
|
|
@@ -22798,9 +23307,11 @@ var import_common60 = __toESM(require_dist());
|
|
|
22798
23307
|
planRebalance,
|
|
22799
23308
|
prepareSquadsProposalUpload,
|
|
22800
23309
|
prepareVaultTransaction,
|
|
23310
|
+
previousPhysicalNav,
|
|
22801
23311
|
priceInAccountingUnit,
|
|
22802
23312
|
readI64LE,
|
|
22803
23313
|
readSplMintSupply,
|
|
23314
|
+
reconcileManagerWalletBalances,
|
|
22804
23315
|
refreshLiveOraclePrices,
|
|
22805
23316
|
resolveExternalWithdraw,
|
|
22806
23317
|
resolveKeypairPath,
|