@aspan/sdk 0.1.4 → 0.1.8
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 +158 -11
- package/dist/index.d.mts +32 -6
- package/dist/index.d.ts +32 -6
- package/dist/index.js +91 -38
- package/dist/index.mjs +91 -38
- package/package.json +1 -1
- package/src/abi/diamond.ts +8 -4
- 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 +118 -42
- package/src/index.ts +5 -4
- package/src/types.ts +8 -0
package/src/abi/diamond.ts
CHANGED
|
@@ -9,7 +9,8 @@ export const DiamondABI = [
|
|
|
9
9
|
name: "mintApUSD",
|
|
10
10
|
inputs: [
|
|
11
11
|
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
12
|
-
{ name: "_lstAmount", type: "uint256", internalType: "uint256" }
|
|
12
|
+
{ name: "_lstAmount", type: "uint256", internalType: "uint256" },
|
|
13
|
+
{ name: "_minOut", type: "uint256", internalType: "uint256" }
|
|
13
14
|
],
|
|
14
15
|
outputs: [{ name: "apUSDAmount", type: "uint256", internalType: "uint256" }],
|
|
15
16
|
stateMutability: "nonpayable"
|
|
@@ -19,7 +20,8 @@ export const DiamondABI = [
|
|
|
19
20
|
name: "redeemApUSD",
|
|
20
21
|
inputs: [
|
|
21
22
|
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
22
|
-
{ name: "_apUSDAmount", type: "uint256", internalType: "uint256" }
|
|
23
|
+
{ name: "_apUSDAmount", type: "uint256", internalType: "uint256" },
|
|
24
|
+
{ name: "_minOut", type: "uint256", internalType: "uint256" }
|
|
23
25
|
],
|
|
24
26
|
outputs: [{ name: "lstAmount", type: "uint256", internalType: "uint256" }],
|
|
25
27
|
stateMutability: "nonpayable"
|
|
@@ -29,7 +31,8 @@ export const DiamondABI = [
|
|
|
29
31
|
name: "mintXBNB",
|
|
30
32
|
inputs: [
|
|
31
33
|
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
32
|
-
{ name: "_lstAmount", type: "uint256", internalType: "uint256" }
|
|
34
|
+
{ name: "_lstAmount", type: "uint256", internalType: "uint256" },
|
|
35
|
+
{ name: "_minOut", type: "uint256", internalType: "uint256" }
|
|
33
36
|
],
|
|
34
37
|
outputs: [{ name: "xBNBAmount", type: "uint256", internalType: "uint256" }],
|
|
35
38
|
stateMutability: "nonpayable"
|
|
@@ -39,7 +42,8 @@ export const DiamondABI = [
|
|
|
39
42
|
name: "redeemXBNB",
|
|
40
43
|
inputs: [
|
|
41
44
|
{ name: "_lstToken", type: "address", internalType: "address" },
|
|
42
|
-
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" }
|
|
45
|
+
{ name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
|
|
46
|
+
{ name: "_minOut", type: "uint256", internalType: "uint256" }
|
|
43
47
|
],
|
|
44
48
|
outputs: [{ name: "lstAmount", type: "uint256", internalType: "uint256" }],
|
|
45
49
|
stateMutability: "nonpayable"
|
package/src/bot/config.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface BotConfig {
|
|
|
17
17
|
statsReportInterval: number;
|
|
18
18
|
crCheckInterval: number;
|
|
19
19
|
|
|
20
|
-
// CR Thresholds (
|
|
20
|
+
// CR Thresholds (BPS: 15000 = 150%, matches contract format)
|
|
21
21
|
crThresholdMode1: bigint;
|
|
22
22
|
crThresholdMode2: bigint;
|
|
23
23
|
|
|
@@ -59,13 +59,13 @@ export function loadConfig(): BotConfig {
|
|
|
59
59
|
), // 5 min
|
|
60
60
|
crCheckInterval: parseInt(process.env.CR_CHECK_INTERVAL_MS ?? "30000", 10), // 30 sec
|
|
61
61
|
|
|
62
|
-
// CR Thresholds
|
|
62
|
+
// CR Thresholds (BPS format to match contract)
|
|
63
63
|
crThresholdMode1: BigInt(
|
|
64
|
-
process.env.CR_THRESHOLD_MODE1 ?? "
|
|
65
|
-
), // 150%
|
|
64
|
+
process.env.CR_THRESHOLD_MODE1 ?? "15000"
|
|
65
|
+
), // 150% in BPS
|
|
66
66
|
crThresholdMode2: BigInt(
|
|
67
|
-
process.env.CR_THRESHOLD_MODE2 ?? "
|
|
68
|
-
), // 130%
|
|
67
|
+
process.env.CR_THRESHOLD_MODE2 ?? "13000"
|
|
68
|
+
), // 130% in BPS
|
|
69
69
|
|
|
70
70
|
// TVL
|
|
71
71
|
tvlImpactThresholdPercent: parseFloat(
|
|
@@ -79,6 +79,14 @@ export class CRMonitor {
|
|
|
79
79
|
const currentCR = stabilityMode.currentCR;
|
|
80
80
|
const now = Date.now();
|
|
81
81
|
|
|
82
|
+
// Skip alerts when protocol is effectively empty
|
|
83
|
+
// CR < 100 BPS (1%) indicates negligible TVL/supply, not a real crisis
|
|
84
|
+
const MIN_MEANINGFUL_CR = 100n; // 1% in BPS
|
|
85
|
+
if (currentCR < MIN_MEANINGFUL_CR) {
|
|
86
|
+
console.log(`[CRMonitor] Protocol effectively empty (CR = ${formatCR(currentCR)}), skipping alerts`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
// Check Mode 2 threshold (< 130%)
|
|
83
91
|
if (currentCR < this.config.crThresholdMode2) {
|
|
84
92
|
if (!this.state.mode2Triggered || this.shouldRepeatAlert(now)) {
|
package/src/client.ts
CHANGED
|
@@ -52,8 +52,10 @@ export interface AspanClientConfig {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
export interface AspanWriteClientConfig extends AspanClientConfig {
|
|
55
|
-
/** Account for signing transactions */
|
|
56
|
-
account
|
|
55
|
+
/** Account for signing transactions (required if walletClient not provided) */
|
|
56
|
+
account?: Account;
|
|
57
|
+
/** External wallet client (for browser environments with wagmi/rainbowkit) */
|
|
58
|
+
walletClient?: WalletClient<Transport, Chain, Account>;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
// ============ Read-Only Client ============
|
|
@@ -100,25 +102,28 @@ export class AspanReadClient {
|
|
|
100
102
|
* Get comprehensive protocol statistics
|
|
101
103
|
*/
|
|
102
104
|
async getProtocolStats(): Promise<ProtocolStats> {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
+
}
|
|
122
127
|
|
|
123
128
|
return {
|
|
124
129
|
tvlInBNB,
|
|
@@ -216,8 +221,8 @@ export class AspanReadClient {
|
|
|
216
221
|
functionName: "getCollateralRatio",
|
|
217
222
|
});
|
|
218
223
|
// Contract returns max uint256 when supply is zero (infinite CR)
|
|
219
|
-
//
|
|
220
|
-
if (cr >
|
|
224
|
+
// CR is in BPS format (10000 = 100%), anything above 100000000 BPS is invalid
|
|
225
|
+
if (cr > 100000000n) {
|
|
221
226
|
return 0n;
|
|
222
227
|
}
|
|
223
228
|
return cr;
|
|
@@ -232,11 +237,17 @@ export class AspanReadClient {
|
|
|
232
237
|
|
|
233
238
|
async getXBNBPriceBNB(): Promise<bigint> {
|
|
234
239
|
try {
|
|
235
|
-
|
|
240
|
+
const price = await this.publicClient.readContract({
|
|
236
241
|
address: this.diamondAddress,
|
|
237
242
|
abi: DiamondABI,
|
|
238
243
|
functionName: "getXBNBPriceBNB",
|
|
239
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;
|
|
240
251
|
} catch (error) {
|
|
241
252
|
// Price undefined when no xBNB exists
|
|
242
253
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -248,11 +259,17 @@ export class AspanReadClient {
|
|
|
248
259
|
|
|
249
260
|
async getXBNBPriceUSD(): Promise<bigint> {
|
|
250
261
|
try {
|
|
251
|
-
|
|
262
|
+
const price = await this.publicClient.readContract({
|
|
252
263
|
address: this.diamondAddress,
|
|
253
264
|
abi: DiamondABI,
|
|
254
265
|
functionName: "getXBNBPriceUSD",
|
|
255
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;
|
|
256
273
|
} catch (error) {
|
|
257
274
|
// Price undefined when no xBNB exists
|
|
258
275
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -264,11 +281,17 @@ export class AspanReadClient {
|
|
|
264
281
|
|
|
265
282
|
async getEffectiveLeverage(): Promise<bigint> {
|
|
266
283
|
try {
|
|
267
|
-
|
|
284
|
+
const leverage = await this.publicClient.readContract({
|
|
268
285
|
address: this.diamondAddress,
|
|
269
286
|
abi: DiamondABI,
|
|
270
287
|
functionName: "getEffectiveLeverage",
|
|
271
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;
|
|
272
295
|
} catch (error) {
|
|
273
296
|
// Leverage undefined when no xBNB exists
|
|
274
297
|
if (this.isZeroSupplyError(error)) {
|
|
@@ -334,8 +357,15 @@ export class AspanReadClient {
|
|
|
334
357
|
functionName: "getCurrentFees",
|
|
335
358
|
});
|
|
336
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
|
+
|
|
337
367
|
return {
|
|
338
|
-
currentCR
|
|
368
|
+
currentCR,
|
|
339
369
|
tierMinCR: result[1],
|
|
340
370
|
apUSDMintFee: result[2],
|
|
341
371
|
apUSDRedeemFee: result[3],
|
|
@@ -398,12 +428,13 @@ export class AspanReadClient {
|
|
|
398
428
|
};
|
|
399
429
|
}
|
|
400
430
|
|
|
401
|
-
async getSupportedLSTs(): Promise<
|
|
402
|
-
|
|
431
|
+
async getSupportedLSTs(): Promise<Address[]> {
|
|
432
|
+
const result = await this.publicClient.readContract({
|
|
403
433
|
address: this.diamondAddress,
|
|
404
434
|
abi: DiamondABI,
|
|
405
435
|
functionName: "getSupportedLSTs",
|
|
406
436
|
});
|
|
437
|
+
return [...result];
|
|
407
438
|
}
|
|
408
439
|
|
|
409
440
|
async isLSTSupported(lstToken: Address): Promise<boolean> {
|
|
@@ -710,6 +741,13 @@ export class AspanReadClient {
|
|
|
710
741
|
functionName: "getCurrentFeeTier",
|
|
711
742
|
});
|
|
712
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
|
+
|
|
713
751
|
return {
|
|
714
752
|
minCR: result[0],
|
|
715
753
|
apUSDMintFee: result[1],
|
|
@@ -717,7 +755,7 @@ export class AspanReadClient {
|
|
|
717
755
|
xBNBMintFee: result[3],
|
|
718
756
|
xBNBRedeemFee: result[4],
|
|
719
757
|
apUSDMintDisabled: result[5],
|
|
720
|
-
currentCR
|
|
758
|
+
currentCR,
|
|
721
759
|
};
|
|
722
760
|
} catch (error) {
|
|
723
761
|
// Return default fee tier when protocol is empty
|
|
@@ -770,9 +808,16 @@ export class AspanReadClient {
|
|
|
770
808
|
functionName: "getStabilityMode",
|
|
771
809
|
});
|
|
772
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
|
+
|
|
773
818
|
return {
|
|
774
819
|
mode: result[0],
|
|
775
|
-
currentCR
|
|
820
|
+
currentCR,
|
|
776
821
|
};
|
|
777
822
|
} catch (error) {
|
|
778
823
|
// Return normal mode when protocol is empty
|
|
@@ -794,9 +839,16 @@ export class AspanReadClient {
|
|
|
794
839
|
functionName: "canTriggerStabilityMode2",
|
|
795
840
|
});
|
|
796
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
|
+
|
|
797
849
|
return {
|
|
798
850
|
canTrigger: result[0],
|
|
799
|
-
currentCR
|
|
851
|
+
currentCR,
|
|
800
852
|
potentialConversion: result[2],
|
|
801
853
|
};
|
|
802
854
|
} catch (error) {
|
|
@@ -829,16 +881,24 @@ export class AspanReadClient {
|
|
|
829
881
|
* Full client with write capabilities for interacting with Aspan Protocol
|
|
830
882
|
*/
|
|
831
883
|
export class AspanClient extends AspanReadClient {
|
|
832
|
-
private readonly walletClient: WalletClient
|
|
884
|
+
private readonly walletClient: WalletClient;
|
|
833
885
|
|
|
834
886
|
constructor(config: AspanWriteClientConfig) {
|
|
835
887
|
super(config);
|
|
836
888
|
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
})
|
|
889
|
+
// Use external walletClient if provided (browser environment with wagmi/rainbowkit)
|
|
890
|
+
// Otherwise create internal walletClient (server environment)
|
|
891
|
+
if (config.walletClient) {
|
|
892
|
+
this.walletClient = config.walletClient;
|
|
893
|
+
} else if (config.account) {
|
|
894
|
+
this.walletClient = createWalletClient({
|
|
895
|
+
account: config.account,
|
|
896
|
+
chain: this.chain,
|
|
897
|
+
transport: http(config.rpcUrl),
|
|
898
|
+
});
|
|
899
|
+
} else {
|
|
900
|
+
throw new Error('Either walletClient or account must be provided');
|
|
901
|
+
}
|
|
842
902
|
}
|
|
843
903
|
|
|
844
904
|
// ============ Pool Write Functions ============
|
|
@@ -850,10 +910,12 @@ export class AspanClient extends AspanReadClient {
|
|
|
850
910
|
*/
|
|
851
911
|
async mintApUSD(params: MintApUSDParams): Promise<Hash> {
|
|
852
912
|
return this.walletClient.writeContract({
|
|
913
|
+
chain: this.chain,
|
|
914
|
+
account: this.walletClient.account!,
|
|
853
915
|
address: this.diamondAddress,
|
|
854
916
|
abi: DiamondABI,
|
|
855
917
|
functionName: "mintApUSD",
|
|
856
|
-
args: [params.lstToken, params.lstAmount],
|
|
918
|
+
args: [params.lstToken, params.lstAmount, params.minOut ?? 0n],
|
|
857
919
|
});
|
|
858
920
|
}
|
|
859
921
|
|
|
@@ -864,10 +926,12 @@ export class AspanClient extends AspanReadClient {
|
|
|
864
926
|
*/
|
|
865
927
|
async redeemApUSD(params: RedeemApUSDParams): Promise<Hash> {
|
|
866
928
|
return this.walletClient.writeContract({
|
|
929
|
+
chain: this.chain,
|
|
930
|
+
account: this.walletClient.account!,
|
|
867
931
|
address: this.diamondAddress,
|
|
868
932
|
abi: DiamondABI,
|
|
869
933
|
functionName: "redeemApUSD",
|
|
870
|
-
args: [params.lstToken, params.apUSDAmount],
|
|
934
|
+
args: [params.lstToken, params.apUSDAmount, params.minOut ?? 0n],
|
|
871
935
|
});
|
|
872
936
|
}
|
|
873
937
|
|
|
@@ -878,10 +942,12 @@ export class AspanClient extends AspanReadClient {
|
|
|
878
942
|
*/
|
|
879
943
|
async mintXBNB(params: MintXBNBParams): Promise<Hash> {
|
|
880
944
|
return this.walletClient.writeContract({
|
|
945
|
+
chain: this.chain,
|
|
946
|
+
account: this.walletClient.account!,
|
|
881
947
|
address: this.diamondAddress,
|
|
882
948
|
abi: DiamondABI,
|
|
883
949
|
functionName: "mintXBNB",
|
|
884
|
-
args: [params.lstToken, params.lstAmount],
|
|
950
|
+
args: [params.lstToken, params.lstAmount, params.minOut ?? 0n],
|
|
885
951
|
});
|
|
886
952
|
}
|
|
887
953
|
|
|
@@ -892,10 +958,12 @@ export class AspanClient extends AspanReadClient {
|
|
|
892
958
|
*/
|
|
893
959
|
async redeemXBNB(params: RedeemXBNBParams): Promise<Hash> {
|
|
894
960
|
return this.walletClient.writeContract({
|
|
961
|
+
chain: this.chain,
|
|
962
|
+
account: this.walletClient.account!,
|
|
895
963
|
address: this.diamondAddress,
|
|
896
964
|
abi: DiamondABI,
|
|
897
965
|
functionName: "redeemXBNB",
|
|
898
|
-
args: [params.lstToken, params.xBNBAmount],
|
|
966
|
+
args: [params.lstToken, params.xBNBAmount, params.minOut ?? 0n],
|
|
899
967
|
});
|
|
900
968
|
}
|
|
901
969
|
|
|
@@ -908,6 +976,8 @@ export class AspanClient extends AspanReadClient {
|
|
|
908
976
|
*/
|
|
909
977
|
async deposit(params: DepositParams): Promise<Hash> {
|
|
910
978
|
return this.walletClient.writeContract({
|
|
979
|
+
chain: this.chain,
|
|
980
|
+
account: this.walletClient.account!,
|
|
911
981
|
address: this.diamondAddress,
|
|
912
982
|
abi: DiamondABI,
|
|
913
983
|
functionName: "deposit",
|
|
@@ -922,6 +992,8 @@ export class AspanClient extends AspanReadClient {
|
|
|
922
992
|
*/
|
|
923
993
|
async withdraw(params: WithdrawParams): Promise<Hash> {
|
|
924
994
|
return this.walletClient.writeContract({
|
|
995
|
+
chain: this.chain,
|
|
996
|
+
account: this.walletClient.account!,
|
|
925
997
|
address: this.diamondAddress,
|
|
926
998
|
abi: DiamondABI,
|
|
927
999
|
functionName: "withdraw",
|
|
@@ -936,6 +1008,8 @@ export class AspanClient extends AspanReadClient {
|
|
|
936
1008
|
*/
|
|
937
1009
|
async withdrawAssets(params: WithdrawAssetsParams): Promise<Hash> {
|
|
938
1010
|
return this.walletClient.writeContract({
|
|
1011
|
+
chain: this.chain,
|
|
1012
|
+
account: this.walletClient.account!,
|
|
939
1013
|
address: this.diamondAddress,
|
|
940
1014
|
abi: DiamondABI,
|
|
941
1015
|
functionName: "withdrawAssets",
|
|
@@ -949,6 +1023,8 @@ export class AspanClient extends AspanReadClient {
|
|
|
949
1023
|
*/
|
|
950
1024
|
async harvestYield(): Promise<Hash> {
|
|
951
1025
|
return this.walletClient.writeContract({
|
|
1026
|
+
chain: this.chain,
|
|
1027
|
+
account: this.walletClient.account!,
|
|
952
1028
|
address: this.diamondAddress,
|
|
953
1029
|
abi: DiamondABI,
|
|
954
1030
|
functionName: "harvestYield",
|
package/src/index.ts
CHANGED
|
@@ -102,12 +102,13 @@ export function formatFeeBPS(bps: number): string {
|
|
|
102
102
|
|
|
103
103
|
/**
|
|
104
104
|
* Format collateral ratio to percentage string
|
|
105
|
-
* @param cr Collateral ratio
|
|
106
|
-
* @returns Percentage string (e.g., "150%")
|
|
105
|
+
* @param cr Collateral ratio in BPS (10000 = 100%, contract format)
|
|
106
|
+
* @returns Percentage string (e.g., "150.00%")
|
|
107
107
|
*/
|
|
108
108
|
export function formatCR(cr: bigint): string {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
// CR is in BPS: 15000 = 150%
|
|
110
|
+
const percentage = Number(cr) / 100;
|
|
111
|
+
return `${percentage.toFixed(2)}%`;
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
/**
|
package/src/types.ts
CHANGED
|
@@ -90,24 +90,32 @@ export interface StabilityMode2Result {
|
|
|
90
90
|
export interface MintApUSDParams {
|
|
91
91
|
lstToken: Address;
|
|
92
92
|
lstAmount: bigint;
|
|
93
|
+
/** Minimum apUSD output for slippage protection (default: 0n) */
|
|
94
|
+
minOut?: bigint;
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
/** Parameters for redeeming apUSD */
|
|
96
98
|
export interface RedeemApUSDParams {
|
|
97
99
|
lstToken: Address;
|
|
98
100
|
apUSDAmount: bigint;
|
|
101
|
+
/** Minimum LST output for slippage protection (default: 0n) */
|
|
102
|
+
minOut?: bigint;
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
/** Parameters for minting xBNB */
|
|
102
106
|
export interface MintXBNBParams {
|
|
103
107
|
lstToken: Address;
|
|
104
108
|
lstAmount: bigint;
|
|
109
|
+
/** Minimum xBNB output for slippage protection (default: 0n) */
|
|
110
|
+
minOut?: bigint;
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
/** Parameters for redeeming xBNB */
|
|
108
114
|
export interface RedeemXBNBParams {
|
|
109
115
|
lstToken: Address;
|
|
110
116
|
xBNBAmount: bigint;
|
|
117
|
+
/** Minimum LST output for slippage protection (default: 0n) */
|
|
118
|
+
minOut?: bigint;
|
|
111
119
|
}
|
|
112
120
|
|
|
113
121
|
/** Parameters for depositing to stability pool */
|