@aspan/sdk 0.4.3 → 0.4.5
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.mts +130 -7
- package/dist/index.d.ts +130 -7
- package/dist/index.js +322 -9
- package/dist/index.mjs +322 -9
- package/package.json +1 -1
- package/src/__tests__/read-client.test.ts +212 -0
- package/src/abi/diamond.ts +45 -3
- package/src/abi/sApUSD.ts +36 -0
- package/src/client.ts +182 -6
- package/src/index.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -405,6 +405,13 @@ var DiamondABI = [
|
|
|
405
405
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
406
406
|
stateMutability: "view"
|
|
407
407
|
},
|
|
408
|
+
{
|
|
409
|
+
type: "function",
|
|
410
|
+
name: "setSApUSD",
|
|
411
|
+
inputs: [{ name: "_sApUSD", type: "address", internalType: "address" }],
|
|
412
|
+
outputs: [],
|
|
413
|
+
stateMutability: "nonpayable"
|
|
414
|
+
},
|
|
408
415
|
{
|
|
409
416
|
type: "function",
|
|
410
417
|
name: "getStabilityPool",
|
|
@@ -426,6 +433,25 @@ var DiamondABI = [
|
|
|
426
433
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
427
434
|
stateMutability: "view"
|
|
428
435
|
},
|
|
436
|
+
{
|
|
437
|
+
type: "function",
|
|
438
|
+
name: "getAllFeeTiers",
|
|
439
|
+
inputs: [],
|
|
440
|
+
outputs: [{
|
|
441
|
+
name: "",
|
|
442
|
+
type: "tuple[]",
|
|
443
|
+
internalType: "struct LibAppStorage.FeeTier[]",
|
|
444
|
+
components: [
|
|
445
|
+
{ name: "minCR", type: "uint256", internalType: "uint256" },
|
|
446
|
+
{ name: "apUSDMintFee", type: "uint16", internalType: "uint16" },
|
|
447
|
+
{ name: "apUSDRedeemFee", type: "uint16", internalType: "uint16" },
|
|
448
|
+
{ name: "xBNBMintFee", type: "uint16", internalType: "uint16" },
|
|
449
|
+
{ name: "xBNBRedeemFee", type: "uint16", internalType: "uint16" },
|
|
450
|
+
{ name: "apUSDMintDisabled", type: "bool", internalType: "bool" }
|
|
451
|
+
]
|
|
452
|
+
}],
|
|
453
|
+
stateMutability: "view"
|
|
454
|
+
},
|
|
429
455
|
{
|
|
430
456
|
type: "function",
|
|
431
457
|
name: "getFeeTier",
|
|
@@ -534,11 +560,27 @@ var DiamondABI = [
|
|
|
534
560
|
},
|
|
535
561
|
{
|
|
536
562
|
type: "function",
|
|
537
|
-
name: "
|
|
538
|
-
inputs: [
|
|
539
|
-
|
|
563
|
+
name: "cleanVaultXBNB",
|
|
564
|
+
inputs: [
|
|
565
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
566
|
+
{ name: "_minApUSDOut", type: "uint256", internalType: "uint256" }
|
|
567
|
+
],
|
|
568
|
+
outputs: [
|
|
569
|
+
{ name: "apUSDMinted", type: "uint256", internalType: "uint256" }
|
|
570
|
+
],
|
|
540
571
|
stateMutability: "nonpayable"
|
|
541
572
|
},
|
|
573
|
+
{
|
|
574
|
+
type: "function",
|
|
575
|
+
name: "previewCleanVaultXBNB",
|
|
576
|
+
inputs: [
|
|
577
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
578
|
+
],
|
|
579
|
+
outputs: [
|
|
580
|
+
{ name: "apUSDOut", type: "uint256", internalType: "uint256" }
|
|
581
|
+
],
|
|
582
|
+
stateMutability: "view"
|
|
583
|
+
},
|
|
542
584
|
// ============ StabilityModeFacet Events ============
|
|
543
585
|
{
|
|
544
586
|
type: "event",
|
|
@@ -603,6 +645,138 @@ var DiamondABI = [
|
|
|
603
645
|
}
|
|
604
646
|
];
|
|
605
647
|
|
|
648
|
+
// src/abi/sApUSD.ts
|
|
649
|
+
var SApUSDABI = [
|
|
650
|
+
// ============ View Functions ============
|
|
651
|
+
{
|
|
652
|
+
type: "function",
|
|
653
|
+
name: "totalAssets",
|
|
654
|
+
inputs: [],
|
|
655
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
656
|
+
stateMutability: "view"
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
type: "function",
|
|
660
|
+
name: "totalSupply",
|
|
661
|
+
inputs: [],
|
|
662
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
663
|
+
stateMutability: "view"
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
type: "function",
|
|
667
|
+
name: "balanceOf",
|
|
668
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
669
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
670
|
+
stateMutability: "view"
|
|
671
|
+
},
|
|
672
|
+
{
|
|
673
|
+
type: "function",
|
|
674
|
+
name: "previewRedeemMulti",
|
|
675
|
+
inputs: [
|
|
676
|
+
{ name: "shares", type: "uint256", internalType: "uint256" }
|
|
677
|
+
],
|
|
678
|
+
outputs: [
|
|
679
|
+
{ name: "assets", type: "address[]", internalType: "address[]" },
|
|
680
|
+
{ name: "amounts", type: "uint256[]", internalType: "uint256[]" }
|
|
681
|
+
],
|
|
682
|
+
stateMutability: "view"
|
|
683
|
+
},
|
|
684
|
+
{
|
|
685
|
+
type: "function",
|
|
686
|
+
name: "hasStabilityConversion",
|
|
687
|
+
inputs: [],
|
|
688
|
+
outputs: [
|
|
689
|
+
{ name: "hasXBNB", type: "bool", internalType: "bool" },
|
|
690
|
+
{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
691
|
+
],
|
|
692
|
+
stateMutability: "view"
|
|
693
|
+
},
|
|
694
|
+
{
|
|
695
|
+
type: "function",
|
|
696
|
+
name: "totalValue",
|
|
697
|
+
inputs: [],
|
|
698
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
699
|
+
stateMutability: "view"
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
type: "function",
|
|
703
|
+
name: "underlyingBalances",
|
|
704
|
+
inputs: [{ name: "_user", type: "address", internalType: "address" }],
|
|
705
|
+
outputs: [
|
|
706
|
+
{ name: "apUSDBalance", type: "uint256", internalType: "uint256" },
|
|
707
|
+
{ name: "xBNBBalance", type: "uint256", internalType: "uint256" }
|
|
708
|
+
],
|
|
709
|
+
stateMutability: "view"
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
type: "function",
|
|
713
|
+
name: "xBNBToApUSDRate",
|
|
714
|
+
inputs: [],
|
|
715
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
716
|
+
stateMutability: "view"
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
type: "function",
|
|
720
|
+
name: "exchangeRate",
|
|
721
|
+
inputs: [],
|
|
722
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
723
|
+
stateMutability: "view"
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
type: "function",
|
|
727
|
+
name: "previewCleanXBNB",
|
|
728
|
+
inputs: [
|
|
729
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
730
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
731
|
+
{ name: "_path", type: "address[]", internalType: "address[]" }
|
|
732
|
+
],
|
|
733
|
+
outputs: [{ name: "expectedApUSD", type: "uint256", internalType: "uint256" }],
|
|
734
|
+
stateMutability: "view"
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
type: "function",
|
|
738
|
+
name: "KEEPER_ROLE",
|
|
739
|
+
inputs: [],
|
|
740
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
741
|
+
stateMutability: "view"
|
|
742
|
+
},
|
|
743
|
+
{
|
|
744
|
+
type: "function",
|
|
745
|
+
name: "hasRole",
|
|
746
|
+
inputs: [
|
|
747
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
748
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
749
|
+
],
|
|
750
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
751
|
+
stateMutability: "view"
|
|
752
|
+
},
|
|
753
|
+
// ============ Keeper Functions ============
|
|
754
|
+
{
|
|
755
|
+
type: "function",
|
|
756
|
+
name: "cleanXBNB",
|
|
757
|
+
inputs: [
|
|
758
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
759
|
+
{ name: "_minApUSDOut", type: "uint256", internalType: "uint256" },
|
|
760
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
761
|
+
{ name: "_path", type: "address[]", internalType: "address[]" },
|
|
762
|
+
{ name: "_deadline", type: "uint256", internalType: "uint256" }
|
|
763
|
+
],
|
|
764
|
+
outputs: [{ name: "apUSDReceived", type: "uint256", internalType: "uint256" }],
|
|
765
|
+
stateMutability: "nonpayable"
|
|
766
|
+
},
|
|
767
|
+
// ============ Events ============
|
|
768
|
+
{
|
|
769
|
+
type: "event",
|
|
770
|
+
name: "VaultCleaned",
|
|
771
|
+
inputs: [
|
|
772
|
+
{ name: "xBNBSold", type: "uint256", indexed: false, internalType: "uint256" },
|
|
773
|
+
{ name: "apUSDReceived", type: "uint256", indexed: false, internalType: "uint256" },
|
|
774
|
+
{ name: "keeper", type: "address", indexed: true, internalType: "address" }
|
|
775
|
+
],
|
|
776
|
+
anonymous: false
|
|
777
|
+
}
|
|
778
|
+
];
|
|
779
|
+
|
|
606
780
|
// src/client.ts
|
|
607
781
|
var pharosTestnet = {
|
|
608
782
|
id: 688689,
|
|
@@ -996,6 +1170,19 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
996
1170
|
args: [user]
|
|
997
1171
|
});
|
|
998
1172
|
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Get user's underlying balances (apUSD + xBNB) from sApUSD vault
|
|
1175
|
+
*/
|
|
1176
|
+
async getBalanceMulti(user) {
|
|
1177
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1178
|
+
const [apUSDBalance, xBNBBalance] = await this.publicClient.readContract({
|
|
1179
|
+
address: sApUSDAddress,
|
|
1180
|
+
abi: SApUSDABI,
|
|
1181
|
+
functionName: "underlyingBalances",
|
|
1182
|
+
args: [user]
|
|
1183
|
+
});
|
|
1184
|
+
return { apUSDBalance, xBNBBalance };
|
|
1185
|
+
}
|
|
999
1186
|
async getUserStabilityPoolPosition(user) {
|
|
1000
1187
|
const [shares, balance] = await Promise.all([
|
|
1001
1188
|
this.getShares(user),
|
|
@@ -1061,6 +1248,32 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1061
1248
|
throw error;
|
|
1062
1249
|
}
|
|
1063
1250
|
}
|
|
1251
|
+
/**
|
|
1252
|
+
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
1253
|
+
* @param shares Amount of sApUSD shares to redeem
|
|
1254
|
+
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
1255
|
+
*/
|
|
1256
|
+
async previewRedeemMulti(shares) {
|
|
1257
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1258
|
+
const [result, conversion] = await Promise.all([
|
|
1259
|
+
this.publicClient.readContract({
|
|
1260
|
+
address: sApUSDAddress,
|
|
1261
|
+
abi: SApUSDABI,
|
|
1262
|
+
functionName: "previewRedeemMulti",
|
|
1263
|
+
args: [shares]
|
|
1264
|
+
}),
|
|
1265
|
+
this.publicClient.readContract({
|
|
1266
|
+
address: sApUSDAddress,
|
|
1267
|
+
abi: SApUSDABI,
|
|
1268
|
+
functionName: "hasStabilityConversion"
|
|
1269
|
+
})
|
|
1270
|
+
]);
|
|
1271
|
+
return {
|
|
1272
|
+
apUSD: result[1][0],
|
|
1273
|
+
xBNB: result[1][1],
|
|
1274
|
+
hasXBNB: conversion[0]
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1064
1277
|
async getPendingYield() {
|
|
1065
1278
|
try {
|
|
1066
1279
|
return await this.publicClient.readContract({
|
|
@@ -1214,6 +1427,93 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1214
1427
|
apUSDMintDisabled: result[5]
|
|
1215
1428
|
};
|
|
1216
1429
|
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Get all fee tiers
|
|
1432
|
+
* @returns Array of fee tiers sorted by minCR descending
|
|
1433
|
+
*/
|
|
1434
|
+
async getAllFeeTiers() {
|
|
1435
|
+
const result = await this.publicClient.readContract({
|
|
1436
|
+
address: this.diamondAddress,
|
|
1437
|
+
abi: DiamondABI,
|
|
1438
|
+
functionName: "getAllFeeTiers"
|
|
1439
|
+
});
|
|
1440
|
+
return result.map((tier) => ({
|
|
1441
|
+
minCR: tier.minCR,
|
|
1442
|
+
apUSDMintFee: tier.apUSDMintFee,
|
|
1443
|
+
apUSDRedeemFee: tier.apUSDRedeemFee,
|
|
1444
|
+
xBNBMintFee: tier.xBNBMintFee,
|
|
1445
|
+
xBNBRedeemFee: tier.xBNBRedeemFee,
|
|
1446
|
+
apUSDMintDisabled: tier.apUSDMintDisabled
|
|
1447
|
+
}));
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Get comprehensive vault (sApUSD) info for frontend display
|
|
1451
|
+
* @returns Vault state including TVL, exchange rate, xBNB status
|
|
1452
|
+
*/
|
|
1453
|
+
async getVaultInfo() {
|
|
1454
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1455
|
+
const [totalSupply, totalAssets, exchangeRate, conversion] = await Promise.all([
|
|
1456
|
+
this.publicClient.readContract({
|
|
1457
|
+
address: sApUSDAddress,
|
|
1458
|
+
abi: SApUSDABI,
|
|
1459
|
+
functionName: "totalSupply"
|
|
1460
|
+
}),
|
|
1461
|
+
this.publicClient.readContract({
|
|
1462
|
+
address: sApUSDAddress,
|
|
1463
|
+
abi: SApUSDABI,
|
|
1464
|
+
functionName: "totalAssets"
|
|
1465
|
+
}),
|
|
1466
|
+
this.publicClient.readContract({
|
|
1467
|
+
address: sApUSDAddress,
|
|
1468
|
+
abi: SApUSDABI,
|
|
1469
|
+
functionName: "exchangeRate"
|
|
1470
|
+
}),
|
|
1471
|
+
this.publicClient.readContract({
|
|
1472
|
+
address: sApUSDAddress,
|
|
1473
|
+
abi: SApUSDABI,
|
|
1474
|
+
functionName: "hasStabilityConversion"
|
|
1475
|
+
})
|
|
1476
|
+
]);
|
|
1477
|
+
return {
|
|
1478
|
+
totalSupply,
|
|
1479
|
+
totalAssets,
|
|
1480
|
+
exchangeRate,
|
|
1481
|
+
hasXBNB: conversion[0],
|
|
1482
|
+
xBNBAmount: conversion[1]
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Get full protocol dashboard data in one call (for frontend overview page)
|
|
1487
|
+
* Batches all key metrics into a single multicall
|
|
1488
|
+
*/
|
|
1489
|
+
async getProtocolOverview() {
|
|
1490
|
+
const [cr, tvlBNB, tvlUSD, apUSD, xBNB, xPriceUSD, xPriceBNB, bnbPrice, fees, sm, staked] = await Promise.all([
|
|
1491
|
+
this.getCollateralRatio(),
|
|
1492
|
+
this.getTVLInBNB(),
|
|
1493
|
+
this.getTVLInUSD(),
|
|
1494
|
+
this.getApUSDSupply(),
|
|
1495
|
+
this.getXBNBSupply(),
|
|
1496
|
+
this.getXBNBPriceUSD(),
|
|
1497
|
+
this.getXBNBPriceBNB(),
|
|
1498
|
+
this.getBNBPriceUSD(),
|
|
1499
|
+
this.getCurrentFeeTier(),
|
|
1500
|
+
this.getStabilityMode(),
|
|
1501
|
+
this.getTotalStaked()
|
|
1502
|
+
]);
|
|
1503
|
+
return {
|
|
1504
|
+
collateralRatio: cr,
|
|
1505
|
+
tvlBNB,
|
|
1506
|
+
tvlUSD,
|
|
1507
|
+
apUSDSupply: apUSD,
|
|
1508
|
+
xBNBSupply: xBNB,
|
|
1509
|
+
xBNBPriceUSD: xPriceUSD,
|
|
1510
|
+
xBNBPriceBNB: xPriceBNB,
|
|
1511
|
+
bnbPriceUSD: bnbPrice,
|
|
1512
|
+
currentFees: fees,
|
|
1513
|
+
stabilityMode: sm,
|
|
1514
|
+
totalStaked: staked
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1217
1517
|
async getCurrentFeeTier() {
|
|
1218
1518
|
try {
|
|
1219
1519
|
const result = await this.publicClient.readContract({
|
|
@@ -1511,18 +1811,31 @@ var AspanClient = class extends AspanReadClient {
|
|
|
1511
1811
|
});
|
|
1512
1812
|
}
|
|
1513
1813
|
/**
|
|
1514
|
-
* Clean
|
|
1515
|
-
* @
|
|
1516
|
-
* @param
|
|
1814
|
+
* Clean xBNB from sApUSD vault by converting back to apUSD
|
|
1815
|
+
* @param xBNBAmount Amount of xBNB to clean
|
|
1816
|
+
* @param minApUSDOut Minimum apUSD to receive (slippage protection)
|
|
1517
1817
|
* @returns Transaction hash
|
|
1518
1818
|
*/
|
|
1519
|
-
async
|
|
1819
|
+
async cleanVaultXBNB(xBNBAmount, minApUSDOut = 0n) {
|
|
1520
1820
|
return this.walletClient.writeContract({
|
|
1521
1821
|
chain: this.chain,
|
|
1522
1822
|
account: this.walletClient.account,
|
|
1523
1823
|
address: this.diamondAddress,
|
|
1524
1824
|
abi: DiamondABI,
|
|
1525
|
-
functionName: "
|
|
1825
|
+
functionName: "cleanVaultXBNB",
|
|
1826
|
+
args: [xBNBAmount, minApUSDOut]
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Preview how much apUSD would be minted from cleaning xBNB
|
|
1831
|
+
* @param xBNBAmount Amount of xBNB to preview
|
|
1832
|
+
* @returns apUSD amount that would be minted
|
|
1833
|
+
*/
|
|
1834
|
+
async previewCleanVaultXBNB(xBNBAmount) {
|
|
1835
|
+
return this.publicClient.readContract({
|
|
1836
|
+
address: this.diamondAddress,
|
|
1837
|
+
abi: DiamondABI,
|
|
1838
|
+
functionName: "previewCleanVaultXBNB",
|
|
1526
1839
|
args: [xBNBAmount]
|
|
1527
1840
|
});
|
|
1528
1841
|
}
|
|
@@ -2441,7 +2754,7 @@ var BSC_ADDRESSES = {
|
|
|
2441
2754
|
router: "0x29dd49b2e98674ee7531f17e4d40a7725918c3f6",
|
|
2442
2755
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
|
|
2443
2756
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
|
|
2444
|
-
sApUSD: "
|
|
2757
|
+
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
|
|
2445
2758
|
// LSTs
|
|
2446
2759
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
|
|
2447
2760
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6",
|
package/package.json
CHANGED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AspanReadClient Tests - Read-only queries against BSC mainnet
|
|
3
|
+
*
|
|
4
|
+
* Tests new SDK methods: previewRedeemMulti, getVaultInfo, getAllFeeTiers, getProtocolOverview
|
|
5
|
+
* No wallet/private key needed — pure view calls.
|
|
6
|
+
*
|
|
7
|
+
* Run with: npm test -- read-client
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { describe, it, expect, beforeAll } from "vitest";
|
|
11
|
+
import { parseEther, zeroAddress, type Address } from "viem";
|
|
12
|
+
import { bsc } from "viem/chains";
|
|
13
|
+
import { AspanReadClient, BSC_ADDRESSES } from "../index";
|
|
14
|
+
|
|
15
|
+
// ============ Configuration ============
|
|
16
|
+
|
|
17
|
+
const DIAMOND = BSC_ADDRESSES.diamond;
|
|
18
|
+
const RPC_URL = process.env.BSC_RPC_URL || "https://bsc-dataseed.binance.org";
|
|
19
|
+
|
|
20
|
+
describe("AspanReadClient - View Functions", () => {
|
|
21
|
+
let client: AspanReadClient;
|
|
22
|
+
|
|
23
|
+
beforeAll(() => {
|
|
24
|
+
client = new AspanReadClient({
|
|
25
|
+
diamondAddress: DIAMOND,
|
|
26
|
+
chain: bsc,
|
|
27
|
+
rpcUrl: RPC_URL,
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ============ Vault Info ============
|
|
32
|
+
|
|
33
|
+
describe("getVaultInfo", () => {
|
|
34
|
+
it("should return vault state with all fields", async () => {
|
|
35
|
+
const info = await client.getVaultInfo();
|
|
36
|
+
|
|
37
|
+
expect(info).toHaveProperty("totalSupply");
|
|
38
|
+
expect(info).toHaveProperty("totalAssets");
|
|
39
|
+
expect(info).toHaveProperty("exchangeRate");
|
|
40
|
+
expect(info).toHaveProperty("hasXBNB");
|
|
41
|
+
expect(info).toHaveProperty("xBNBAmount");
|
|
42
|
+
|
|
43
|
+
expect(typeof info.totalSupply).toBe("bigint");
|
|
44
|
+
expect(typeof info.totalAssets).toBe("bigint");
|
|
45
|
+
expect(typeof info.exchangeRate).toBe("bigint");
|
|
46
|
+
expect(typeof info.hasXBNB).toBe("boolean");
|
|
47
|
+
expect(typeof info.xBNBAmount).toBe("bigint");
|
|
48
|
+
|
|
49
|
+
// Exchange rate should be > 0 (at least 1e18 for 1:1)
|
|
50
|
+
expect(info.exchangeRate).toBeGreaterThan(0n);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// ============ Preview Redeem Multi ============
|
|
55
|
+
|
|
56
|
+
describe("previewRedeemMulti", () => {
|
|
57
|
+
it("should return apUSD and xBNB amounts for given shares", async () => {
|
|
58
|
+
const shares = parseEther("1"); // 1 share
|
|
59
|
+
const preview = await client.previewRedeemMulti(shares);
|
|
60
|
+
|
|
61
|
+
expect(preview).toHaveProperty("apUSD");
|
|
62
|
+
expect(preview).toHaveProperty("xBNB");
|
|
63
|
+
expect(preview).toHaveProperty("hasXBNB");
|
|
64
|
+
|
|
65
|
+
expect(typeof preview.apUSD).toBe("bigint");
|
|
66
|
+
expect(typeof preview.xBNB).toBe("bigint");
|
|
67
|
+
expect(typeof preview.hasXBNB).toBe("boolean");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should return zero for zero shares", async () => {
|
|
71
|
+
const preview = await client.previewRedeemMulti(0n);
|
|
72
|
+
|
|
73
|
+
expect(preview.apUSD).toBe(0n);
|
|
74
|
+
expect(preview.xBNB).toBe(0n);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("should have consistent hasXBNB with getVaultInfo", async () => {
|
|
78
|
+
const shares = parseEther("1");
|
|
79
|
+
const [preview, vault] = await Promise.all([
|
|
80
|
+
client.previewRedeemMulti(shares),
|
|
81
|
+
client.getVaultInfo(),
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
expect(preview.hasXBNB).toBe(vault.hasXBNB);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ============ Fee Tiers ============
|
|
89
|
+
|
|
90
|
+
describe("getAllFeeTiers", () => {
|
|
91
|
+
it("should return non-empty array of fee tiers", async () => {
|
|
92
|
+
const tiers = await client.getAllFeeTiers();
|
|
93
|
+
|
|
94
|
+
expect(Array.isArray(tiers)).toBe(true);
|
|
95
|
+
expect(tiers.length).toBeGreaterThan(0);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should have correct fee tier structure", async () => {
|
|
99
|
+
const tiers = await client.getAllFeeTiers();
|
|
100
|
+
const tier = tiers[0];
|
|
101
|
+
|
|
102
|
+
expect(tier).toHaveProperty("minCR");
|
|
103
|
+
expect(tier).toHaveProperty("apUSDMintFee");
|
|
104
|
+
expect(tier).toHaveProperty("apUSDRedeemFee");
|
|
105
|
+
expect(tier).toHaveProperty("xBNBMintFee");
|
|
106
|
+
expect(tier).toHaveProperty("xBNBRedeemFee");
|
|
107
|
+
expect(tier).toHaveProperty("apUSDMintDisabled");
|
|
108
|
+
|
|
109
|
+
expect(typeof tier.minCR).toBe("bigint");
|
|
110
|
+
expect(typeof tier.apUSDMintDisabled).toBe("boolean");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should be sorted by minCR descending", async () => {
|
|
114
|
+
const tiers = await client.getAllFeeTiers();
|
|
115
|
+
|
|
116
|
+
for (let i = 1; i < tiers.length; i++) {
|
|
117
|
+
expect(tiers[i - 1].minCR).toBeGreaterThanOrEqual(tiers[i].minCR);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should match getFeeTierCount", async () => {
|
|
122
|
+
const [tiers, count] = await Promise.all([
|
|
123
|
+
client.getAllFeeTiers(),
|
|
124
|
+
client.getFeeTierCount(),
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
expect(BigInt(tiers.length)).toBe(count);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// ============ Protocol Overview ============
|
|
132
|
+
|
|
133
|
+
describe("getProtocolOverview", () => {
|
|
134
|
+
it("should return all protocol metrics", async () => {
|
|
135
|
+
const overview = await client.getProtocolOverview();
|
|
136
|
+
|
|
137
|
+
expect(overview).toHaveProperty("collateralRatio");
|
|
138
|
+
expect(overview).toHaveProperty("tvlBNB");
|
|
139
|
+
expect(overview).toHaveProperty("tvlUSD");
|
|
140
|
+
expect(overview).toHaveProperty("apUSDSupply");
|
|
141
|
+
expect(overview).toHaveProperty("xBNBSupply");
|
|
142
|
+
expect(overview).toHaveProperty("xBNBPriceUSD");
|
|
143
|
+
expect(overview).toHaveProperty("xBNBPriceBNB");
|
|
144
|
+
expect(overview).toHaveProperty("bnbPriceUSD");
|
|
145
|
+
expect(overview).toHaveProperty("currentFees");
|
|
146
|
+
expect(overview).toHaveProperty("stabilityMode");
|
|
147
|
+
expect(overview).toHaveProperty("totalStaked");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should have positive TVL and prices", async () => {
|
|
151
|
+
const overview = await client.getProtocolOverview();
|
|
152
|
+
|
|
153
|
+
expect(overview.tvlBNB).toBeGreaterThan(0n);
|
|
154
|
+
expect(overview.tvlUSD).toBeGreaterThan(0n);
|
|
155
|
+
expect(overview.bnbPriceUSD).toBeGreaterThan(0n);
|
|
156
|
+
expect(overview.collateralRatio).toBeGreaterThan(0n);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it("should have valid currentFees structure", async () => {
|
|
160
|
+
const overview = await client.getProtocolOverview();
|
|
161
|
+
const fees = overview.currentFees;
|
|
162
|
+
|
|
163
|
+
expect(fees).toHaveProperty("minCR");
|
|
164
|
+
expect(fees).toHaveProperty("apUSDMintFee");
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it("should have valid stabilityMode structure", async () => {
|
|
168
|
+
const overview = await client.getProtocolOverview();
|
|
169
|
+
const sm = overview.stabilityMode;
|
|
170
|
+
|
|
171
|
+
expect(sm).toHaveProperty("mode");
|
|
172
|
+
// mode should be 0 (normal), 1, or 2
|
|
173
|
+
expect([0, 1, 2]).toContain(sm.mode);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ============ Existing view methods consistency ============
|
|
178
|
+
|
|
179
|
+
describe("cross-method consistency", () => {
|
|
180
|
+
it("vault totalStaked should match getVaultInfo totalSupply context", async () => {
|
|
181
|
+
const [staked, vault] = await Promise.all([
|
|
182
|
+
client.getTotalStaked(),
|
|
183
|
+
client.getVaultInfo(),
|
|
184
|
+
]);
|
|
185
|
+
|
|
186
|
+
// totalStaked from Diamond should relate to vault totalAssets
|
|
187
|
+
expect(typeof staked).toBe("bigint");
|
|
188
|
+
expect(typeof vault.totalAssets).toBe("bigint");
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it("exchangeRate from getVaultInfo should match getExchangeRate", async () => {
|
|
192
|
+
const [vault, rate] = await Promise.all([
|
|
193
|
+
client.getVaultInfo(),
|
|
194
|
+
client.getExchangeRate(),
|
|
195
|
+
]);
|
|
196
|
+
|
|
197
|
+
expect(vault.exchangeRate).toBe(rate);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe("getBalanceMulti", () => {
|
|
202
|
+
it("should return apUSD and xBNB balances for a user", async () => {
|
|
203
|
+
const testUser = zeroAddress; // zero address will have 0 balances
|
|
204
|
+
const result = await client.getBalanceMulti(testUser);
|
|
205
|
+
|
|
206
|
+
expect(typeof result.apUSDBalance).toBe("bigint");
|
|
207
|
+
expect(typeof result.xBNBBalance).toBe("bigint");
|
|
208
|
+
expect(result.apUSDBalance).toBe(0n);
|
|
209
|
+
expect(result.xBNBBalance).toBe(0n);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
});
|
package/src/abi/diamond.ts
CHANGED
|
@@ -406,6 +406,13 @@ export const DiamondABI = [
|
|
|
406
406
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
407
407
|
stateMutability: "view"
|
|
408
408
|
},
|
|
409
|
+
{
|
|
410
|
+
type: "function",
|
|
411
|
+
name: "setSApUSD",
|
|
412
|
+
inputs: [{ name: "_sApUSD", type: "address", internalType: "address" }],
|
|
413
|
+
outputs: [],
|
|
414
|
+
stateMutability: "nonpayable"
|
|
415
|
+
},
|
|
409
416
|
{
|
|
410
417
|
type: "function",
|
|
411
418
|
name: "getStabilityPool",
|
|
@@ -427,6 +434,25 @@ export const DiamondABI = [
|
|
|
427
434
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
428
435
|
stateMutability: "view"
|
|
429
436
|
},
|
|
437
|
+
{
|
|
438
|
+
type: "function",
|
|
439
|
+
name: "getAllFeeTiers",
|
|
440
|
+
inputs: [],
|
|
441
|
+
outputs: [{
|
|
442
|
+
name: "",
|
|
443
|
+
type: "tuple[]",
|
|
444
|
+
internalType: "struct LibAppStorage.FeeTier[]",
|
|
445
|
+
components: [
|
|
446
|
+
{ name: "minCR", type: "uint256", internalType: "uint256" },
|
|
447
|
+
{ name: "apUSDMintFee", type: "uint16", internalType: "uint16" },
|
|
448
|
+
{ name: "apUSDRedeemFee", type: "uint16", internalType: "uint16" },
|
|
449
|
+
{ name: "xBNBMintFee", type: "uint16", internalType: "uint16" },
|
|
450
|
+
{ name: "xBNBRedeemFee", type: "uint16", internalType: "uint16" },
|
|
451
|
+
{ name: "apUSDMintDisabled", type: "bool", internalType: "bool" },
|
|
452
|
+
],
|
|
453
|
+
}],
|
|
454
|
+
stateMutability: "view"
|
|
455
|
+
},
|
|
430
456
|
{
|
|
431
457
|
type: "function",
|
|
432
458
|
name: "getFeeTier",
|
|
@@ -536,11 +562,27 @@ export const DiamondABI = [
|
|
|
536
562
|
},
|
|
537
563
|
{
|
|
538
564
|
type: "function",
|
|
539
|
-
name: "
|
|
540
|
-
inputs: [
|
|
541
|
-
|
|
565
|
+
name: "cleanVaultXBNB",
|
|
566
|
+
inputs: [
|
|
567
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
568
|
+
{ name: "_minApUSDOut", type: "uint256", internalType: "uint256" }
|
|
569
|
+
],
|
|
570
|
+
outputs: [
|
|
571
|
+
{ name: "apUSDMinted", type: "uint256", internalType: "uint256" }
|
|
572
|
+
],
|
|
542
573
|
stateMutability: "nonpayable"
|
|
543
574
|
},
|
|
575
|
+
{
|
|
576
|
+
type: "function",
|
|
577
|
+
name: "previewCleanVaultXBNB",
|
|
578
|
+
inputs: [
|
|
579
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
580
|
+
],
|
|
581
|
+
outputs: [
|
|
582
|
+
{ name: "apUSDOut", type: "uint256", internalType: "uint256" }
|
|
583
|
+
],
|
|
584
|
+
stateMutability: "view"
|
|
585
|
+
},
|
|
544
586
|
|
|
545
587
|
// ============ StabilityModeFacet Events ============
|
|
546
588
|
{
|