@aspan/sdk 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -4
- package/dist/index.d.mts +245 -8
- package/dist/index.d.ts +245 -8
- package/dist/index.js +278 -8
- package/dist/index.mjs +265 -7
- package/package.json +1 -1
- package/src/__tests__/fork.test.ts +2 -2
- package/src/abi/diamond.ts +74 -0
- package/src/abi/sApUSD.ts +100 -0
- package/src/bot/config.ts +51 -1
- package/src/bot/index.ts +69 -1
- package/src/bot/services/fee-manager.ts +303 -0
- package/src/bot/services/risk-keeper.ts +517 -0
- package/src/client.ts +215 -1
- package/src/index.ts +30 -6
- package/src/router.ts +69 -0
package/dist/index.mjs
CHANGED
|
@@ -476,6 +476,30 @@ var DiamondABI = [
|
|
|
476
476
|
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
477
477
|
stateMutability: "view"
|
|
478
478
|
},
|
|
479
|
+
{
|
|
480
|
+
type: "function",
|
|
481
|
+
name: "bootstrap",
|
|
482
|
+
inputs: [
|
|
483
|
+
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
484
|
+
{ name: "_lstAmount", type: "uint256", internalType: "uint256" }
|
|
485
|
+
],
|
|
486
|
+
outputs: [{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }],
|
|
487
|
+
stateMutability: "nonpayable"
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
type: "function",
|
|
491
|
+
name: "isBootstrapped",
|
|
492
|
+
inputs: [],
|
|
493
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
494
|
+
stateMutability: "view"
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
type: "function",
|
|
498
|
+
name: "getBootstrapXBNBAmount",
|
|
499
|
+
inputs: [],
|
|
500
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
501
|
+
stateMutability: "view"
|
|
502
|
+
},
|
|
479
503
|
// ============ StabilityModeFacet ============
|
|
480
504
|
{
|
|
481
505
|
type: "function",
|
|
@@ -508,6 +532,13 @@ var DiamondABI = [
|
|
|
508
532
|
],
|
|
509
533
|
stateMutability: "nonpayable"
|
|
510
534
|
},
|
|
535
|
+
{
|
|
536
|
+
type: "function",
|
|
537
|
+
name: "cleanXbnb",
|
|
538
|
+
inputs: [{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" }],
|
|
539
|
+
outputs: [],
|
|
540
|
+
stateMutability: "nonpayable"
|
|
541
|
+
},
|
|
511
542
|
// ============ StabilityModeFacet Events ============
|
|
512
543
|
{
|
|
513
544
|
type: "event",
|
|
@@ -527,10 +558,78 @@ var DiamondABI = [
|
|
|
527
558
|
inputs: [],
|
|
528
559
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
529
560
|
stateMutability: "view"
|
|
561
|
+
},
|
|
562
|
+
// ============ Fee Manager ============
|
|
563
|
+
{
|
|
564
|
+
type: "function",
|
|
565
|
+
name: "setFeeManager",
|
|
566
|
+
inputs: [{ name: "_feeManager", type: "address", internalType: "address" }],
|
|
567
|
+
outputs: [],
|
|
568
|
+
stateMutability: "nonpayable"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
type: "function",
|
|
572
|
+
name: "getFeeManager",
|
|
573
|
+
inputs: [],
|
|
574
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
575
|
+
stateMutability: "view"
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
type: "function",
|
|
579
|
+
name: "setFeeTiers",
|
|
580
|
+
inputs: [{
|
|
581
|
+
name: "_tiers",
|
|
582
|
+
type: "tuple[]",
|
|
583
|
+
internalType: "struct LibAppStorage.FeeTier[]",
|
|
584
|
+
components: [
|
|
585
|
+
{ name: "minCR", type: "uint256", internalType: "uint256" },
|
|
586
|
+
{ name: "apUSDMintFee", type: "uint16", internalType: "uint16" },
|
|
587
|
+
{ name: "apUSDRedeemFee", type: "uint16", internalType: "uint16" },
|
|
588
|
+
{ name: "xBNBMintFee", type: "uint16", internalType: "uint16" },
|
|
589
|
+
{ name: "xBNBRedeemFee", type: "uint16", internalType: "uint16" },
|
|
590
|
+
{ name: "apUSDMintDisabled", type: "bool", internalType: "bool" }
|
|
591
|
+
]
|
|
592
|
+
}],
|
|
593
|
+
outputs: [],
|
|
594
|
+
stateMutability: "nonpayable"
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
type: "event",
|
|
598
|
+
name: "FeeManagerSet",
|
|
599
|
+
inputs: [
|
|
600
|
+
{ name: "feeManager", type: "address", indexed: true, internalType: "address" }
|
|
601
|
+
],
|
|
602
|
+
anonymous: false
|
|
530
603
|
}
|
|
531
604
|
];
|
|
532
605
|
|
|
533
606
|
// src/client.ts
|
|
607
|
+
var pharosTestnet = {
|
|
608
|
+
id: 688689,
|
|
609
|
+
name: "Pharos Atlantic Testnet",
|
|
610
|
+
nativeCurrency: { name: "PHRS", symbol: "PHRS", decimals: 18 },
|
|
611
|
+
rpcUrls: {
|
|
612
|
+
default: { http: ["https://atlantic.dplabs-internal.com"] }
|
|
613
|
+
},
|
|
614
|
+
blockExplorers: {
|
|
615
|
+
default: { name: "Pharos Explorer", url: "https://atlantic.pharosscan.xyz" }
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
var CHAIN_IDS = {
|
|
619
|
+
BSC: 56,
|
|
620
|
+
BSC_TESTNET: 97,
|
|
621
|
+
PHAROS: 688689
|
|
622
|
+
};
|
|
623
|
+
var CHAIN_MAP = {
|
|
624
|
+
[CHAIN_IDS.BSC]: bsc,
|
|
625
|
+
[CHAIN_IDS.BSC_TESTNET]: bscTestnet,
|
|
626
|
+
[CHAIN_IDS.PHAROS]: pharosTestnet
|
|
627
|
+
};
|
|
628
|
+
function getChainById(chainId) {
|
|
629
|
+
const chain = CHAIN_MAP[chainId];
|
|
630
|
+
if (!chain) throw new Error(`[Aspan SDK] Unsupported chainId: ${chainId}`);
|
|
631
|
+
return chain;
|
|
632
|
+
}
|
|
534
633
|
var AspanReadClient = class _AspanReadClient {
|
|
535
634
|
publicClient;
|
|
536
635
|
diamondAddress;
|
|
@@ -1171,6 +1270,29 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1171
1270
|
functionName: "isPaused"
|
|
1172
1271
|
});
|
|
1173
1272
|
}
|
|
1273
|
+
// ============ Bootstrap View Functions ============
|
|
1274
|
+
/**
|
|
1275
|
+
* Check if xBNB liquidity has been bootstrapped
|
|
1276
|
+
* @returns true if bootstrap has been called
|
|
1277
|
+
*/
|
|
1278
|
+
async isBootstrapped() {
|
|
1279
|
+
return this.publicClient.readContract({
|
|
1280
|
+
address: this.diamondAddress,
|
|
1281
|
+
abi: DiamondABI,
|
|
1282
|
+
functionName: "isBootstrapped"
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Get the amount of xBNB locked in bootstrap (burned to dead address)
|
|
1287
|
+
* @returns xBNB amount in wei
|
|
1288
|
+
*/
|
|
1289
|
+
async getBootstrapXBNBAmount() {
|
|
1290
|
+
return this.publicClient.readContract({
|
|
1291
|
+
address: this.diamondAddress,
|
|
1292
|
+
abi: DiamondABI,
|
|
1293
|
+
functionName: "getBootstrapXBNBAmount"
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1174
1296
|
// ============ Stability Mode View Functions ============
|
|
1175
1297
|
async getStabilityMode() {
|
|
1176
1298
|
try {
|
|
@@ -1370,6 +1492,75 @@ var AspanClient = class extends AspanReadClient {
|
|
|
1370
1492
|
functionName: "harvestYield"
|
|
1371
1493
|
});
|
|
1372
1494
|
}
|
|
1495
|
+
// ============ Risk Management Functions ============
|
|
1496
|
+
/**
|
|
1497
|
+
* Trigger Stability Mode 2 forced conversion
|
|
1498
|
+
* @description Anyone can call when CR < 130%. Burns apUSD from stability pool
|
|
1499
|
+
* and mints xBNB to compensate stakers.
|
|
1500
|
+
* @param targetCR Target CR to restore to (in BPS, e.g., 14000 = 140%)
|
|
1501
|
+
* @returns Transaction hash
|
|
1502
|
+
*/
|
|
1503
|
+
async triggerStabilityMode2(targetCR = 14000n) {
|
|
1504
|
+
return this.walletClient.writeContract({
|
|
1505
|
+
chain: this.chain,
|
|
1506
|
+
account: this.walletClient.account,
|
|
1507
|
+
address: this.diamondAddress,
|
|
1508
|
+
abi: DiamondABI,
|
|
1509
|
+
functionName: "triggerStabilityMode2",
|
|
1510
|
+
args: [targetCR]
|
|
1511
|
+
});
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Clean underwater xBNB (burn without getting LST back)
|
|
1515
|
+
* @description Only works when xBNB is underwater (price = 0)
|
|
1516
|
+
* @param xBNBAmount Amount of xBNB to clean (burn)
|
|
1517
|
+
* @returns Transaction hash
|
|
1518
|
+
*/
|
|
1519
|
+
async cleanXbnb(xBNBAmount) {
|
|
1520
|
+
return this.walletClient.writeContract({
|
|
1521
|
+
chain: this.chain,
|
|
1522
|
+
account: this.walletClient.account,
|
|
1523
|
+
address: this.diamondAddress,
|
|
1524
|
+
abi: DiamondABI,
|
|
1525
|
+
functionName: "cleanXbnb",
|
|
1526
|
+
args: [xBNBAmount]
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
// ============ Fee Management Functions ============
|
|
1530
|
+
/**
|
|
1531
|
+
* Set fee tiers (requires feeManager or owner role)
|
|
1532
|
+
* @param tiers Array of fee tier configurations
|
|
1533
|
+
* @returns Transaction hash
|
|
1534
|
+
*/
|
|
1535
|
+
async setFeeTiers(tiers) {
|
|
1536
|
+
return this.walletClient.writeContract({
|
|
1537
|
+
chain: this.chain,
|
|
1538
|
+
account: this.walletClient.account,
|
|
1539
|
+
address: this.diamondAddress,
|
|
1540
|
+
abi: DiamondABI,
|
|
1541
|
+
functionName: "setFeeTiers",
|
|
1542
|
+
args: [tiers]
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
// ============ Admin Functions ============
|
|
1546
|
+
/**
|
|
1547
|
+
* Bootstrap xBNB liquidity (owner only)
|
|
1548
|
+
* @description Initializes xBNB supply by minting to dead address, preventing extreme initial prices.
|
|
1549
|
+
* Similar to Uniswap V2's MINIMUM_LIQUIDITY. Can only be called once.
|
|
1550
|
+
* @param lstToken LST token address to deposit
|
|
1551
|
+
* @param lstAmount Amount of LST to deposit for bootstrap
|
|
1552
|
+
* @returns Transaction hash
|
|
1553
|
+
*/
|
|
1554
|
+
async bootstrap(lstToken, lstAmount) {
|
|
1555
|
+
return this.walletClient.writeContract({
|
|
1556
|
+
chain: this.chain,
|
|
1557
|
+
account: this.walletClient.account,
|
|
1558
|
+
address: this.diamondAddress,
|
|
1559
|
+
abi: DiamondABI,
|
|
1560
|
+
functionName: "bootstrap",
|
|
1561
|
+
args: [lstToken, lstAmount]
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1373
1564
|
// ============ Transaction Helpers ============
|
|
1374
1565
|
/**
|
|
1375
1566
|
* Wait for transaction confirmation
|
|
@@ -1410,6 +1601,29 @@ function createAspanTestnetClient(diamondAddress, account, rpcUrl) {
|
|
|
1410
1601
|
rpcUrl
|
|
1411
1602
|
});
|
|
1412
1603
|
}
|
|
1604
|
+
function createAspanPharosReadClient(diamondAddress, rpcUrl) {
|
|
1605
|
+
return new AspanReadClient({
|
|
1606
|
+
diamondAddress,
|
|
1607
|
+
chain: pharosTestnet,
|
|
1608
|
+
rpcUrl
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
function createAspanPharosClient(diamondAddress, account, rpcUrl) {
|
|
1612
|
+
return new AspanClient({
|
|
1613
|
+
diamondAddress,
|
|
1614
|
+
account,
|
|
1615
|
+
chain: pharosTestnet,
|
|
1616
|
+
rpcUrl
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
function createAspanReadClientForChain(diamondAddress, chainId = CHAIN_IDS.BSC, rpcUrl) {
|
|
1620
|
+
const chain = getChainById(chainId);
|
|
1621
|
+
return new AspanReadClient({ diamondAddress, chain, rpcUrl });
|
|
1622
|
+
}
|
|
1623
|
+
function createAspanWriteClientForChain(diamondAddress, chainId = CHAIN_IDS.BSC, walletClient, rpcUrl) {
|
|
1624
|
+
const chain = getChainById(chainId);
|
|
1625
|
+
return new AspanClient({ diamondAddress, chain, walletClient, rpcUrl });
|
|
1626
|
+
}
|
|
1413
1627
|
|
|
1414
1628
|
// src/router.ts
|
|
1415
1629
|
import {
|
|
@@ -2181,6 +2395,29 @@ function createRouterTestnetClient(routerAddress, account, rpcUrl) {
|
|
|
2181
2395
|
rpcUrl
|
|
2182
2396
|
});
|
|
2183
2397
|
}
|
|
2398
|
+
function createRouterPharosReadClient(routerAddress, rpcUrl) {
|
|
2399
|
+
return new AspanRouterReadClient({
|
|
2400
|
+
routerAddress,
|
|
2401
|
+
chain: pharosTestnet,
|
|
2402
|
+
rpcUrl
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
function createRouterPharosClient(routerAddress, account, rpcUrl) {
|
|
2406
|
+
return new AspanRouterClient({
|
|
2407
|
+
routerAddress,
|
|
2408
|
+
account,
|
|
2409
|
+
chain: pharosTestnet,
|
|
2410
|
+
rpcUrl
|
|
2411
|
+
});
|
|
2412
|
+
}
|
|
2413
|
+
function createRouterReadClientForChain(routerAddress, chainId = CHAIN_IDS.BSC, rpcUrl) {
|
|
2414
|
+
const chain = getChainById(chainId);
|
|
2415
|
+
return new AspanRouterReadClient({ routerAddress, chain, rpcUrl });
|
|
2416
|
+
}
|
|
2417
|
+
function createRouterWriteClientForChain(routerAddress, chainId = CHAIN_IDS.BSC, walletClient, rpcUrl) {
|
|
2418
|
+
const chain = getChainById(chainId);
|
|
2419
|
+
return new AspanRouterClient({ routerAddress, chain, walletClient, rpcUrl });
|
|
2420
|
+
}
|
|
2184
2421
|
|
|
2185
2422
|
// src/types.ts
|
|
2186
2423
|
function encodeV3Path(tokens, fees) {
|
|
@@ -2200,20 +2437,29 @@ var PRECISION = 10n ** 18n;
|
|
|
2200
2437
|
var BPS_PRECISION = 10000n;
|
|
2201
2438
|
var PRICE_PRECISION = 10n ** 8n;
|
|
2202
2439
|
var BSC_ADDRESSES = {
|
|
2203
|
-
diamond: "
|
|
2204
|
-
router: "
|
|
2205
|
-
apUSD: "
|
|
2206
|
-
xBNB: "
|
|
2207
|
-
sApUSD: "
|
|
2440
|
+
diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
|
|
2441
|
+
router: "0x29dd49b2e98674ee7531f17e4d40a7725918c3f6",
|
|
2442
|
+
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
|
|
2443
|
+
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
|
|
2444
|
+
sApUSD: "0x73407A291c007a47CC926EcD5CaC256A1E2d00cF",
|
|
2208
2445
|
// LSTs
|
|
2209
2446
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
|
|
2210
2447
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6",
|
|
2211
|
-
wclisBNB: "
|
|
2448
|
+
wclisBNB: "0x448f7c2fa4e5135a4a5B50879602cf3CD428e108",
|
|
2212
2449
|
// Stablecoins
|
|
2213
2450
|
USDT: "0x55d398326f99059fF775485246999027B3197955",
|
|
2214
2451
|
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
2215
2452
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"
|
|
2216
2453
|
};
|
|
2454
|
+
var PHAROS_ADDRESSES = {
|
|
2455
|
+
diamond: "0x67011Ce4B5E534FA78dD9922559B7005197DBcc8",
|
|
2456
|
+
apUSD: "0x82ac96db027772cE8a770e099370b5D7941B3ae4",
|
|
2457
|
+
xBNB: "0xFF43b2f50b2c6c588d14Ea4565Ee5Eb93e438576",
|
|
2458
|
+
sApUSD: "0xFA4B826CfD5faaAfA48E4963d8a7d6Cf9889A9A8",
|
|
2459
|
+
mockLST: "0xc7BB55759e8e04AfAA620De96E9E133B1FAd3e18",
|
|
2460
|
+
mockPriceFeed: "0xa2B41DDE7a7BB0A897DE476Ea441fB27A6978682",
|
|
2461
|
+
mockExchangeRate: "0xffA1938e072Ea3b144EA7e61662dd8B0818D82B9"
|
|
2462
|
+
};
|
|
2217
2463
|
function formatAmount(amount, decimals = 4) {
|
|
2218
2464
|
const divisor = 10n ** BigInt(18 - decimals);
|
|
2219
2465
|
const scaled = amount / divisor;
|
|
@@ -2252,23 +2498,35 @@ export {
|
|
|
2252
2498
|
AspanRouterReadClient,
|
|
2253
2499
|
BPS_PRECISION,
|
|
2254
2500
|
BSC_ADDRESSES,
|
|
2501
|
+
CHAIN_IDS,
|
|
2255
2502
|
DiamondABI,
|
|
2503
|
+
PHAROS_ADDRESSES,
|
|
2256
2504
|
PRECISION,
|
|
2257
2505
|
PRICE_PRECISION,
|
|
2258
2506
|
RouterABI,
|
|
2259
2507
|
calculateAPY,
|
|
2260
2508
|
createAspanClient,
|
|
2509
|
+
createAspanPharosClient,
|
|
2510
|
+
createAspanPharosReadClient,
|
|
2261
2511
|
createAspanReadClient,
|
|
2512
|
+
createAspanReadClientForChain,
|
|
2262
2513
|
createAspanTestnetClient,
|
|
2263
2514
|
createAspanTestnetReadClient,
|
|
2515
|
+
createAspanWriteClientForChain,
|
|
2264
2516
|
createRouterClient,
|
|
2517
|
+
createRouterPharosClient,
|
|
2518
|
+
createRouterPharosReadClient,
|
|
2265
2519
|
createRouterReadClient,
|
|
2520
|
+
createRouterReadClientForChain,
|
|
2266
2521
|
createRouterTestnetClient,
|
|
2267
2522
|
createRouterTestnetReadClient,
|
|
2523
|
+
createRouterWriteClientForChain,
|
|
2268
2524
|
encodeV3Path,
|
|
2269
2525
|
formatAmount,
|
|
2270
2526
|
formatCR,
|
|
2271
2527
|
formatFeeBPS,
|
|
2272
2528
|
formatPriceUSD,
|
|
2273
|
-
|
|
2529
|
+
getChainById,
|
|
2530
|
+
parseAmount,
|
|
2531
|
+
pharosTestnet
|
|
2274
2532
|
};
|
package/package.json
CHANGED
|
@@ -27,8 +27,8 @@ const TOKENS = {
|
|
|
27
27
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" as Address,
|
|
28
28
|
USDT: "0x55d398326f99059fF775485246999027B3197955" as Address,
|
|
29
29
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B" as Address,
|
|
30
|
-
apUSD: "
|
|
31
|
-
xBNB: "
|
|
30
|
+
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as Address,
|
|
31
|
+
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as Address,
|
|
32
32
|
};
|
|
33
33
|
|
|
34
34
|
const ERC20_ABI = [
|
package/src/abi/diamond.ts
CHANGED
|
@@ -477,6 +477,30 @@ export const DiamondABI = [
|
|
|
477
477
|
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
478
478
|
stateMutability: "view"
|
|
479
479
|
},
|
|
480
|
+
{
|
|
481
|
+
type: "function",
|
|
482
|
+
name: "bootstrap",
|
|
483
|
+
inputs: [
|
|
484
|
+
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
485
|
+
{ name: "_lstAmount", type: "uint256", internalType: "uint256" }
|
|
486
|
+
],
|
|
487
|
+
outputs: [{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }],
|
|
488
|
+
stateMutability: "nonpayable"
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
type: "function",
|
|
492
|
+
name: "isBootstrapped",
|
|
493
|
+
inputs: [],
|
|
494
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
495
|
+
stateMutability: "view"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
type: "function",
|
|
499
|
+
name: "getBootstrapXBNBAmount",
|
|
500
|
+
inputs: [],
|
|
501
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
502
|
+
stateMutability: "view"
|
|
503
|
+
},
|
|
480
504
|
|
|
481
505
|
// ============ StabilityModeFacet ============
|
|
482
506
|
{
|
|
@@ -510,6 +534,13 @@ export const DiamondABI = [
|
|
|
510
534
|
],
|
|
511
535
|
stateMutability: "nonpayable"
|
|
512
536
|
},
|
|
537
|
+
{
|
|
538
|
+
type: "function",
|
|
539
|
+
name: "cleanXbnb",
|
|
540
|
+
inputs: [{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" }],
|
|
541
|
+
outputs: [],
|
|
542
|
+
stateMutability: "nonpayable"
|
|
543
|
+
},
|
|
513
544
|
|
|
514
545
|
// ============ StabilityModeFacet Events ============
|
|
515
546
|
{
|
|
@@ -531,5 +562,48 @@ export const DiamondABI = [
|
|
|
531
562
|
inputs: [],
|
|
532
563
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
533
564
|
stateMutability: "view"
|
|
565
|
+
},
|
|
566
|
+
|
|
567
|
+
// ============ Fee Manager ============
|
|
568
|
+
{
|
|
569
|
+
type: "function",
|
|
570
|
+
name: "setFeeManager",
|
|
571
|
+
inputs: [{ name: "_feeManager", type: "address", internalType: "address" }],
|
|
572
|
+
outputs: [],
|
|
573
|
+
stateMutability: "nonpayable"
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
type: "function",
|
|
577
|
+
name: "getFeeManager",
|
|
578
|
+
inputs: [],
|
|
579
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
580
|
+
stateMutability: "view"
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
type: "function",
|
|
584
|
+
name: "setFeeTiers",
|
|
585
|
+
inputs: [{
|
|
586
|
+
name: "_tiers",
|
|
587
|
+
type: "tuple[]",
|
|
588
|
+
internalType: "struct LibAppStorage.FeeTier[]",
|
|
589
|
+
components: [
|
|
590
|
+
{ name: "minCR", type: "uint256", internalType: "uint256" },
|
|
591
|
+
{ name: "apUSDMintFee", type: "uint16", internalType: "uint16" },
|
|
592
|
+
{ name: "apUSDRedeemFee", type: "uint16", internalType: "uint16" },
|
|
593
|
+
{ name: "xBNBMintFee", type: "uint16", internalType: "uint16" },
|
|
594
|
+
{ name: "xBNBRedeemFee", type: "uint16", internalType: "uint16" },
|
|
595
|
+
{ name: "apUSDMintDisabled", type: "bool", internalType: "bool" }
|
|
596
|
+
]
|
|
597
|
+
}],
|
|
598
|
+
outputs: [],
|
|
599
|
+
stateMutability: "nonpayable"
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
type: "event",
|
|
603
|
+
name: "FeeManagerSet",
|
|
604
|
+
inputs: [
|
|
605
|
+
{ name: "feeManager", type: "address", indexed: true, internalType: "address" }
|
|
606
|
+
],
|
|
607
|
+
anonymous: false
|
|
534
608
|
}
|
|
535
609
|
] as const;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SApUSD (Staked ApUSD) Vault ABI
|
|
3
|
+
* Multi-asset vault for staking apUSD and absorbing xBNB during stability events
|
|
4
|
+
*/
|
|
5
|
+
export const SApUSDABI = [
|
|
6
|
+
// ============ View Functions ============
|
|
7
|
+
{
|
|
8
|
+
type: "function",
|
|
9
|
+
name: "totalAssets",
|
|
10
|
+
inputs: [],
|
|
11
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
12
|
+
stateMutability: "view"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
type: "function",
|
|
16
|
+
name: "totalSupply",
|
|
17
|
+
inputs: [],
|
|
18
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
19
|
+
stateMutability: "view"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: "function",
|
|
23
|
+
name: "balanceOf",
|
|
24
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
25
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
26
|
+
stateMutability: "view"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
type: "function",
|
|
30
|
+
name: "hasStabilityConversion",
|
|
31
|
+
inputs: [],
|
|
32
|
+
outputs: [
|
|
33
|
+
{ name: "hasXBNB", type: "bool", internalType: "bool" },
|
|
34
|
+
{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
35
|
+
],
|
|
36
|
+
stateMutability: "view"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: "function",
|
|
40
|
+
name: "exchangeRate",
|
|
41
|
+
inputs: [],
|
|
42
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
43
|
+
stateMutability: "view"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: "function",
|
|
47
|
+
name: "previewCleanXBNB",
|
|
48
|
+
inputs: [
|
|
49
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
50
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
51
|
+
{ name: "_path", type: "address[]", internalType: "address[]" }
|
|
52
|
+
],
|
|
53
|
+
outputs: [{ name: "expectedApUSD", type: "uint256", internalType: "uint256" }],
|
|
54
|
+
stateMutability: "view"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: "function",
|
|
58
|
+
name: "KEEPER_ROLE",
|
|
59
|
+
inputs: [],
|
|
60
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
61
|
+
stateMutability: "view"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
type: "function",
|
|
65
|
+
name: "hasRole",
|
|
66
|
+
inputs: [
|
|
67
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
68
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
69
|
+
],
|
|
70
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
71
|
+
stateMutability: "view"
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
// ============ Keeper Functions ============
|
|
75
|
+
{
|
|
76
|
+
type: "function",
|
|
77
|
+
name: "cleanXBNB",
|
|
78
|
+
inputs: [
|
|
79
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
80
|
+
{ name: "_minApUSDOut", type: "uint256", internalType: "uint256" },
|
|
81
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
82
|
+
{ name: "_path", type: "address[]", internalType: "address[]" },
|
|
83
|
+
{ name: "_deadline", type: "uint256", internalType: "uint256" }
|
|
84
|
+
],
|
|
85
|
+
outputs: [{ name: "apUSDReceived", type: "uint256", internalType: "uint256" }],
|
|
86
|
+
stateMutability: "nonpayable"
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
// ============ Events ============
|
|
90
|
+
{
|
|
91
|
+
type: "event",
|
|
92
|
+
name: "VaultCleaned",
|
|
93
|
+
inputs: [
|
|
94
|
+
{ name: "xBNBSold", type: "uint256", indexed: false, internalType: "uint256" },
|
|
95
|
+
{ name: "apUSDReceived", type: "uint256", indexed: false, internalType: "uint256" },
|
|
96
|
+
{ name: "keeper", type: "address", indexed: true, internalType: "address" }
|
|
97
|
+
],
|
|
98
|
+
anonymous: false
|
|
99
|
+
}
|
|
100
|
+
] as const;
|
package/src/bot/config.ts
CHANGED
|
@@ -32,6 +32,29 @@ export interface BotConfig {
|
|
|
32
32
|
maxRetries: number;
|
|
33
33
|
retryDelayMs: number;
|
|
34
34
|
retryBackoffMultiplier: number;
|
|
35
|
+
|
|
36
|
+
// Risk Keeper Configuration (optional)
|
|
37
|
+
riskKeeper?: {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
sApUSDAddress: Address;
|
|
40
|
+
routerAddress: Address;
|
|
41
|
+
wbnbAddress: Address;
|
|
42
|
+
privateKey: `0x${string}`;
|
|
43
|
+
sm2CooldownMs: number;
|
|
44
|
+
sm2MaxPoolPercent: number;
|
|
45
|
+
twapIntervalMs: number;
|
|
46
|
+
twapPercentage: number;
|
|
47
|
+
maxSlippageBps: number;
|
|
48
|
+
twapStartCR: bigint;
|
|
49
|
+
maxVolatilityPercent: number;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Fee Manager Configuration (optional)
|
|
53
|
+
feeManager?: {
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
privateKey: `0x${string}`;
|
|
56
|
+
checkIntervalMs: number;
|
|
57
|
+
};
|
|
35
58
|
}
|
|
36
59
|
|
|
37
60
|
export function loadConfig(): BotConfig {
|
|
@@ -50,7 +73,7 @@ export function loadConfig(): BotConfig {
|
|
|
50
73
|
|
|
51
74
|
// Contract
|
|
52
75
|
diamondAddress: (process.env.DIAMOND_ADDRESS ??
|
|
53
|
-
"
|
|
76
|
+
"0x6a11B30d3a70727d5477D6d8090e144443fA1c78") as Address,
|
|
54
77
|
|
|
55
78
|
// Intervals
|
|
56
79
|
statsReportInterval: parseInt(
|
|
@@ -80,5 +103,32 @@ export function loadConfig(): BotConfig {
|
|
|
80
103
|
maxRetries: parseInt(process.env.MAX_RETRIES ?? "3", 10),
|
|
81
104
|
retryDelayMs: parseInt(process.env.RETRY_DELAY_MS ?? "1000", 10),
|
|
82
105
|
retryBackoffMultiplier: parseFloat(process.env.RETRY_BACKOFF ?? "2"),
|
|
106
|
+
|
|
107
|
+
// Risk Keeper (optional - only enabled if private key is provided)
|
|
108
|
+
riskKeeper: process.env.KEEPER_PRIVATE_KEY
|
|
109
|
+
? {
|
|
110
|
+
enabled: process.env.RISK_KEEPER_ENABLED === "true",
|
|
111
|
+
sApUSDAddress: (process.env.SAPUSD_ADDRESS ?? "") as Address,
|
|
112
|
+
routerAddress: (process.env.ROUTER_ADDRESS ?? "0x10ED43C718714eb63d5aA57B78B54704E256024E") as Address, // PancakeSwap V2
|
|
113
|
+
wbnbAddress: (process.env.WBNB_ADDRESS ?? "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c") as Address,
|
|
114
|
+
privateKey: process.env.KEEPER_PRIVATE_KEY as `0x${string}`,
|
|
115
|
+
sm2CooldownMs: parseInt(process.env.SM2_COOLDOWN_MS ?? "1800000", 10), // 30 min
|
|
116
|
+
sm2MaxPoolPercent: parseInt(process.env.SM2_MAX_POOL_PERCENT ?? "40", 10), // 40%
|
|
117
|
+
twapIntervalMs: parseInt(process.env.TWAP_INTERVAL_MS ?? "600000", 10), // 10 min
|
|
118
|
+
twapPercentage: parseInt(process.env.TWAP_PERCENTAGE ?? "5", 10), // 5%
|
|
119
|
+
maxSlippageBps: parseInt(process.env.MAX_SLIPPAGE_BPS ?? "50", 10), // 0.5%
|
|
120
|
+
twapStartCR: BigInt(process.env.TWAP_START_CR ?? "13500"), // 135%
|
|
121
|
+
maxVolatilityPercent: parseInt(process.env.MAX_VOLATILITY_PERCENT ?? "5", 10), // 5%
|
|
122
|
+
}
|
|
123
|
+
: undefined,
|
|
124
|
+
|
|
125
|
+
// Fee Manager (optional - uses same or different private key)
|
|
126
|
+
feeManager: process.env.FEE_MANAGER_ENABLED === "true" && process.env.FEE_MANAGER_PRIVATE_KEY
|
|
127
|
+
? {
|
|
128
|
+
enabled: true,
|
|
129
|
+
privateKey: process.env.FEE_MANAGER_PRIVATE_KEY as `0x${string}`,
|
|
130
|
+
checkIntervalMs: parseInt(process.env.FEE_CHECK_INTERVAL_MS ?? "60000", 10), // 1 min
|
|
131
|
+
}
|
|
132
|
+
: undefined,
|
|
83
133
|
};
|
|
84
134
|
}
|