@aspan/sdk 0.4.4 → 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 +95 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +284 -0
- package/dist/index.mjs +284 -0
- package/package.json +1 -1
- package/src/__tests__/read-client.test.ts +212 -0
- package/src/abi/diamond.ts +26 -0
- package/src/abi/sApUSD.ts +36 -0
- package/src/client.ts +162 -0
package/dist/index.d.mts
CHANGED
|
@@ -457,11 +457,28 @@ declare class AspanReadClient {
|
|
|
457
457
|
getOracleBounds(priceFeed: Address): Promise<OracleBounds>;
|
|
458
458
|
getShares(user: Address): Promise<bigint>;
|
|
459
459
|
getBalance(user: Address): Promise<bigint>;
|
|
460
|
+
/**
|
|
461
|
+
* Get user's underlying balances (apUSD + xBNB) from sApUSD vault
|
|
462
|
+
*/
|
|
463
|
+
getBalanceMulti(user: Address): Promise<{
|
|
464
|
+
apUSDBalance: bigint;
|
|
465
|
+
xBNBBalance: bigint;
|
|
466
|
+
}>;
|
|
460
467
|
getUserStabilityPoolPosition(user: Address): Promise<UserStabilityPoolPosition>;
|
|
461
468
|
getExchangeRate(): Promise<bigint>;
|
|
462
469
|
getTotalStaked(): Promise<bigint>;
|
|
463
470
|
previewDeposit(assets: bigint): Promise<bigint>;
|
|
464
471
|
previewRedeem(shares: bigint): Promise<bigint>;
|
|
472
|
+
/**
|
|
473
|
+
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
474
|
+
* @param shares Amount of sApUSD shares to redeem
|
|
475
|
+
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
476
|
+
*/
|
|
477
|
+
previewRedeemMulti(shares: bigint): Promise<{
|
|
478
|
+
apUSD: bigint;
|
|
479
|
+
xBNB: bigint;
|
|
480
|
+
hasXBNB: boolean;
|
|
481
|
+
}>;
|
|
465
482
|
getPendingYield(): Promise<bigint>;
|
|
466
483
|
getTotalYieldGenerated(): Promise<bigint>;
|
|
467
484
|
getLSTYieldInfo(lstToken: Address): Promise<LSTYieldInfo>;
|
|
@@ -474,6 +491,39 @@ declare class AspanReadClient {
|
|
|
474
491
|
getTreasury(): Promise<Address>;
|
|
475
492
|
getFeeTierCount(): Promise<bigint>;
|
|
476
493
|
getFeeTier(index: bigint): Promise<FeeTier>;
|
|
494
|
+
/**
|
|
495
|
+
* Get all fee tiers
|
|
496
|
+
* @returns Array of fee tiers sorted by minCR descending
|
|
497
|
+
*/
|
|
498
|
+
getAllFeeTiers(): Promise<FeeTier[]>;
|
|
499
|
+
/**
|
|
500
|
+
* Get comprehensive vault (sApUSD) info for frontend display
|
|
501
|
+
* @returns Vault state including TVL, exchange rate, xBNB status
|
|
502
|
+
*/
|
|
503
|
+
getVaultInfo(): Promise<{
|
|
504
|
+
totalSupply: bigint;
|
|
505
|
+
totalAssets: bigint;
|
|
506
|
+
exchangeRate: bigint;
|
|
507
|
+
hasXBNB: boolean;
|
|
508
|
+
xBNBAmount: bigint;
|
|
509
|
+
}>;
|
|
510
|
+
/**
|
|
511
|
+
* Get full protocol dashboard data in one call (for frontend overview page)
|
|
512
|
+
* Batches all key metrics into a single multicall
|
|
513
|
+
*/
|
|
514
|
+
getProtocolOverview(): Promise<{
|
|
515
|
+
collateralRatio: bigint;
|
|
516
|
+
tvlBNB: bigint;
|
|
517
|
+
tvlUSD: bigint;
|
|
518
|
+
apUSDSupply: bigint;
|
|
519
|
+
xBNBSupply: bigint;
|
|
520
|
+
xBNBPriceUSD: bigint;
|
|
521
|
+
xBNBPriceBNB: bigint;
|
|
522
|
+
bnbPriceUSD: bigint;
|
|
523
|
+
currentFees: CurrentFeeTier;
|
|
524
|
+
stabilityMode: StabilityModeInfo;
|
|
525
|
+
totalStaked: bigint;
|
|
526
|
+
}>;
|
|
477
527
|
getCurrentFeeTier(): Promise<CurrentFeeTier>;
|
|
478
528
|
getMaxPriceAge(): Promise<bigint>;
|
|
479
529
|
getMinDepositPeriod(): Promise<bigint>;
|
|
@@ -1529,6 +1579,16 @@ declare const DiamondABI: readonly [{
|
|
|
1529
1579
|
readonly internalType: "address";
|
|
1530
1580
|
}];
|
|
1531
1581
|
readonly stateMutability: "view";
|
|
1582
|
+
}, {
|
|
1583
|
+
readonly type: "function";
|
|
1584
|
+
readonly name: "setSApUSD";
|
|
1585
|
+
readonly inputs: readonly [{
|
|
1586
|
+
readonly name: "_sApUSD";
|
|
1587
|
+
readonly type: "address";
|
|
1588
|
+
readonly internalType: "address";
|
|
1589
|
+
}];
|
|
1590
|
+
readonly outputs: readonly [];
|
|
1591
|
+
readonly stateMutability: "nonpayable";
|
|
1532
1592
|
}, {
|
|
1533
1593
|
readonly type: "function";
|
|
1534
1594
|
readonly name: "getStabilityPool";
|
|
@@ -1559,6 +1619,41 @@ declare const DiamondABI: readonly [{
|
|
|
1559
1619
|
readonly internalType: "uint256";
|
|
1560
1620
|
}];
|
|
1561
1621
|
readonly stateMutability: "view";
|
|
1622
|
+
}, {
|
|
1623
|
+
readonly type: "function";
|
|
1624
|
+
readonly name: "getAllFeeTiers";
|
|
1625
|
+
readonly inputs: readonly [];
|
|
1626
|
+
readonly outputs: readonly [{
|
|
1627
|
+
readonly name: "";
|
|
1628
|
+
readonly type: "tuple[]";
|
|
1629
|
+
readonly internalType: "struct LibAppStorage.FeeTier[]";
|
|
1630
|
+
readonly components: readonly [{
|
|
1631
|
+
readonly name: "minCR";
|
|
1632
|
+
readonly type: "uint256";
|
|
1633
|
+
readonly internalType: "uint256";
|
|
1634
|
+
}, {
|
|
1635
|
+
readonly name: "apUSDMintFee";
|
|
1636
|
+
readonly type: "uint16";
|
|
1637
|
+
readonly internalType: "uint16";
|
|
1638
|
+
}, {
|
|
1639
|
+
readonly name: "apUSDRedeemFee";
|
|
1640
|
+
readonly type: "uint16";
|
|
1641
|
+
readonly internalType: "uint16";
|
|
1642
|
+
}, {
|
|
1643
|
+
readonly name: "xBNBMintFee";
|
|
1644
|
+
readonly type: "uint16";
|
|
1645
|
+
readonly internalType: "uint16";
|
|
1646
|
+
}, {
|
|
1647
|
+
readonly name: "xBNBRedeemFee";
|
|
1648
|
+
readonly type: "uint16";
|
|
1649
|
+
readonly internalType: "uint16";
|
|
1650
|
+
}, {
|
|
1651
|
+
readonly name: "apUSDMintDisabled";
|
|
1652
|
+
readonly type: "bool";
|
|
1653
|
+
readonly internalType: "bool";
|
|
1654
|
+
}];
|
|
1655
|
+
}];
|
|
1656
|
+
readonly stateMutability: "view";
|
|
1562
1657
|
}, {
|
|
1563
1658
|
readonly type: "function";
|
|
1564
1659
|
readonly name: "getFeeTier";
|
package/dist/index.d.ts
CHANGED
|
@@ -457,11 +457,28 @@ declare class AspanReadClient {
|
|
|
457
457
|
getOracleBounds(priceFeed: Address): Promise<OracleBounds>;
|
|
458
458
|
getShares(user: Address): Promise<bigint>;
|
|
459
459
|
getBalance(user: Address): Promise<bigint>;
|
|
460
|
+
/**
|
|
461
|
+
* Get user's underlying balances (apUSD + xBNB) from sApUSD vault
|
|
462
|
+
*/
|
|
463
|
+
getBalanceMulti(user: Address): Promise<{
|
|
464
|
+
apUSDBalance: bigint;
|
|
465
|
+
xBNBBalance: bigint;
|
|
466
|
+
}>;
|
|
460
467
|
getUserStabilityPoolPosition(user: Address): Promise<UserStabilityPoolPosition>;
|
|
461
468
|
getExchangeRate(): Promise<bigint>;
|
|
462
469
|
getTotalStaked(): Promise<bigint>;
|
|
463
470
|
previewDeposit(assets: bigint): Promise<bigint>;
|
|
464
471
|
previewRedeem(shares: bigint): Promise<bigint>;
|
|
472
|
+
/**
|
|
473
|
+
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
474
|
+
* @param shares Amount of sApUSD shares to redeem
|
|
475
|
+
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
476
|
+
*/
|
|
477
|
+
previewRedeemMulti(shares: bigint): Promise<{
|
|
478
|
+
apUSD: bigint;
|
|
479
|
+
xBNB: bigint;
|
|
480
|
+
hasXBNB: boolean;
|
|
481
|
+
}>;
|
|
465
482
|
getPendingYield(): Promise<bigint>;
|
|
466
483
|
getTotalYieldGenerated(): Promise<bigint>;
|
|
467
484
|
getLSTYieldInfo(lstToken: Address): Promise<LSTYieldInfo>;
|
|
@@ -474,6 +491,39 @@ declare class AspanReadClient {
|
|
|
474
491
|
getTreasury(): Promise<Address>;
|
|
475
492
|
getFeeTierCount(): Promise<bigint>;
|
|
476
493
|
getFeeTier(index: bigint): Promise<FeeTier>;
|
|
494
|
+
/**
|
|
495
|
+
* Get all fee tiers
|
|
496
|
+
* @returns Array of fee tiers sorted by minCR descending
|
|
497
|
+
*/
|
|
498
|
+
getAllFeeTiers(): Promise<FeeTier[]>;
|
|
499
|
+
/**
|
|
500
|
+
* Get comprehensive vault (sApUSD) info for frontend display
|
|
501
|
+
* @returns Vault state including TVL, exchange rate, xBNB status
|
|
502
|
+
*/
|
|
503
|
+
getVaultInfo(): Promise<{
|
|
504
|
+
totalSupply: bigint;
|
|
505
|
+
totalAssets: bigint;
|
|
506
|
+
exchangeRate: bigint;
|
|
507
|
+
hasXBNB: boolean;
|
|
508
|
+
xBNBAmount: bigint;
|
|
509
|
+
}>;
|
|
510
|
+
/**
|
|
511
|
+
* Get full protocol dashboard data in one call (for frontend overview page)
|
|
512
|
+
* Batches all key metrics into a single multicall
|
|
513
|
+
*/
|
|
514
|
+
getProtocolOverview(): Promise<{
|
|
515
|
+
collateralRatio: bigint;
|
|
516
|
+
tvlBNB: bigint;
|
|
517
|
+
tvlUSD: bigint;
|
|
518
|
+
apUSDSupply: bigint;
|
|
519
|
+
xBNBSupply: bigint;
|
|
520
|
+
xBNBPriceUSD: bigint;
|
|
521
|
+
xBNBPriceBNB: bigint;
|
|
522
|
+
bnbPriceUSD: bigint;
|
|
523
|
+
currentFees: CurrentFeeTier;
|
|
524
|
+
stabilityMode: StabilityModeInfo;
|
|
525
|
+
totalStaked: bigint;
|
|
526
|
+
}>;
|
|
477
527
|
getCurrentFeeTier(): Promise<CurrentFeeTier>;
|
|
478
528
|
getMaxPriceAge(): Promise<bigint>;
|
|
479
529
|
getMinDepositPeriod(): Promise<bigint>;
|
|
@@ -1529,6 +1579,16 @@ declare const DiamondABI: readonly [{
|
|
|
1529
1579
|
readonly internalType: "address";
|
|
1530
1580
|
}];
|
|
1531
1581
|
readonly stateMutability: "view";
|
|
1582
|
+
}, {
|
|
1583
|
+
readonly type: "function";
|
|
1584
|
+
readonly name: "setSApUSD";
|
|
1585
|
+
readonly inputs: readonly [{
|
|
1586
|
+
readonly name: "_sApUSD";
|
|
1587
|
+
readonly type: "address";
|
|
1588
|
+
readonly internalType: "address";
|
|
1589
|
+
}];
|
|
1590
|
+
readonly outputs: readonly [];
|
|
1591
|
+
readonly stateMutability: "nonpayable";
|
|
1532
1592
|
}, {
|
|
1533
1593
|
readonly type: "function";
|
|
1534
1594
|
readonly name: "getStabilityPool";
|
|
@@ -1559,6 +1619,41 @@ declare const DiamondABI: readonly [{
|
|
|
1559
1619
|
readonly internalType: "uint256";
|
|
1560
1620
|
}];
|
|
1561
1621
|
readonly stateMutability: "view";
|
|
1622
|
+
}, {
|
|
1623
|
+
readonly type: "function";
|
|
1624
|
+
readonly name: "getAllFeeTiers";
|
|
1625
|
+
readonly inputs: readonly [];
|
|
1626
|
+
readonly outputs: readonly [{
|
|
1627
|
+
readonly name: "";
|
|
1628
|
+
readonly type: "tuple[]";
|
|
1629
|
+
readonly internalType: "struct LibAppStorage.FeeTier[]";
|
|
1630
|
+
readonly components: readonly [{
|
|
1631
|
+
readonly name: "minCR";
|
|
1632
|
+
readonly type: "uint256";
|
|
1633
|
+
readonly internalType: "uint256";
|
|
1634
|
+
}, {
|
|
1635
|
+
readonly name: "apUSDMintFee";
|
|
1636
|
+
readonly type: "uint16";
|
|
1637
|
+
readonly internalType: "uint16";
|
|
1638
|
+
}, {
|
|
1639
|
+
readonly name: "apUSDRedeemFee";
|
|
1640
|
+
readonly type: "uint16";
|
|
1641
|
+
readonly internalType: "uint16";
|
|
1642
|
+
}, {
|
|
1643
|
+
readonly name: "xBNBMintFee";
|
|
1644
|
+
readonly type: "uint16";
|
|
1645
|
+
readonly internalType: "uint16";
|
|
1646
|
+
}, {
|
|
1647
|
+
readonly name: "xBNBRedeemFee";
|
|
1648
|
+
readonly type: "uint16";
|
|
1649
|
+
readonly internalType: "uint16";
|
|
1650
|
+
}, {
|
|
1651
|
+
readonly name: "apUSDMintDisabled";
|
|
1652
|
+
readonly type: "bool";
|
|
1653
|
+
readonly internalType: "bool";
|
|
1654
|
+
}];
|
|
1655
|
+
}];
|
|
1656
|
+
readonly stateMutability: "view";
|
|
1562
1657
|
}, {
|
|
1563
1658
|
readonly type: "function";
|
|
1564
1659
|
readonly name: "getFeeTier";
|
package/dist/index.js
CHANGED
|
@@ -463,6 +463,13 @@ var DiamondABI = [
|
|
|
463
463
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
464
464
|
stateMutability: "view"
|
|
465
465
|
},
|
|
466
|
+
{
|
|
467
|
+
type: "function",
|
|
468
|
+
name: "setSApUSD",
|
|
469
|
+
inputs: [{ name: "_sApUSD", type: "address", internalType: "address" }],
|
|
470
|
+
outputs: [],
|
|
471
|
+
stateMutability: "nonpayable"
|
|
472
|
+
},
|
|
466
473
|
{
|
|
467
474
|
type: "function",
|
|
468
475
|
name: "getStabilityPool",
|
|
@@ -484,6 +491,25 @@ var DiamondABI = [
|
|
|
484
491
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
485
492
|
stateMutability: "view"
|
|
486
493
|
},
|
|
494
|
+
{
|
|
495
|
+
type: "function",
|
|
496
|
+
name: "getAllFeeTiers",
|
|
497
|
+
inputs: [],
|
|
498
|
+
outputs: [{
|
|
499
|
+
name: "",
|
|
500
|
+
type: "tuple[]",
|
|
501
|
+
internalType: "struct LibAppStorage.FeeTier[]",
|
|
502
|
+
components: [
|
|
503
|
+
{ name: "minCR", type: "uint256", internalType: "uint256" },
|
|
504
|
+
{ name: "apUSDMintFee", type: "uint16", internalType: "uint16" },
|
|
505
|
+
{ name: "apUSDRedeemFee", type: "uint16", internalType: "uint16" },
|
|
506
|
+
{ name: "xBNBMintFee", type: "uint16", internalType: "uint16" },
|
|
507
|
+
{ name: "xBNBRedeemFee", type: "uint16", internalType: "uint16" },
|
|
508
|
+
{ name: "apUSDMintDisabled", type: "bool", internalType: "bool" }
|
|
509
|
+
]
|
|
510
|
+
}],
|
|
511
|
+
stateMutability: "view"
|
|
512
|
+
},
|
|
487
513
|
{
|
|
488
514
|
type: "function",
|
|
489
515
|
name: "getFeeTier",
|
|
@@ -677,6 +703,138 @@ var DiamondABI = [
|
|
|
677
703
|
}
|
|
678
704
|
];
|
|
679
705
|
|
|
706
|
+
// src/abi/sApUSD.ts
|
|
707
|
+
var SApUSDABI = [
|
|
708
|
+
// ============ View Functions ============
|
|
709
|
+
{
|
|
710
|
+
type: "function",
|
|
711
|
+
name: "totalAssets",
|
|
712
|
+
inputs: [],
|
|
713
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
714
|
+
stateMutability: "view"
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
type: "function",
|
|
718
|
+
name: "totalSupply",
|
|
719
|
+
inputs: [],
|
|
720
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
721
|
+
stateMutability: "view"
|
|
722
|
+
},
|
|
723
|
+
{
|
|
724
|
+
type: "function",
|
|
725
|
+
name: "balanceOf",
|
|
726
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
727
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
728
|
+
stateMutability: "view"
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
type: "function",
|
|
732
|
+
name: "previewRedeemMulti",
|
|
733
|
+
inputs: [
|
|
734
|
+
{ name: "shares", type: "uint256", internalType: "uint256" }
|
|
735
|
+
],
|
|
736
|
+
outputs: [
|
|
737
|
+
{ name: "assets", type: "address[]", internalType: "address[]" },
|
|
738
|
+
{ name: "amounts", type: "uint256[]", internalType: "uint256[]" }
|
|
739
|
+
],
|
|
740
|
+
stateMutability: "view"
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
type: "function",
|
|
744
|
+
name: "hasStabilityConversion",
|
|
745
|
+
inputs: [],
|
|
746
|
+
outputs: [
|
|
747
|
+
{ name: "hasXBNB", type: "bool", internalType: "bool" },
|
|
748
|
+
{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
749
|
+
],
|
|
750
|
+
stateMutability: "view"
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
type: "function",
|
|
754
|
+
name: "totalValue",
|
|
755
|
+
inputs: [],
|
|
756
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
757
|
+
stateMutability: "view"
|
|
758
|
+
},
|
|
759
|
+
{
|
|
760
|
+
type: "function",
|
|
761
|
+
name: "underlyingBalances",
|
|
762
|
+
inputs: [{ name: "_user", type: "address", internalType: "address" }],
|
|
763
|
+
outputs: [
|
|
764
|
+
{ name: "apUSDBalance", type: "uint256", internalType: "uint256" },
|
|
765
|
+
{ name: "xBNBBalance", type: "uint256", internalType: "uint256" }
|
|
766
|
+
],
|
|
767
|
+
stateMutability: "view"
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
type: "function",
|
|
771
|
+
name: "xBNBToApUSDRate",
|
|
772
|
+
inputs: [],
|
|
773
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
774
|
+
stateMutability: "view"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
type: "function",
|
|
778
|
+
name: "exchangeRate",
|
|
779
|
+
inputs: [],
|
|
780
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
781
|
+
stateMutability: "view"
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
type: "function",
|
|
785
|
+
name: "previewCleanXBNB",
|
|
786
|
+
inputs: [
|
|
787
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
788
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
789
|
+
{ name: "_path", type: "address[]", internalType: "address[]" }
|
|
790
|
+
],
|
|
791
|
+
outputs: [{ name: "expectedApUSD", type: "uint256", internalType: "uint256" }],
|
|
792
|
+
stateMutability: "view"
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
type: "function",
|
|
796
|
+
name: "KEEPER_ROLE",
|
|
797
|
+
inputs: [],
|
|
798
|
+
outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
|
|
799
|
+
stateMutability: "view"
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
type: "function",
|
|
803
|
+
name: "hasRole",
|
|
804
|
+
inputs: [
|
|
805
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
806
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
807
|
+
],
|
|
808
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
809
|
+
stateMutability: "view"
|
|
810
|
+
},
|
|
811
|
+
// ============ Keeper Functions ============
|
|
812
|
+
{
|
|
813
|
+
type: "function",
|
|
814
|
+
name: "cleanXBNB",
|
|
815
|
+
inputs: [
|
|
816
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
817
|
+
{ name: "_minApUSDOut", type: "uint256", internalType: "uint256" },
|
|
818
|
+
{ name: "_router", type: "address", internalType: "address" },
|
|
819
|
+
{ name: "_path", type: "address[]", internalType: "address[]" },
|
|
820
|
+
{ name: "_deadline", type: "uint256", internalType: "uint256" }
|
|
821
|
+
],
|
|
822
|
+
outputs: [{ name: "apUSDReceived", type: "uint256", internalType: "uint256" }],
|
|
823
|
+
stateMutability: "nonpayable"
|
|
824
|
+
},
|
|
825
|
+
// ============ Events ============
|
|
826
|
+
{
|
|
827
|
+
type: "event",
|
|
828
|
+
name: "VaultCleaned",
|
|
829
|
+
inputs: [
|
|
830
|
+
{ name: "xBNBSold", type: "uint256", indexed: false, internalType: "uint256" },
|
|
831
|
+
{ name: "apUSDReceived", type: "uint256", indexed: false, internalType: "uint256" },
|
|
832
|
+
{ name: "keeper", type: "address", indexed: true, internalType: "address" }
|
|
833
|
+
],
|
|
834
|
+
anonymous: false
|
|
835
|
+
}
|
|
836
|
+
];
|
|
837
|
+
|
|
680
838
|
// src/client.ts
|
|
681
839
|
var pharosTestnet = {
|
|
682
840
|
id: 688689,
|
|
@@ -1070,6 +1228,19 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1070
1228
|
args: [user]
|
|
1071
1229
|
});
|
|
1072
1230
|
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Get user's underlying balances (apUSD + xBNB) from sApUSD vault
|
|
1233
|
+
*/
|
|
1234
|
+
async getBalanceMulti(user) {
|
|
1235
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1236
|
+
const [apUSDBalance, xBNBBalance] = await this.publicClient.readContract({
|
|
1237
|
+
address: sApUSDAddress,
|
|
1238
|
+
abi: SApUSDABI,
|
|
1239
|
+
functionName: "underlyingBalances",
|
|
1240
|
+
args: [user]
|
|
1241
|
+
});
|
|
1242
|
+
return { apUSDBalance, xBNBBalance };
|
|
1243
|
+
}
|
|
1073
1244
|
async getUserStabilityPoolPosition(user) {
|
|
1074
1245
|
const [shares, balance] = await Promise.all([
|
|
1075
1246
|
this.getShares(user),
|
|
@@ -1135,6 +1306,32 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1135
1306
|
throw error;
|
|
1136
1307
|
}
|
|
1137
1308
|
}
|
|
1309
|
+
/**
|
|
1310
|
+
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
1311
|
+
* @param shares Amount of sApUSD shares to redeem
|
|
1312
|
+
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
1313
|
+
*/
|
|
1314
|
+
async previewRedeemMulti(shares) {
|
|
1315
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1316
|
+
const [result, conversion] = await Promise.all([
|
|
1317
|
+
this.publicClient.readContract({
|
|
1318
|
+
address: sApUSDAddress,
|
|
1319
|
+
abi: SApUSDABI,
|
|
1320
|
+
functionName: "previewRedeemMulti",
|
|
1321
|
+
args: [shares]
|
|
1322
|
+
}),
|
|
1323
|
+
this.publicClient.readContract({
|
|
1324
|
+
address: sApUSDAddress,
|
|
1325
|
+
abi: SApUSDABI,
|
|
1326
|
+
functionName: "hasStabilityConversion"
|
|
1327
|
+
})
|
|
1328
|
+
]);
|
|
1329
|
+
return {
|
|
1330
|
+
apUSD: result[1][0],
|
|
1331
|
+
xBNB: result[1][1],
|
|
1332
|
+
hasXBNB: conversion[0]
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1138
1335
|
async getPendingYield() {
|
|
1139
1336
|
try {
|
|
1140
1337
|
return await this.publicClient.readContract({
|
|
@@ -1288,6 +1485,93 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1288
1485
|
apUSDMintDisabled: result[5]
|
|
1289
1486
|
};
|
|
1290
1487
|
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Get all fee tiers
|
|
1490
|
+
* @returns Array of fee tiers sorted by minCR descending
|
|
1491
|
+
*/
|
|
1492
|
+
async getAllFeeTiers() {
|
|
1493
|
+
const result = await this.publicClient.readContract({
|
|
1494
|
+
address: this.diamondAddress,
|
|
1495
|
+
abi: DiamondABI,
|
|
1496
|
+
functionName: "getAllFeeTiers"
|
|
1497
|
+
});
|
|
1498
|
+
return result.map((tier) => ({
|
|
1499
|
+
minCR: tier.minCR,
|
|
1500
|
+
apUSDMintFee: tier.apUSDMintFee,
|
|
1501
|
+
apUSDRedeemFee: tier.apUSDRedeemFee,
|
|
1502
|
+
xBNBMintFee: tier.xBNBMintFee,
|
|
1503
|
+
xBNBRedeemFee: tier.xBNBRedeemFee,
|
|
1504
|
+
apUSDMintDisabled: tier.apUSDMintDisabled
|
|
1505
|
+
}));
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Get comprehensive vault (sApUSD) info for frontend display
|
|
1509
|
+
* @returns Vault state including TVL, exchange rate, xBNB status
|
|
1510
|
+
*/
|
|
1511
|
+
async getVaultInfo() {
|
|
1512
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
1513
|
+
const [totalSupply, totalAssets, exchangeRate, conversion] = await Promise.all([
|
|
1514
|
+
this.publicClient.readContract({
|
|
1515
|
+
address: sApUSDAddress,
|
|
1516
|
+
abi: SApUSDABI,
|
|
1517
|
+
functionName: "totalSupply"
|
|
1518
|
+
}),
|
|
1519
|
+
this.publicClient.readContract({
|
|
1520
|
+
address: sApUSDAddress,
|
|
1521
|
+
abi: SApUSDABI,
|
|
1522
|
+
functionName: "totalAssets"
|
|
1523
|
+
}),
|
|
1524
|
+
this.publicClient.readContract({
|
|
1525
|
+
address: sApUSDAddress,
|
|
1526
|
+
abi: SApUSDABI,
|
|
1527
|
+
functionName: "exchangeRate"
|
|
1528
|
+
}),
|
|
1529
|
+
this.publicClient.readContract({
|
|
1530
|
+
address: sApUSDAddress,
|
|
1531
|
+
abi: SApUSDABI,
|
|
1532
|
+
functionName: "hasStabilityConversion"
|
|
1533
|
+
})
|
|
1534
|
+
]);
|
|
1535
|
+
return {
|
|
1536
|
+
totalSupply,
|
|
1537
|
+
totalAssets,
|
|
1538
|
+
exchangeRate,
|
|
1539
|
+
hasXBNB: conversion[0],
|
|
1540
|
+
xBNBAmount: conversion[1]
|
|
1541
|
+
};
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* Get full protocol dashboard data in one call (for frontend overview page)
|
|
1545
|
+
* Batches all key metrics into a single multicall
|
|
1546
|
+
*/
|
|
1547
|
+
async getProtocolOverview() {
|
|
1548
|
+
const [cr, tvlBNB, tvlUSD, apUSD, xBNB, xPriceUSD, xPriceBNB, bnbPrice, fees, sm, staked] = await Promise.all([
|
|
1549
|
+
this.getCollateralRatio(),
|
|
1550
|
+
this.getTVLInBNB(),
|
|
1551
|
+
this.getTVLInUSD(),
|
|
1552
|
+
this.getApUSDSupply(),
|
|
1553
|
+
this.getXBNBSupply(),
|
|
1554
|
+
this.getXBNBPriceUSD(),
|
|
1555
|
+
this.getXBNBPriceBNB(),
|
|
1556
|
+
this.getBNBPriceUSD(),
|
|
1557
|
+
this.getCurrentFeeTier(),
|
|
1558
|
+
this.getStabilityMode(),
|
|
1559
|
+
this.getTotalStaked()
|
|
1560
|
+
]);
|
|
1561
|
+
return {
|
|
1562
|
+
collateralRatio: cr,
|
|
1563
|
+
tvlBNB,
|
|
1564
|
+
tvlUSD,
|
|
1565
|
+
apUSDSupply: apUSD,
|
|
1566
|
+
xBNBSupply: xBNB,
|
|
1567
|
+
xBNBPriceUSD: xPriceUSD,
|
|
1568
|
+
xBNBPriceBNB: xPriceBNB,
|
|
1569
|
+
bnbPriceUSD: bnbPrice,
|
|
1570
|
+
currentFees: fees,
|
|
1571
|
+
stabilityMode: sm,
|
|
1572
|
+
totalStaked: staked
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1291
1575
|
async getCurrentFeeTier() {
|
|
1292
1576
|
try {
|
|
1293
1577
|
const result = await this.publicClient.readContract({
|
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",
|
|
@@ -619,6 +645,138 @@ var DiamondABI = [
|
|
|
619
645
|
}
|
|
620
646
|
];
|
|
621
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
|
+
|
|
622
780
|
// src/client.ts
|
|
623
781
|
var pharosTestnet = {
|
|
624
782
|
id: 688689,
|
|
@@ -1012,6 +1170,19 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1012
1170
|
args: [user]
|
|
1013
1171
|
});
|
|
1014
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
|
+
}
|
|
1015
1186
|
async getUserStabilityPoolPosition(user) {
|
|
1016
1187
|
const [shares, balance] = await Promise.all([
|
|
1017
1188
|
this.getShares(user),
|
|
@@ -1077,6 +1248,32 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1077
1248
|
throw error;
|
|
1078
1249
|
}
|
|
1079
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
|
+
}
|
|
1080
1277
|
async getPendingYield() {
|
|
1081
1278
|
try {
|
|
1082
1279
|
return await this.publicClient.readContract({
|
|
@@ -1230,6 +1427,93 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1230
1427
|
apUSDMintDisabled: result[5]
|
|
1231
1428
|
};
|
|
1232
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
|
+
}
|
|
1233
1517
|
async getCurrentFeeTier() {
|
|
1234
1518
|
try {
|
|
1235
1519
|
const result = await this.publicClient.readContract({
|
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",
|
package/src/abi/sApUSD.ts
CHANGED
|
@@ -25,6 +25,18 @@ export const SApUSDABI = [
|
|
|
25
25
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
26
26
|
stateMutability: "view"
|
|
27
27
|
},
|
|
28
|
+
{
|
|
29
|
+
type: "function",
|
|
30
|
+
name: "previewRedeemMulti",
|
|
31
|
+
inputs: [
|
|
32
|
+
{ name: "shares", type: "uint256", internalType: "uint256" }
|
|
33
|
+
],
|
|
34
|
+
outputs: [
|
|
35
|
+
{ name: "assets", type: "address[]", internalType: "address[]" },
|
|
36
|
+
{ name: "amounts", type: "uint256[]", internalType: "uint256[]" }
|
|
37
|
+
],
|
|
38
|
+
stateMutability: "view"
|
|
39
|
+
},
|
|
28
40
|
{
|
|
29
41
|
type: "function",
|
|
30
42
|
name: "hasStabilityConversion",
|
|
@@ -35,6 +47,30 @@ export const SApUSDABI = [
|
|
|
35
47
|
],
|
|
36
48
|
stateMutability: "view"
|
|
37
49
|
},
|
|
50
|
+
{
|
|
51
|
+
type: "function",
|
|
52
|
+
name: "totalValue",
|
|
53
|
+
inputs: [],
|
|
54
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
55
|
+
stateMutability: "view"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "function",
|
|
59
|
+
name: "underlyingBalances",
|
|
60
|
+
inputs: [{ name: "_user", type: "address", internalType: "address" }],
|
|
61
|
+
outputs: [
|
|
62
|
+
{ name: "apUSDBalance", type: "uint256", internalType: "uint256" },
|
|
63
|
+
{ name: "xBNBBalance", type: "uint256", internalType: "uint256" }
|
|
64
|
+
],
|
|
65
|
+
stateMutability: "view"
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "function",
|
|
69
|
+
name: "xBNBToApUSDRate",
|
|
70
|
+
inputs: [],
|
|
71
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
72
|
+
stateMutability: "view"
|
|
73
|
+
},
|
|
38
74
|
{
|
|
39
75
|
type: "function",
|
|
40
76
|
name: "exchangeRate",
|
package/src/client.ts
CHANGED
|
@@ -54,6 +54,7 @@ export function getChainById(chainId: number): Chain {
|
|
|
54
54
|
return chain;
|
|
55
55
|
}
|
|
56
56
|
import { DiamondABI } from "./abi/diamond";
|
|
57
|
+
import { SApUSDABI } from "./abi/sApUSD";
|
|
57
58
|
import type {
|
|
58
59
|
LSTInfo,
|
|
59
60
|
LSTYieldInfo,
|
|
@@ -525,6 +526,20 @@ export class AspanReadClient {
|
|
|
525
526
|
});
|
|
526
527
|
}
|
|
527
528
|
|
|
529
|
+
/**
|
|
530
|
+
* Get user's underlying balances (apUSD + xBNB) from sApUSD vault
|
|
531
|
+
*/
|
|
532
|
+
async getBalanceMulti(user: Address): Promise<{ apUSDBalance: bigint; xBNBBalance: bigint }> {
|
|
533
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
534
|
+
const [apUSDBalance, xBNBBalance] = await this.publicClient.readContract({
|
|
535
|
+
address: sApUSDAddress,
|
|
536
|
+
abi: SApUSDABI,
|
|
537
|
+
functionName: "underlyingBalances",
|
|
538
|
+
args: [user],
|
|
539
|
+
});
|
|
540
|
+
return { apUSDBalance, xBNBBalance };
|
|
541
|
+
}
|
|
542
|
+
|
|
528
543
|
async getUserStabilityPoolPosition(
|
|
529
544
|
user: Address
|
|
530
545
|
): Promise<UserStabilityPoolPosition> {
|
|
@@ -599,6 +614,37 @@ export class AspanReadClient {
|
|
|
599
614
|
}
|
|
600
615
|
}
|
|
601
616
|
|
|
617
|
+
/**
|
|
618
|
+
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
619
|
+
* @param shares Amount of sApUSD shares to redeem
|
|
620
|
+
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
621
|
+
*/
|
|
622
|
+
async previewRedeemMulti(shares: bigint): Promise<{
|
|
623
|
+
apUSD: bigint;
|
|
624
|
+
xBNB: bigint;
|
|
625
|
+
hasXBNB: boolean;
|
|
626
|
+
}> {
|
|
627
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
628
|
+
const [result, conversion] = await Promise.all([
|
|
629
|
+
this.publicClient.readContract({
|
|
630
|
+
address: sApUSDAddress,
|
|
631
|
+
abi: SApUSDABI,
|
|
632
|
+
functionName: "previewRedeemMulti",
|
|
633
|
+
args: [shares],
|
|
634
|
+
}) as Promise<[Address[], bigint[]]>,
|
|
635
|
+
this.publicClient.readContract({
|
|
636
|
+
address: sApUSDAddress,
|
|
637
|
+
abi: SApUSDABI,
|
|
638
|
+
functionName: "hasStabilityConversion",
|
|
639
|
+
}) as Promise<[boolean, bigint]>,
|
|
640
|
+
]);
|
|
641
|
+
return {
|
|
642
|
+
apUSD: result[1][0],
|
|
643
|
+
xBNB: result[1][1],
|
|
644
|
+
hasXBNB: conversion[0],
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
|
|
602
648
|
async getPendingYield(): Promise<bigint> {
|
|
603
649
|
try {
|
|
604
650
|
return await this.publicClient.readContract({
|
|
@@ -770,6 +816,122 @@ export class AspanReadClient {
|
|
|
770
816
|
};
|
|
771
817
|
}
|
|
772
818
|
|
|
819
|
+
/**
|
|
820
|
+
* Get all fee tiers
|
|
821
|
+
* @returns Array of fee tiers sorted by minCR descending
|
|
822
|
+
*/
|
|
823
|
+
async getAllFeeTiers(): Promise<FeeTier[]> {
|
|
824
|
+
const result = await this.publicClient.readContract({
|
|
825
|
+
address: this.diamondAddress,
|
|
826
|
+
abi: DiamondABI,
|
|
827
|
+
functionName: "getAllFeeTiers",
|
|
828
|
+
}) as unknown as Array<{
|
|
829
|
+
minCR: bigint;
|
|
830
|
+
apUSDMintFee: number;
|
|
831
|
+
apUSDRedeemFee: number;
|
|
832
|
+
xBNBMintFee: number;
|
|
833
|
+
xBNBRedeemFee: number;
|
|
834
|
+
apUSDMintDisabled: boolean;
|
|
835
|
+
}>;
|
|
836
|
+
return result.map((tier) => ({
|
|
837
|
+
minCR: tier.minCR,
|
|
838
|
+
apUSDMintFee: tier.apUSDMintFee,
|
|
839
|
+
apUSDRedeemFee: tier.apUSDRedeemFee,
|
|
840
|
+
xBNBMintFee: tier.xBNBMintFee,
|
|
841
|
+
xBNBRedeemFee: tier.xBNBRedeemFee,
|
|
842
|
+
apUSDMintDisabled: tier.apUSDMintDisabled,
|
|
843
|
+
}));
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Get comprehensive vault (sApUSD) info for frontend display
|
|
848
|
+
* @returns Vault state including TVL, exchange rate, xBNB status
|
|
849
|
+
*/
|
|
850
|
+
async getVaultInfo(): Promise<{
|
|
851
|
+
totalSupply: bigint;
|
|
852
|
+
totalAssets: bigint;
|
|
853
|
+
exchangeRate: bigint;
|
|
854
|
+
hasXBNB: boolean;
|
|
855
|
+
xBNBAmount: bigint;
|
|
856
|
+
}> {
|
|
857
|
+
const sApUSDAddress = await this.getSApUSD();
|
|
858
|
+
const [totalSupply, totalAssets, exchangeRate, conversion] = await Promise.all([
|
|
859
|
+
this.publicClient.readContract({
|
|
860
|
+
address: sApUSDAddress,
|
|
861
|
+
abi: SApUSDABI,
|
|
862
|
+
functionName: "totalSupply",
|
|
863
|
+
}) as Promise<bigint>,
|
|
864
|
+
this.publicClient.readContract({
|
|
865
|
+
address: sApUSDAddress,
|
|
866
|
+
abi: SApUSDABI,
|
|
867
|
+
functionName: "totalAssets",
|
|
868
|
+
}) as Promise<bigint>,
|
|
869
|
+
this.publicClient.readContract({
|
|
870
|
+
address: sApUSDAddress,
|
|
871
|
+
abi: SApUSDABI,
|
|
872
|
+
functionName: "exchangeRate",
|
|
873
|
+
}) as Promise<bigint>,
|
|
874
|
+
this.publicClient.readContract({
|
|
875
|
+
address: sApUSDAddress,
|
|
876
|
+
abi: SApUSDABI,
|
|
877
|
+
functionName: "hasStabilityConversion",
|
|
878
|
+
}) as Promise<[boolean, bigint]>,
|
|
879
|
+
]);
|
|
880
|
+
return {
|
|
881
|
+
totalSupply,
|
|
882
|
+
totalAssets,
|
|
883
|
+
exchangeRate,
|
|
884
|
+
hasXBNB: conversion[0],
|
|
885
|
+
xBNBAmount: conversion[1],
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/**
|
|
890
|
+
* Get full protocol dashboard data in one call (for frontend overview page)
|
|
891
|
+
* Batches all key metrics into a single multicall
|
|
892
|
+
*/
|
|
893
|
+
async getProtocolOverview(): Promise<{
|
|
894
|
+
collateralRatio: bigint;
|
|
895
|
+
tvlBNB: bigint;
|
|
896
|
+
tvlUSD: bigint;
|
|
897
|
+
apUSDSupply: bigint;
|
|
898
|
+
xBNBSupply: bigint;
|
|
899
|
+
xBNBPriceUSD: bigint;
|
|
900
|
+
xBNBPriceBNB: bigint;
|
|
901
|
+
bnbPriceUSD: bigint;
|
|
902
|
+
currentFees: CurrentFeeTier;
|
|
903
|
+
stabilityMode: StabilityModeInfo;
|
|
904
|
+
totalStaked: bigint;
|
|
905
|
+
}> {
|
|
906
|
+
const [cr, tvlBNB, tvlUSD, apUSD, xBNB, xPriceUSD, xPriceBNB, bnbPrice, fees, sm, staked] =
|
|
907
|
+
await Promise.all([
|
|
908
|
+
this.getCollateralRatio(),
|
|
909
|
+
this.getTVLInBNB(),
|
|
910
|
+
this.getTVLInUSD(),
|
|
911
|
+
this.getApUSDSupply(),
|
|
912
|
+
this.getXBNBSupply(),
|
|
913
|
+
this.getXBNBPriceUSD(),
|
|
914
|
+
this.getXBNBPriceBNB(),
|
|
915
|
+
this.getBNBPriceUSD(),
|
|
916
|
+
this.getCurrentFeeTier(),
|
|
917
|
+
this.getStabilityMode(),
|
|
918
|
+
this.getTotalStaked(),
|
|
919
|
+
]);
|
|
920
|
+
return {
|
|
921
|
+
collateralRatio: cr,
|
|
922
|
+
tvlBNB,
|
|
923
|
+
tvlUSD,
|
|
924
|
+
apUSDSupply: apUSD,
|
|
925
|
+
xBNBSupply: xBNB,
|
|
926
|
+
xBNBPriceUSD: xPriceUSD,
|
|
927
|
+
xBNBPriceBNB: xPriceBNB,
|
|
928
|
+
bnbPriceUSD: bnbPrice,
|
|
929
|
+
currentFees: fees,
|
|
930
|
+
stabilityMode: sm,
|
|
931
|
+
totalStaked: staked,
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
|
|
773
935
|
async getCurrentFeeTier(): Promise<CurrentFeeTier> {
|
|
774
936
|
try {
|
|
775
937
|
const result = await this.publicClient.readContract({
|