@aspan/sdk 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +273 -11
- package/dist/index.d.mts +1209 -3
- package/dist/index.d.ts +1209 -3
- package/dist/index.js +1111 -32
- package/dist/index.mjs +1109 -32
- package/package.json +1 -1
- package/src/abi/diamond.ts +8 -4
- package/src/abi/router.ts +554 -0
- package/src/bot/config.ts +6 -6
- package/src/bot/monitors/cr-monitor.ts +8 -0
- package/src/bot/monitors/stats-monitor.ts +1 -1
- package/src/client.ts +81 -32
- package/src/index.ts +40 -4
- package/src/router.ts +686 -0
- package/src/types.ts +226 -0
package/src/client.ts
CHANGED
|
@@ -102,25 +102,28 @@ export class AspanReadClient {
|
|
|
102
102
|
* Get comprehensive protocol statistics
|
|
103
103
|
*/
|
|
104
104
|
async getProtocolStats(): Promise<ProtocolStats> {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
105
|
+
// First get supplies to determine if xBNB exists
|
|
106
|
+
const [tvlInBNB, tvlInUSD, collateralRatio, apUSDSupply, xBNBSupply] =
|
|
107
|
+
await Promise.all([
|
|
108
|
+
this.getTVLInBNB(),
|
|
109
|
+
this.getTVLInUSD(),
|
|
110
|
+
this.getCollateralRatio(),
|
|
111
|
+
this.getApUSDSupply(),
|
|
112
|
+
this.getXBNBSupply(),
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
// Only fetch xBNB price and leverage if xBNB supply exists
|
|
116
|
+
let xBNBPriceBNB = 0n;
|
|
117
|
+
let xBNBPriceUSD = 0n;
|
|
118
|
+
let effectiveLeverage = 0n;
|
|
119
|
+
|
|
120
|
+
if (xBNBSupply > 0n) {
|
|
121
|
+
[xBNBPriceBNB, xBNBPriceUSD, effectiveLeverage] = await Promise.all([
|
|
122
|
+
this.getXBNBPriceBNB(),
|
|
123
|
+
this.getXBNBPriceUSD(),
|
|
124
|
+
this.getEffectiveLeverage(),
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
124
127
|
|
|
125
128
|
return {
|
|
126
129
|
tvlInBNB,
|
|
@@ -218,8 +221,8 @@ export class AspanReadClient {
|
|
|
218
221
|
functionName: "getCollateralRatio",
|
|
219
222
|
});
|
|
220
223
|
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
221
|
-
//
|
|
222
|
-
if (cr >
|
|
224
|
+
// CR is in BPS format (10000 = 100%), anything above 100000000 BPS is invalid
|
|
225
|
+
if (cr > 100000000n) {
|
|
223
226
|
return 0n;
|
|
224
227
|
}
|
|
225
228
|
return cr;
|
|
@@ -234,11 +237,17 @@ export class AspanReadClient {
|
|
|
234
237
|
|
|
235
238
|
async getXBNBPriceBNB(): Promise<bigint> {
|
|
236
239
|
try {
|
|
237
|
-
|
|
240
|
+
const price = await this.publicClient.readContract({
|
|
238
241
|
address: this.diamondAddress,
|
|
239
242
|
abi: DiamondABI,
|
|
240
243
|
functionName: "getXBNBPriceBNB",
|
|
241
244
|
});
|
|
245
|
+
// Contract returns extreme values when xBNB supply is zero
|
|
246
|
+
// Normal xBNB price should be < 1000 BNB (1000 * 1e18)
|
|
247
|
+
if (price > 1000n * 10n ** 18n) {
|
|
248
|
+
return 0n;
|
|
249
|
+
}
|
|
250
|
+
return price;
|
|
242
251
|
} catch (error) {
|
|
243
252
|
// Price undefined when no xBNB exists
|
|
244
253
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -250,11 +259,17 @@ export class AspanReadClient {
|
|
|
250
259
|
|
|
251
260
|
async getXBNBPriceUSD(): Promise<bigint> {
|
|
252
261
|
try {
|
|
253
|
-
|
|
262
|
+
const price = await this.publicClient.readContract({
|
|
254
263
|
address: this.diamondAddress,
|
|
255
264
|
abi: DiamondABI,
|
|
256
265
|
functionName: "getXBNBPriceUSD",
|
|
257
266
|
});
|
|
267
|
+
// Contract returns extreme values when xBNB supply is zero
|
|
268
|
+
// xBNBPriceUSD is in 18 decimals, normal price should be < $1,000,000 (1e6 * 1e18)
|
|
269
|
+
if (price > 1000000n * 10n ** 18n) {
|
|
270
|
+
return 0n;
|
|
271
|
+
}
|
|
272
|
+
return price;
|
|
258
273
|
} catch (error) {
|
|
259
274
|
// Price undefined when no xBNB exists
|
|
260
275
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -266,11 +281,17 @@ export class AspanReadClient {
|
|
|
266
281
|
|
|
267
282
|
async getEffectiveLeverage(): Promise<bigint> {
|
|
268
283
|
try {
|
|
269
|
-
|
|
284
|
+
const leverage = await this.publicClient.readContract({
|
|
270
285
|
address: this.diamondAddress,
|
|
271
286
|
abi: DiamondABI,
|
|
272
287
|
functionName: "getEffectiveLeverage",
|
|
273
288
|
});
|
|
289
|
+
// Contract returns extreme values when xBNB supply is zero
|
|
290
|
+
// Normal leverage should be < 100x (100 * 1e18)
|
|
291
|
+
if (leverage > 100n * 10n ** 18n) {
|
|
292
|
+
return 0n;
|
|
293
|
+
}
|
|
294
|
+
return leverage;
|
|
274
295
|
} catch (error) {
|
|
275
296
|
// Leverage undefined when no xBNB exists
|
|
276
297
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -336,8 +357,15 @@ export class AspanReadClient {
|
|
|
336
357
|
functionName: "getCurrentFees",
|
|
337
358
|
});
|
|
338
359
|
|
|
360
|
+
let currentCR = result[0];
|
|
361
|
+
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
362
|
+
// CR is in BPS format (10000 = 100%)
|
|
363
|
+
if (currentCR > 100000000n) {
|
|
364
|
+
currentCR = 0n;
|
|
365
|
+
}
|
|
366
|
+
|
|
339
367
|
return {
|
|
340
|
-
currentCR
|
|
368
|
+
currentCR,
|
|
341
369
|
tierMinCR: result[1],
|
|
342
370
|
apUSDMintFee: result[2],
|
|
343
371
|
apUSDRedeemFee: result[3],
|
|
@@ -713,6 +741,13 @@ export class AspanReadClient {
|
|
|
713
741
|
functionName: "getCurrentFeeTier",
|
|
714
742
|
});
|
|
715
743
|
|
|
744
|
+
let currentCR = result[6];
|
|
745
|
+
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
746
|
+
// CR is in BPS format (10000 = 100%)
|
|
747
|
+
if (currentCR > 100000000n) {
|
|
748
|
+
currentCR = 0n;
|
|
749
|
+
}
|
|
750
|
+
|
|
716
751
|
return {
|
|
717
752
|
minCR: result[0],
|
|
718
753
|
apUSDMintFee: result[1],
|
|
@@ -720,7 +755,7 @@ export class AspanReadClient {
|
|
|
720
755
|
xBNBMintFee: result[3],
|
|
721
756
|
xBNBRedeemFee: result[4],
|
|
722
757
|
apUSDMintDisabled: result[5],
|
|
723
|
-
currentCR
|
|
758
|
+
currentCR,
|
|
724
759
|
};
|
|
725
760
|
} catch (error) {
|
|
726
761
|
// Return default fee tier when protocol is empty
|
|
@@ -773,9 +808,16 @@ export class AspanReadClient {
|
|
|
773
808
|
functionName: "getStabilityMode",
|
|
774
809
|
});
|
|
775
810
|
|
|
811
|
+
let currentCR = result[1];
|
|
812
|
+
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
813
|
+
// CR is in BPS format (10000 = 100%)
|
|
814
|
+
if (currentCR > 100000000n) {
|
|
815
|
+
currentCR = 0n;
|
|
816
|
+
}
|
|
817
|
+
|
|
776
818
|
return {
|
|
777
819
|
mode: result[0],
|
|
778
|
-
currentCR
|
|
820
|
+
currentCR,
|
|
779
821
|
};
|
|
780
822
|
} catch (error) {
|
|
781
823
|
// Return normal mode when protocol is empty
|
|
@@ -797,9 +839,16 @@ export class AspanReadClient {
|
|
|
797
839
|
functionName: "canTriggerStabilityMode2",
|
|
798
840
|
});
|
|
799
841
|
|
|
842
|
+
let currentCR = result[1];
|
|
843
|
+
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
844
|
+
// CR is in BPS format (10000 = 100%)
|
|
845
|
+
if (currentCR > 100000000n) {
|
|
846
|
+
currentCR = 0n;
|
|
847
|
+
}
|
|
848
|
+
|
|
800
849
|
return {
|
|
801
850
|
canTrigger: result[0],
|
|
802
|
-
currentCR
|
|
851
|
+
currentCR,
|
|
803
852
|
potentialConversion: result[2],
|
|
804
853
|
};
|
|
805
854
|
} catch (error) {
|
|
@@ -866,7 +915,7 @@ export class AspanClient extends AspanReadClient {
|
|
|
866
915
|
address: this.diamondAddress,
|
|
867
916
|
abi: DiamondABI,
|
|
868
917
|
functionName: "mintApUSD",
|
|
869
|
-
args: [params.lstToken, params.lstAmount],
|
|
918
|
+
args: [params.lstToken, params.lstAmount, params.minOut ?? 0n],
|
|
870
919
|
});
|
|
871
920
|
}
|
|
872
921
|
|
|
@@ -882,7 +931,7 @@ export class AspanClient extends AspanReadClient {
|
|
|
882
931
|
address: this.diamondAddress,
|
|
883
932
|
abi: DiamondABI,
|
|
884
933
|
functionName: "redeemApUSD",
|
|
885
|
-
args: [params.lstToken, params.apUSDAmount],
|
|
934
|
+
args: [params.lstToken, params.apUSDAmount, params.minOut ?? 0n],
|
|
886
935
|
});
|
|
887
936
|
}
|
|
888
937
|
|
|
@@ -898,7 +947,7 @@ export class AspanClient extends AspanReadClient {
|
|
|
898
947
|
address: this.diamondAddress,
|
|
899
948
|
abi: DiamondABI,
|
|
900
949
|
functionName: "mintXBNB",
|
|
901
|
-
args: [params.lstToken, params.lstAmount],
|
|
950
|
+
args: [params.lstToken, params.lstAmount, params.minOut ?? 0n],
|
|
902
951
|
});
|
|
903
952
|
}
|
|
904
953
|
|
|
@@ -914,7 +963,7 @@ export class AspanClient extends AspanReadClient {
|
|
|
914
963
|
address: this.diamondAddress,
|
|
915
964
|
abi: DiamondABI,
|
|
916
965
|
functionName: "redeemXBNB",
|
|
917
|
-
args: [params.lstToken, params.xBNBAmount],
|
|
966
|
+
args: [params.lstToken, params.xBNBAmount, params.minOut ?? 0n],
|
|
918
967
|
});
|
|
919
968
|
}
|
|
920
969
|
|
package/src/index.ts
CHANGED
|
@@ -17,6 +17,18 @@ export {
|
|
|
17
17
|
type AspanWriteClientConfig,
|
|
18
18
|
} from "./client";
|
|
19
19
|
|
|
20
|
+
// ============ Router Client Classes ============
|
|
21
|
+
export {
|
|
22
|
+
AspanRouterReadClient,
|
|
23
|
+
AspanRouterClient,
|
|
24
|
+
createRouterReadClient,
|
|
25
|
+
createRouterClient,
|
|
26
|
+
createRouterTestnetReadClient,
|
|
27
|
+
createRouterTestnetClient,
|
|
28
|
+
type AspanRouterClientConfig,
|
|
29
|
+
type AspanRouterWriteClientConfig,
|
|
30
|
+
} from "./router";
|
|
31
|
+
|
|
20
32
|
// ============ Types ============
|
|
21
33
|
export type {
|
|
22
34
|
// Core types
|
|
@@ -54,10 +66,33 @@ export type {
|
|
|
54
66
|
// Transaction result
|
|
55
67
|
TransactionResult,
|
|
56
68
|
TransactionReceipt,
|
|
69
|
+
// Router types
|
|
70
|
+
RouterSwapParams,
|
|
71
|
+
RouterMintParams,
|
|
72
|
+
SwapAndMintParams,
|
|
73
|
+
StakeAndMintParams,
|
|
74
|
+
SwapAndMintDefaultParams,
|
|
75
|
+
RouterMintApUSDParams,
|
|
76
|
+
RouterMintXBNBParams,
|
|
77
|
+
RouterRedeemApUSDParams,
|
|
78
|
+
RouterRedeemXBNBParams,
|
|
79
|
+
RouterRedeemAndSwapParams,
|
|
80
|
+
RouterRedeemAndUnstakeParams,
|
|
81
|
+
WithdrawalRequestInfo,
|
|
82
|
+
ExpectedOutput,
|
|
83
|
+
// Router events
|
|
84
|
+
SwapAndMintEvent,
|
|
85
|
+
StakeAndMintEvent,
|
|
86
|
+
RouterMintEvent,
|
|
87
|
+
RouterRedeemEvent,
|
|
88
|
+
RedeemAndSwapEvent,
|
|
89
|
+
UnstakeRequestedEvent,
|
|
90
|
+
UnstakeClaimedEvent,
|
|
57
91
|
} from "./types";
|
|
58
92
|
|
|
59
93
|
// ============ ABI ============
|
|
60
94
|
export { DiamondABI } from "./abi/diamond";
|
|
95
|
+
export { RouterABI } from "./abi/router";
|
|
61
96
|
|
|
62
97
|
// ============ Constants ============
|
|
63
98
|
export const PRECISION = 10n ** 18n;
|
|
@@ -102,12 +137,13 @@ export function formatFeeBPS(bps: number): string {
|
|
|
102
137
|
|
|
103
138
|
/**
|
|
104
139
|
* Format collateral ratio to percentage string
|
|
105
|
-
* @param cr Collateral ratio
|
|
106
|
-
* @returns Percentage string (e.g., "150%")
|
|
140
|
+
* @param cr Collateral ratio in BPS (10000 = 100%, contract format)
|
|
141
|
+
* @returns Percentage string (e.g., "150.00%")
|
|
107
142
|
*/
|
|
108
143
|
export function formatCR(cr: bigint): string {
|
|
109
|
-
|
|
110
|
-
|
|
144
|
+
// CR is in BPS: 15000 = 150%
|
|
145
|
+
const percentage = Number(cr) / 100;
|
|
146
|
+
return `${percentage.toFixed(2)}%`;
|
|
111
147
|
}
|
|
112
148
|
|
|
113
149
|
/**
|