@perena/vault-sdk 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +306 -149
- package/dist/index.js +1262 -233
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -250,9 +250,9 @@ var require_meta = __commonJS({
|
|
|
250
250
|
exports2.toCustomAccountMeta = toCustomAccountMeta;
|
|
251
251
|
exports2.toCustomAccountMetaFromWeb3AccountMeta = toCustomAccountMetaFromWeb3AccountMeta;
|
|
252
252
|
var roles_1 = require_roles();
|
|
253
|
-
function toCustomAccountMeta(
|
|
253
|
+
function toCustomAccountMeta(address12, isWritable, requiredAtaDetails, isSigner) {
|
|
254
254
|
const role = (0, roles_1.getAccountRole)(isWritable ?? false, isSigner ?? false);
|
|
255
|
-
return { address:
|
|
255
|
+
return { address: address12, role, isRequiredAta: requiredAtaDetails };
|
|
256
256
|
}
|
|
257
257
|
function toCustomAccountMetaFromWeb3AccountMeta(web3AccountMeta) {
|
|
258
258
|
return toCustomAccountMeta(web3AccountMeta.pubkey.toBase58(), web3AccountMeta.isWritable, void 0, web3AccountMeta.isSigner);
|
|
@@ -611,12 +611,12 @@ var require_transaction = __commonJS({
|
|
|
611
611
|
async function sendVersionedTransaction({ connection, payer, instructions: instructions2, lookupTables }) {
|
|
612
612
|
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash("confirmed");
|
|
613
613
|
const lookupTableAccounts = await fetchLookupTables(connection, lookupTables);
|
|
614
|
-
const
|
|
614
|
+
const message2 = new web3_js_1.TransactionMessage({
|
|
615
615
|
payerKey: payer.publicKey,
|
|
616
616
|
recentBlockhash: blockhash,
|
|
617
617
|
instructions: instructions2
|
|
618
618
|
}).compileToV0Message(lookupTableAccounts);
|
|
619
|
-
const tx = new web3_js_1.VersionedTransaction(
|
|
619
|
+
const tx = new web3_js_1.VersionedTransaction(message2);
|
|
620
620
|
tx.sign([payer]);
|
|
621
621
|
const signature = await connection.sendRawTransaction(tx.serialize(), {
|
|
622
622
|
skipPreflight: true
|
|
@@ -1200,8 +1200,8 @@ var require_cpiClient = __commonJS({
|
|
|
1200
1200
|
var kit_1 = require("@solana/kit");
|
|
1201
1201
|
var common_1 = require_dist();
|
|
1202
1202
|
var constants_1 = require_constants3();
|
|
1203
|
-
function account(
|
|
1204
|
-
return { address:
|
|
1203
|
+
function account(address12, role) {
|
|
1204
|
+
return { address: address12, role };
|
|
1205
1205
|
}
|
|
1206
1206
|
function requiredAddress(value, label) {
|
|
1207
1207
|
if (!value) {
|
|
@@ -1290,7 +1290,7 @@ var require_cpiClient = __commonJS({
|
|
|
1290
1290
|
});
|
|
1291
1291
|
const bankAndOracleRemainingAccounts = [
|
|
1292
1292
|
account(this.accounts.bank, kit_1.AccountRole.READONLY),
|
|
1293
|
-
...this.accounts.oracleAccounts.map((
|
|
1293
|
+
...this.accounts.oracleAccounts.map((address12) => account(address12, kit_1.AccountRole.READONLY))
|
|
1294
1294
|
];
|
|
1295
1295
|
return {
|
|
1296
1296
|
cpiType: params.cpiType ?? common_1.CpiTypes.MARGINFI_WITHDRAW,
|
|
@@ -1414,11 +1414,17 @@ __export(index_exports, {
|
|
|
1414
1414
|
JupiterPriceSource: () => JupiterPriceSource,
|
|
1415
1415
|
JupiterSwapBuilder: () => JupiterSwapBuilder,
|
|
1416
1416
|
KaminoPositionProvider: () => KaminoPositionProvider,
|
|
1417
|
+
LOCAL_PROTOCOL_ADMIN: () => LOCAL_PROTOCOL_ADMIN,
|
|
1418
|
+
LivePriceSource: () => LivePriceSource,
|
|
1417
1419
|
MAX_PRICE_STALENESS_THRESHOLD_SECS: () => MAX_PRICE_STALENESS_THRESHOLD_SECS,
|
|
1418
1420
|
ManagerRedepositAssetBuilder: () => ManagerRedepositAssetBuilder,
|
|
1419
1421
|
ManagerWithdrawAssetBuilder: () => ManagerWithdrawAssetBuilder,
|
|
1420
1422
|
MarginfiPositionProvider: () => MarginfiPositionProvider,
|
|
1421
1423
|
MockYieldTracker: () => MockYieldTracker,
|
|
1424
|
+
NEST_API_BASE_URL: () => NEST_API_BASE_URL,
|
|
1425
|
+
NEST_RWA_SHARE_MINT: () => NEST_RWA_SHARE_MINT,
|
|
1426
|
+
NEST_VAULT_SLUG: () => NEST_VAULT_SLUG,
|
|
1427
|
+
NestPriceSource: () => NestPriceSource,
|
|
1422
1428
|
OracleService: () => OracleService,
|
|
1423
1429
|
PROGRAM_FEE_EXEMPT_OWNER_WHITELIST: () => PROGRAM_FEE_EXEMPT_OWNER_WHITELIST,
|
|
1424
1430
|
PROTOCOL_ADMIN: () => PROTOCOL_ADMIN,
|
|
@@ -1461,6 +1467,7 @@ __export(index_exports, {
|
|
|
1461
1467
|
WithdrawalQueueService: () => WithdrawalQueueService,
|
|
1462
1468
|
addCashflowUpdate: () => addCashflowUpdate,
|
|
1463
1469
|
address: () => import_kit10.address,
|
|
1470
|
+
applyEffectiveApy: () => applyEffectiveApy,
|
|
1464
1471
|
confirmYieldPayment: () => confirmYieldPayment,
|
|
1465
1472
|
createAccount: () => createAccount,
|
|
1466
1473
|
createLiveConsensusOracleDeps: () => createLiveConsensusOracleDeps,
|
|
@@ -1472,7 +1479,9 @@ __export(index_exports, {
|
|
|
1472
1479
|
dateToStr: () => dateToStr,
|
|
1473
1480
|
defaultKeypairPath: () => defaultKeypairPath,
|
|
1474
1481
|
deleteAccount: () => deleteAccount,
|
|
1482
|
+
fetchNestTokenPrice: () => fetchNestTokenPrice,
|
|
1475
1483
|
findSquadsWalletRoute: () => findSquadsWalletRoute,
|
|
1484
|
+
formatSettlementSimulation: () => formatSettlementSimulation,
|
|
1476
1485
|
fromUiAmount: () => fromUiAmount,
|
|
1477
1486
|
getAccounts: () => getAccounts,
|
|
1478
1487
|
getBalance: () => getBalance,
|
|
@@ -1493,6 +1502,7 @@ __export(index_exports, {
|
|
|
1493
1502
|
resolveSquadsWalletRoute: () => resolveSquadsWalletRoute,
|
|
1494
1503
|
roundToNextUtcMidnight: () => roundToNextUtcMidnight,
|
|
1495
1504
|
runLiveConsensusOracle: () => runLiveConsensusOracle,
|
|
1505
|
+
simulateConsensusOracleSettlement: () => simulateConsensusOracleSettlement,
|
|
1496
1506
|
systemClock: () => systemClock,
|
|
1497
1507
|
toUiAmount: () => toUiAmount,
|
|
1498
1508
|
updateAccount: () => updateAccount,
|
|
@@ -1511,6 +1521,9 @@ var VAULT_PROGRAM_ID = (0, import_kit.address)(
|
|
|
1511
1521
|
);
|
|
1512
1522
|
var VAULT_PROGRAM_PUBLIC_KEY = new import_web3.PublicKey(VAULT_PROGRAM_ID);
|
|
1513
1523
|
var PROTOCOL_ADMIN = (0, import_kit.address)(
|
|
1524
|
+
"4jMRBkpWrfhhwFYTwG3o7hmsXQwbJUwdyUX8htB6KwLJ"
|
|
1525
|
+
);
|
|
1526
|
+
var LOCAL_PROTOCOL_ADMIN = (0, import_kit.address)(
|
|
1514
1527
|
"BQJZAhDnvgSGHjdAbzQEXRBYzSBuWgSYqDzhDnUSRWGR"
|
|
1515
1528
|
);
|
|
1516
1529
|
var PROTOCOL_FEE_RECIPIENT = (0, import_kit.address)(
|
|
@@ -1522,7 +1535,7 @@ var PROGRAM_FEE_EXEMPT_OWNER_WHITELIST = [
|
|
|
1522
1535
|
(0, import_kit.address)("LYC8YiiSzQfPpxUW2tpxfuPKGZwywAJhXKUfDP2B66f")
|
|
1523
1536
|
];
|
|
1524
1537
|
var VAULT_CREATOR_WHITELIST = [
|
|
1525
|
-
(0, import_kit.address)("
|
|
1538
|
+
(0, import_kit.address)("4jMRBkpWrfhhwFYTwG3o7hmsXQwbJUwdyUX8htB6KwLJ")
|
|
1526
1539
|
];
|
|
1527
1540
|
var TOKEN_PROGRAM_ID = (0, import_kit.address)(
|
|
1528
1541
|
import_spl_token.TOKEN_2022_PROGRAM_ID.toBase58()
|
|
@@ -1768,8 +1781,7 @@ var IDL = {
|
|
|
1768
1781
|
{
|
|
1769
1782
|
"name": "fee_asset_mint",
|
|
1770
1783
|
"docs": [
|
|
1771
|
-
"
|
|
1772
|
-
"an `is_base` holding; choose a mint whose vault ATA has liquidity."
|
|
1784
|
+
"Legacy fee-asset account retained in this instruction's account schema."
|
|
1773
1785
|
]
|
|
1774
1786
|
},
|
|
1775
1787
|
{
|
|
@@ -1832,7 +1844,7 @@ var IDL = {
|
|
|
1832
1844
|
{
|
|
1833
1845
|
"name": "fee_vault",
|
|
1834
1846
|
"docs": [
|
|
1835
|
-
"
|
|
1847
|
+
"Legacy fee-vault account retained in this instruction's account schema."
|
|
1836
1848
|
],
|
|
1837
1849
|
"writable": true
|
|
1838
1850
|
},
|
|
@@ -1926,84 +1938,18 @@ var IDL = {
|
|
|
1926
1938
|
"signer": true
|
|
1927
1939
|
},
|
|
1928
1940
|
{
|
|
1929
|
-
"name": "vault"
|
|
1930
|
-
},
|
|
1931
|
-
{
|
|
1932
|
-
"name": "fee_asset_mint",
|
|
1933
|
-
"docs": [
|
|
1934
|
-
"Vault base asset whose fee-vault ATA should be swept. Must match an",
|
|
1935
|
-
"`is_base` holding with a fresh price."
|
|
1936
|
-
]
|
|
1937
|
-
},
|
|
1938
|
-
{
|
|
1939
|
-
"name": "fee_vault",
|
|
1940
|
-
"docs": [
|
|
1941
|
-
"Per-vault fee-vault PDA: token authority + accounting for accrued fees."
|
|
1942
|
-
],
|
|
1941
|
+
"name": "vault",
|
|
1943
1942
|
"writable": true
|
|
1944
1943
|
},
|
|
1945
1944
|
{
|
|
1946
|
-
"name": "
|
|
1947
|
-
"writable": true
|
|
1948
|
-
"pda": {
|
|
1949
|
-
"seeds": [
|
|
1950
|
-
{
|
|
1951
|
-
"kind": "account",
|
|
1952
|
-
"path": "fee_vault"
|
|
1953
|
-
},
|
|
1954
|
-
{
|
|
1955
|
-
"kind": "account",
|
|
1956
|
-
"path": "fee_asset_token_program"
|
|
1957
|
-
},
|
|
1958
|
-
{
|
|
1959
|
-
"kind": "account",
|
|
1960
|
-
"path": "fee_asset_mint"
|
|
1961
|
-
}
|
|
1962
|
-
],
|
|
1963
|
-
"program": {
|
|
1964
|
-
"kind": "const",
|
|
1965
|
-
"value": [
|
|
1966
|
-
140,
|
|
1967
|
-
151,
|
|
1968
|
-
37,
|
|
1969
|
-
143,
|
|
1970
|
-
78,
|
|
1971
|
-
36,
|
|
1972
|
-
137,
|
|
1973
|
-
241,
|
|
1974
|
-
187,
|
|
1975
|
-
61,
|
|
1976
|
-
16,
|
|
1977
|
-
41,
|
|
1978
|
-
20,
|
|
1979
|
-
142,
|
|
1980
|
-
13,
|
|
1981
|
-
131,
|
|
1982
|
-
11,
|
|
1983
|
-
90,
|
|
1984
|
-
19,
|
|
1985
|
-
153,
|
|
1986
|
-
218,
|
|
1987
|
-
255,
|
|
1988
|
-
16,
|
|
1989
|
-
132,
|
|
1990
|
-
4,
|
|
1991
|
-
142,
|
|
1992
|
-
123,
|
|
1993
|
-
216,
|
|
1994
|
-
219,
|
|
1995
|
-
233,
|
|
1996
|
-
248,
|
|
1997
|
-
89
|
|
1998
|
-
]
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
1945
|
+
"name": "share_mint",
|
|
1946
|
+
"writable": true
|
|
2001
1947
|
},
|
|
2002
1948
|
{
|
|
2003
1949
|
"name": "fee_collector"
|
|
2004
1950
|
},
|
|
2005
1951
|
{
|
|
2006
|
-
"name": "
|
|
1952
|
+
"name": "fee_collector_share_ata",
|
|
2007
1953
|
"writable": true,
|
|
2008
1954
|
"pda": {
|
|
2009
1955
|
"seeds": [
|
|
@@ -2013,11 +1959,11 @@ var IDL = {
|
|
|
2013
1959
|
},
|
|
2014
1960
|
{
|
|
2015
1961
|
"kind": "account",
|
|
2016
|
-
"path": "
|
|
1962
|
+
"path": "share_token_program"
|
|
2017
1963
|
},
|
|
2018
1964
|
{
|
|
2019
1965
|
"kind": "account",
|
|
2020
|
-
"path": "
|
|
1966
|
+
"path": "share_mint"
|
|
2021
1967
|
}
|
|
2022
1968
|
],
|
|
2023
1969
|
"program": {
|
|
@@ -2063,7 +2009,7 @@ var IDL = {
|
|
|
2063
2009
|
"name": "protocol_fee_collector"
|
|
2064
2010
|
},
|
|
2065
2011
|
{
|
|
2066
|
-
"name": "
|
|
2012
|
+
"name": "protocol_fee_collector_share_ata",
|
|
2067
2013
|
"writable": true,
|
|
2068
2014
|
"pda": {
|
|
2069
2015
|
"seeds": [
|
|
@@ -2073,11 +2019,11 @@ var IDL = {
|
|
|
2073
2019
|
},
|
|
2074
2020
|
{
|
|
2075
2021
|
"kind": "account",
|
|
2076
|
-
"path": "
|
|
2022
|
+
"path": "share_token_program"
|
|
2077
2023
|
},
|
|
2078
2024
|
{
|
|
2079
2025
|
"kind": "account",
|
|
2080
|
-
"path": "
|
|
2026
|
+
"path": "share_mint"
|
|
2081
2027
|
}
|
|
2082
2028
|
],
|
|
2083
2029
|
"program": {
|
|
@@ -2120,7 +2066,7 @@ var IDL = {
|
|
|
2120
2066
|
}
|
|
2121
2067
|
},
|
|
2122
2068
|
{
|
|
2123
|
-
"name": "
|
|
2069
|
+
"name": "share_token_program"
|
|
2124
2070
|
},
|
|
2125
2071
|
{
|
|
2126
2072
|
"name": "associated_token_program",
|
|
@@ -3003,7 +2949,9 @@ var IDL = {
|
|
|
3003
2949
|
{
|
|
3004
2950
|
"name": "share_mint",
|
|
3005
2951
|
"docs": [
|
|
3006
|
-
"Curator-supplied share mint. Its decimals
|
|
2952
|
+
"Curator-supplied share mint. Its decimals define the vault accounting",
|
|
2953
|
+
"precision. `asset_mint` may use a different precision, which is stored",
|
|
2954
|
+
"on its holding and handled by holding-price conversion.",
|
|
3007
2955
|
"Unless `for_migration`, it must have zero supply with mint authority on",
|
|
3008
2956
|
"the curator; authority is transferred to the vault PDA on success.",
|
|
3009
2957
|
"Migration uses the legacy bank mint and defers transfer."
|
|
@@ -3227,8 +3175,8 @@ var IDL = {
|
|
|
3227
3175
|
{
|
|
3228
3176
|
"name": "fee_vault",
|
|
3229
3177
|
"docs": [
|
|
3230
|
-
"
|
|
3231
|
-
"
|
|
3178
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
3179
|
+
"New fees accrue as pending vault shares."
|
|
3232
3180
|
],
|
|
3233
3181
|
"writable": true
|
|
3234
3182
|
},
|
|
@@ -3522,8 +3470,8 @@ var IDL = {
|
|
|
3522
3470
|
{
|
|
3523
3471
|
"name": "fee_vault",
|
|
3524
3472
|
"docs": [
|
|
3525
|
-
"
|
|
3526
|
-
"
|
|
3473
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
3474
|
+
"New fees accrue as pending vault shares."
|
|
3527
3475
|
],
|
|
3528
3476
|
"writable": true
|
|
3529
3477
|
},
|
|
@@ -4018,8 +3966,8 @@ var IDL = {
|
|
|
4018
3966
|
{
|
|
4019
3967
|
"name": "fee_vault",
|
|
4020
3968
|
"docs": [
|
|
4021
|
-
"
|
|
4022
|
-
"
|
|
3969
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
3970
|
+
"New fees accrue as pending vault shares."
|
|
4023
3971
|
],
|
|
4024
3972
|
"writable": true
|
|
4025
3973
|
},
|
|
@@ -4320,8 +4268,8 @@ var IDL = {
|
|
|
4320
4268
|
{
|
|
4321
4269
|
"name": "fee_vault",
|
|
4322
4270
|
"docs": [
|
|
4323
|
-
"
|
|
4324
|
-
"
|
|
4271
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
4272
|
+
"New fees accrue as pending vault shares."
|
|
4325
4273
|
],
|
|
4326
4274
|
"writable": true
|
|
4327
4275
|
},
|
|
@@ -5111,8 +5059,8 @@ var IDL = {
|
|
|
5111
5059
|
{
|
|
5112
5060
|
"name": "fee_vault",
|
|
5113
5061
|
"docs": [
|
|
5114
|
-
"
|
|
5115
|
-
"
|
|
5062
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
5063
|
+
"New fees accrue as pending vault shares."
|
|
5116
5064
|
],
|
|
5117
5065
|
"writable": true
|
|
5118
5066
|
},
|
|
@@ -5400,8 +5348,8 @@ var IDL = {
|
|
|
5400
5348
|
{
|
|
5401
5349
|
"name": "fee_vault",
|
|
5402
5350
|
"docs": [
|
|
5403
|
-
"
|
|
5404
|
-
"
|
|
5351
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
5352
|
+
"New fees accrue as pending vault shares."
|
|
5405
5353
|
],
|
|
5406
5354
|
"writable": true
|
|
5407
5355
|
},
|
|
@@ -5695,8 +5643,8 @@ var IDL = {
|
|
|
5695
5643
|
{
|
|
5696
5644
|
"name": "fee_vault",
|
|
5697
5645
|
"docs": [
|
|
5698
|
-
"
|
|
5699
|
-
"
|
|
5646
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
5647
|
+
"New fees accrue as pending vault shares."
|
|
5700
5648
|
],
|
|
5701
5649
|
"writable": true
|
|
5702
5650
|
},
|
|
@@ -6000,8 +5948,8 @@ var IDL = {
|
|
|
6000
5948
|
{
|
|
6001
5949
|
"name": "fee_vault",
|
|
6002
5950
|
"docs": [
|
|
6003
|
-
"
|
|
6004
|
-
"
|
|
5951
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
5952
|
+
"New fees accrue as pending vault shares."
|
|
6005
5953
|
],
|
|
6006
5954
|
"writable": true
|
|
6007
5955
|
},
|
|
@@ -7422,9 +7370,6 @@ var IDL = {
|
|
|
7422
7370
|
},
|
|
7423
7371
|
{
|
|
7424
7372
|
"name": "idle_bank_tranche",
|
|
7425
|
-
"docs": [
|
|
7426
|
-
"path rejects initialized state because it cannot represent junior claims."
|
|
7427
|
-
],
|
|
7428
7373
|
"pda": {
|
|
7429
7374
|
"seeds": [
|
|
7430
7375
|
{
|
|
@@ -7583,7 +7528,7 @@ var IDL = {
|
|
|
7583
7528
|
{
|
|
7584
7529
|
"name": "yielding_bank_tranche",
|
|
7585
7530
|
"docs": [
|
|
7586
|
-
"
|
|
7531
|
+
"tranche was already consumed by its regular vault migrations."
|
|
7587
7532
|
],
|
|
7588
7533
|
"pda": {
|
|
7589
7534
|
"seeds": [
|
|
@@ -7761,9 +7706,6 @@ var IDL = {
|
|
|
7761
7706
|
},
|
|
7762
7707
|
{
|
|
7763
7708
|
"name": "vault_tranche_state",
|
|
7764
|
-
"docs": [
|
|
7765
|
-
"be initialized and consistent with destination.tranching_enabled."
|
|
7766
|
-
],
|
|
7767
7709
|
"writable": true,
|
|
7768
7710
|
"pda": {
|
|
7769
7711
|
"seeds": [
|
|
@@ -9787,6 +9729,69 @@ var IDL = {
|
|
|
9787
9729
|
}
|
|
9788
9730
|
]
|
|
9789
9731
|
},
|
|
9732
|
+
{
|
|
9733
|
+
"name": "trigger_bank_circuit_breaker",
|
|
9734
|
+
"discriminator": [
|
|
9735
|
+
250,
|
|
9736
|
+
236,
|
|
9737
|
+
165,
|
|
9738
|
+
211,
|
|
9739
|
+
181,
|
|
9740
|
+
241,
|
|
9741
|
+
74,
|
|
9742
|
+
84
|
|
9743
|
+
],
|
|
9744
|
+
"accounts": [
|
|
9745
|
+
{
|
|
9746
|
+
"name": "bank_state",
|
|
9747
|
+
"writable": true,
|
|
9748
|
+
"pda": {
|
|
9749
|
+
"seeds": [
|
|
9750
|
+
{
|
|
9751
|
+
"kind": "const",
|
|
9752
|
+
"value": [
|
|
9753
|
+
66,
|
|
9754
|
+
65,
|
|
9755
|
+
78,
|
|
9756
|
+
75
|
|
9757
|
+
]
|
|
9758
|
+
},
|
|
9759
|
+
{
|
|
9760
|
+
"kind": "account",
|
|
9761
|
+
"path": "bank_state"
|
|
9762
|
+
}
|
|
9763
|
+
]
|
|
9764
|
+
}
|
|
9765
|
+
},
|
|
9766
|
+
{
|
|
9767
|
+
"name": "bank_manager",
|
|
9768
|
+
"writable": true,
|
|
9769
|
+
"signer": true
|
|
9770
|
+
},
|
|
9771
|
+
{
|
|
9772
|
+
"name": "system_program",
|
|
9773
|
+
"address": "11111111111111111111111111111111"
|
|
9774
|
+
},
|
|
9775
|
+
{
|
|
9776
|
+
"name": "token_program",
|
|
9777
|
+
"address": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
|
|
9778
|
+
}
|
|
9779
|
+
],
|
|
9780
|
+
"args": [
|
|
9781
|
+
{
|
|
9782
|
+
"name": "is_halted",
|
|
9783
|
+
"type": "bool"
|
|
9784
|
+
},
|
|
9785
|
+
{
|
|
9786
|
+
"name": "is_halted_deposit",
|
|
9787
|
+
"type": "bool"
|
|
9788
|
+
},
|
|
9789
|
+
{
|
|
9790
|
+
"name": "is_halted_withdrawal",
|
|
9791
|
+
"type": "bool"
|
|
9792
|
+
}
|
|
9793
|
+
]
|
|
9794
|
+
},
|
|
9790
9795
|
{
|
|
9791
9796
|
"name": "trigger_vault_circuit_breaker",
|
|
9792
9797
|
"discriminator": [
|
|
@@ -10548,8 +10553,8 @@ var IDL = {
|
|
|
10548
10553
|
{
|
|
10549
10554
|
"name": "destination_fee_vault",
|
|
10550
10555
|
"docs": [
|
|
10551
|
-
"
|
|
10552
|
-
"
|
|
10556
|
+
"Legacy fee-vault account retained in this instruction's account schema.",
|
|
10557
|
+
"New fees accrue as pending vault shares."
|
|
10553
10558
|
],
|
|
10554
10559
|
"writable": true
|
|
10555
10560
|
},
|
|
@@ -11866,21 +11871,11 @@ var IDL = {
|
|
|
11866
11871
|
{
|
|
11867
11872
|
"name": "FeeVault",
|
|
11868
11873
|
"docs": [
|
|
11869
|
-
"
|
|
11870
|
-
"",
|
|
11871
|
-
"The PDA is both the token authority over the fee-asset ATAs that physically",
|
|
11872
|
-
"hold accrued fees and the ledger of what is owed to whom. All four fee types",
|
|
11873
|
-
"\u2014 mint, burn, performance, and protocol \u2014 accrue here.",
|
|
11874
|
-
"",
|
|
11875
|
-
"Ledger amounts (`*_owed` / `*_collected`) are denominated in the vault's",
|
|
11876
|
-
"**accounting unit** (the same unit as TVL / holding prices), not raw token",
|
|
11877
|
-
"units. Token custody may still be split across ATAs for different base-asset",
|
|
11878
|
-
"mints; the permissionless fee crank converts each ATA's balance to accounting",
|
|
11879
|
-
"value via that mint's fresh holding price, pays out, and reduces these",
|
|
11880
|
-
"counters by the accounting value cleared.",
|
|
11874
|
+
"Legacy per-vault fee custody account.",
|
|
11881
11875
|
"",
|
|
11882
|
-
"
|
|
11883
|
-
"
|
|
11876
|
+
"New fee accrual is denominated in canonical vault shares and stored on",
|
|
11877
|
+
"`VaultAccounting`. This account remains in existing instruction schemas for",
|
|
11878
|
+
"compatibility; its historical accounting-unit counters are no longer updated."
|
|
11884
11879
|
],
|
|
11885
11880
|
"serialization": "bytemuck",
|
|
11886
11881
|
"repr": {
|
|
@@ -12105,8 +12100,9 @@ var IDL = {
|
|
|
12105
12100
|
{
|
|
12106
12101
|
"name": "migrate_amount",
|
|
12107
12102
|
"docs": [
|
|
12108
|
-
"
|
|
12109
|
-
"
|
|
12103
|
+
"Partial migration remains unsupported. `None` performs a regular full",
|
|
12104
|
+
"vault migration; `Some(0)` explicitly marks the final in-scope vault and",
|
|
12105
|
+
"permits bounded terminal source-accounting reconciliation."
|
|
12110
12106
|
],
|
|
12111
12107
|
"type": {
|
|
12112
12108
|
"option": "u64"
|
|
@@ -13410,10 +13406,16 @@ var IDL = {
|
|
|
13410
13406
|
}
|
|
13411
13407
|
},
|
|
13412
13408
|
{
|
|
13413
|
-
"name": "
|
|
13409
|
+
"name": "migration_in_progress",
|
|
13414
13410
|
"docs": [
|
|
13415
|
-
"
|
|
13416
|
-
"
|
|
13411
|
+
"True while a legacy migration destination is still receiving backing",
|
|
13412
|
+
"and receipt-supply accounting. Oracle mutation and NAV settlement stay",
|
|
13413
|
+
"disabled until every configured receipt mint authority has moved to this vault",
|
|
13414
|
+
"and migration finalization clears the flag.",
|
|
13415
|
+
"",
|
|
13416
|
+
"This occupies the former `apy_settle_skip` padding byte, preserving the",
|
|
13417
|
+
"on-chain account layout for already-deployed vaults. Existing vaults read",
|
|
13418
|
+
"it as false."
|
|
13417
13419
|
],
|
|
13418
13420
|
"type": {
|
|
13419
13421
|
"defined": {
|
|
@@ -13724,7 +13726,7 @@ var IDL = {
|
|
|
13724
13726
|
{
|
|
13725
13727
|
"name": "tvl_limit",
|
|
13726
13728
|
"docs": [
|
|
13727
|
-
"Maximum TVL in
|
|
13729
|
+
"Maximum TVL in vault accounting units. `0` disables the cap."
|
|
13728
13730
|
],
|
|
13729
13731
|
"type": "u64"
|
|
13730
13732
|
},
|
|
@@ -14784,7 +14786,7 @@ var IDL = {
|
|
|
14784
14786
|
{
|
|
14785
14787
|
"name": "total_mint_supply",
|
|
14786
14788
|
"docs": [
|
|
14787
|
-
"
|
|
14789
|
+
"Effective share supply: physical mint supply plus unminted fee shares."
|
|
14788
14790
|
],
|
|
14789
14791
|
"type": "u64"
|
|
14790
14792
|
},
|
|
@@ -14838,12 +14840,26 @@ var IDL = {
|
|
|
14838
14840
|
}
|
|
14839
14841
|
}
|
|
14840
14842
|
},
|
|
14843
|
+
{
|
|
14844
|
+
"name": "pending_curator_fee_shares",
|
|
14845
|
+
"docs": [
|
|
14846
|
+
"Vault shares owed to the curator but not yet minted."
|
|
14847
|
+
],
|
|
14848
|
+
"type": "u64"
|
|
14849
|
+
},
|
|
14850
|
+
{
|
|
14851
|
+
"name": "pending_protocol_fee_shares",
|
|
14852
|
+
"docs": [
|
|
14853
|
+
"Vault shares owed to the protocol but not yet minted."
|
|
14854
|
+
],
|
|
14855
|
+
"type": "u64"
|
|
14856
|
+
},
|
|
14841
14857
|
{
|
|
14842
14858
|
"name": "_padding1",
|
|
14843
14859
|
"type": {
|
|
14844
14860
|
"array": [
|
|
14845
14861
|
"u64",
|
|
14846
|
-
|
|
14862
|
+
30
|
|
14847
14863
|
]
|
|
14848
14864
|
}
|
|
14849
14865
|
},
|
|
@@ -14892,8 +14908,8 @@ var IDL = {
|
|
|
14892
14908
|
{
|
|
14893
14909
|
"name": "asset_decimals",
|
|
14894
14910
|
"docs": [
|
|
14895
|
-
"
|
|
14896
|
-
"
|
|
14911
|
+
"Vault accounting precision. This matches the vault share mint; each",
|
|
14912
|
+
"holding stores its own mint precision independently."
|
|
14897
14913
|
],
|
|
14898
14914
|
"type": "u8"
|
|
14899
14915
|
},
|
|
@@ -14925,7 +14941,7 @@ var IDL = {
|
|
|
14925
14941
|
{
|
|
14926
14942
|
"name": "tvl_limit",
|
|
14927
14943
|
"docs": [
|
|
14928
|
-
"Maximum TVL in
|
|
14944
|
+
"Maximum TVL in vault accounting units. `0` disables the cap."
|
|
14929
14945
|
],
|
|
14930
14946
|
"type": "u64"
|
|
14931
14947
|
},
|
|
@@ -15709,8 +15725,8 @@ function coerceBool(value) {
|
|
|
15709
15725
|
if (value && typeof value.toBool === "function") {
|
|
15710
15726
|
return value.toBool();
|
|
15711
15727
|
}
|
|
15712
|
-
const
|
|
15713
|
-
return Boolean(
|
|
15728
|
+
const record2 = value;
|
|
15729
|
+
return Boolean(record2?.value ?? record2?.[0]);
|
|
15714
15730
|
}
|
|
15715
15731
|
|
|
15716
15732
|
// src/client/builders/base.ts
|
|
@@ -15746,8 +15762,8 @@ function coerceBool2(value) {
|
|
|
15746
15762
|
if (value && typeof value.toBool === "function") {
|
|
15747
15763
|
return value.toBool();
|
|
15748
15764
|
}
|
|
15749
|
-
const
|
|
15750
|
-
return Boolean(
|
|
15765
|
+
const record2 = value;
|
|
15766
|
+
return Boolean(record2?.value ?? record2?.[0]);
|
|
15751
15767
|
}
|
|
15752
15768
|
function pubkeyToAddress(value) {
|
|
15753
15769
|
if (typeof value === "string") return (0, import_kit5.address)(value);
|
|
@@ -15757,8 +15773,8 @@ function pubkeyToAddress(value) {
|
|
|
15757
15773
|
return (0, import_kit5.address)(String(value));
|
|
15758
15774
|
}
|
|
15759
15775
|
function tokenProgramAddressFromIdlEnum(value) {
|
|
15760
|
-
const
|
|
15761
|
-
if (
|
|
15776
|
+
const record2 = value;
|
|
15777
|
+
if (record2 && "token2022" in record2) {
|
|
15762
15778
|
return TOKEN_PROGRAM_ID;
|
|
15763
15779
|
}
|
|
15764
15780
|
return (0, import_kit5.address)(import_spl_token2.TOKEN_PROGRAM_ID.toBase58());
|
|
@@ -16132,7 +16148,7 @@ var CreateVaultBuilder = class extends VaultBuilderBase {
|
|
|
16132
16148
|
const [vault] = await this.pda.deriveVaultPda(vaultId);
|
|
16133
16149
|
const [vaultOracle] = await this.pda.deriveVaultOraclePda(vault);
|
|
16134
16150
|
const [feeVault] = await this.pda.deriveFeeAuthorityPda(vault);
|
|
16135
|
-
const
|
|
16151
|
+
const accountingDecimals = (await (0, import_token.fetchMint)(this.rpc, txArgs.shareMint)).data.decimals;
|
|
16136
16152
|
return {
|
|
16137
16153
|
curator: txArgs.curator,
|
|
16138
16154
|
vault,
|
|
@@ -16157,7 +16173,7 @@ var CreateVaultBuilder = class extends VaultBuilderBase {
|
|
|
16157
16173
|
initialMintSharePrice: null,
|
|
16158
16174
|
basePriceOracleType: txArgs.basePriceOracleType ?? 1,
|
|
16159
16175
|
basePrice: new import_core3.BN(
|
|
16160
|
-
(txArgs.basePrice ?? 10n ** BigInt(
|
|
16176
|
+
(txArgs.basePrice ?? 10n ** BigInt(accountingDecimals)).toString()
|
|
16161
16177
|
),
|
|
16162
16178
|
basePriceOracleAccount: txArgs.basePriceOracleAccount ?? DEFAULT_PRICE_ORACLE_ACCOUNT,
|
|
16163
16179
|
forMigration: txArgs.forMigration ?? false
|
|
@@ -16333,8 +16349,9 @@ var SetProtocolFeeBuilder = class extends VaultBuilderBase {
|
|
|
16333
16349
|
const [derivedVaultOracle] = await this.pda.deriveVaultOraclePda(
|
|
16334
16350
|
txArgs.vault
|
|
16335
16351
|
);
|
|
16352
|
+
const defaultProtocolAuthority = this.program.programId.toBase58() === VAULT_PROGRAM_ID ? LOCAL_PROTOCOL_ADMIN : PROTOCOL_ADMIN;
|
|
16336
16353
|
return {
|
|
16337
|
-
protocolAuthority: txArgs.protocolAuthority ??
|
|
16354
|
+
protocolAuthority: txArgs.protocolAuthority ?? defaultProtocolAuthority,
|
|
16338
16355
|
vault: txArgs.vault,
|
|
16339
16356
|
vaultOracle: txArgs.vaultOracle ?? derivedVaultOracle,
|
|
16340
16357
|
args: {
|
|
@@ -16531,82 +16548,53 @@ var CrankPerformanceFeesBuilder = class extends VaultBuilderBase {
|
|
|
16531
16548
|
return this.program.methods.crankPerformanceFees().accountsPartial({
|
|
16532
16549
|
cranker: (0, import_common18.toWeb3Pk)(args.cranker),
|
|
16533
16550
|
vault: (0, import_common18.toWeb3Pk)(args.vault),
|
|
16534
|
-
|
|
16535
|
-
feeVault: (0, import_common18.toWeb3Pk)(args.feeVault),
|
|
16536
|
-
feeVaultAta: (0, import_common18.toWeb3Pk)(args.feeVaultAta),
|
|
16551
|
+
shareMint: (0, import_common18.toWeb3Pk)(args.shareMint),
|
|
16537
16552
|
feeCollector: (0, import_common18.toWeb3Pk)(args.feeCollector),
|
|
16538
|
-
|
|
16553
|
+
feeCollectorShareAta: (0, import_common18.toWeb3Pk)(args.feeCollectorShareAta),
|
|
16539
16554
|
protocolFeeCollector: (0, import_common18.toWeb3Pk)(args.protocolFeeCollector),
|
|
16540
|
-
|
|
16541
|
-
args.
|
|
16555
|
+
protocolFeeCollectorShareAta: (0, import_common18.toWeb3Pk)(
|
|
16556
|
+
args.protocolFeeCollectorShareAta
|
|
16542
16557
|
),
|
|
16543
|
-
|
|
16558
|
+
shareTokenProgram: (0, import_common18.toWeb3Pk)(args.shareTokenProgram),
|
|
16544
16559
|
associatedTokenProgram: import_spl_token6.ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
16545
16560
|
systemProgram: import_web38.SystemProgram.programId
|
|
16546
16561
|
}).instruction().then(import_common18.toKitInstruction);
|
|
16547
16562
|
}
|
|
16548
16563
|
async deriveIxArgs(txArgs) {
|
|
16549
|
-
const
|
|
16564
|
+
const vaultState = await this.account.fetchVault(txArgs.vault);
|
|
16565
|
+
const shareMint = (0, import_common18.fromWeb3Pk)(vaultState.mint);
|
|
16566
|
+
const shareTokenProgram = txArgs.shareTokenProgram ?? tokenProgramAddressFromIdlEnum(vaultState.mintTokenProgram);
|
|
16567
|
+
const feeCollector = await resolveVaultFeeCollector(
|
|
16550
16568
|
this.account,
|
|
16551
16569
|
txArgs.vault,
|
|
16552
|
-
txArgs.
|
|
16570
|
+
txArgs.feeCollector
|
|
16553
16571
|
);
|
|
16554
|
-
const [feeVault] = await this.pda.deriveFeeAuthorityPda(txArgs.vault);
|
|
16555
|
-
const [feeCollector, feeAssetTokenProgram] = await Promise.all([
|
|
16556
|
-
resolveVaultFeeCollector(this.account, txArgs.vault, txArgs.feeCollector),
|
|
16557
|
-
resolveFeeAssetTokenProgram(
|
|
16558
|
-
this.account,
|
|
16559
|
-
txArgs.vault,
|
|
16560
|
-
feeAssetMint,
|
|
16561
|
-
txArgs.feeAssetTokenProgram
|
|
16562
|
-
)
|
|
16563
|
-
]);
|
|
16564
16572
|
const protocolFeeCollector = resolveProtocolFeeRecipient(
|
|
16565
16573
|
txArgs.protocolFeeCollector
|
|
16566
16574
|
);
|
|
16567
16575
|
return {
|
|
16568
16576
|
cranker: txArgs.cranker,
|
|
16569
16577
|
vault: txArgs.vault,
|
|
16570
|
-
|
|
16571
|
-
feeVault,
|
|
16572
|
-
feeVaultAta: (0, import_common18.getAtaAddress)(
|
|
16573
|
-
feeAssetMint,
|
|
16574
|
-
feeVault,
|
|
16575
|
-
feeAssetTokenProgram,
|
|
16576
|
-
true
|
|
16577
|
-
),
|
|
16578
|
+
shareMint,
|
|
16578
16579
|
feeCollector,
|
|
16579
|
-
|
|
16580
|
-
|
|
16580
|
+
feeCollectorShareAta: (0, import_common18.getAtaAddress)(
|
|
16581
|
+
shareMint,
|
|
16581
16582
|
feeCollector,
|
|
16582
|
-
|
|
16583
|
+
shareTokenProgram
|
|
16583
16584
|
),
|
|
16584
16585
|
protocolFeeCollector,
|
|
16585
16586
|
// The protocol fee recipient is a hardcoded protocol-controlled address
|
|
16586
16587
|
// that may be off-curve (e.g. a PDA / multisig vault), so allow an
|
|
16587
16588
|
// off-curve owner when deriving its ATA.
|
|
16588
|
-
|
|
16589
|
-
|
|
16589
|
+
protocolFeeCollectorShareAta: (0, import_common18.getAtaAddress)(
|
|
16590
|
+
shareMint,
|
|
16590
16591
|
protocolFeeCollector,
|
|
16591
|
-
|
|
16592
|
+
shareTokenProgram,
|
|
16592
16593
|
true
|
|
16593
16594
|
),
|
|
16594
|
-
|
|
16595
|
+
shareTokenProgram
|
|
16595
16596
|
};
|
|
16596
16597
|
}
|
|
16597
|
-
async buildPreambleInstructions(args) {
|
|
16598
|
-
const payer = (0, import_common18.toWeb3Pk)(args.cranker);
|
|
16599
|
-
return [
|
|
16600
|
-
(0, import_spl_token6.createAssociatedTokenAccountIdempotentInstruction)(
|
|
16601
|
-
payer,
|
|
16602
|
-
(0, import_common18.toWeb3Pk)(args.feeVaultAta),
|
|
16603
|
-
(0, import_common18.toWeb3Pk)(args.feeVault),
|
|
16604
|
-
(0, import_common18.toWeb3Pk)(args.feeAssetMint),
|
|
16605
|
-
(0, import_common18.toWeb3Pk)(args.feeAssetTokenProgram),
|
|
16606
|
-
import_spl_token6.ASSOCIATED_TOKEN_PROGRAM_ID
|
|
16607
|
-
)
|
|
16608
|
-
].map(import_common18.toKitInstruction);
|
|
16609
|
-
}
|
|
16610
16598
|
async buildPlanExtras(args) {
|
|
16611
16599
|
return {
|
|
16612
16600
|
postSuccessCacheInvalidations: [{ vaultPda: args.vault }]
|
|
@@ -16614,11 +16602,10 @@ var CrankPerformanceFeesBuilder = class extends VaultBuilderBase {
|
|
|
16614
16602
|
}
|
|
16615
16603
|
async getTx(txArgs) {
|
|
16616
16604
|
const args = await this.deriveIxArgs(txArgs);
|
|
16617
|
-
const preambleInstructions = await this.buildPreambleInstructions(args);
|
|
16618
16605
|
const instruction = await this.getIx(args);
|
|
16619
16606
|
const extras = await this.buildPlanExtras(args);
|
|
16620
16607
|
return {
|
|
16621
|
-
instructions: [
|
|
16608
|
+
instructions: [instruction],
|
|
16622
16609
|
...extras ?? {}
|
|
16623
16610
|
};
|
|
16624
16611
|
}
|
|
@@ -19287,6 +19274,70 @@ var JupiterPriceSource = class {
|
|
|
19287
19274
|
}
|
|
19288
19275
|
};
|
|
19289
19276
|
|
|
19277
|
+
// src/services/consensusOracle/nestPriceSource.ts
|
|
19278
|
+
var import_kit12 = require("@solana/kit");
|
|
19279
|
+
var NEST_API_BASE_URL = "https://api.nest.credit/v1";
|
|
19280
|
+
var NEST_VAULT_SLUG = "nest-perena-vault";
|
|
19281
|
+
var NEST_RWA_SHARE_MINT = (0, import_kit12.address)(
|
|
19282
|
+
"VyXKJnVhkSkB6KAozSZCiLQbuB1k1r6Nu4etNYVo5LJ"
|
|
19283
|
+
);
|
|
19284
|
+
async function fetchNestTokenPrice(nestVaultSlug = NEST_VAULT_SLUG, opts = {}) {
|
|
19285
|
+
const baseUrl = (opts.baseUrl ?? NEST_API_BASE_URL).replace(/\/$/, "");
|
|
19286
|
+
const response = await (opts.fetchFn ?? fetch)(
|
|
19287
|
+
`${baseUrl}/vaults/${encodeURIComponent(nestVaultSlug)}/price`
|
|
19288
|
+
);
|
|
19289
|
+
if (!response.ok) {
|
|
19290
|
+
throw new Error(
|
|
19291
|
+
`Nest price API request failed: ${response.status} ${response.statusText}`
|
|
19292
|
+
);
|
|
19293
|
+
}
|
|
19294
|
+
const body = await response.json();
|
|
19295
|
+
const price = [body.data?.interpolatedPrice, body.data?.price].map(Number).find((candidate) => Number.isFinite(candidate) && candidate > 0);
|
|
19296
|
+
if (price === void 0) {
|
|
19297
|
+
throw new Error("Nest price API returned no positive share price");
|
|
19298
|
+
}
|
|
19299
|
+
return price;
|
|
19300
|
+
}
|
|
19301
|
+
var NestPriceSource = class {
|
|
19302
|
+
constructor(opts = {}) {
|
|
19303
|
+
this.shareMint = opts.shareMint ?? NEST_RWA_SHARE_MINT;
|
|
19304
|
+
this.nestVaultSlug = opts.nestVaultSlug ?? NEST_VAULT_SLUG;
|
|
19305
|
+
this.options = { baseUrl: opts.baseUrl, fetchFn: opts.fetchFn };
|
|
19306
|
+
}
|
|
19307
|
+
async fetchUsdPrices(mints) {
|
|
19308
|
+
if (!mints.some((mint) => mint.toString() === this.shareMint.toString())) {
|
|
19309
|
+
return {};
|
|
19310
|
+
}
|
|
19311
|
+
return {
|
|
19312
|
+
[this.shareMint.toString()]: await fetchNestTokenPrice(
|
|
19313
|
+
this.nestVaultSlug,
|
|
19314
|
+
this.options
|
|
19315
|
+
)
|
|
19316
|
+
};
|
|
19317
|
+
}
|
|
19318
|
+
};
|
|
19319
|
+
|
|
19320
|
+
// src/services/consensusOracle/livePriceSource.ts
|
|
19321
|
+
var LivePriceSource = class {
|
|
19322
|
+
constructor(opts = {}) {
|
|
19323
|
+
this.jupiter = opts.jupiter ?? new JupiterPriceSource();
|
|
19324
|
+
this.nest = opts.nest ?? new NestPriceSource();
|
|
19325
|
+
}
|
|
19326
|
+
async fetchUsdPrices(mints) {
|
|
19327
|
+
const unique = [
|
|
19328
|
+
...new Map(mints.map((mint) => [mint.toString(), mint])).values()
|
|
19329
|
+
];
|
|
19330
|
+
const nestMint = this.nest.shareMint.toString();
|
|
19331
|
+
const jupiterMints = unique.filter((mint) => mint.toString() !== nestMint);
|
|
19332
|
+
const nestMints = unique.filter((mint) => mint.toString() === nestMint);
|
|
19333
|
+
const [jupiterPrices, nestPrices] = await Promise.all([
|
|
19334
|
+
this.jupiter.fetchUsdPrices(jupiterMints),
|
|
19335
|
+
this.nest.fetchUsdPrices(nestMints)
|
|
19336
|
+
]);
|
|
19337
|
+
return { ...jupiterPrices, ...nestPrices };
|
|
19338
|
+
}
|
|
19339
|
+
};
|
|
19340
|
+
|
|
19290
19341
|
// src/services/consensusOracle/jupiterBalanceSource.ts
|
|
19291
19342
|
var import_web323 = require("@solana/web3.js");
|
|
19292
19343
|
var import_spl_token19 = require("@solana/spl-token");
|
|
@@ -19395,12 +19446,12 @@ var StaticPositionProvider = class {
|
|
|
19395
19446
|
};
|
|
19396
19447
|
|
|
19397
19448
|
// src/services/consensusOracle/kaminoPositionProvider.ts
|
|
19398
|
-
var
|
|
19449
|
+
var import_kit13 = require("@solana/kit");
|
|
19399
19450
|
var import_web324 = require("@solana/web3.js");
|
|
19400
19451
|
var import_klend_sdk = require("@kamino-finance/klend-sdk");
|
|
19401
19452
|
async function readKaminoBalance(manager, vault, sharesHolder) {
|
|
19402
19453
|
const userShares = await manager.getUserSharesBalanceSingleVault(
|
|
19403
|
-
(0,
|
|
19454
|
+
(0, import_kit13.address)(sharesHolder.toBase58()),
|
|
19404
19455
|
vault
|
|
19405
19456
|
);
|
|
19406
19457
|
const tokensPerShare = await manager.getTokensPerShareSingleVault(vault);
|
|
@@ -19416,7 +19467,7 @@ var KaminoPositionProvider = class {
|
|
|
19416
19467
|
async positionsFor(ctx) {
|
|
19417
19468
|
const refs = ctx.refs.filter((r) => r.kind === "kamino");
|
|
19418
19469
|
if (refs.length === 0) return [];
|
|
19419
|
-
const rpc = (0,
|
|
19470
|
+
const rpc = (0, import_kit13.createSolanaRpc)(this.rpcUrl);
|
|
19420
19471
|
const slotDuration = await (0, import_klend_sdk.getMedianSlotDurationInMsFromLastEpochs)();
|
|
19421
19472
|
const manager = new import_klend_sdk.KaminoManager(rpc, slotDuration);
|
|
19422
19473
|
const out = [];
|
|
@@ -19429,7 +19480,7 @@ var KaminoPositionProvider = class {
|
|
|
19429
19480
|
);
|
|
19430
19481
|
continue;
|
|
19431
19482
|
}
|
|
19432
|
-
const kVault = new import_klend_sdk.KaminoVault(rpc, (0,
|
|
19483
|
+
const kVault = new import_klend_sdk.KaminoVault(rpc, (0, import_kit13.address)(vaultState));
|
|
19433
19484
|
const amount = await readKaminoBalance(
|
|
19434
19485
|
manager,
|
|
19435
19486
|
kVault,
|
|
@@ -19548,7 +19599,7 @@ function createLiveConsensusOracleDeps(connection, opts = {}) {
|
|
|
19548
19599
|
const log = opts.log ?? (() => {
|
|
19549
19600
|
});
|
|
19550
19601
|
const deps = {
|
|
19551
|
-
priceSource: new
|
|
19602
|
+
priceSource: new LivePriceSource(),
|
|
19552
19603
|
balanceSource: new JupiterBalanceSource(connection, {
|
|
19553
19604
|
rpcOnly: opts.rpcOnly ?? false,
|
|
19554
19605
|
log
|
|
@@ -19571,8 +19622,861 @@ function createLiveConsensusOracleDeps(connection, opts = {}) {
|
|
|
19571
19622
|
}
|
|
19572
19623
|
|
|
19573
19624
|
// src/services/consensusOracle/consensusOracleService.ts
|
|
19574
|
-
var
|
|
19625
|
+
var import_web327 = require("@solana/web3.js");
|
|
19575
19626
|
var import_common41 = __toESM(require_dist());
|
|
19627
|
+
|
|
19628
|
+
// src/services/consensusOracle/settlementSimulator.ts
|
|
19629
|
+
var import_kit14 = require("@solana/kit");
|
|
19630
|
+
var import_web326 = require("@solana/web3.js");
|
|
19631
|
+
var DEFAULT_SHARE_PRICE = 1000000n;
|
|
19632
|
+
var BPS_DENOMINATOR2 = 10000n;
|
|
19633
|
+
var SECONDS_PER_YEAR = 31536000n;
|
|
19634
|
+
var DEFAULT_STALENESS_SECS = 86400n;
|
|
19635
|
+
var CONSENSUS_MAX_DIFF_BPS = 8n;
|
|
19636
|
+
var MIN_CONSENSUS_SIGNERS = 2;
|
|
19637
|
+
var MAX_HOLDINGS = 12;
|
|
19638
|
+
var MAX_SIGNERS = 4;
|
|
19639
|
+
var ENTRY_SIZE = 272;
|
|
19640
|
+
var ENTRIES_OFFSET = 40;
|
|
19641
|
+
var PRICE_OFFSET = 40;
|
|
19642
|
+
var EXTERNAL_OFFSET = PRICE_OFFSET + MAX_HOLDINGS * 8;
|
|
19643
|
+
var APY_SCALE = 1000000000000000000n;
|
|
19644
|
+
var APY_LN_2 = 693147180559945309n;
|
|
19645
|
+
var APY_SERIES_TERMS = 32;
|
|
19646
|
+
function simulateConsensusOracleSettlement(args) {
|
|
19647
|
+
const warnings = [];
|
|
19648
|
+
const blockers = [];
|
|
19649
|
+
const vaultAccounting = record(args.vault.accounting);
|
|
19650
|
+
const feesConfig = record(args.vault.config.fees);
|
|
19651
|
+
const apyConfig = record(args.vault.config.apy);
|
|
19652
|
+
const tranchingEnabled = bool(args.vault.tranchingEnabled);
|
|
19653
|
+
const currentTvl = bigint(vaultAccounting.tvl);
|
|
19654
|
+
const pendingCuratorShares = bigint(vaultAccounting.pendingCuratorFeeShares);
|
|
19655
|
+
const pendingProtocolShares = bigint(
|
|
19656
|
+
vaultAccounting.pendingProtocolFeeShares
|
|
19657
|
+
);
|
|
19658
|
+
const cachedSupply = bigint(vaultAccounting.totalMintSupply);
|
|
19659
|
+
const reconciledSupply = args.physicalShareSupply === void 0 ? cachedSupply : args.physicalShareSupply + pendingCuratorShares + pendingProtocolShares;
|
|
19660
|
+
if (args.physicalShareSupply === void 0) {
|
|
19661
|
+
warnings.push(
|
|
19662
|
+
"regular share-mint supply was unavailable; using cached effective supply"
|
|
19663
|
+
);
|
|
19664
|
+
} else if (reconciledSupply !== cachedSupply) {
|
|
19665
|
+
warnings.push(
|
|
19666
|
+
`crank supply reconciliation changes regular supply ${cachedSupply} -> ${reconciledSupply}`
|
|
19667
|
+
);
|
|
19668
|
+
}
|
|
19669
|
+
const holdings = args.vault.holdings.map(decodeHolding);
|
|
19670
|
+
const oracle = decodeOracleData(args.oracleData, args.nowTs);
|
|
19671
|
+
const signerEntry = oracle.entries.find(
|
|
19672
|
+
(entry) => entry.signer === args.signer.toString()
|
|
19673
|
+
);
|
|
19674
|
+
if (!signerEntry) {
|
|
19675
|
+
blockers.push(`signer ${args.signer} is not registered in the oracle`);
|
|
19676
|
+
} else {
|
|
19677
|
+
signerEntry.lastUpdateTs = args.nowTs;
|
|
19678
|
+
for (const update of args.updates) {
|
|
19679
|
+
signerEntry.prices[update.holdingIndex] = update.price;
|
|
19680
|
+
signerEntry.externalAmounts[update.holdingIndex] = update.externalAmount;
|
|
19681
|
+
}
|
|
19682
|
+
}
|
|
19683
|
+
const consensus = applyConsensus(
|
|
19684
|
+
holdings,
|
|
19685
|
+
oracle.entries,
|
|
19686
|
+
args.nowTs,
|
|
19687
|
+
oracle.stalenessThresholdSecs
|
|
19688
|
+
);
|
|
19689
|
+
const proposedUpdatesLanded = args.updates.filter(
|
|
19690
|
+
(update) => consensus.find(
|
|
19691
|
+
(result) => result.holdingIndex === update.holdingIndex && result.wouldUpdateHolding
|
|
19692
|
+
)
|
|
19693
|
+
).length;
|
|
19694
|
+
const consensusSummary = {
|
|
19695
|
+
allProposedUpdatesLand: proposedUpdatesLanded === args.updates.length && args.updates.length > 0,
|
|
19696
|
+
proposedUpdatesLanded,
|
|
19697
|
+
proposedUpdatesTotal: args.updates.length
|
|
19698
|
+
};
|
|
19699
|
+
const currentTranche = tranchingEnabled ? decodeTrancheState(args.trancheState, args, warnings, blockers) : void 0;
|
|
19700
|
+
const current = snapshot(
|
|
19701
|
+
currentTvl,
|
|
19702
|
+
reconciledSupply,
|
|
19703
|
+
bigint(vaultAccounting.mintSharePrice),
|
|
19704
|
+
currentTranche
|
|
19705
|
+
);
|
|
19706
|
+
let grossNav;
|
|
19707
|
+
try {
|
|
19708
|
+
grossNav = grossNavFromHoldings(
|
|
19709
|
+
holdings,
|
|
19710
|
+
args.nowTs,
|
|
19711
|
+
positiveOrDefault(
|
|
19712
|
+
bigint(args.vault.config.priceStalenessThresholdSecs),
|
|
19713
|
+
DEFAULT_STALENESS_SECS
|
|
19714
|
+
)
|
|
19715
|
+
);
|
|
19716
|
+
} catch (error) {
|
|
19717
|
+
blockers.push(message(error));
|
|
19718
|
+
}
|
|
19719
|
+
if (grossNav === void 0 || blockers.length > 0) {
|
|
19720
|
+
return {
|
|
19721
|
+
nowTs: args.nowTs,
|
|
19722
|
+
assetDecimals: args.vault.config.assetDecimals,
|
|
19723
|
+
...consensusSummary,
|
|
19724
|
+
canSettle: false,
|
|
19725
|
+
blockers,
|
|
19726
|
+
warnings,
|
|
19727
|
+
consensus,
|
|
19728
|
+
grossNav,
|
|
19729
|
+
current
|
|
19730
|
+
};
|
|
19731
|
+
}
|
|
19732
|
+
try {
|
|
19733
|
+
const settlement = settleVault({
|
|
19734
|
+
grossNav,
|
|
19735
|
+
nowTs: args.nowTs,
|
|
19736
|
+
currentTvl,
|
|
19737
|
+
currentSharePrice: bigint(vaultAccounting.mintSharePrice),
|
|
19738
|
+
totalSupply: reconciledSupply,
|
|
19739
|
+
lossesEnabled: bool(args.vault.lossesEnabled),
|
|
19740
|
+
accountingLastUpdateTs: bigint(vaultAccounting.lastUpdateTs),
|
|
19741
|
+
priorSettledNavTs: oracle.settledNavTs,
|
|
19742
|
+
performanceFeeBps: number(feesConfig.performanceFeeBps),
|
|
19743
|
+
protocolFeeBps: number(feesConfig.protocolFeeBps),
|
|
19744
|
+
hwmSharePrice: bigint(vaultAccounting.hwmSharePrice),
|
|
19745
|
+
fixedApyBps: number(apyConfig.fixedApyBps),
|
|
19746
|
+
maxApyBps: number(apyConfig.maxApyBps),
|
|
19747
|
+
apyAnchorSharePrice: bigint(apyConfig.anchorSharePrice),
|
|
19748
|
+
apyAnchorTs: bigint(apyConfig.anchorTs),
|
|
19749
|
+
tranche: currentTranche
|
|
19750
|
+
});
|
|
19751
|
+
return {
|
|
19752
|
+
nowTs: args.nowTs,
|
|
19753
|
+
assetDecimals: args.vault.config.assetDecimals,
|
|
19754
|
+
...consensusSummary,
|
|
19755
|
+
canSettle: true,
|
|
19756
|
+
blockers,
|
|
19757
|
+
warnings,
|
|
19758
|
+
consensus,
|
|
19759
|
+
grossNav,
|
|
19760
|
+
settledAccountingNav: settlement.settledAccountingNav,
|
|
19761
|
+
current,
|
|
19762
|
+
projected: settlement.projected,
|
|
19763
|
+
performanceFees: settlement.performanceFees
|
|
19764
|
+
};
|
|
19765
|
+
} catch (error) {
|
|
19766
|
+
blockers.push(message(error));
|
|
19767
|
+
return {
|
|
19768
|
+
nowTs: args.nowTs,
|
|
19769
|
+
assetDecimals: args.vault.config.assetDecimals,
|
|
19770
|
+
...consensusSummary,
|
|
19771
|
+
canSettle: false,
|
|
19772
|
+
blockers,
|
|
19773
|
+
warnings,
|
|
19774
|
+
consensus,
|
|
19775
|
+
grossNav,
|
|
19776
|
+
current
|
|
19777
|
+
};
|
|
19778
|
+
}
|
|
19779
|
+
}
|
|
19780
|
+
function applyConsensus(holdings, entries, nowTs, stalenessThresholdSecs) {
|
|
19781
|
+
const results = [];
|
|
19782
|
+
for (let index = 0; index < holdings.length; index += 1) {
|
|
19783
|
+
const holding = holdings[index];
|
|
19784
|
+
if (holding.cleared || holding.priceOracleType !== "consensusoracle") {
|
|
19785
|
+
continue;
|
|
19786
|
+
}
|
|
19787
|
+
const reports = entries.filter(
|
|
19788
|
+
(entry) => entry.signer !== import_web326.PublicKey.default.toBase58() && isFresh(entry.lastUpdateTs, nowTs, stalenessThresholdSecs) && (entry.prices[index] ?? 0n) > 0n
|
|
19789
|
+
);
|
|
19790
|
+
const prices = reports.map((entry) => entry.prices[index] ?? 0n);
|
|
19791
|
+
const amounts = reports.map((entry) => entry.externalAmounts[index] ?? 0n);
|
|
19792
|
+
let reason;
|
|
19793
|
+
if (reports.length < MIN_CONSENSUS_SIGNERS) {
|
|
19794
|
+
reason = `only ${reports.length} fresh priced report(s); need ${MIN_CONSENSUS_SIGNERS}`;
|
|
19795
|
+
} else if (!withinDeviation(prices)) {
|
|
19796
|
+
reason = `price reports exceed ${CONSENSUS_MAX_DIFF_BPS}bps pairwise deviation`;
|
|
19797
|
+
} else if (!withinDeviation(amounts)) {
|
|
19798
|
+
reason = `external-amount reports exceed ${CONSENSUS_MAX_DIFF_BPS}bps pairwise deviation`;
|
|
19799
|
+
}
|
|
19800
|
+
if (reason) {
|
|
19801
|
+
results.push({
|
|
19802
|
+
holdingIndex: index,
|
|
19803
|
+
mint: holding.mint,
|
|
19804
|
+
reportCount: reports.length,
|
|
19805
|
+
wouldUpdateHolding: false,
|
|
19806
|
+
reason
|
|
19807
|
+
});
|
|
19808
|
+
continue;
|
|
19809
|
+
}
|
|
19810
|
+
const settledPrice = average(prices);
|
|
19811
|
+
const settledExternalAmount = average(amounts);
|
|
19812
|
+
const latestTs = reports.reduce(
|
|
19813
|
+
(latest, entry) => entry.lastUpdateTs > latest ? entry.lastUpdateTs : latest,
|
|
19814
|
+
0n
|
|
19815
|
+
);
|
|
19816
|
+
const wouldUpdateHolding = latestTs > holding.lastUpdateTs && latestTs <= nowTs;
|
|
19817
|
+
if (wouldUpdateHolding) {
|
|
19818
|
+
holding.price = settledPrice;
|
|
19819
|
+
holding.externalAmount = settledExternalAmount;
|
|
19820
|
+
holding.lastUpdateTs = latestTs;
|
|
19821
|
+
if (!holding.isBase && holding.localAmount === 0n && holding.externalAmount === 0n) {
|
|
19822
|
+
holding.cleared = true;
|
|
19823
|
+
}
|
|
19824
|
+
}
|
|
19825
|
+
results.push({
|
|
19826
|
+
holdingIndex: index,
|
|
19827
|
+
mint: holding.mint,
|
|
19828
|
+
reportCount: reports.length,
|
|
19829
|
+
settledPrice,
|
|
19830
|
+
settledExternalAmount,
|
|
19831
|
+
wouldUpdateHolding,
|
|
19832
|
+
reason: wouldUpdateHolding ? void 0 : `aggregate timestamp ${latestTs} is not newer than holding timestamp ${holding.lastUpdateTs}`
|
|
19833
|
+
});
|
|
19834
|
+
}
|
|
19835
|
+
return results;
|
|
19836
|
+
}
|
|
19837
|
+
function settleVault(args) {
|
|
19838
|
+
if (args.grossNav < args.currentTvl && !args.lossesEnabled) {
|
|
19839
|
+
throw new Error(
|
|
19840
|
+
`crank would fail LossesDisabled: gross NAV ${args.grossNav} < current TVL ${args.currentTvl}`
|
|
19841
|
+
);
|
|
19842
|
+
}
|
|
19843
|
+
const priorTs = args.priorSettledNavTs > 0n ? args.priorSettledNavTs : max(args.accountingLastUpdateTs, args.apyAnchorTs);
|
|
19844
|
+
const nextApyValue = args.tranche ? args.grossNav : sharePriceForValue(args.grossNav, args.totalSupply);
|
|
19845
|
+
if (nextApyValue !== void 0) {
|
|
19846
|
+
validateRealizedApy(
|
|
19847
|
+
args.tranche ? args.currentTvl : args.currentSharePrice,
|
|
19848
|
+
priorTs,
|
|
19849
|
+
nextApyValue,
|
|
19850
|
+
args.nowTs,
|
|
19851
|
+
args.maxApyBps
|
|
19852
|
+
);
|
|
19853
|
+
}
|
|
19854
|
+
let regularValue;
|
|
19855
|
+
let regularSharePrice = args.currentSharePrice;
|
|
19856
|
+
let curatorFee = 0n;
|
|
19857
|
+
let protocolFee = 0n;
|
|
19858
|
+
let settledAccountingNav;
|
|
19859
|
+
if (args.tranche) {
|
|
19860
|
+
settledAccountingNav = args.grossNav;
|
|
19861
|
+
regularValue = settleTrancheNav(
|
|
19862
|
+
args.tranche,
|
|
19863
|
+
args.currentTvl,
|
|
19864
|
+
settledAccountingNav,
|
|
19865
|
+
args.nowTs
|
|
19866
|
+
);
|
|
19867
|
+
const juniorFees = settleShareClassPerformanceFee(
|
|
19868
|
+
args.tranche.junior,
|
|
19869
|
+
args.performanceFeeBps,
|
|
19870
|
+
args.protocolFeeBps
|
|
19871
|
+
);
|
|
19872
|
+
const regularFees = settleRegularPerformanceFee(
|
|
19873
|
+
regularValue,
|
|
19874
|
+
args.totalSupply,
|
|
19875
|
+
args.hwmSharePrice,
|
|
19876
|
+
args.performanceFeeBps,
|
|
19877
|
+
args.protocolFeeBps
|
|
19878
|
+
);
|
|
19879
|
+
regularValue = regularFees.netValue;
|
|
19880
|
+
regularSharePrice = sharePriceForValue(regularValue, args.totalSupply) ?? regularSharePrice;
|
|
19881
|
+
curatorFee = juniorFees.curator + regularFees.fees.curator;
|
|
19882
|
+
protocolFee = juniorFees.protocol + regularFees.fees.protocol;
|
|
19883
|
+
} else {
|
|
19884
|
+
settledAccountingNav = settleFixedApyNav({
|
|
19885
|
+
currentSharePrice: args.currentSharePrice,
|
|
19886
|
+
reportedNav: args.grossNav,
|
|
19887
|
+
nowTs: args.nowTs,
|
|
19888
|
+
totalSupply: args.totalSupply,
|
|
19889
|
+
fixedApyBps: args.fixedApyBps,
|
|
19890
|
+
anchorSharePrice: args.apyAnchorSharePrice,
|
|
19891
|
+
anchorTs: args.apyAnchorTs
|
|
19892
|
+
});
|
|
19893
|
+
const regularFees = settleRegularPerformanceFee(
|
|
19894
|
+
settledAccountingNav,
|
|
19895
|
+
args.totalSupply,
|
|
19896
|
+
args.hwmSharePrice,
|
|
19897
|
+
args.performanceFeeBps,
|
|
19898
|
+
args.protocolFeeBps
|
|
19899
|
+
);
|
|
19900
|
+
regularValue = regularFees.netValue;
|
|
19901
|
+
regularSharePrice = sharePriceForValue(regularValue, args.totalSupply) ?? regularSharePrice;
|
|
19902
|
+
curatorFee = regularFees.fees.curator;
|
|
19903
|
+
protocolFee = regularFees.fees.protocol;
|
|
19904
|
+
}
|
|
19905
|
+
const totalFees = curatorFee + protocolFee;
|
|
19906
|
+
const netRegularBacking = mulDiv2(
|
|
19907
|
+
args.totalSupply,
|
|
19908
|
+
regularSharePrice,
|
|
19909
|
+
DEFAULT_SHARE_PRICE
|
|
19910
|
+
);
|
|
19911
|
+
let mintedShares = 0n;
|
|
19912
|
+
if (totalFees > 0n) {
|
|
19913
|
+
mintedShares = args.totalSupply === 0n ? totalFees : mulDiv2(totalFees, args.totalSupply, netRegularBacking);
|
|
19914
|
+
if (mintedShares === 0n) {
|
|
19915
|
+
throw new Error(
|
|
19916
|
+
"crank would fail ZeroAssetAmount while accruing fee shares"
|
|
19917
|
+
);
|
|
19918
|
+
}
|
|
19919
|
+
}
|
|
19920
|
+
const projectedSupply = args.totalSupply + mintedShares;
|
|
19921
|
+
const projected = snapshot(
|
|
19922
|
+
// Fee value is carved out, then added back when converted to vault shares.
|
|
19923
|
+
settledAccountingNav,
|
|
19924
|
+
projectedSupply,
|
|
19925
|
+
regularSharePrice,
|
|
19926
|
+
args.tranche
|
|
19927
|
+
);
|
|
19928
|
+
return {
|
|
19929
|
+
settledAccountingNav,
|
|
19930
|
+
projected,
|
|
19931
|
+
performanceFees: {
|
|
19932
|
+
curator: curatorFee,
|
|
19933
|
+
protocol: protocolFee,
|
|
19934
|
+
total: totalFees,
|
|
19935
|
+
mintedShares
|
|
19936
|
+
}
|
|
19937
|
+
};
|
|
19938
|
+
}
|
|
19939
|
+
function settleTrancheNav(tranche, currentTvl, nextTvl, nowTs) {
|
|
19940
|
+
const before = tranche.junior.value + tranche.senior.value;
|
|
19941
|
+
if (before === 0n) {
|
|
19942
|
+
tranche.lastSettledTs = nowTs;
|
|
19943
|
+
return nextTvl;
|
|
19944
|
+
}
|
|
19945
|
+
if (currentTvl <= 0n || before > currentTvl) {
|
|
19946
|
+
throw new Error(
|
|
19947
|
+
`crank would fail InvalidArgument: tranche value ${before}, current TVL ${currentTvl}`
|
|
19948
|
+
);
|
|
19949
|
+
}
|
|
19950
|
+
const after = mulDiv2(before, nextTvl, currentTvl);
|
|
19951
|
+
if (after >= before) {
|
|
19952
|
+
let gain = after - before;
|
|
19953
|
+
const entitlement = seniorEntitlement(tranche, nowTs);
|
|
19954
|
+
const seniorGain = entitlement < gain ? entitlement : gain;
|
|
19955
|
+
tranche.senior.value += seniorGain;
|
|
19956
|
+
gain -= seniorGain;
|
|
19957
|
+
if (gain > 0n) {
|
|
19958
|
+
if (tranche.junior.totalSupply > 0n) tranche.junior.value += gain;
|
|
19959
|
+
else tranche.senior.value += gain;
|
|
19960
|
+
}
|
|
19961
|
+
} else {
|
|
19962
|
+
const loss = before - after;
|
|
19963
|
+
const juniorLoss = tranche.junior.value < loss ? tranche.junior.value : loss;
|
|
19964
|
+
tranche.junior.value -= juniorLoss;
|
|
19965
|
+
tranche.senior.value -= loss - juniorLoss;
|
|
19966
|
+
}
|
|
19967
|
+
refreshShareClass(tranche.junior);
|
|
19968
|
+
refreshShareClass(tranche.senior);
|
|
19969
|
+
tranche.lastSettledTs = nowTs;
|
|
19970
|
+
return nextTvl - tranche.junior.value - tranche.senior.value;
|
|
19971
|
+
}
|
|
19972
|
+
function seniorEntitlement(tranche, nowTs) {
|
|
19973
|
+
if (tranche.seniorApyAnchorTs <= 0n) {
|
|
19974
|
+
tranche.seniorApyAnchorSharePrice = tranche.senior.sharePrice;
|
|
19975
|
+
tranche.seniorApyAnchorTs = tranche.lastSettledTs > 0n ? tranche.lastSettledTs : nowTs;
|
|
19976
|
+
}
|
|
19977
|
+
if (tranche.seniorFixedApyBps === 0 || tranche.seniorApyAnchorSharePrice === 0n || tranche.senior.totalSupply === 0n || tranche.seniorApyAnchorTs <= 0n || nowTs <= tranche.seniorApyAnchorTs) {
|
|
19978
|
+
return 0n;
|
|
19979
|
+
}
|
|
19980
|
+
const targetPrice = applyEffectiveApy(
|
|
19981
|
+
tranche.seniorApyAnchorSharePrice,
|
|
19982
|
+
tranche.seniorFixedApyBps,
|
|
19983
|
+
nowTs - tranche.seniorApyAnchorTs
|
|
19984
|
+
);
|
|
19985
|
+
const targetValue = mulDiv2(
|
|
19986
|
+
targetPrice,
|
|
19987
|
+
tranche.senior.totalSupply,
|
|
19988
|
+
DEFAULT_SHARE_PRICE
|
|
19989
|
+
);
|
|
19990
|
+
return targetValue > tranche.senior.value ? targetValue - tranche.senior.value : 0n;
|
|
19991
|
+
}
|
|
19992
|
+
function settleShareClassPerformanceFee(shareClass, performanceFeeBps, protocolFeeBps) {
|
|
19993
|
+
refreshShareClass(shareClass);
|
|
19994
|
+
const grossPrice = shareClass.sharePrice;
|
|
19995
|
+
if (shareClass.hwmSharePrice === 0n) {
|
|
19996
|
+
shareClass.hwmSharePrice = grossPrice;
|
|
19997
|
+
return noFees();
|
|
19998
|
+
}
|
|
19999
|
+
if (performanceFeeBps + protocolFeeBps === 0 || shareClass.totalSupply === 0n || grossPrice <= shareClass.hwmSharePrice) {
|
|
20000
|
+
return noFees();
|
|
20001
|
+
}
|
|
20002
|
+
const gainValue = mulDiv2(
|
|
20003
|
+
grossPrice - shareClass.hwmSharePrice,
|
|
20004
|
+
shareClass.totalSupply,
|
|
20005
|
+
DEFAULT_SHARE_PRICE
|
|
20006
|
+
);
|
|
20007
|
+
const fees = feeAmounts(gainValue, performanceFeeBps, protocolFeeBps);
|
|
20008
|
+
const total = fees.curator + fees.protocol;
|
|
20009
|
+
if (total > 0n) {
|
|
20010
|
+
shareClass.value -= total;
|
|
20011
|
+
refreshShareClass(shareClass);
|
|
20012
|
+
shareClass.hwmSharePrice = shareClass.sharePrice;
|
|
20013
|
+
}
|
|
20014
|
+
return fees;
|
|
20015
|
+
}
|
|
20016
|
+
function settleRegularPerformanceFee(grossValue, supply, hwmSharePrice, performanceFeeBps, protocolFeeBps) {
|
|
20017
|
+
if (supply === 0n) return { netValue: grossValue, fees: noFees() };
|
|
20018
|
+
const grossPrice = sharePriceForValue(grossValue, supply);
|
|
20019
|
+
if (hwmSharePrice === 0n || grossPrice <= hwmSharePrice || performanceFeeBps + protocolFeeBps === 0) {
|
|
20020
|
+
return { netValue: grossValue, fees: noFees() };
|
|
20021
|
+
}
|
|
20022
|
+
const gainValue = mulDiv2(
|
|
20023
|
+
supply,
|
|
20024
|
+
grossPrice - hwmSharePrice,
|
|
20025
|
+
DEFAULT_SHARE_PRICE
|
|
20026
|
+
);
|
|
20027
|
+
const fees = feeAmounts(gainValue, performanceFeeBps, protocolFeeBps);
|
|
20028
|
+
return {
|
|
20029
|
+
netValue: grossValue - fees.curator - fees.protocol,
|
|
20030
|
+
fees
|
|
20031
|
+
};
|
|
20032
|
+
}
|
|
20033
|
+
function settleFixedApyNav(args) {
|
|
20034
|
+
if (args.fixedApyBps === 0 || args.currentSharePrice === 0n || args.totalSupply === 0n || args.anchorSharePrice === 0n || args.anchorTs <= 0n) {
|
|
20035
|
+
return args.reportedNav;
|
|
20036
|
+
}
|
|
20037
|
+
if (args.nowTs <= args.anchorTs) {
|
|
20038
|
+
const anchoredNav = mulDiv2(
|
|
20039
|
+
args.totalSupply,
|
|
20040
|
+
args.anchorSharePrice,
|
|
20041
|
+
DEFAULT_SHARE_PRICE
|
|
20042
|
+
);
|
|
20043
|
+
if (args.reportedNav !== anchoredNav) {
|
|
20044
|
+
throw new Error("crank would fail InvalidOracleUpdate at APY anchor");
|
|
20045
|
+
}
|
|
20046
|
+
return args.reportedNav;
|
|
20047
|
+
}
|
|
20048
|
+
const fixedPrice = applyEffectiveApy(
|
|
20049
|
+
args.anchorSharePrice,
|
|
20050
|
+
args.fixedApyBps,
|
|
20051
|
+
args.nowTs - args.anchorTs
|
|
20052
|
+
);
|
|
20053
|
+
const fixedNav = mulDiv2(args.totalSupply, fixedPrice, DEFAULT_SHARE_PRICE);
|
|
20054
|
+
return args.reportedNav >= fixedNav ? fixedNav : args.reportedNav;
|
|
20055
|
+
}
|
|
20056
|
+
function validateRealizedApy(priorValue, priorTs, nextValue, nextTs, maxApyBps) {
|
|
20057
|
+
if (maxApyBps === 0 || priorValue === 0n || priorTs <= 0n || nextValue <= priorValue) {
|
|
20058
|
+
return;
|
|
20059
|
+
}
|
|
20060
|
+
const elapsed = nextTs - priorTs;
|
|
20061
|
+
if (elapsed <= 0n) throw new Error("crank would fail MaxApyExceeded");
|
|
20062
|
+
const lhs = (nextValue - priorValue) * BPS_DENOMINATOR2 * SECONDS_PER_YEAR;
|
|
20063
|
+
const rhs = BigInt(maxApyBps) * priorValue * elapsed;
|
|
20064
|
+
if (lhs > rhs) {
|
|
20065
|
+
const implied = lhs / (priorValue * elapsed);
|
|
20066
|
+
throw new Error(
|
|
20067
|
+
`crank would fail MaxApyExceeded: implied ${implied}bps > ${maxApyBps}bps`
|
|
20068
|
+
);
|
|
20069
|
+
}
|
|
20070
|
+
}
|
|
20071
|
+
function grossNavFromHoldings(holdings, nowTs, stalenessSecs) {
|
|
20072
|
+
let nav = 0n;
|
|
20073
|
+
for (const holding of holdings) {
|
|
20074
|
+
if (holding.cleared) continue;
|
|
20075
|
+
const amount = holding.localAmount + holding.externalAmount;
|
|
20076
|
+
if (amount === 0n && !holding.isBase) continue;
|
|
20077
|
+
if (holding.price <= 0n) {
|
|
20078
|
+
throw new Error(`crank blocked: holding ${holding.mint} is unpriced`);
|
|
20079
|
+
}
|
|
20080
|
+
if (holding.priceOracleType !== "none" && (holding.lastUpdateTs <= 0n || nowTs - holding.lastUpdateTs < 0n || nowTs - holding.lastUpdateTs > stalenessSecs)) {
|
|
20081
|
+
throw new Error(
|
|
20082
|
+
`crank blocked: holding ${holding.mint} price is stale (ts=${holding.lastUpdateTs})`
|
|
20083
|
+
);
|
|
20084
|
+
}
|
|
20085
|
+
if (amount > 0n) {
|
|
20086
|
+
nav += mulDiv2(amount, holding.price, 10n ** BigInt(holding.decimals));
|
|
20087
|
+
}
|
|
20088
|
+
}
|
|
20089
|
+
return nav;
|
|
20090
|
+
}
|
|
20091
|
+
function decodeOracleData(data, nowTs) {
|
|
20092
|
+
if (data.length < ENTRIES_OFFSET + MAX_SIGNERS * ENTRY_SIZE) {
|
|
20093
|
+
throw new Error(`oracle payload is too short (${data.length} bytes)`);
|
|
20094
|
+
}
|
|
20095
|
+
const entries = [];
|
|
20096
|
+
for (let signerIndex = 0; signerIndex < MAX_SIGNERS; signerIndex += 1) {
|
|
20097
|
+
const offset = ENTRIES_OFFSET + signerIndex * ENTRY_SIZE;
|
|
20098
|
+
const signerBytes = new Uint8Array(data.slice(offset, offset + 32));
|
|
20099
|
+
const prices = Array.from(
|
|
20100
|
+
{ length: MAX_HOLDINGS },
|
|
20101
|
+
(_, holdingIndex) => readU64(data, offset + PRICE_OFFSET + holdingIndex * 8)
|
|
20102
|
+
);
|
|
20103
|
+
const externalAmounts = Array.from(
|
|
20104
|
+
{ length: MAX_HOLDINGS },
|
|
20105
|
+
(_, holdingIndex) => readU64(data, offset + EXTERNAL_OFFSET + holdingIndex * 8)
|
|
20106
|
+
);
|
|
20107
|
+
entries.push({
|
|
20108
|
+
signer: new import_web326.PublicKey(signerBytes).toBase58(),
|
|
20109
|
+
lastUpdateTs: readI64(data, offset + 32),
|
|
20110
|
+
prices,
|
|
20111
|
+
externalAmounts
|
|
20112
|
+
});
|
|
20113
|
+
}
|
|
20114
|
+
const pendingOffset = ENTRIES_OFFSET + MAX_SIGNERS * ENTRY_SIZE;
|
|
20115
|
+
const pendingEffectiveTs = readI64(data, pendingOffset + 128);
|
|
20116
|
+
const pendingCount = data[pendingOffset + 136] ?? 0;
|
|
20117
|
+
if (pendingCount > 0 && pendingCount <= MAX_SIGNERS && nowTs >= pendingEffectiveTs) {
|
|
20118
|
+
for (let index = 0; index < MAX_SIGNERS; index += 1) {
|
|
20119
|
+
const signerBytes = new Uint8Array(
|
|
20120
|
+
data.slice(pendingOffset + index * 32, pendingOffset + (index + 1) * 32)
|
|
20121
|
+
);
|
|
20122
|
+
entries[index] = {
|
|
20123
|
+
signer: index < pendingCount ? new import_web326.PublicKey(signerBytes).toBase58() : import_web326.PublicKey.default.toBase58(),
|
|
20124
|
+
lastUpdateTs: 0n,
|
|
20125
|
+
prices: Array(MAX_HOLDINGS).fill(0n),
|
|
20126
|
+
externalAmounts: Array(MAX_HOLDINGS).fill(0n)
|
|
20127
|
+
};
|
|
20128
|
+
}
|
|
20129
|
+
}
|
|
20130
|
+
return {
|
|
20131
|
+
settledNavTs: readI64(data, 8),
|
|
20132
|
+
stalenessThresholdSecs: positiveOrDefault(
|
|
20133
|
+
readI64(data, 32),
|
|
20134
|
+
DEFAULT_STALENESS_SECS
|
|
20135
|
+
),
|
|
20136
|
+
entries
|
|
20137
|
+
};
|
|
20138
|
+
}
|
|
20139
|
+
function decodeHolding(value) {
|
|
20140
|
+
const holding = record(value);
|
|
20141
|
+
const mintString = pubkeyString3(holding.mint);
|
|
20142
|
+
return {
|
|
20143
|
+
mint: (0, import_kit14.address)(mintString),
|
|
20144
|
+
decimals: number(holding.decimals),
|
|
20145
|
+
priceOracleType: variant(holding.priceOracleType),
|
|
20146
|
+
isBase: bool(holding.isBase),
|
|
20147
|
+
localAmount: bigint(holding.localAmount),
|
|
20148
|
+
externalAmount: bigint(holding.externalAmount),
|
|
20149
|
+
price: bigint(holding.price),
|
|
20150
|
+
lastUpdateTs: bigint(holding.lastUpdateTs),
|
|
20151
|
+
cleared: mintString === import_web326.PublicKey.default.toBase58()
|
|
20152
|
+
};
|
|
20153
|
+
}
|
|
20154
|
+
function decodeTrancheState(decoded, args, warnings, blockers) {
|
|
20155
|
+
if (!decoded) {
|
|
20156
|
+
blockers.push("tranching is enabled but the tranche state was unavailable");
|
|
20157
|
+
return void 0;
|
|
20158
|
+
}
|
|
20159
|
+
const junior = decodeShareClass(decoded.junior);
|
|
20160
|
+
const senior = decodeShareClass(decoded.senior);
|
|
20161
|
+
if (args.physicalJuniorSupply === void 0) {
|
|
20162
|
+
warnings.push(
|
|
20163
|
+
"junior mint supply unavailable; using cached tranche supply"
|
|
20164
|
+
);
|
|
20165
|
+
} else {
|
|
20166
|
+
junior.totalSupply = args.physicalJuniorSupply;
|
|
20167
|
+
refreshShareClass(junior);
|
|
20168
|
+
}
|
|
20169
|
+
if (args.physicalSeniorSupply === void 0) {
|
|
20170
|
+
warnings.push(
|
|
20171
|
+
"senior mint supply unavailable; using cached tranche supply"
|
|
20172
|
+
);
|
|
20173
|
+
} else {
|
|
20174
|
+
senior.totalSupply = args.physicalSeniorSupply;
|
|
20175
|
+
refreshShareClass(senior);
|
|
20176
|
+
}
|
|
20177
|
+
return {
|
|
20178
|
+
junior,
|
|
20179
|
+
senior,
|
|
20180
|
+
seniorFixedApyBps: number(decoded.config.seniorFixedApyBps),
|
|
20181
|
+
lastSettledTs: bigint(decoded.lastSettledTs),
|
|
20182
|
+
seniorApyAnchorSharePrice: bigint(decoded.seniorApyAnchorSharePrice),
|
|
20183
|
+
seniorApyAnchorTs: bigint(decoded.seniorApyAnchorTs)
|
|
20184
|
+
};
|
|
20185
|
+
}
|
|
20186
|
+
function decodeShareClass(value) {
|
|
20187
|
+
const decoded = record(value);
|
|
20188
|
+
return {
|
|
20189
|
+
value: bigint(decoded.value),
|
|
20190
|
+
totalSupply: bigint(decoded.totalSupply),
|
|
20191
|
+
sharePrice: bigint(decoded.sharePrice),
|
|
20192
|
+
hwmSharePrice: bigint(decoded.hwmSharePrice)
|
|
20193
|
+
};
|
|
20194
|
+
}
|
|
20195
|
+
function snapshot(tvl, regularSupply, regularSharePrice, tranche) {
|
|
20196
|
+
const regularValue = mulDiv2(
|
|
20197
|
+
regularSupply,
|
|
20198
|
+
regularSharePrice,
|
|
20199
|
+
DEFAULT_SHARE_PRICE
|
|
20200
|
+
);
|
|
20201
|
+
return {
|
|
20202
|
+
tvl,
|
|
20203
|
+
regular: {
|
|
20204
|
+
value: regularValue,
|
|
20205
|
+
totalSupply: regularSupply,
|
|
20206
|
+
sharePrice: regularSharePrice
|
|
20207
|
+
},
|
|
20208
|
+
...tranche ? {
|
|
20209
|
+
junior: publicShareClass(tranche.junior),
|
|
20210
|
+
senior: publicShareClass(tranche.senior)
|
|
20211
|
+
} : {}
|
|
20212
|
+
};
|
|
20213
|
+
}
|
|
20214
|
+
function publicShareClass(value) {
|
|
20215
|
+
return {
|
|
20216
|
+
value: value.value,
|
|
20217
|
+
totalSupply: value.totalSupply,
|
|
20218
|
+
sharePrice: value.sharePrice
|
|
20219
|
+
};
|
|
20220
|
+
}
|
|
20221
|
+
function refreshShareClass(value) {
|
|
20222
|
+
value.sharePrice = value.totalSupply === 0n ? DEFAULT_SHARE_PRICE : mulDiv2(value.value, DEFAULT_SHARE_PRICE, value.totalSupply);
|
|
20223
|
+
}
|
|
20224
|
+
function sharePriceForValue(value, supply) {
|
|
20225
|
+
return supply === 0n ? void 0 : mulDiv2(value, DEFAULT_SHARE_PRICE, supply);
|
|
20226
|
+
}
|
|
20227
|
+
function feeAmounts(value, performanceFeeBps, protocolFeeBps) {
|
|
20228
|
+
return {
|
|
20229
|
+
curator: mulDiv2(value, BigInt(performanceFeeBps), BPS_DENOMINATOR2),
|
|
20230
|
+
protocol: mulDiv2(value, BigInt(protocolFeeBps), BPS_DENOMINATOR2)
|
|
20231
|
+
};
|
|
20232
|
+
}
|
|
20233
|
+
function noFees() {
|
|
20234
|
+
return { curator: 0n, protocol: 0n };
|
|
20235
|
+
}
|
|
20236
|
+
function withinDeviation(values) {
|
|
20237
|
+
for (let i = 0; i < values.length; i += 1) {
|
|
20238
|
+
for (let j = i + 1; j < values.length; j += 1) {
|
|
20239
|
+
const a = values[i];
|
|
20240
|
+
const b = values[j];
|
|
20241
|
+
if (a === b) continue;
|
|
20242
|
+
if (a === 0n || b === 0n) return false;
|
|
20243
|
+
const diff = abs(a * BPS_DENOMINATOR2 / b - BPS_DENOMINATOR2);
|
|
20244
|
+
if (diff > CONSENSUS_MAX_DIFF_BPS) return false;
|
|
20245
|
+
}
|
|
20246
|
+
}
|
|
20247
|
+
return true;
|
|
20248
|
+
}
|
|
20249
|
+
function average(values) {
|
|
20250
|
+
return values.reduce((sum, value) => sum + value, 0n) / BigInt(values.length);
|
|
20251
|
+
}
|
|
20252
|
+
function isFresh(lastTs, nowTs, staleness) {
|
|
20253
|
+
if (lastTs <= 0n) return false;
|
|
20254
|
+
const age = nowTs - lastTs;
|
|
20255
|
+
return age >= 0n && age <= staleness;
|
|
20256
|
+
}
|
|
20257
|
+
function applyEffectiveApy(anchor, apyBps, elapsedSecs) {
|
|
20258
|
+
if (anchor === 0n || apyBps === 0 || elapsedSecs === 0n) return anchor;
|
|
20259
|
+
if (apyBps < 0 || apyBps > 1e4) throw new Error("invalid APY bps");
|
|
20260
|
+
const base = APY_SCALE + mulDiv2(BigInt(apyBps), APY_SCALE, BPS_DENOMINATOR2);
|
|
20261
|
+
const wholeYears = elapsedSecs / SECONDS_PER_YEAR;
|
|
20262
|
+
const remainder = elapsedSecs % SECONDS_PER_YEAR;
|
|
20263
|
+
const wholeMultiplier = fixedPointPow(base, wholeYears);
|
|
20264
|
+
const fractionalMultiplier = remainder === 0n ? APY_SCALE : fixedPointExp(
|
|
20265
|
+
mulDiv2(
|
|
20266
|
+
fixedPointLnBetweenOneAndTwo(base),
|
|
20267
|
+
remainder,
|
|
20268
|
+
SECONDS_PER_YEAR
|
|
20269
|
+
)
|
|
20270
|
+
);
|
|
20271
|
+
return mulDiv2(
|
|
20272
|
+
anchor,
|
|
20273
|
+
fixedPointMul(wholeMultiplier, fractionalMultiplier),
|
|
20274
|
+
APY_SCALE
|
|
20275
|
+
);
|
|
20276
|
+
}
|
|
20277
|
+
function fixedPointMul(lhs, rhs) {
|
|
20278
|
+
const lhsWhole = lhs / APY_SCALE;
|
|
20279
|
+
const lhsRemainder = lhs % APY_SCALE;
|
|
20280
|
+
const rhsWhole = rhs / APY_SCALE;
|
|
20281
|
+
const rhsRemainder = rhs % APY_SCALE;
|
|
20282
|
+
return lhsWhole * rhs + lhsRemainder * rhsWhole + lhsRemainder * rhsRemainder / APY_SCALE;
|
|
20283
|
+
}
|
|
20284
|
+
function fixedPointPow(baseInput, exponentInput) {
|
|
20285
|
+
let base = baseInput;
|
|
20286
|
+
let exponent = exponentInput;
|
|
20287
|
+
let result = APY_SCALE;
|
|
20288
|
+
while (exponent > 0n) {
|
|
20289
|
+
if ((exponent & 1n) === 1n) result = fixedPointMul(result, base);
|
|
20290
|
+
exponent >>= 1n;
|
|
20291
|
+
if (exponent > 0n) base = fixedPointMul(base, base);
|
|
20292
|
+
}
|
|
20293
|
+
return result;
|
|
20294
|
+
}
|
|
20295
|
+
function fixedPointLnBetweenOneAndTwo(value) {
|
|
20296
|
+
if (value < APY_SCALE || value > 2n * APY_SCALE) {
|
|
20297
|
+
throw new Error("APY logarithm input out of range");
|
|
20298
|
+
}
|
|
20299
|
+
const z = mulDiv2(value - APY_SCALE, APY_SCALE, value + APY_SCALE);
|
|
20300
|
+
const zSquared = fixedPointMul(z, z);
|
|
20301
|
+
let power = z;
|
|
20302
|
+
let sum = 0n;
|
|
20303
|
+
for (let index = 0; index < APY_SERIES_TERMS; index += 1) {
|
|
20304
|
+
sum += power / BigInt(2 * index + 1);
|
|
20305
|
+
power = fixedPointMul(power, zSquared);
|
|
20306
|
+
}
|
|
20307
|
+
return sum * 2n;
|
|
20308
|
+
}
|
|
20309
|
+
function fixedPointExp(value) {
|
|
20310
|
+
if (value > APY_LN_2) throw new Error("APY exponent input out of range");
|
|
20311
|
+
let sum = APY_SCALE;
|
|
20312
|
+
let term = APY_SCALE;
|
|
20313
|
+
for (let divisor = 1; divisor <= APY_SERIES_TERMS; divisor += 1) {
|
|
20314
|
+
term = fixedPointMul(term, value) / BigInt(divisor);
|
|
20315
|
+
if (term === 0n) break;
|
|
20316
|
+
sum += term;
|
|
20317
|
+
}
|
|
20318
|
+
return sum;
|
|
20319
|
+
}
|
|
20320
|
+
function readU64(data, offset) {
|
|
20321
|
+
let value = 0n;
|
|
20322
|
+
for (let index = 0; index < 8; index += 1) {
|
|
20323
|
+
value |= BigInt(data[offset + index] ?? 0) << BigInt(index * 8);
|
|
20324
|
+
}
|
|
20325
|
+
return value;
|
|
20326
|
+
}
|
|
20327
|
+
function readI64(data, offset) {
|
|
20328
|
+
const value = readU64(data, offset);
|
|
20329
|
+
return value >= 0x8000000000000000n ? value - 0x10000000000000000n : value;
|
|
20330
|
+
}
|
|
20331
|
+
function mulDiv2(a, b, c) {
|
|
20332
|
+
if (c === 0n) throw new Error("division by zero in settlement simulation");
|
|
20333
|
+
return a * b / c;
|
|
20334
|
+
}
|
|
20335
|
+
function record(value) {
|
|
20336
|
+
return value && typeof value === "object" ? value : {};
|
|
20337
|
+
}
|
|
20338
|
+
function bigint(value) {
|
|
20339
|
+
if (value === void 0 || value === null) return 0n;
|
|
20340
|
+
if (typeof value === "bigint") return value;
|
|
20341
|
+
if (typeof value === "number" || typeof value === "string") {
|
|
20342
|
+
return BigInt(value);
|
|
20343
|
+
}
|
|
20344
|
+
return BigInt(String(value));
|
|
20345
|
+
}
|
|
20346
|
+
function number(value) {
|
|
20347
|
+
return Number(bigint(value));
|
|
20348
|
+
}
|
|
20349
|
+
function bool(value) {
|
|
20350
|
+
if (typeof value === "boolean") return value;
|
|
20351
|
+
if (typeof value === "number") return value !== 0;
|
|
20352
|
+
if (value && typeof value.toBool === "function") {
|
|
20353
|
+
return value.toBool();
|
|
20354
|
+
}
|
|
20355
|
+
const pod = value;
|
|
20356
|
+
return Boolean(pod?.value ?? pod?.[0]);
|
|
20357
|
+
}
|
|
20358
|
+
function variant(value) {
|
|
20359
|
+
return (value && typeof value === "object" ? Object.keys(value)[0] ?? "" : String(value ?? "")).toLowerCase();
|
|
20360
|
+
}
|
|
20361
|
+
function pubkeyString3(value) {
|
|
20362
|
+
if (typeof value === "string") return value;
|
|
20363
|
+
if (value && typeof value.toBase58 === "function") {
|
|
20364
|
+
return value.toBase58();
|
|
20365
|
+
}
|
|
20366
|
+
return String(value);
|
|
20367
|
+
}
|
|
20368
|
+
function positiveOrDefault(value, fallback) {
|
|
20369
|
+
return value > 0n ? value : fallback;
|
|
20370
|
+
}
|
|
20371
|
+
function max(a, b) {
|
|
20372
|
+
return a > b ? a : b;
|
|
20373
|
+
}
|
|
20374
|
+
function abs(value) {
|
|
20375
|
+
return value < 0n ? -value : value;
|
|
20376
|
+
}
|
|
20377
|
+
function message(error) {
|
|
20378
|
+
return error instanceof Error ? error.message : String(error);
|
|
20379
|
+
}
|
|
20380
|
+
function formatSettlementSimulation(simulation) {
|
|
20381
|
+
const lines = [];
|
|
20382
|
+
lines.push(
|
|
20383
|
+
` proposed oracle values: ${simulation.allProposedUpdatesLand ? "WOULD REACH CONSENSUS" : "WOULD NOT ALL LAND"} (${simulation.proposedUpdatesLanded}/${simulation.proposedUpdatesTotal} holdings)`
|
|
20384
|
+
);
|
|
20385
|
+
lines.push(
|
|
20386
|
+
` crank simulation: ${simulation.canSettle ? "WOULD SETTLE" : "BLOCKED"}`
|
|
20387
|
+
);
|
|
20388
|
+
for (const holding of simulation.consensus) {
|
|
20389
|
+
const detail = holding.settledPrice ? `price=${holding.settledPrice} external=${holding.settledExternalAmount}` : holding.reason ?? "no aggregate";
|
|
20390
|
+
lines.push(
|
|
20391
|
+
` consensus #${holding.holdingIndex} ${holding.mint}: ${holding.reportCount} report(s), ${holding.wouldUpdateHolding ? "lands" : "unchanged"} (${detail})`
|
|
20392
|
+
);
|
|
20393
|
+
}
|
|
20394
|
+
if (simulation.grossNav !== void 0) {
|
|
20395
|
+
lines.push(
|
|
20396
|
+
` gross NAV: ${formatUnits(
|
|
20397
|
+
simulation.grossNav,
|
|
20398
|
+
simulation.assetDecimals
|
|
20399
|
+
)} [${simulation.grossNav}]`
|
|
20400
|
+
);
|
|
20401
|
+
}
|
|
20402
|
+
if (simulation.settledAccountingNav !== void 0 && simulation.settledAccountingNav !== simulation.grossNav) {
|
|
20403
|
+
lines.push(
|
|
20404
|
+
` accounting NAV after fixed APY: ${formatUnits(
|
|
20405
|
+
simulation.settledAccountingNav,
|
|
20406
|
+
simulation.assetDecimals
|
|
20407
|
+
)} [${simulation.settledAccountingNav}]`
|
|
20408
|
+
);
|
|
20409
|
+
}
|
|
20410
|
+
if (simulation.projected) {
|
|
20411
|
+
lines.push(
|
|
20412
|
+
` TVL: ${formatTransition(
|
|
20413
|
+
simulation.current.tvl,
|
|
20414
|
+
simulation.projected.tvl,
|
|
20415
|
+
simulation.assetDecimals
|
|
20416
|
+
)}`
|
|
20417
|
+
);
|
|
20418
|
+
lines.push(
|
|
20419
|
+
` regular: ${formatTransition(
|
|
20420
|
+
simulation.current.regular.sharePrice,
|
|
20421
|
+
simulation.projected.regular.sharePrice,
|
|
20422
|
+
6
|
|
20423
|
+
)} per share`
|
|
20424
|
+
);
|
|
20425
|
+
lines.push(
|
|
20426
|
+
` supply ${simulation.current.regular.totalSupply} -> ${simulation.projected.regular.totalSupply}, backing ${simulation.current.regular.value} -> ${simulation.projected.regular.value}`
|
|
20427
|
+
);
|
|
20428
|
+
if (simulation.current.junior && simulation.projected.junior) {
|
|
20429
|
+
lines.push(
|
|
20430
|
+
` junior: ${formatTransition(
|
|
20431
|
+
simulation.current.junior.sharePrice,
|
|
20432
|
+
simulation.projected.junior.sharePrice,
|
|
20433
|
+
6
|
|
20434
|
+
)} per share`
|
|
20435
|
+
);
|
|
20436
|
+
lines.push(
|
|
20437
|
+
` supply ${simulation.current.junior.totalSupply} -> ${simulation.projected.junior.totalSupply}, value ${simulation.current.junior.value} -> ${simulation.projected.junior.value}`
|
|
20438
|
+
);
|
|
20439
|
+
}
|
|
20440
|
+
if (simulation.current.senior && simulation.projected.senior) {
|
|
20441
|
+
lines.push(
|
|
20442
|
+
` senior: ${formatTransition(
|
|
20443
|
+
simulation.current.senior.sharePrice,
|
|
20444
|
+
simulation.projected.senior.sharePrice,
|
|
20445
|
+
6
|
|
20446
|
+
)} per share`
|
|
20447
|
+
);
|
|
20448
|
+
lines.push(
|
|
20449
|
+
` supply ${simulation.current.senior.totalSupply} -> ${simulation.projected.senior.totalSupply}, value ${simulation.current.senior.value} -> ${simulation.projected.senior.value}`
|
|
20450
|
+
);
|
|
20451
|
+
}
|
|
20452
|
+
}
|
|
20453
|
+
if (simulation.performanceFees) {
|
|
20454
|
+
lines.push(
|
|
20455
|
+
` performance fees: curator=${simulation.performanceFees.curator} protocol=${simulation.performanceFees.protocol} total=${simulation.performanceFees.total} fee_shares=${simulation.performanceFees.mintedShares}`
|
|
20456
|
+
);
|
|
20457
|
+
}
|
|
20458
|
+
for (const blocker of simulation.blockers)
|
|
20459
|
+
lines.push(` BLOCKER: ${blocker}`);
|
|
20460
|
+
for (const warning of simulation.warnings)
|
|
20461
|
+
lines.push(` warning: ${warning}`);
|
|
20462
|
+
return lines;
|
|
20463
|
+
}
|
|
20464
|
+
function formatTransition(before, after, decimals) {
|
|
20465
|
+
return `${formatUnits(before, decimals)} [${before}] -> ${formatUnits(
|
|
20466
|
+
after,
|
|
20467
|
+
decimals
|
|
20468
|
+
)} [${after}]`;
|
|
20469
|
+
}
|
|
20470
|
+
function formatUnits(value, decimals) {
|
|
20471
|
+
const negative = value < 0n;
|
|
20472
|
+
const absolute = negative ? -value : value;
|
|
20473
|
+
const scale = 10n ** BigInt(decimals);
|
|
20474
|
+
const whole = absolute / scale;
|
|
20475
|
+
const fraction = (absolute % scale).toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
20476
|
+
return `${negative ? "-" : ""}${whole}${fraction ? `.${fraction}` : ""}`;
|
|
20477
|
+
}
|
|
20478
|
+
|
|
20479
|
+
// src/services/consensusOracle/consensusOracleService.ts
|
|
19576
20480
|
var SYSTEM_PROGRAM2 = "11111111111111111111111111111111";
|
|
19577
20481
|
var CONSENSUS_ORACLE_VARIANT = "consensusoracle";
|
|
19578
20482
|
function variantName2(value) {
|
|
@@ -19582,8 +20486,8 @@ function variantName2(value) {
|
|
|
19582
20486
|
function coerceBool3(value) {
|
|
19583
20487
|
if (typeof value === "boolean") return value;
|
|
19584
20488
|
if (typeof value === "number") return value !== 0;
|
|
19585
|
-
const
|
|
19586
|
-
return Boolean(
|
|
20489
|
+
const record2 = value;
|
|
20490
|
+
return Boolean(record2?.value ?? record2?.[0]);
|
|
19587
20491
|
}
|
|
19588
20492
|
function priceInAccountingUnit(usd, baseUsd, assetDecimals) {
|
|
19589
20493
|
return BigInt(Math.round(usd / baseUsd * 10 ** assetDecimals));
|
|
@@ -19605,7 +20509,7 @@ function parseExternalLiquidityRefs(vaultState) {
|
|
|
19605
20509
|
if (!data || data.length < 40) continue;
|
|
19606
20510
|
if (data[0] !== 1) continue;
|
|
19607
20511
|
const pubkeyBytes = new Uint8Array(data.slice(8, 40));
|
|
19608
|
-
const userAccount = new
|
|
20512
|
+
const userAccount = new import_web327.PublicKey(pubkeyBytes).toBase58();
|
|
19609
20513
|
refs.push({
|
|
19610
20514
|
kind: "marginfi",
|
|
19611
20515
|
mint: "",
|
|
@@ -19630,23 +20534,60 @@ var ConsensusOracleService = class {
|
|
|
19630
20534
|
});
|
|
19631
20535
|
const dryRun = opts.dryRun ?? false;
|
|
19632
20536
|
const vaultState = await this.fetchDecodedVault(target.vault);
|
|
19633
|
-
const
|
|
20537
|
+
const receiptMints = await this.fetchReceiptMints(target.vault, vaultState);
|
|
20538
|
+
const consensusHoldings = selectConsensusHoldings(
|
|
20539
|
+
vaultState.holdings,
|
|
20540
|
+
receiptMints
|
|
20541
|
+
);
|
|
20542
|
+
const filteredCount = vaultState.holdings.filter(
|
|
20543
|
+
(holding) => receiptMints.has((0, import_common41.fromWeb3Pk)(holding.mint).toString())
|
|
20544
|
+
).length;
|
|
20545
|
+
if (filteredCount > 0) {
|
|
20546
|
+
log(
|
|
20547
|
+
`vault ${target.vault}: excluded ${filteredCount} vault/tranche receipt mint holding(s)`
|
|
20548
|
+
);
|
|
20549
|
+
}
|
|
19634
20550
|
if (consensusHoldings.length === 0) {
|
|
19635
20551
|
log(`vault ${target.vault}: no consensus holdings, skipping`);
|
|
19636
20552
|
return { vault: target.vault, updates: [], dryRun };
|
|
19637
20553
|
}
|
|
19638
|
-
|
|
20554
|
+
const filteredTarget = filterTargetHoldings(target, receiptMints);
|
|
20555
|
+
await this.assertNoUnconfirmedYieldPayments(filteredTarget);
|
|
19639
20556
|
const inputs = await this.gatherPricingInputs(
|
|
19640
|
-
|
|
20557
|
+
filteredTarget,
|
|
19641
20558
|
vaultState,
|
|
19642
20559
|
consensusHoldings
|
|
19643
20560
|
);
|
|
19644
20561
|
const updates = await this.buildUpdates(consensusHoldings, inputs);
|
|
19645
20562
|
if (dryRun) {
|
|
19646
20563
|
log(`vault ${target.vault}: dry run, ${updates.length} holding(s)`);
|
|
19647
|
-
|
|
20564
|
+
try {
|
|
20565
|
+
const settlementSimulation = await this.simulateDryRunSettlement(
|
|
20566
|
+
signer,
|
|
20567
|
+
target.vault,
|
|
20568
|
+
vaultState,
|
|
20569
|
+
updates
|
|
20570
|
+
);
|
|
20571
|
+
return {
|
|
20572
|
+
vault: target.vault,
|
|
20573
|
+
updates,
|
|
20574
|
+
dryRun: true,
|
|
20575
|
+
settlementSimulation
|
|
20576
|
+
};
|
|
20577
|
+
} catch (error) {
|
|
20578
|
+
const settlementSimulationError = error instanceof Error ? error.message : String(error);
|
|
20579
|
+
log(
|
|
20580
|
+
`vault ${target.vault}: settlement simulation unavailable: ${settlementSimulationError}`
|
|
20581
|
+
);
|
|
20582
|
+
return {
|
|
20583
|
+
vault: target.vault,
|
|
20584
|
+
updates,
|
|
20585
|
+
dryRun: true,
|
|
20586
|
+
settlementSimulationError
|
|
20587
|
+
};
|
|
20588
|
+
}
|
|
19648
20589
|
}
|
|
19649
|
-
const { updateSignature, crankSignature, crankSkippedReason } = await this.settleVault(signer,
|
|
20590
|
+
const { updateSignature, crankSignature, crankSkippedReason } = await this.settleVault(signer, filteredTarget, updates, vaultState, log);
|
|
19650
20591
|
return {
|
|
19651
20592
|
vault: target.vault,
|
|
19652
20593
|
updates,
|
|
@@ -19656,6 +20597,43 @@ var ConsensusOracleService = class {
|
|
|
19656
20597
|
crankSkippedReason
|
|
19657
20598
|
};
|
|
19658
20599
|
}
|
|
20600
|
+
/** Read canonical supplies and replay the exact on-chain settlement path. */
|
|
20601
|
+
async simulateDryRunSettlement(signer, vault, vaultState, updates) {
|
|
20602
|
+
const tranchingEnabled = coerceBool3(vaultState.tranchingEnabled);
|
|
20603
|
+
const [oracleState, trancheState] = await Promise.all([
|
|
20604
|
+
this.client.account.fetchVaultOracleForVault(vault, { fresh: true }),
|
|
20605
|
+
tranchingEnabled ? this.client.account.fetchVaultTrancheStateForVault(vault, {
|
|
20606
|
+
fresh: true
|
|
20607
|
+
}) : Promise.resolve(void 0)
|
|
20608
|
+
]);
|
|
20609
|
+
const mintKeys = [new import_web327.PublicKey(vaultState.mint)];
|
|
20610
|
+
if (trancheState) {
|
|
20611
|
+
mintKeys.push(
|
|
20612
|
+
new import_web327.PublicKey(trancheState.config.juniorMint),
|
|
20613
|
+
new import_web327.PublicKey(trancheState.config.seniorMint)
|
|
20614
|
+
);
|
|
20615
|
+
}
|
|
20616
|
+
const mintAccounts = await this.client.provider.connection.getMultipleAccountsInfo(
|
|
20617
|
+
mintKeys,
|
|
20618
|
+
"confirmed"
|
|
20619
|
+
);
|
|
20620
|
+
const supplies = mintAccounts.map((info, index) => {
|
|
20621
|
+
if (!info)
|
|
20622
|
+
throw new Error(`share mint ${mintKeys[index]} does not exist`);
|
|
20623
|
+
return readSplMintSupply(info.data);
|
|
20624
|
+
});
|
|
20625
|
+
return simulateConsensusOracleSettlement({
|
|
20626
|
+
vault: vaultState,
|
|
20627
|
+
oracleData: oracleState.data,
|
|
20628
|
+
trancheState,
|
|
20629
|
+
updates,
|
|
20630
|
+
signer: (0, import_common41.fromWeb3Pk)(signer.publicKey),
|
|
20631
|
+
nowTs: BigInt(Math.floor(this.clock.now() / 1e3)),
|
|
20632
|
+
physicalShareSupply: supplies[0],
|
|
20633
|
+
physicalJuniorSupply: tranchingEnabled ? supplies[1] : void 0,
|
|
20634
|
+
physicalSeniorSupply: tranchingEnabled ? supplies[2] : void 0
|
|
20635
|
+
});
|
|
20636
|
+
}
|
|
19659
20637
|
/**
|
|
19660
20638
|
* Fail closed while any configured yield account has an unsettled payment.
|
|
19661
20639
|
* The payout must be confirmed only after it is visible in the same wallet
|
|
@@ -19777,6 +20755,28 @@ var ConsensusOracleService = class {
|
|
|
19777
20755
|
fresh: true
|
|
19778
20756
|
});
|
|
19779
20757
|
}
|
|
20758
|
+
/**
|
|
20759
|
+
* Receipt mints issued by this vault are liabilities/shares, not underlying
|
|
20760
|
+
* assets for its own NAV. Exclude them even if they were registered as
|
|
20761
|
+
* consensus-priced holdings.
|
|
20762
|
+
*/
|
|
20763
|
+
async fetchReceiptMints(vault, vaultState) {
|
|
20764
|
+
const receiptMints = /* @__PURE__ */ new Set();
|
|
20765
|
+
if (vaultState.mint) {
|
|
20766
|
+
receiptMints.add((0, import_common41.fromWeb3Pk)(vaultState.mint).toString());
|
|
20767
|
+
}
|
|
20768
|
+
if (!coerceBool3(vaultState.tranchingEnabled)) return receiptMints;
|
|
20769
|
+
const trancheState = await this.client.account.fetchVaultTrancheStateForVault(vault, {
|
|
20770
|
+
fresh: true
|
|
20771
|
+
});
|
|
20772
|
+
receiptMints.add(
|
|
20773
|
+
(0, import_common41.fromWeb3Pk)(trancheState.config.juniorMint).toString()
|
|
20774
|
+
);
|
|
20775
|
+
receiptMints.add(
|
|
20776
|
+
(0, import_common41.fromWeb3Pk)(trancheState.config.seniorMint).toString()
|
|
20777
|
+
);
|
|
20778
|
+
return receiptMints;
|
|
20779
|
+
}
|
|
19780
20780
|
/** Fetch every external input the per-holding updates draw on, in parallel-ish. */
|
|
19781
20781
|
async gatherPricingInputs(target, vaultState, consensusHoldings) {
|
|
19782
20782
|
const manager = (0, import_common41.fromWeb3Pk)(vaultState.roles.manager);
|
|
@@ -19948,8 +20948,8 @@ var ConsensusOracleService = class {
|
|
|
19948
20948
|
const nowSecs = BigInt(Math.floor(this.clock.now() / 1e3));
|
|
19949
20949
|
const elapsedSecs = nowSecs - settledNavTs;
|
|
19950
20950
|
if (elapsedSecs <= 0n) return;
|
|
19951
|
-
const
|
|
19952
|
-
const apyBps = (prospectiveNav - settledNav) *
|
|
20951
|
+
const SECONDS_PER_YEAR3 = 365n * 24n * 3600n;
|
|
20952
|
+
const apyBps = (prospectiveNav - settledNav) * SECONDS_PER_YEAR3 * 10000n / (settledNav * elapsedSecs);
|
|
19953
20953
|
log(
|
|
19954
20954
|
`vault ${vault}: prospective NAV ${prospectiveNav} vs settled ${settledNav} (elapsed ${elapsedSecs}s) \u2192 implied APY ${apyBps}bps`
|
|
19955
20955
|
);
|
|
@@ -19965,13 +20965,23 @@ function readI64LE(data, offset) {
|
|
|
19965
20965
|
if (value >= 0x8000000000000000n) value -= 0x10000000000000000n;
|
|
19966
20966
|
return value;
|
|
19967
20967
|
}
|
|
19968
|
-
|
|
19969
|
-
|
|
20968
|
+
function readSplMintSupply(data) {
|
|
20969
|
+
if (data.length < 44) {
|
|
20970
|
+
throw new Error(`invalid SPL mint account: expected at least 44 bytes`);
|
|
20971
|
+
}
|
|
20972
|
+
let supply = 0n;
|
|
20973
|
+
for (let i = 0; i < 8; i += 1) {
|
|
20974
|
+
supply |= BigInt(data[36 + i]) << BigInt(8 * i);
|
|
20975
|
+
}
|
|
20976
|
+
return supply;
|
|
20977
|
+
}
|
|
20978
|
+
var ENTRY_SIZE2 = 272;
|
|
20979
|
+
var ENTRIES_OFFSET2 = 40;
|
|
19970
20980
|
var MAX_CONSENSUS_SIGNERS = 4;
|
|
19971
20981
|
function signerInOracleData(data, signerBytes) {
|
|
19972
20982
|
const ZERO_PUBKEY = new Uint8Array(32);
|
|
19973
20983
|
for (let i = 0; i < MAX_CONSENSUS_SIGNERS; i++) {
|
|
19974
|
-
const off =
|
|
20984
|
+
const off = ENTRIES_OFFSET2 + i * ENTRY_SIZE2;
|
|
19975
20985
|
const slice = data.slice(off, off + 32);
|
|
19976
20986
|
if (slice.length < 32) break;
|
|
19977
20987
|
const bytes = new Uint8Array(slice);
|
|
@@ -19981,12 +20991,21 @@ function signerInOracleData(data, signerBytes) {
|
|
|
19981
20991
|
}
|
|
19982
20992
|
return false;
|
|
19983
20993
|
}
|
|
19984
|
-
function selectConsensusHoldings(holdings) {
|
|
20994
|
+
function selectConsensusHoldings(holdings, excludedMints = /* @__PURE__ */ new Set()) {
|
|
19985
20995
|
return holdings.map((holding, holdingIndex) => ({ holding, holdingIndex })).filter(({ holding }) => {
|
|
19986
20996
|
const mint = (0, import_common41.fromWeb3Pk)(holding.mint);
|
|
19987
|
-
return mint !== SYSTEM_PROGRAM2 && variantName2(holding.priceOracleType).toLowerCase() === CONSENSUS_ORACLE_VARIANT;
|
|
20997
|
+
return mint !== SYSTEM_PROGRAM2 && !excludedMints.has(mint.toString()) && variantName2(holding.priceOracleType).toLowerCase() === CONSENSUS_ORACLE_VARIANT;
|
|
19988
20998
|
});
|
|
19989
20999
|
}
|
|
21000
|
+
function filterTargetHoldings(target, excludedMints) {
|
|
21001
|
+
if (!target.holdings?.length || excludedMints.size === 0) return target;
|
|
21002
|
+
return {
|
|
21003
|
+
...target,
|
|
21004
|
+
holdings: target.holdings.filter(
|
|
21005
|
+
(holding) => !excludedMints.has(holding.mint.toString())
|
|
21006
|
+
)
|
|
21007
|
+
};
|
|
21008
|
+
}
|
|
19990
21009
|
|
|
19991
21010
|
// src/services/consensusOracle/runLiveConsensusOracle.ts
|
|
19992
21011
|
async function runLiveConsensusOracle(env, oracleSigner, opts = {}) {
|
|
@@ -20010,7 +21029,7 @@ async function runLiveConsensusOracle(env, oracleSigner, opts = {}) {
|
|
|
20010
21029
|
}
|
|
20011
21030
|
|
|
20012
21031
|
// src/services/consensusOracle/mockYieldTracker.ts
|
|
20013
|
-
var
|
|
21032
|
+
var SECONDS_PER_YEAR2 = 365 * 24 * 60 * 60;
|
|
20014
21033
|
var MockYieldTracker = class {
|
|
20015
21034
|
constructor(opts = {}) {
|
|
20016
21035
|
this.accounts = /* @__PURE__ */ new Map();
|
|
@@ -20065,12 +21084,12 @@ var MockYieldTracker = class {
|
|
|
20065
21084
|
let segStart = windowStartMs;
|
|
20066
21085
|
for (const cf of boundaries) {
|
|
20067
21086
|
const dtSecs = (cf.ts - segStart) / 1e3;
|
|
20068
|
-
totalYield += principal * apr * (dtSecs /
|
|
21087
|
+
totalYield += principal * apr * (dtSecs / SECONDS_PER_YEAR2);
|
|
20069
21088
|
principal += cf.amount;
|
|
20070
21089
|
segStart = cf.ts;
|
|
20071
21090
|
}
|
|
20072
21091
|
const tailSecs = Math.max(0, (windowEndMs - segStart) / 1e3);
|
|
20073
|
-
totalYield += principal * apr * (tailSecs /
|
|
21092
|
+
totalYield += principal * apr * (tailSecs / SECONDS_PER_YEAR2);
|
|
20074
21093
|
const paidYield = state.yieldPayments.reduce((sum, payment) => {
|
|
20075
21094
|
return payment.status === "confirmed" && payment.effectiveAt > windowStartMs && payment.effectiveAt <= windowEndMs ? sum + payment.amount : sum;
|
|
20076
21095
|
}, 0);
|
|
@@ -20090,22 +21109,22 @@ var MockYieldTracker = class {
|
|
|
20090
21109
|
async getTotalYield(accountNames, start, end) {
|
|
20091
21110
|
let total = 0;
|
|
20092
21111
|
for (const name of accountNames) {
|
|
20093
|
-
const
|
|
20094
|
-
total +=
|
|
21112
|
+
const snapshot2 = await this.getYield(name, start, end);
|
|
21113
|
+
total += snapshot2.totalYield;
|
|
20095
21114
|
}
|
|
20096
21115
|
return total;
|
|
20097
21116
|
}
|
|
20098
21117
|
async getTotalOutstandingYield(accountNames, start, end) {
|
|
20099
21118
|
let total = 0;
|
|
20100
21119
|
for (const name of accountNames) {
|
|
20101
|
-
const
|
|
20102
|
-
total +=
|
|
21120
|
+
const snapshot2 = await this.getYield(name, start, end);
|
|
21121
|
+
total += snapshot2.outstandingYield;
|
|
20103
21122
|
}
|
|
20104
21123
|
return total;
|
|
20105
21124
|
}
|
|
20106
21125
|
async getBalance(accountName, atTime) {
|
|
20107
|
-
const
|
|
20108
|
-
return
|
|
21126
|
+
const snapshot2 = await this.getYield(accountName, void 0, atTime);
|
|
21127
|
+
return snapshot2.principalAtEnd + snapshot2.outstandingYield;
|
|
20109
21128
|
}
|
|
20110
21129
|
async addCashflow(params) {
|
|
20111
21130
|
const state = this.require(params.accountName);
|
|
@@ -20157,12 +21176,12 @@ var MockYieldTracker = class {
|
|
|
20157
21176
|
let cumulativePaid = 0;
|
|
20158
21177
|
for (const candidate of chronologicalPayments) {
|
|
20159
21178
|
cumulativePaid += candidate.amount;
|
|
20160
|
-
const
|
|
21179
|
+
const snapshot2 = await this.getYield(
|
|
20161
21180
|
params.accountName,
|
|
20162
21181
|
void 0,
|
|
20163
21182
|
new Date(candidate.effectiveAt)
|
|
20164
21183
|
);
|
|
20165
|
-
if (cumulativePaid >
|
|
21184
|
+
if (cumulativePaid > snapshot2.totalYield + 1e-9) {
|
|
20166
21185
|
throw new Error("Confirmed payment exceeds accrued unpaid yield");
|
|
20167
21186
|
}
|
|
20168
21187
|
}
|
|
@@ -20172,8 +21191,8 @@ var MockYieldTracker = class {
|
|
|
20172
21191
|
};
|
|
20173
21192
|
|
|
20174
21193
|
// src/services/externalLiquidityIntegrityService.ts
|
|
20175
|
-
var
|
|
20176
|
-
var
|
|
21194
|
+
var import_kit15 = require("@solana/kit");
|
|
21195
|
+
var import_web328 = require("@solana/web3.js");
|
|
20177
21196
|
var import_common42 = __toESM(require_dist());
|
|
20178
21197
|
var import_marginfi2 = __toESM(require_dist2());
|
|
20179
21198
|
function parseActiveSlots(externalLiquidity) {
|
|
@@ -20186,7 +21205,7 @@ function parseActiveSlots(externalLiquidity) {
|
|
|
20186
21205
|
if (discriminant === 0) continue;
|
|
20187
21206
|
if (discriminant !== 1) continue;
|
|
20188
21207
|
const pubkeyBytes = new Uint8Array(data.slice(8, 40));
|
|
20189
|
-
const userAccount = (0, import_common42.toAddress)(new
|
|
21208
|
+
const userAccount = (0, import_common42.toAddress)(new import_web328.PublicKey(pubkeyBytes));
|
|
20190
21209
|
results.push({ index: i, source: "marginfi", userAccount });
|
|
20191
21210
|
}
|
|
20192
21211
|
return results;
|
|
@@ -20252,7 +21271,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20252
21271
|
return result;
|
|
20253
21272
|
}
|
|
20254
21273
|
const hwManagerAddress = (0, import_common42.fromWeb3Pk)(hwManager.publicKey);
|
|
20255
|
-
const vaultPk = new
|
|
21274
|
+
const vaultPk = new import_web328.PublicKey(vault.toString());
|
|
20256
21275
|
const registeredHwManager = pubkeyStr(
|
|
20257
21276
|
vaultState.roles.hwManager
|
|
20258
21277
|
);
|
|
@@ -20279,7 +21298,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20279
21298
|
continue;
|
|
20280
21299
|
}
|
|
20281
21300
|
for (const holding of holdings) {
|
|
20282
|
-
const mintAddress = (0,
|
|
21301
|
+
const mintAddress = (0, import_kit15.address)(pubkeyStr(holding.mint));
|
|
20283
21302
|
const localAmount = toBigInt2(holding.localAmount);
|
|
20284
21303
|
const marginfiAccounts = (0, import_marginfi2.marginfiAccountsForMint)(mintAddress);
|
|
20285
21304
|
if (!marginfiAccounts) {
|
|
@@ -20395,11 +21414,17 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20395
21414
|
JupiterPriceSource,
|
|
20396
21415
|
JupiterSwapBuilder,
|
|
20397
21416
|
KaminoPositionProvider,
|
|
21417
|
+
LOCAL_PROTOCOL_ADMIN,
|
|
21418
|
+
LivePriceSource,
|
|
20398
21419
|
MAX_PRICE_STALENESS_THRESHOLD_SECS,
|
|
20399
21420
|
ManagerRedepositAssetBuilder,
|
|
20400
21421
|
ManagerWithdrawAssetBuilder,
|
|
20401
21422
|
MarginfiPositionProvider,
|
|
20402
21423
|
MockYieldTracker,
|
|
21424
|
+
NEST_API_BASE_URL,
|
|
21425
|
+
NEST_RWA_SHARE_MINT,
|
|
21426
|
+
NEST_VAULT_SLUG,
|
|
21427
|
+
NestPriceSource,
|
|
20403
21428
|
OracleService,
|
|
20404
21429
|
PROGRAM_FEE_EXEMPT_OWNER_WHITELIST,
|
|
20405
21430
|
PROTOCOL_ADMIN,
|
|
@@ -20442,6 +21467,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20442
21467
|
WithdrawalQueueService,
|
|
20443
21468
|
addCashflowUpdate,
|
|
20444
21469
|
address,
|
|
21470
|
+
applyEffectiveApy,
|
|
20445
21471
|
confirmYieldPayment,
|
|
20446
21472
|
createAccount,
|
|
20447
21473
|
createLiveConsensusOracleDeps,
|
|
@@ -20453,7 +21479,9 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20453
21479
|
dateToStr,
|
|
20454
21480
|
defaultKeypairPath,
|
|
20455
21481
|
deleteAccount,
|
|
21482
|
+
fetchNestTokenPrice,
|
|
20456
21483
|
findSquadsWalletRoute,
|
|
21484
|
+
formatSettlementSimulation,
|
|
20457
21485
|
fromUiAmount,
|
|
20458
21486
|
getAccounts,
|
|
20459
21487
|
getBalance,
|
|
@@ -20474,6 +21502,7 @@ var ExternalLiquidityIntegrityService = class {
|
|
|
20474
21502
|
resolveSquadsWalletRoute,
|
|
20475
21503
|
roundToNextUtcMidnight,
|
|
20476
21504
|
runLiveConsensusOracle,
|
|
21505
|
+
simulateConsensusOracleSettlement,
|
|
20477
21506
|
systemClock,
|
|
20478
21507
|
toUiAmount,
|
|
20479
21508
|
updateAccount,
|