@aspan/sdk 0.3.1 → 0.4.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 CHANGED
@@ -12,26 +12,30 @@ pnpm add @aspan/sdk
12
12
 
13
13
  ## Contract Addresses (BSC Mainnet)
14
14
 
15
+ ```typescript
16
+ import { BSC_ADDRESSES } from "@aspan/sdk";
17
+
18
+ // Or use directly:
19
+ // BSC_ADDRESSES.diamond, BSC_ADDRESSES.router, etc.
20
+ ```
15
21
 
16
22
  | Contract | Address |
17
23
  |----------|---------|
18
24
  | **Diamond (Main Entry)** | `0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f` |
19
- | **Router** | `0x159B2990966B0E4f07cD58c9Def513EA1fF81c0C` |
20
- | **wclisBNB** | `0x439faaC2229559121C4Ad4fd8B3FE13Dff038046` |
25
+ | **Router** | `0x813d3D1A3154950E2f1d8718305426a335A974A9` |
21
26
  | **ApUSD** | `0x1977097E2E5697A6DD91b6732F368a14F50f6B3d` |
22
27
  | **XBNB** | `0xB78eB4d5928bAb158Eb23c3154544084cD2661d5` |
23
28
  | **SApUSD** | `0xE2BE739C4aA4126ee72D612d9548C38B1B0e5A1b` |
24
- | **SlisBNBAdapter** | `0x1B0b8001624CC67031f1c30cCDC12fBdD5752376` |
29
+ | **wclisBNB** | `0x439faaC2229559121C4Ad4fd8B3FE13Dff038046` |
25
30
 
26
31
  ## Quick Start
27
32
 
28
33
  ### Read-Only Client (Query Data)
29
34
 
30
35
  ```typescript
31
- import { createAspanReadClient, formatAmount, formatCR } from "@aspan/sdk";
36
+ import { createAspanReadClient, formatAmount, formatCR, BSC_ADDRESSES } from "@aspan/sdk";
32
37
 
33
- const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";
34
- const client = createAspanReadClient(DIAMOND, "https://bsc-dataseed.binance.org/");
38
+ const client = createAspanReadClient(BSC_ADDRESSES.diamond, "https://bsc-dataseed.binance.org/");
35
39
 
36
40
  const stats = await client.getProtocolStats();
37
41
  console.log("TVL:", formatAmount(stats.tvlInUSD), "USD");
@@ -41,19 +45,17 @@ console.log("CR:", formatCR(stats.collateralRatio));
41
45
  ### Write Client - Browser (React/wagmi)
42
46
 
43
47
  ```typescript
44
- import { AspanClient } from "@aspan/sdk";
48
+ import { AspanClient, BSC_ADDRESSES } from "@aspan/sdk";
45
49
  import { useWalletClient } from "wagmi";
46
50
 
