@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/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
- const [
106
- tvlInBNB,
107
- tvlInUSD,
108
- collateralRatio,
109
- apUSDSupply,
110
- xBNBSupply,
111
- xBNBPriceBNB,
112
- xBNBPriceUSD,
113
- effectiveLeverage,
114
- ] = await Promise.all([
115
- this.getTVLInBNB(),
116
- this.getTVLInUSD(),
117
- this.getCollateralRatio(),
118
- this.getApUSDSupply(),
119
- this.getXBNBSupply(),
120
- this.getXBNBPriceBNB(),
121
- this.getXBNBPriceUSD(),
122
- this.getEffectiveLeverage(),
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
- // Treat anything above 1000000% (10000 * 1e18) as zero/undefined
222
- if (cr > 10000n * 10n ** 18n) {
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
- return await this.publicClient.readContract({
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
- return await this.publicClient.readContract({
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
- return await this.publicClient.readContract({
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: result[0],
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: result[6],
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: result[1],
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: result[1],
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 (18 decimals, 1e18 = 100%)
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
- const percentage = (cr * 100n) / PRECISION;
110
- return `${percentage}%`;
144
+ // CR is in BPS: 15000 = 150%
145
+ const percentage = Number(cr) / 100;
146
+ return `${percentage.toFixed(2)}%`;
111
147
  }
112
148
 
113
149
  /**