@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/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({
|
|
@@ -1115,22 +1277,36 @@ export class AspanClient extends AspanReadClient {
|
|
|
1115
1277
|
}
|
|
1116
1278
|
|
|
1117
1279
|
/**
|
|
1118
|
-
* Clean
|
|
1119
|
-
* @
|
|
1120
|
-
* @param
|
|
1280
|
+
* Clean xBNB from sApUSD vault by converting back to apUSD
|
|
1281
|
+
* @param xBNBAmount Amount of xBNB to clean
|
|
1282
|
+
* @param minApUSDOut Minimum apUSD to receive (slippage protection)
|
|
1121
1283
|
* @returns Transaction hash
|
|
1122
1284
|
*/
|
|
1123
|
-
async
|
|
1285
|
+
async cleanVaultXBNB(xBNBAmount: bigint, minApUSDOut: bigint = 0n): Promise<Hash> {
|
|
1124
1286
|
return this.walletClient.writeContract({
|
|
1125
1287
|
chain: this.chain,
|
|
1126
1288
|
account: this.walletClient.account!,
|
|
1127
1289
|
address: this.diamondAddress,
|
|
1128
1290
|
abi: DiamondABI,
|
|
1129
|
-
functionName: "
|
|
1130
|
-
args: [xBNBAmount],
|
|
1291
|
+
functionName: "cleanVaultXBNB",
|
|
1292
|
+
args: [xBNBAmount, minApUSDOut],
|
|
1131
1293
|
});
|
|
1132
1294
|
}
|
|
1133
1295
|
|
|
1296
|
+
/**
|
|
1297
|
+
* Preview how much apUSD would be minted from cleaning xBNB
|
|
1298
|
+
* @param xBNBAmount Amount of xBNB to preview
|
|
1299
|
+
* @returns apUSD amount that would be minted
|
|
1300
|
+
*/
|
|
1301
|
+
async previewCleanVaultXBNB(xBNBAmount: bigint): Promise<bigint> {
|
|
1302
|
+
return this.publicClient.readContract({
|
|
1303
|
+
address: this.diamondAddress,
|
|
1304
|
+
abi: DiamondABI,
|
|
1305
|
+
functionName: "previewCleanVaultXBNB",
|
|
1306
|
+
args: [xBNBAmount],
|
|
1307
|
+
}) as Promise<bigint>;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1134
1310
|
// ============ Fee Management Functions ============
|
|
1135
1311
|
|
|
1136
1312
|
/**
|
package/src/index.ts
CHANGED
|
@@ -120,7 +120,7 @@ export const BSC_ADDRESSES = {
|
|
|
120
120
|
router: "0x29dd49b2e98674ee7531f17e4d40a7725918c3f6" as const,
|
|
121
121
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as const,
|
|
122
122
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as const,
|
|
123
|
-
sApUSD: "
|
|
123
|
+
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB" as const,
|
|
124
124
|
// LSTs
|
|
125
125
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B" as const,
|
|
126
126
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6" as const,
|