47
- const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";
48
-
49
51
  function MyComponent() {
50
52
  const { data: walletClient } = useWalletClient();
51
53
 
52
54
  const getClient = () => {
53
55
  if (!walletClient) return null;
54
56
  return new AspanClient({
55
- diamondAddress: DIAMOND,
56
- walletClient: walletClient, // Pass wagmi's walletClient
57
+ diamondAddress: BSC_ADDRESSES.diamond,
58
+ walletClient: walletClient,
57
59
  });
58
60
  };
59
61
 
@@ -62,7 +64,7 @@ function MyComponent() {
62
64
  if (!client) return;
63
65
 
64
66
  const hash = await client.mintApUSD({
65
- lstToken: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
67
+ lstToken: BSC_ADDRESSES.slisBNB,
66
68
  lstAmount: parseAmount("1"),
67
69
  });
68
70
  console.log("Tx hash:", hash);
@@ -73,14 +75,14 @@ function MyComponent() {
73
75
  ### Write Client - Node.js / Server
74
76
 
75
77
  ```typescript
76
- import { createAspanClient, parseAmount } from "@aspan/sdk";
78
+ import { createAspanClient, parseAmount, BSC_ADDRESSES } from "@aspan/sdk";
77
79
  import { privateKeyToAccount } from "viem/accounts";
78
80
 
79
81
  const account = privateKeyToAccount("0x...");
80
- const client = createAspanClient(DIAMOND, account);
82
+ const client = createAspanClient(BSC_ADDRESSES.diamond, account);
81
83
 
82
84
  const hash = await client.mintApUSD({
83
- lstToken: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
85
+ lstToken: BSC_ADDRESSES.slisBNB,
84
86
  lstAmount: parseAmount("1"),
85
87
  });
86
88
  ```
@@ -94,41 +96,37 @@ AspanRouter is a periphery contract that enables users to mint/redeem apUSD or x
94
96
  ### Router Client Setup
95
97
 
96
98
  ```typescript
97
- import { createRouterClient, AspanRouterClient } from "@aspan/sdk";
99
+ import { createRouterClient, AspanRouterClient, BSC_ADDRESSES } from "@aspan/sdk";
98
100
  import { privateKeyToAccount } from "viem/accounts";
99
- import { zeroAddress } from "viem";
100
-
101
- const ROUTER = "0x159B2990966B0E4f07cD58c9Def513EA1fF81c0C";
102
101
 
103
102
  // Node.js
104
103
  const account = privateKeyToAccount("0x...");
105
- const router = createRouterClient(ROUTER, account);
104
+ const router = createRouterClient(BSC_ADDRESSES.router, account);
106
105
 
107
106
  // Browser (wagmi)
108
107
  const router = new AspanRouterClient({
109
- routerAddress: ROUTER,
108
+ routerAddress: BSC_ADDRESSES.router,
110
109
  walletClient, // from useWalletClient()
111
110
  });
112
111
  ```
113
112
 
114
- ### Swap USDT/USDC → apUSD (One-Click)
113
+ ### Swap USDT/USDC → apUSD or xBNB (One-Click)
115
114
 
116
115
  ```typescript
117
- import { parseAmount, type SwapAndMintParams } from "@aspan/sdk";
116
+ import { parseAmount, BSC_ADDRESSES, type SwapAndMintParams } from "@aspan/sdk";
118
117
  import { zeroAddress } from "viem";
119
118
 
120
- const USDT = "0x55d398326f99059fF775485246999027B3197955";
121
-
122
119
  // Full control with SwapParams + MintParams
123
120
  const params: SwapAndMintParams = {
124
121
  swapParams: {
125
- inputToken: USDT,
122
+ inputToken: BSC_ADDRESSES.USDT,
126
123
  inputAmount: parseAmount("100"), // 100 USDT
127
124
  targetLST: zeroAddress, // Use default LST
128
125
  minLSTOut: 0n, // Or set slippage protection
129
126
  poolFee: 2500, // 0.25% V3 pool fee
130
127
  },
131
128
  mintParams: {
129
+ mintXBNB: false, // false = apUSD, true = xBNB
132
130
  minMintOut: parseAmount("99"), // Min 99 apUSD (1% slippage)
133
131
  recipient: zeroAddress, // Send to msg.sender
134
132
  deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
@@ -136,77 +134,56 @@ const params: SwapAndMintParams = {
136
134
  };
137
135
 
138
136
  // Approve USDT first, then swap+mint
139
- const hash = await router.swapAndMintApUSD(params);
137
+ const hash = await router.swapAndMint(params);
140
138
  await router.waitForTransaction(hash);
141
139
  ```
142
140
 
143
- ### Simplified: Swap → apUSD (Default LST)
141
+ ### Simplified: Swap → apUSD/xBNB (Default LST)
144
142
 
145
143
  ```typescript
146
- // Simpler API using default LST and V2
147
- const hash = await router.swapAndMintApUSDDefault({
148
- inputToken: USDT,
144
+ // Simpler API using default LST
145
+ const hash = await router.swapAndMintDefault({
146
+ inputToken: BSC_ADDRESSES.USDT,
149
147
  inputAmount: parseAmount("100"),
148
+ mintXBNB: false, // false = apUSD, true = xBNB
150
149
  minMintOut: parseAmount("99"),
151
150
  deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
152
151
  });
153
152
  ```
154
153
 
155
- ### Stake Native BNB → apUSD (Bypasses DEX)
154
+ ### Stake Native BNB → apUSD/xBNB (Bypasses DEX)
156
155
 
157
156
  Direct BNB staking gets better rates for large amounts by bypassing DEX.
158
157
 
159
158
  ```typescript
160
- // Stake BNB directly to Lista/Astherus → mint apUSD
161
- const hash = await router.stakeAndMintApUSD(
162
- parseAmount("99"), // minMintOut
163
- parseAmount("1"), // 1 BNB to stake (sent as value)
164
- );
165
-
166
- // Or with full control
159
+ // Stake BNB directly to Lista/Astherus → mint apUSD or xBNB
167
160
  const hash = await router.stakeAndMint({
168
- targetLST: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", // slisBNB
169
- isXBNB: false,
161
+ targetLST: BSC_ADDRESSES.slisBNB,
162
+ isXBNB: false, // false = apUSD, true = xBNB
170
163
  minMintOut: parseAmount("99"),
171
164
  deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
172
- value: parseAmount("1"), // 1 BNB
173
- });
174
- ```
175
-
176
- ### Swap → xBNB (Leveraged Long)
177
-
178
- ```typescript
179
- // Full params
180
- const hash = await router.swapAndMintXBNB(params);
181
-
182
- // Or simplified
183
- const hash = await router.swapAndMintXBNBDefault({
184
- inputToken: USDT,
185
- inputAmount: parseAmount("1000"),
186
- minMintOut: parseAmount("1"), // Min 1 xBNB
187
- deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
165
+ value: parseAmount("1"), // 1 BNB
188
166
  });
189
-
190
- // Or stake BNB directly
191
- const hash = await router.stakeAndMintXBNB(parseAmount("1"), parseAmount("10"));
192
167
  ```
193
168
 
194
169
  ### Direct Mint/Redeem via Router
195
170
 
196
- If you already have LST, use direct functions (still routes through Diamond):
171
+ If you already have LST, use direct functions:
197
172
 
198
173
  ```typescript
199
- // Mint apUSD with LST
200
- const hash = await router.mintApUSD({
201
- lst: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", // slisBNB
174
+ // Mint apUSD or xBNB with LST
175
+ const hash = await router.mint({
176
+ lst: BSC_ADDRESSES.slisBNB,
202
177
  lstAmount: parseAmount("10"),
178
+ mintXBNB: false, // false = apUSD, true = xBNB
203
179
  minOut: parseAmount("99"),
204
180
  });
205
181
 
206
- // Redeem apUSD for LST
207
- const hash = await router.redeemApUSD({
208
- lst: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
209
- apUSDAmount: parseAmount("100"),
182
+ // Redeem apUSD or xBNB for LST
183
+ const hash = await router.redeem({
184
+ lst: BSC_ADDRESSES.slisBNB,
185
+ redeemXBNB: false, // false = redeem apUSD, true = redeem xBNB
186
+ amount: parseAmount("100"),
210
187
  minOut: parseAmount("0.9"),
211
188
  });
212
189
  ```
@@ -214,31 +191,45 @@ const hash = await router.redeemApUSD({
214
191
  ### Redeem + Swap to USDT/BNB (V3 Path)
215
192
 
216
193
  ```typescript
217
- import { encodeV3Path } from "@aspan/sdk";
218
-
219
- const SLISBNB = "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
220
- const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
221
- const USDT = "0x55d398326f99059fF775485246999027B3197955";
194
+ import { encodeV3Path, BSC_ADDRESSES } from "@aspan/sdk";
222
195
 
223
196
  // Encode V3 swap path: slisBNB → WBNB → USDT
224
- // Use encodeV3Path helper or get optimal path from PancakeSwap Quoter
225
197
  const path = encodeV3Path(
226
- [SLISBNB, WBNB, USDT], // tokens
198
+ [BSC_ADDRESSES.slisBNB, BSC_ADDRESSES.WBNB, BSC_ADDRESSES.USDT],
227
199
  [500, 500] // pool fees (0.05% each hop)
228
200
  );
229
201
 
230
- // Redeem apUSD and swap LST to USDT via V3 path
231
- const hash = await router.redeemApUSDAndSwap({
232
- lst: SLISBNB,
233
- amount: parseAmount("100"), // 100 apUSD
234
- path, // V3 encoded path
235
- minOut: parseAmount("99"), // Min 99 USDT
202
+ // Redeem apUSD/xBNB and swap LST to output token via V3 path
203
+ const hash = await router.redeemAndSwap({
204
+ lst: BSC_ADDRESSES.slisBNB,
205
+ redeemXBNB: false, // false = redeem apUSD, true = redeem xBNB
206
+ amount: parseAmount("100"),
207
+ path,
208
+ minOut: parseAmount("99"),
236
209
  deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
210
+ unwrapBNB: false, // true to unwrap WBNB → native BNB
237
211
  });
238
212
  ```
239
213
 
240
- > **Note**: For optimal swap paths and quotes, use PancakeSwap V3 Quoter contract:
241
- > `0xB048Bbc1Ee6b733FFfCFb9e9CeF7375518e25997` (BSC Mainnet)
214
+ ### Get Native BNB (Auto-unwrap)
215
+
216
+ ```typescript
217
+ // Redeem and get native BNB (auto-unwrap WBNB)
218
+ const path = encodeV3Path(
219
+ [BSC_ADDRESSES.slisBNB, BSC_ADDRESSES.WBNB],
220
+ [2500] // 0.25% pool fee
221
+ );
222
+
223
+ const hash = await router.redeemAndSwap({
224
+ lst: BSC_ADDRESSES.slisBNB,
225
+ redeemXBNB: false,
226
+ amount: parseAmount("100"),
227
+ path,
228
+ minOut: parseAmount("0.15"),
229
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
230
+ unwrapBNB: true, // Auto-unwrap to native BNB!
231
+ });
232
+ ```
242
233
 
243
234
  ### Native Unstake (7-15 Day Unbonding)
244
235
 
@@ -246,9 +237,11 @@ For no-slippage BNB redemption, use Lista's native unstake:
246
237
 
247
238
  ```typescript
248
239
  // Request unstake (starts 7-15 day unbonding period)
249
- const hash = await router.redeemApUSDAndRequestUnstake(parseAmount("100"));
240
+ const hash = await router.redeemAndRequestUnstake({
241
+ redeemXBNB: false, // false = redeem apUSD, true = redeem xBNB
242
+ amount: parseAmount("100"),
243
+ });
250
244
  const receipt = await router.waitForTransaction(hash);
251
- // Parse event to get requestIndex...
252
245
 
253
246
  // Check withdrawal status
254
247
  const indices = await router.getUserWithdrawalIndices(account.address);
@@ -258,7 +251,7 @@ for (const idx of indices) {
258
251
  }
259
252
 
260
253
  // Claim BNB after unbonding
261
- const hash = await router.claimUnstake(requestIndex);
254
+ const claimHash = await router.claimUnstake(requestIndex);
262
255
  ```
263
256
 
264
257
  ### Router View Functions
@@ -266,518 +259,287 @@ const hash = await router.claimUnstake(requestIndex);
266
259
  ```typescript
267
260
  // Check supported tokens
268
261
  const defaultLST = await router.getDefaultLST();
269
- const isSupported = await router.isSupportedInputToken(USDT);
270
- const isLSTSupported = await router.isSupportedLST(slisBNB);
262
+ const isSupported = await router.isSupportedInputToken(BSC_ADDRESSES.USDT);
263
+ const isLSTSupported = await router.isSupportedLST(BSC_ADDRESSES.slisBNB);
271
264
 
272
- // Preview mint/redeem with LST (accurate with fees)
273
- const apUSDOut = await router.previewMintApUSD(slisBNB, parseAmount("1"));
274
- const xBNBOut = await router.previewMintXBNB(slisBNB, parseAmount("1"));
275
- const lstFromApUSD = await router.previewRedeemApUSD(slisBNB, parseAmount("100"));
276
- const lstFromXBNB = await router.previewRedeemXBNB(slisBNB, parseAmount("10"));
265
+ // Preview mint/redeem (accurate with fees)
266
+ const apUSDOut = await router.previewMint(BSC_ADDRESSES.slisBNB, parseAmount("1"), false);
267
+ const xBNBOut = await router.previewMint(BSC_ADDRESSES.slisBNB, parseAmount("1"), true);
268
+ const lstFromApUSD = await router.previewRedeem(BSC_ADDRESSES.slisBNB, false, parseAmount("100"));
269
+ const lstFromXBNB = await router.previewRedeem(BSC_ADDRESSES.slisBNB, true, parseAmount("10"));
277
270
 
278
271
  // Get token addresses
279
272
  const wbnb = await router.getWBNB();
280
273
  const usdt = await router.getUSDT();
281
274
  const slisBNB = await router.getSlisBNB();
282
- const wclisBNB = await router.getWclisBNB();
283
275
  ```
284
276
 
285
277
  ---
286
278
 
287
- ## User Flows
288
-
289
- ### Flow 1: Mint apUSD (Stablecoin)
279
+ ## Use Cases
290
280
 
291
- User deposits LST (e.g., slisBNB) to mint apUSD stablecoin.
281
+ ### 1. New User: USDT apUSD (One-Click)
292
282
 
293
- #### Browser (React/wagmi)
283
+ The simplest way to mint apUSD stablecoin with USDT.
294
284
 
295
285
  ```typescript
296
- import { AspanClient, parseAmount } from "@aspan/sdk";
297
- import { useWalletClient } from "wagmi";
286
+ import { createRouterClient, parseAmount, BSC_ADDRESSES } from "@aspan/sdk";
298
287
 
299
- const DIAMOND = "0x10d25Ae0690533e0BA9E64EC7ae77dbD4fE8A46f";
300
- const SLISBNB = "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
288
+ const router = createRouterClient(BSC_ADDRESSES.router, account);
301
289
 
302
- function MintComponent() {
303
- const { data: walletClient } = useWalletClient();
304
-
305
- const handleMint = async () => {
306
- if (!walletClient) return;
307
-
308
- const client = new AspanClient({
309
- diamondAddress: DIAMOND,
310
- walletClient,
311
- });
312
-
313
- const lstAmount = parseAmount("10"); // 10 slisBNB
314
-
315
- // Step 1: Check LST is supported
316
- const isSupported = await client.isLSTSupported(SLISBNB);
317
- if (!isSupported) throw new Error("LST not supported");
318
-
319
- // Step 2: Check current fees
320
- const fees = await client.getCurrentFees();
321
- if (fees.apUSDMintDisabled) throw new Error("Minting disabled");
322
-
323
- // Step 3: Approve LST (use wagmi's useWriteContract or viem)
324
- // ...
325
-
326
- // Step 4: Calculate minOut for slippage protection (e.g., 0.5% slippage)
327
- const expectedApUSD = lstAmount; // Simplified, use actual calculation
328
- const minOut = expectedApUSD * 995n / 1000n; // 0.5% slippage
329
-
330
- // Step 5: Mint apUSD
331
- const hash = await client.mintApUSD({ lstToken: SLISBNB, lstAmount, minOut });
332
- const receipt = await client.waitForTransaction(hash);
333
- console.log("Minted apUSD:", receipt.status);
334
- };
335
- }
336
- ```
337
-
338
- #### Node.js / Server
339
-
340
- ```typescript
341
- import { createAspanClient, parseAmount } from "@aspan/sdk";
342
- import { privateKeyToAccount } from "viem/accounts";
343
-
344
- const account = privateKeyToAccount("0x...");
345
- const client = createAspanClient(DIAMOND, account);
346
-
347
- const SLISBNB = "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
348
- const lstAmount = parseAmount("10"); // 10 slisBNB
349
-
350
- // Step 1: Check LST is supported
351
- const isSupported = await client.isLSTSupported(SLISBNB);
352
- if (!isSupported) throw new Error("LST not supported");
353
-
354
- // Step 2: Check current fees
355
- const fees = await client.getCurrentFees();
356
- console.log("Mint fee:", fees.apUSDMintFee / 100, "%");
357
- if (fees.apUSDMintDisabled) throw new Error("Minting disabled in current CR");
358
-
359
- // Step 3: Approve LST spending (use viem directly)
360
- // await walletClient.writeContract({
361
- // address: SLISBNB,
362
- // abi: erc20Abi,
363
- // functionName: "approve",
364
- // args: [DIAMOND, lstAmount],
365
- // });
366
-
367
- // Step 4: Mint apUSD with slippage protection
368
- const minOut = lstAmount * 995n / 1000n; // 0.5% slippage tolerance
369
- const hash = await client.mintApUSD({ lstToken: SLISBNB, lstAmount, minOut });
370
- const receipt = await client.waitForTransaction(hash);
371
- console.log("Minted apUSD:", receipt.status);
290
+ // 100 USDT → apUSD (auto DEX swap + mint)
291
+ const hash = await router.swapAndMintDefault({
292
+ inputToken: BSC_ADDRESSES.USDT,
293
+ inputAmount: parseAmount("100"),
294
+ mintXBNB: false, // apUSD
295
+ minMintOut: parseAmount("99"),
296
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
297
+ });
372
298
  ```
373
299
 
374
- ### Flow 2: Redeem apUSD for LST
300
+ ### 2. BNB Holder: BNB apUSD/xBNB (Direct Stake)
375
301
 
376
- User burns apUSD to get back LST.
302
+ For large BNB amounts, stake directly to Lista to avoid DEX slippage.
377
303
 
378
304
  ```typescript
379
- const apUSDAmount = parseAmount("5000"); // 5000 apUSD
380
-
381
- // Step 1: Check available LST liquidity
382
- const collateral = await client.getLSTCollateral(SLISBNB);
383
- const lstPrice = await client.getLSTPriceUSD(SLISBNB);
384
- const maxRedeemable = (collateral * lstPrice) / parseAmount("1");
385
- console.log("Max redeemable:", formatAmount(maxRedeemable), "USD");
386
-
387
- // Step 2: Approve apUSD spending (use viem directly)
388
-
389
- // Step 3: Calculate expected LST output and set minOut
390
- const expectedLST = (apUSDAmount * parseAmount("1")) / lstPrice;
391
- const minOut = expectedLST * 995n / 1000n; // 0.5% slippage
392
-
393
- // Step 4: Redeem with slippage protection
394
- const hash = await client.redeemApUSD({ lstToken: SLISBNB, apUSDAmount, minOut });
395
- await client.waitForTransaction(hash);
305
+ // 1 BNB → apUSD (direct stake, no DEX slippage)
306
+ const hash = await router.stakeAndMint({
307
+ targetLST: BSC_ADDRESSES.slisBNB,
308
+ isXBNB: false, // false = apUSD, true = xBNB
309
+ minMintOut: parseAmount("750"),
310
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
311
+ value: parseAmount("1"), // 1 BNB
312
+ });
396
313
  ```
397
314
 
398
- ### Flow 3: Mint xBNB (Leveraged Long)
315
+ ### 3. Leverage Trader: BNB xBNB (Long BNB)
399
316
 
400
- User deposits LST to mint xBNB, a leveraged long position on BNB.
317
+ xBNB is leveraged BNB exposure, ideal for bullish BNB traders.
401
318
 
402
319
  ```typescript
403
- // Step 1: Check xBNB price and leverage
404
- const xBNBPrice = await client.getXBNBPriceBNB();
405
- const leverage = await client.getEffectiveLeverage();
406
- console.log("xBNB Price:", formatAmount(xBNBPrice), "BNB");
407
- console.log("Effective Leverage:", formatAmount(leverage), "x");
408
-
409
- // Step 2: Check if xBNB is underwater (price = 0)
410
- if (xBNBPrice === 0n) {
411
- throw new Error("xBNB underwater - cannot mint");
412
- }
320
+ // 1 BNB xBNB (~1.2x leverage)
321
+ const hash = await router.stakeAndMint({
322
+ targetLST: BSC_ADDRESSES.slisBNB,
323
+ isXBNB: true, // xBNB
324
+ minMintOut: parseAmount("0.001"),
325
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
326
+ value: parseAmount("1"),
327
+ });
413
328
 
414
- // Step 3: Approve LST, then mint xBNB with slippage protection
415
- const minOut = 0n; // Set appropriate minOut based on expected xBNB output
416
- const hash = await client.mintXBNB({ lstToken: SLISBNB, lstAmount, minOut });
417
- await client.waitForTransaction(hash);
329
+ // Check current leverage
330
+ const stats = await client.getProtocolStats();
331
+ console.log("xBNB Leverage:", formatAmount(stats.effectiveLeverage), "x");
418
332
  ```
419
333
 
420
- ### Flow 4: Redeem xBNB for LST
334
+ ### 4. Yield Farming: apUSD sApUSD (Stability Pool)
421
335
 
422
- User burns xBNB to get back LST.
336
+ Deposit apUSD into the Stability Pool to earn protocol yield.
423
337
 
424
338
  ```typescript
425
- const xBNBAmount = parseAmount("100"); // 100 xBNB
339
+ import { createAspanClient, parseAmount, BSC_ADDRESSES } from "@aspan/sdk";
426
340
 
427
- // Step 1: Check xBNB price (ensure not underwater)
428
- const xBNBPrice = await client.getXBNBPriceBNB();
429
- if (xBNBPrice === 0n) {
430
- throw new Error("xBNB is underwater - redemption may result in 0 LST");
431
- }
432
-
433
- // Step 2: Check current fees
434
- const fees = await client.getCurrentFees();
435
- console.log("xBNB Redeem fee:", fees.xBNBRedeemFee / 100, "%");
341
+ const client = createAspanClient(BSC_ADDRESSES.diamond, account);
436
342
 
437
- // Step 3: Check available LST liquidity
438
- const collateral = await client.getLSTCollateral(SLISBNB);
439
- console.log("Available collateral:", formatAmount(collateral));
343
+ // Deposit apUSD
344
+ const hash = await client.deposit({ apUSDAmount: parseAmount("1000") });
440
345
 
441
- // Step 4: Approve xBNB spending (use viem directly)
442
- // ...
443
-
444
- // Step 5: Calculate expected LST and set minOut for slippage protection
445
- const expectedLST = (xBNBAmount * xBNBPrice) / parseAmount("1");
446
- const minOut = expectedLST * 995n / 1000n; // 0.5% slippage
447
-
448
- // Step 6: Redeem xBNB
449
- const hash = await client.redeemXBNB({ lstToken: SLISBNB, xBNBAmount, minOut });
450
- await client.waitForTransaction(hash);
346
+ // Check earnings
347
+ const position = await client.getUserStabilityPoolPosition(account.address);
348
+ console.log("sApUSD Balance:", formatAmount(position.balance));
349
+ console.log("Earned:", formatAmount(position.balance - position.deposited));
451
350
  ```
452
351
 
453
- ### Flow 5: Stake apUSD to Earn Yield (sApUSD)
352
+ ### 5. Quick Exit: apUSD/xBNB USDT
454
353
 
455
- User deposits apUSD to stability pool to earn LST yield.
354
+ Exit to USDT via DEX swap when you need liquidity fast.
456
355
 
457
356
  ```typescript
458
- // Step 1: Check stability pool stats
459
- const poolStats = await client.getStabilityPoolStats();
460
- console.log("Total Staked:", formatAmount(poolStats.totalStaked));
461
- console.log("Exchange Rate:", formatAmount(poolStats.exchangeRate));
462
-
463
- // Step 2: Preview deposit
464
- const depositAmount = parseAmount("1000");
465
- const expectedShares = await client.previewDeposit(depositAmount);
466
- console.log("Expected shares:", formatAmount(expectedShares));
357
+ import { encodeV3Path, BSC_ADDRESSES } from "@aspan/sdk";
467
358
 
468
- // Step 3: Approve apUSD, then deposit
469
- const hash = await client.deposit({ apUSDAmount: depositAmount });
470
- await client.waitForTransaction(hash);
359
+ // Path: slisBNB WBNB → USDT (PancakeSwap V3)
360
+ const path = encodeV3Path(
361
+ [BSC_ADDRESSES.slisBNB, BSC_ADDRESSES.WBNB, BSC_ADDRESSES.USDT],
362
+ [500, 500]
363
+ );
471
364
 
472
- // Step 4: Check position
473
- const position = await client.getUserStabilityPoolPosition(account.address);
474
- console.log("Shares:", formatAmount(position.shares));
475
- console.log("Balance (incl. yield):", formatAmount(position.balance));
365
+ // 100 apUSD USDT
366
+ const hash = await router.redeemAndSwap({
367
+ lst: BSC_ADDRESSES.slisBNB,
368
+ redeemXBNB: false, // apUSD
369
+ amount: parseAmount("100"),
370
+ path,
371
+ minOut: parseAmount("99"),
372
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
373
+ unwrapBNB: false,
374
+ });
476
375
  ```
477
376
 
478
- ### Flow 6: Withdraw from Stability Pool
377
+ ### 6. Quick Exit: apUSD/xBNB Native BNB (Lista StableSwap)
479
378
 
480
- User withdraws their staked apUSD plus accumulated yield.
379
+ Exit to native BNB using Lista StableSwap for better rates on slisBNB → WBNB.
481
380
 
482
381
  ```typescript
483
- // Step 1: Get user's shares
484
- const shares = await client.getShares(account.address);
485
-
486
- // Step 2: Preview redemption
487
- const expectedAssets = await client.previewRedeem(shares);
488
- console.log("Expected apUSD:", formatAmount(expectedAssets));
489
-
490
- // Step 3: Approve sApUSD shares transfer
491
- // const sApUSD = await client.getSApUSD();
492
-
493
- // Step 4: Withdraw all shares
494
- const hash = await client.withdraw({ shares });
495
- await client.waitForTransaction(hash);
382
+ // For slisBNB WBNB, Router auto-routes through Lista StableSwap
383
+ // Just use a single-hop path
384
+ const path = encodeV3Path(
385
+ [BSC_ADDRESSES.slisBNB, BSC_ADDRESSES.WBNB],
386
+ [100] // Fee tier ignored for Lista StableSwap route
387
+ );
496
388
 
497
- // Or withdraw specific amount of apUSD:
498
- // const hash = await client.withdrawAssets({ assets: parseAmount("500") });
389
+ // xBNB Native BNB
390
+ const hash = await router.redeemAndSwap({
391
+ lst: BSC_ADDRESSES.slisBNB,
392
+ redeemXBNB: true, // xBNB
393
+ amount: parseAmount("0.001"),
394
+ path,
395
+ minOut: parseAmount("0.8"),
396
+ deadline: BigInt(Math.floor(Date.now() / 1000) + 3600),
397
+ unwrapBNB: true, // Auto-unwrap WBNB to native BNB
398
+ });
499
399
  ```
500
400
 
501
- ### Flow 7: Manual Yield Harvest
401
+ ### 7. Zero-Slippage Exit: Lista Native Unstake (7 Days)
502
402
 
503
- Anyone can trigger yield harvest to distribute pending LST yield.
403
+ Don't want to pay DEX slippage? Use Lista native unstake for 1:1 BNB redemption after 7 days.
504
404
 
505
405
  ```typescript
506
- // Step 1: Check pending yield
507
- const yieldStats = await client.getYieldStats();
508
- console.log("Pending yield:", formatAmount(yieldStats.pendingYield), "USD");
509
- console.log("Preview harvest:", formatAmount(yieldStats.previewedHarvest), "USD");
510
-
511
- // Step 2: Harvest (if there's yield)
512
- if (yieldStats.pendingYield + yieldStats.previewedHarvest > 0n) {
513
- const hash = await client.harvestYield();
514
- await client.waitForTransaction(hash);
406
+ // Step 1: Request unstake
407
+ const hash = await router.redeemAndRequestUnstake({
408
+ redeemXBNB: false, // apUSD
409
+ amount: parseAmount("100"),
410
+ });
411
+ await router.waitForTransaction(hash);
412
+
413
+ // Step 2: Check status
414
+ const indices = await router.getUserWithdrawalIndices(account.address);
415
+ for (const idx of indices) {
416
+ const status = await router.getWithdrawalStatus(idx);
417
+ console.log(`#${idx}: ${status.isClaimable ? "Claimable" : "Pending"}, ${formatAmount(status.bnbAmount)} BNB`);
515
418
  }
419
+
420
+ // Step 3: Claim BNB after 7 days
421
+ const claimHash = await router.claimUnstake(requestIndex);
516
422
  ```
517
423
 
518
424
  ---
519
425
 
520
- ## Protocol Metrics Guide
521
-
522
- Based on protocol-analysis.md, here's how to read all key metrics:
523
-
524
- ### Core Metrics (Section 3: Core Math Model)
525
-
526
- | Metric | SDK Method | Description |
527
- |--------|------------|-------------|
528
- | **TVL** | `getTVLInUSD()` | Total Value Locked in USD |
529
- | **TVL (BNB)** | `getTVLInBNB()` | TVL in BNB terms |
530
- | **apUSD Supply** | `getApUSDSupply()` | Total apUSD minted |
531
- | **xBNB Supply** | `getXBNBSupply()` | Total xBNB minted |
532
-
533
- ```typescript
534
- const stats = await client.getProtocolStats();
535
- // stats.tvlInUSD - TVL = sum of all LST collateral value
536
- // stats.apUSDSupply - stable portion of the pool
537
- // stats.xBNBSupply - leveraged long portion
538
- ```
426
+ ## User Flows
539
427
 
540
- ### xBNB Price (Section 3.3 & 4)
428
+ ### Flow 1: Mint apUSD (Stablecoin)
541
429
 
542
- | Metric | SDK Method | Formula |
543
- |--------|------------|---------|
544
- | **xBNB Price (BNB)** | `getXBNBPriceBNB()` | `(TVL_BNB - apUSD_value_BNB) / xBNB_supply` |
545
- | **xBNB Price (USD)** | `getXBNBPriceUSD()` | `xBNB_price_BNB * BNB_price_USD` |
430
+ User deposits LST (e.g., slisBNB) to mint apUSD stablecoin.
546
431
 
547
432
  ```typescript
548
- const xBNBPriceBNB = await client.getXBNBPriceBNB();
549
- const xBNBPriceUSD = await client.getXBNBPriceUSD();
550
- // Price = 0 means xBNB is "underwater" (TVL <= apUSD value)
551
- ```
552
-
553
- ### Collateral Ratio (Section 7)
554
-
555
- | Metric | SDK Method | Formula |
556
- |--------|------------|---------|
557
- | **CR** | `getCollateralRatio()` | `(TVL_USD / apUSD_supply) * 10000` (BPS) |
433
+ import { createAspanClient, parseAmount, BSC_ADDRESSES } from "@aspan/sdk";
434
+ import { privateKeyToAccount } from "viem/accounts";
558
435
 
559
- ```typescript
560
- const cr = await client.getCollateralRatio();
561
- // CR in BPS: 15000 = 150%, 13000 = 130%, 10000 = 100%
562
- console.log("CR:", Number(cr) / 100, "%");
563
- ```
436
+ const account = privateKeyToAccount("0x...");
437
+ const client = createAspanClient(BSC_ADDRESSES.diamond, account);
564
438
 
565
- ### Effective Leverage (Section 5)
439
+ const lstAmount = parseAmount("10"); // 10 slisBNB
566
440
 
567
- | Metric | SDK Method | Formula |
568
- |--------|------------|---------|
569
- | **Leverage** | `getEffectiveLeverage()` | `TVL / xBNB_market_cap` |
441
+ // Check fees
442
+ const fees = await client.getCurrentFees();
443
+ if (fees.apUSDMintDisabled) throw new Error("Minting disabled in current CR");
570
444
 
571
- ```typescript
572
- const leverage = await client.getEffectiveLeverage();
573
- // 1e18 = 1x, 2e18 = 2x leverage
574
- console.log("Leverage:", formatAmount(leverage), "x");
445
+ // Approve LST, then mint with slippage protection
446
+ const minOut = lstAmount * 995n / 1000n; // 0.5% slippage tolerance
447
+ const hash = await client.mintApUSD({
448
+ lstToken: BSC_ADDRESSES.slisBNB,
449
+ lstAmount,
450
+ minOut,
451
+ });
452
+ await client.waitForTransaction(hash);
575
453
  ```
576
454
 
577
- ### Stability Mode (Section 8)
578
-
579
- | Mode | CR Range | Description |
580
- |------|----------|-------------|
581
- | **Normal (0)** | CR >= 150% | Standard operations |
582
- | **Mode 1 (1)** | 130% <= CR < 150% | Fee adjustments active |
583
- | **Mode 2 (2)** | CR < 130% | Forced conversion possible |
455
+ ### Flow 2: Redeem apUSD for LST
584
456
 
585
457
  ```typescript
586
- const mode = await client.getStabilityMode();
587
- // mode.mode: 0=Normal, 1=StabilityMode1, 2=StabilityMode2
588
- // mode.currentCR: Current CR in BPS
589
-
590
- const mode2Info = await client.canTriggerStabilityMode2();
591
- // mode2Info.canTrigger: true if CR < 130%
592
- // mode2Info.potentialConversion: apUSD that would be converted
593
- ```
458
+ const apUSDAmount = parseAmount("5000");
594
459
 
595
- ### Fee Tiers (Section 8.2)
596
-
597
- | Mode | apUSD Mint | apUSD Redeem | xBNB Mint | xBNB Redeem |
598
- |------|------------|--------------|-----------|-------------|
599
- | Normal | 0.2% | 0.2% | 1% | 1% |
600
- | Mode 1 | 0.3% | 0.1% | 0.25% | 4% |
601
- | Mode 2 | **Disabled** | 0% | 0% | 8% |
460
+ // Calculate expected LST and set minOut
461
+ const lstPrice = await client.getLSTPriceUSD(BSC_ADDRESSES.slisBNB);
462
+ const expectedLST = (apUSDAmount * parseAmount("1")) / lstPrice;
463
+ const minOut = expectedLST * 995n / 1000n;
602
464
 
603
- ```typescript
604
- const fees = await client.getCurrentFees();
605
- // fees.currentCR - Current CR
606
- // fees.tierMinCR - Tier threshold
607
- // fees.apUSDMintFee - in BPS (20 = 0.2%)
608
- // fees.apUSDMintDisabled - true in Mode 2
465
+ const hash = await client.redeemApUSD({
466
+ lstToken: BSC_ADDRESSES.slisBNB,
467
+ apUSDAmount,
468
+ minOut,
469
+ });
609
470
  ```
610
471
 
611
- ### Stability Pool / Yield (Section 6)
612
-
613
- | Metric | SDK Method | Description |
614
- |--------|------------|-------------|
615
- | **Total Staked** | `getTotalStaked()` | apUSD in stability pool |
616
- | **Exchange Rate** | `getExchangeRate()` | sApUSD to apUSD ratio |
617
- | **Pending Yield** | `getPendingYield()` | Yield waiting to be distributed |
618
- | **Total Generated** | `getTotalYieldGenerated()` | All-time yield |
472
+ ### Flow 3: Stake apUSD to Earn Yield (sApUSD)
619
473
 
620
474
  ```typescript
475
+ // Check pool stats
621
476
  const poolStats = await client.getStabilityPoolStats();
622
- const yieldStats = await client.getYieldStats();
623
-
624
- // APY calculation (Section 6.2-6.3)
625
- // APY = LST_yield_rate * (TVL / staked_apUSD)
626
- const amplification = stats.tvlInUSD / poolStats.totalStaked;
627
- const estimatedAPY = 0.08 * Number(amplification); // Assuming 8% LST yield
628
- ```
629
-
630
- ### LST Information
631
-
632
- ```typescript
633
- // Get all supported LSTs
634
- const lsts = await client.getSupportedLSTs();
635
-
636
- for (const lst of lsts) {
637
- const info = await client.getLSTInfo(lst);
638
- const price = await client.getLSTPriceUSD(lst);
639
- const collateral = await client.getLSTCollateral(lst);
640
- const yieldInfo = await client.getLSTYieldInfo(lst);
641
-
642
- console.log(`LST: ${lst}`);
643
- console.log(` Accepted: ${info.isAccepted}`);
644
- console.log(` Collateral: ${formatAmount(collateral)}`);
645
- console.log(` Price: $${formatAmount(price)}`);
646
- console.log(` Exchange Rate: ${formatAmount(yieldInfo.lastExchangeRate)}`);
647
- }
648
- ```
649
-
650
- ### Oracle / Prices
477
+ console.log("Exchange Rate:", formatAmount(poolStats.exchangeRate));
651
478
 
652
- ```typescript
653
- const bnbPrice = await client.getBNBPriceUSD();
654
- console.log("BNB Price:", formatPriceUSD(bnbPrice));
655
- // Note: BNB price is 8 decimals (Chainlink format)
479
+ // Deposit apUSD
480
+ const hash = await client.deposit({ apUSDAmount: parseAmount("1000") });
656
481
 
657
- const lstPrice = await client.getLSTPriceUSD(SLISBNB);
658
- console.log("LST Price:", formatAmount(lstPrice), "USD");
659
- // Note: LST price is 18 decimals
482
+ // Check position
483
+ const position = await client.getUserStabilityPoolPosition(account.address);
484
+ console.log("Balance (incl. yield):", formatAmount(position.balance));
660
485
  ```
661
486
 
662
487
  ---
663
488
 
664
- ## Complete Dashboard Example
489
+ ## Protocol Metrics
665
490
 
666
491
  ```typescript
667
- import {
668
- createAspanReadClient,
669
- formatAmount,
670
- formatCR,
671
- formatFeeBPS,
672
- formatPriceUSD,
673
- } from "@aspan/sdk";
674
-
675
- const DIAMOND = "0xa67e91ebbb709516c563bcf1d9dae355aaf6d2ef";
676
- const client = createAspanReadClient(DIAMOND);
677
-
678
- async function displayDashboard() {
679
- // === Protocol Overview ===
680
- const stats = await client.getProtocolStats();
681
- const mode = await client.getStabilityMode();
682
- const fees = await client.getCurrentFees();
683
-
684
- console.log("=== Aspan Protocol Dashboard ===");
685
- console.log(`TVL: $${formatAmount(stats.tvlInUSD)}`);
686
- console.log(`CR: ${formatCR(stats.collateralRatio)}`);
687
- console.log(`Stability Mode: ${mode.mode === 0 ? "Normal" : `Mode ${mode.mode}`}`);
688
- console.log(`Effective Leverage: ${formatAmount(stats.effectiveLeverage)}x`);
689
-
690
- // === Token Stats ===
691
- console.log("\n=== Tokens ===");
692
- console.log(`apUSD Supply: ${formatAmount(stats.apUSDSupply)}`);
693
- console.log(`xBNB Supply: ${formatAmount(stats.xBNBSupply)}`);
694
- console.log(`xBNB Price: ${formatAmount(stats.xBNBPriceBNB)} BNB`);
695
-
696
- // === Current Fees ===
697
- console.log("\n=== Current Fees ===");
698
- console.log(`apUSD Mint: ${formatFeeBPS(fees.apUSDMintFee)}${fees.apUSDMintDisabled ? " (DISABLED)" : ""}`);
699
- console.log(`apUSD Redeem: ${formatFeeBPS(fees.apUSDRedeemFee)}`);
700
- console.log(`xBNB Mint: ${formatFeeBPS(fees.xBNBMintFee)}`);
701
- console.log(`xBNB Redeem: ${formatFeeBPS(fees.xBNBRedeemFee)}`);
702
-
703
- // === Stability Pool ===
704
- const poolStats = await client.getStabilityPoolStats();
705
- const yieldStats = await client.getYieldStats();
706
-
707
- console.log("\n=== Stability Pool (sApUSD) ===");
708
- console.log(`Total Staked: ${formatAmount(poolStats.totalStaked)} apUSD`);
709
- console.log(`Exchange Rate: ${formatAmount(poolStats.exchangeRate)}`);
710
- console.log(`Pending Yield: $${formatAmount(yieldStats.pendingYield)}`);
711
- console.log(`Total Yield Generated: $${formatAmount(yieldStats.totalYieldGenerated)}`);
712
-
713
- // === LST Collateral ===
714
- const lsts = await client.getSupportedLSTs();
715
- console.log("\n=== LST Collateral ===");
716
- for (const lst of lsts) {
717
- const collateral = await client.getLSTCollateral(lst);
718
- const price = await client.getLSTPriceUSD(lst);
719
- const value = (collateral * price) / 10n ** 18n;
720
- console.log(`${lst.slice(0, 10)}...: ${formatAmount(collateral)} ($${formatAmount(value)})`);
721
- }
722
- }
492
+ const stats = await client.getProtocolStats();
493
+ const fees = await client.getCurrentFees();
494
+ const mode = await client.getStabilityMode();
723
495
 
724
- displayDashboard();
496
+ console.log("TVL:", formatAmount(stats.tvlInUSD), "USD");
497
+ console.log("CR:", formatCR(stats.collateralRatio));
498
+ console.log("Stability Mode:", mode.mode);
499
+ console.log("xBNB Price:", formatAmount(stats.xBNBPriceBNB), "BNB");
500
+ console.log("Leverage:", formatAmount(stats.effectiveLeverage), "x");
725
501
  ```
726
502
 
727
503
  ---
728
504
 
729
505
  ## API Reference
730
506
 
731
- ### Client Configuration
732
-
733
- | Option | Type | Required | Description |
734
- |--------|------|----------|-------------|
735
- | `diamondAddress` | `Address` | ✅ | Diamond contract address |
736
- | `chain` | `Chain` | ❌ | Chain config (default: BSC Mainnet) |
737
- | `rpcUrl` | `string` | ❌ | RPC URL (default: BSC public RPC) |
738
- | `walletClient` | `WalletClient` | ⚠️ | For browser/wagmi (required if no account) |
739
- | `account` | `Account` | ⚠️ | For Node.js (required if no walletClient) |
740
-
741
- > ⚠️ Write client requires either `walletClient` (browser) or `account` (Node.js)
507
+ ### Router Write Functions (v2.0.0)
742
508
 
743
- ### View Functions
744
-
745
- | Category | Methods |
746
- |----------|---------|
747
- | **Stats** | `getProtocolStats()`, `getStabilityPoolStats()`, `getYieldStats()` |
748
- | **Pool** | `getTVLInBNB()`, `getTVLInUSD()`, `getCollateralRatio()`, `getXBNBPriceBNB()`, `getXBNBPriceUSD()`, `getEffectiveLeverage()`, `getApUSDSupply()`, `getXBNBSupply()`, `getLSTCollateral()`, `getCurrentFees()` |
749
- | **Stability Pool** | `getShares()`, `getBalance()`, `getUserStabilityPoolPosition()`, `getExchangeRate()`, `getTotalStaked()`, `previewDeposit()`, `previewRedeem()`, `getPendingYield()` |
750
- | **Yield** | `getTotalYieldGenerated()`, `getLSTYieldInfo()`, `getMinHarvestInterval()`, `getLastHarvestTimestamp()`, `previewHarvest()` |
751
- | **Oracle** | `getBNBPriceUSD()`, `getLSTPriceUSD()`, `getLSTInfo()`, `getSupportedLSTs()`, `isLSTSupported()`, `getBNBPriceFeed()`, `getOracleBounds()` |
752
- | **Config** | `getTokens()`, `getSApUSD()`, `getStabilityPool()`, `getTreasury()`, `getFeeTierCount()`, `getFeeTier()`, `getCurrentFeeTier()`, `getMaxPriceAge()`, `getMinDepositPeriod()`, `isPaused()` |
753
- | **Stability Mode** | `getStabilityMode()`, `canTriggerStabilityMode2()` |
754
- | **Ownership** | `getOwner()` |
755
-
756
- ### Write Functions
757
-
758
- | Category | Methods |
759
- |----------|---------|
760
- | **Pool** | `mintApUSD()`, `redeemApUSD()`, `mintXBNB()`, `redeemXBNB()` |
761
- | **Stability Pool** | `deposit()`, `withdraw()`, `withdrawAssets()`, `harvestYield()` |
509
+ | Function | Description |
510
+ |----------|-------------|
511
+ | `swapAndMint(params)` | Swap input token → LST → mint apUSD/xBNB |
512
+ | `swapAndMintDefault(params)` | Simplified swap+mint using default LST |
513
+ | `stakeAndMint(params)` | Stake BNB directly → LST → mint apUSD/xBNB |
514
+ | `mint(params)` | Direct mint apUSD/xBNB with LST |
515
+ | `redeem(params)` | Direct redeem apUSD/xBNB for LST |
516
+ | `redeemAndSwap(params)` | Redeem + swap LST to output token (V3 path, optional unwrapBNB) |
517
+ | `redeemAndRequestUnstake(params)` | Redeem + request native unstake from Lista |
518
+ | `claimUnstake(requestIndex)` | Claim BNB after unbonding period |
762
519
 
763
520
  ### Router View Functions
764
521
 
765
- | Category | Methods |
766
- |----------|---------|
767
- | **Config** | `getDefaultLST()`, `isSupportedInputToken()`, `isSupportedLST()`, `getDiamond()` |
768
- | **Preview** | `previewMintApUSD()`, `previewMintXBNB()`, `previewRedeemApUSD()`, `previewRedeemXBNB()` |
769
- | **Unstake** | `getUserWithdrawalIndices()`, `getWithdrawalStatus()` |
770
- | **Addresses** | `getWBNB()`, `getUSDT()`, `getUSDC()`, `getSlisBNB()`, `getAsBNB()`, `getWclisBNB()`, `getApUSD()`, `getXBNB()` |
771
-
772
- ### Router Write Functions
773
-
774
- | Category | Methods |
775
- |----------|---------|
776
- | **Swap+Mint** | `swapAndMintApUSD()`, `swapAndMintXBNB()`, `swapAndMintApUSDDefault()`, `swapAndMintXBNBDefault()` |
777
- | **Stake+Mint** | `stakeAndMint()`, `stakeAndMintApUSD()`, `stakeAndMintXBNB()` |
778
- | **Direct** | `mintApUSD()`, `mintXBNB()`, `redeemApUSD()`, `redeemXBNB()` |
779
- | **Redeem+Swap** | `redeemApUSDAndSwap()`, `redeemXBNBAndSwap()` (V3 path) |
780
- | **Native Unstake** | `redeemApUSDAndRequestUnstake()`, `redeemXBNBAndRequestUnstake()`, `claimUnstake()` |
522
+ | Function | Description |
523
+ |----------|-------------|
524
+ | `previewMint(lst, amount, mintXBNB)` | Preview mint output |
525
+ | `previewRedeem(lst, redeemXBNB, amount)` | Preview redeem output |
526
+ | `getDefaultLST()` | Get default LST address |
527
+ | `isSupportedInputToken(token)` | Check if input token supported |
528
+ | `isSupportedLST(lst)` | Check if LST supported |
529
+ | `getUserWithdrawalIndices(user)` | Get user's unstake request indices |
530
+ | `getWithdrawalStatus(index)` | Check unstake request status |
531
+
532
+ ### Diamond Write Functions
533
+
534
+ | Function | Description |
535
+ |----------|-------------|
536
+ | `mintApUSD(params)` | Mint apUSD with LST |
537
+ | `redeemApUSD(params)` | Redeem apUSD for LST |
538
+ | `mintXBNB(params)` | Mint xBNB with LST |
539
+ | `redeemXBNB(params)` | Redeem xBNB for LST |
540
+ | `deposit(params)` | Deposit apUSD to stability pool |
541
+ | `withdraw(params)` | Withdraw from stability pool |
542
+ | `harvestYield()` | Trigger yield distribution |
781
543
 
782
544
  ---
783
545
 
@@ -790,7 +552,8 @@ import {
790
552
  formatFeeBPS, // 25 -> "0.25%"
791
553
  formatCR, // 15000n -> "150%"
792
554
  formatPriceUSD, // 58325000000n -> "$583.25"
793
- calculateAPY, // (oldRate, newRate, days) -> APY%
555
+ encodeV3Path, // Encode PancakeSwap V3 swap path
556
+ BSC_ADDRESSES, // All contract addresses
794
557
  PRECISION, // 10^18
795
558
  BPS_PRECISION, // 10000
796
559
  PRICE_PRECISION, // 10^8
@@ -809,13 +572,8 @@ import {
809
572
  createRouterTestnetClient,
810
573
  } from "@aspan/sdk";
811
574
 
812
- // Diamond client (testnet)
813
575
  const client = createAspanTestnetReadClient("0x...");
814
- const writeClient = createAspanTestnetClient("0x...", account);
815
-
816
- // Router client (testnet)
817
- const routerRead = createRouterTestnetReadClient("0x...");
818
- const routerWrite = createRouterTestnetClient("0x...", account);
576
+ const router = createRouterTestnetClient("0x...", account);
819
577
  ```
820
578
 
821
579
  ## License