@aspan/sdk 0.4.7 → 0.4.9

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.mjs CHANGED
@@ -245,15 +245,25 @@ var DiamondABI = [
245
245
  {
246
246
  type: "function",
247
247
  name: "deposit",
248
- inputs: [{ name: "_apUSDAmount", type: "uint256", internalType: "uint256" }],
248
+ inputs: [
249
+ { name: "assets", type: "uint256", internalType: "uint256" },
250
+ { name: "receiver", type: "address", internalType: "address" }
251
+ ],
249
252
  outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
250
253
  stateMutability: "nonpayable"
251
254
  },
252
255
  {
253
256
  type: "function",
254
- name: "withdraw",
255
- inputs: [{ name: "_shares", type: "uint256", internalType: "uint256" }],
256
- outputs: [{ name: "assets", type: "uint256", internalType: "uint256" }],
257
+ name: "redeem",
258
+ inputs: [
259
+ { name: "shares", type: "uint256", internalType: "uint256" },
260
+ { name: "receiver", type: "address", internalType: "address" },
261
+ { name: "owner", type: "address", internalType: "address" }
262
+ ],
263
+ outputs: [
264
+ { name: "apUSDOut", type: "uint256", internalType: "uint256" },
265
+ { name: "xBNBOut", type: "uint256", internalType: "uint256" }
266
+ ],
257
267
  stateMutability: "nonpayable"
258
268
  },
259
269
  {
@@ -834,7 +844,8 @@ var AspanReadClient = class _AspanReadClient {
834
844
  this.chain = config.chain ?? bsc;
835
845
  this.publicClient = createPublicClient({
836
846
  chain: this.chain,
837
- transport: http(config.rpcUrl)
847
+ transport: http(config.rpcUrl),
848
+ batch: { multicall: true }
838
849
  });
839
850
  }
840
851
  /**
@@ -1743,22 +1754,22 @@ var AspanClient = class extends AspanReadClient {
1743
1754
  address: this.diamondAddress,
1744
1755
  abi: DiamondABI,
1745
1756
  functionName: "deposit",
1746
- args: [params.apUSDAmount]
1757
+ args: [params.assets, params.receiver]
1747
1758
  });
1748
1759
  }
1749
1760
  /**
1750
- * Withdraw from stability pool by shares
1751
- * @param params Withdraw parameters
1761
+ * Redeem from stability pool by shares
1762
+ * @param params Redeem parameters
1752
1763
  * @returns Transaction hash
1753
1764
  */
1754
- async withdraw(params) {
1765
+ async redeem(params) {
1755
1766
  return this.walletClient.writeContract({
1756
1767
  chain: this.chain,
1757
1768
  account: this.walletClient.account,
1758
1769
  address: this.diamondAddress,
1759
1770
  abi: DiamondABI,
1760
- functionName: "withdraw",
1761
- args: [params.shares]
1771
+ functionName: "redeem",
1772
+ args: [params.shares, params.receiver, params.owner]
1762
1773
  });
1763
1774
  }
1764
1775
  /**
@@ -2330,14 +2341,23 @@ var AspanRouterReadClient = class {
2330
2341
  publicClient;
2331
2342
  routerAddress;
2332
2343
  chain;
2344
+ _addressCache = /* @__PURE__ */ new Map();
2333
2345
  constructor(config) {
2334
2346
  this.routerAddress = config.routerAddress;
2335
2347
  this.chain = config.chain ?? bsc2;
2336
2348
  this.publicClient = createPublicClient2({
2337
2349
  chain: this.chain,
2338
- transport: http2(config.rpcUrl)
2350
+ transport: http2(config.rpcUrl),
2351
+ batch: { multicall: true }
2339
2352
  });
2340
2353
  }
2354
+ async _getCachedAddress(key, fetcher) {
2355
+ const cached = this._addressCache.get(key);
2356
+ if (cached) return cached;
2357
+ const addr = await fetcher();
2358
+ this._addressCache.set(key, addr);
2359
+ return addr;
2360
+ }
2341
2361
  // ============ View Functions ============
2342
2362
  /**
2343
2363
  * Get the default LST address
@@ -2398,11 +2418,14 @@ var AspanRouterReadClient = class {
2398
2418
  * Get the Diamond contract address
2399
2419
  */
2400
2420
  async getDiamond() {
2401
- return this.publicClient.readContract({
2402
- address: this.routerAddress,
2403
- abi: RouterABI,
2404
- functionName: "diamond"
2405
- });
2421
+ return this._getCachedAddress(
2422
+ "diamond",
2423
+ async () => this.publicClient.readContract({
2424
+ address: this.routerAddress,
2425
+ abi: RouterABI,
2426
+ functionName: "diamond"
2427
+ })
2428
+ );
2406
2429
  }
2407
2430
  /**
2408
2431
  * Preview mint output for a given LST amount
@@ -2438,39 +2461,41 @@ var AspanRouterReadClient = class {
2438
2461
  */
2439
2462
  async previewMintByInput(inputToken, inputAmount, targetLST, mintXBNB) {
2440
2463
  if (inputAmount === 0n) return { lstAmount: 0n, mintedAmount: 0n };
2441
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
2442
- this.getDiamond(),
2443
- this.getWBNB(),
2444
- this.getUSDT(),
2445
- this.getUSDC()
2446
- ]);
2447
- const [bnbPrice8, lstPrice] = await Promise.all([
2448
- this.publicClient.readContract({
2449
- address: diamond,
2450
- abi: DiamondABI,
2451
- functionName: "getBNBPriceUSD"
2452
- }),
2453
- this.publicClient.readContract({
2454
- address: diamond,
2455
- abi: DiamondABI,
2456
- functionName: "getLSTPriceUSD",
2457
- args: [targetLST]
2458
- })
2459
- ]);
2460
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2461
- const lstPrice18 = BigInt(lstPrice);
2462
- const one = 10n ** 18n;
2463
2464
  let lstAmount = 0n;
2464
2465
  const inNorm = inputToken.toLowerCase();
2465
2466
  if (inNorm === targetLST.toLowerCase()) {
2466
2467
  lstAmount = inputAmount;
2467
- } else if (inNorm === zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
2468
- const usdValue = inputAmount * bnbPrice18 / one;
2469
- lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
2470
- } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
2471
- lstAmount = lstPrice18 === 0n ? 0n : inputAmount * one / lstPrice18;
2472
2468
  } else {
2473
- throw new Error("Unsupported input token for SDK preview");
2469
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2470
+ this.getDiamond(),
2471
+ this.getWBNB(),
2472
+ this.getUSDT(),
2473
+ this.getUSDC()
2474
+ ]);
2475
+ const [bnbPrice8, lstPrice] = await Promise.all([
2476
+ this.publicClient.readContract({
2477
+ address: diamond,
2478
+ abi: DiamondABI,
2479
+ functionName: "getBNBPriceUSD"
2480
+ }),
2481
+ this.publicClient.readContract({
2482
+ address: diamond,
2483
+ abi: DiamondABI,
2484
+ functionName: "getLSTPriceUSD",
2485
+ args: [targetLST]
2486
+ })
2487
+ ]);
2488
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2489
+ const lstPrice18 = BigInt(lstPrice);
2490
+ const one = 10n ** 18n;
2491
+ if (inNorm === zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
2492
+ const usdValue = inputAmount * bnbPrice18 / one;
2493
+ lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
2494
+ } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
2495
+ lstAmount = lstPrice18 === 0n ? 0n : inputAmount * one / lstPrice18;
2496
+ } else {
2497
+ throw new Error("Unsupported input token for SDK preview");
2498
+ }
2474
2499
  }
2475
2500
  const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
2476
2501
  return { lstAmount, mintedAmount };
@@ -2482,39 +2507,41 @@ var AspanRouterReadClient = class {
2482
2507
  async previewRedeemToOutput(lst, redeemXBNB, amount, outputToken) {
2483
2508
  const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
2484
2509
  if (lstAmount === 0n) return { lstAmount: 0n, outputAmount: 0n };
2485
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
2486
- this.getDiamond(),
2487
- this.getWBNB(),
2488
- this.getUSDT(),
2489
- this.getUSDC()
2490
- ]);
2491
- const [bnbPrice8, lstPrice] = await Promise.all([
2492
- this.publicClient.readContract({
2493
- address: diamond,
2494
- abi: DiamondABI,
2495
- functionName: "getBNBPriceUSD"
2496
- }),
2497
- this.publicClient.readContract({
2498
- address: diamond,
2499
- abi: DiamondABI,
2500
- functionName: "getLSTPriceUSD",
2501
- args: [lst]
2502
- })
2503
- ]);
2504
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2505
- const lstPrice18 = BigInt(lstPrice);
2506
- const one = 10n ** 18n;
2507
- const usdValue = lstAmount * lstPrice18 / one;
2508
2510
  let outputAmount = 0n;
2509
2511
  const outNorm = outputToken.toLowerCase();
2510
2512
  if (outNorm === lst.toLowerCase()) {
2511
2513
  outputAmount = lstAmount;
2512
- } else if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
2513
- outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
2514
- } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
2515
- outputAmount = usdValue;
2516
2514
  } else {
2517
- throw new Error("Unsupported output token for SDK preview");
2515
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2516
+ this.getDiamond(),
2517
+ this.getWBNB(),
2518
+ this.getUSDT(),
2519
+ this.getUSDC()
2520
+ ]);
2521
+ const [bnbPrice8, lstPrice] = await Promise.all([
2522
+ this.publicClient.readContract({
2523
+ address: diamond,
2524
+ abi: DiamondABI,
2525
+ functionName: "getBNBPriceUSD"
2526
+ }),
2527
+ this.publicClient.readContract({
2528
+ address: diamond,
2529
+ abi: DiamondABI,
2530
+ functionName: "getLSTPriceUSD",
2531
+ args: [lst]
2532
+ })
2533
+ ]);
2534
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2535
+ const lstPrice18 = BigInt(lstPrice);
2536
+ const one = 10n ** 18n;
2537
+ const usdValue = lstAmount * lstPrice18 / one;
2538
+ if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
2539
+ outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
2540
+ } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
2541
+ outputAmount = usdValue;
2542
+ } else {
2543
+ throw new Error("Unsupported output token for SDK preview");
2544
+ }
2518
2545
  }
2519
2546
  return { lstAmount, outputAmount };
2520
2547
  }
@@ -2547,60 +2574,84 @@ var AspanRouterReadClient = class {
2547
2574
  }
2548
2575
  // ============ Token Address Getters ============
2549
2576
  async getWBNB() {
2550
- return this.publicClient.readContract({
2551
- address: this.routerAddress,
2552
- abi: RouterABI,
2553
- functionName: "wbnb"
2554
- });
2577
+ return this._getCachedAddress(
2578
+ "wbnb",
2579
+ async () => this.publicClient.readContract({
2580
+ address: this.routerAddress,
2581
+ abi: RouterABI,
2582
+ functionName: "wbnb"
2583
+ })
2584
+ );
2555
2585
  }
2556
2586
  async getUSDT() {
2557
- return this.publicClient.readContract({
2558
- address: this.routerAddress,
2559
- abi: RouterABI,
2560
- functionName: "usdt"
2561
- });
2587
+ return this._getCachedAddress(
2588
+ "usdt",
2589
+ async () => this.publicClient.readContract({
2590
+ address: this.routerAddress,
2591
+ abi: RouterABI,
2592
+ functionName: "usdt"
2593
+ })
2594
+ );
2562
2595
  }
2563
2596
  async getUSDC() {
2564
- return this.publicClient.readContract({
2565
- address: this.routerAddress,
2566
- abi: RouterABI,
2567
- functionName: "usdc"
2568
- });
2597
+ return this._getCachedAddress(
2598
+ "usdc",
2599
+ async () => this.publicClient.readContract({
2600
+ address: this.routerAddress,
2601
+ abi: RouterABI,
2602
+ functionName: "usdc"
2603
+ })
2604
+ );
2569
2605
  }
2570
2606
  async getSlisBNB() {
2571
- return this.publicClient.readContract({
2572
- address: this.routerAddress,
2573
- abi: RouterABI,
2574
- functionName: "slisBNB"
2575
- });
2607
+ return this._getCachedAddress(
2608
+ "slisBNB",
2609
+ async () => this.publicClient.readContract({
2610
+ address: this.routerAddress,
2611
+ abi: RouterABI,
2612
+ functionName: "slisBNB"
2613
+ })
2614
+ );
2576
2615
  }
2577
2616
  async getAsBNB() {
2578
- return this.publicClient.readContract({
2579
- address: this.routerAddress,
2580
- abi: RouterABI,
2581
- functionName: "asBNB"
2582
- });
2617
+ return this._getCachedAddress(
2618
+ "asBNB",
2619
+ async () => this.publicClient.readContract({
2620
+ address: this.routerAddress,
2621
+ abi: RouterABI,
2622
+ functionName: "asBNB"
2623
+ })
2624
+ );
2583
2625
  }
2584
2626
  async getWclisBNB() {
2585
- return this.publicClient.readContract({
2586
- address: this.routerAddress,
2587
- abi: RouterABI,
2588
- functionName: "wclisBNB"
2589
- });
2627
+ return this._getCachedAddress(
2628
+ "wclisBNB",
2629
+ async () => this.publicClient.readContract({
2630
+ address: this.routerAddress,
2631
+ abi: RouterABI,
2632
+ functionName: "wclisBNB"
2633
+ })
2634
+ );
2590
2635
  }
2591
2636
  async getApUSD() {
2592
- return this.publicClient.readContract({
2593
- address: this.routerAddress,
2594
- abi: RouterABI,
2595
- functionName: "apUSD"
2596
- });
2637
+ return this._getCachedAddress(
2638
+ "apUSD",
2639
+ async () => this.publicClient.readContract({
2640
+ address: this.routerAddress,
2641
+ abi: RouterABI,
2642
+ functionName: "apUSD"
2643
+ })
2644
+ );
2597
2645
  }
2598
2646
  async getXBNB() {
2599
- return this.publicClient.readContract({
2600
- address: this.routerAddress,
2601
- abi: RouterABI,
2602
- functionName: "xBNB"
2603
- });
2647
+ return this._getCachedAddress(
2648
+ "xBNB",
2649
+ async () => this.publicClient.readContract({
2650
+ address: this.routerAddress,
2651
+ abi: RouterABI,
2652
+ functionName: "xBNB"
2653
+ })
2654
+ );
2604
2655
  }
2605
2656
  };
2606
2657
  var AspanRouterClient = class extends AspanRouterReadClient {
@@ -2856,7 +2907,7 @@ var BPS_PRECISION = 10000n;
2856
2907
  var PRICE_PRECISION = 10n ** 8n;
2857
2908
  var BSC_ADDRESSES = {
2858
2909
  diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
2859
- router: "0x34a64c4EbDe830773083BA8c9469456616F6723b",
2910
+ router: "0x1Ca976d2043dfb785c7F3A17535B3A38c50113f3",
2860
2911
  apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
2861
2912
  xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
2862
2913
  sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspan/sdk",
3
- "version": "0.4.7",
3
+ "version": "0.4.9",
4
4
  "description": "TypeScript SDK for Aspan Protocol - LST-backed stablecoin on BNB Chain",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -61,7 +61,7 @@ const BSC_RPC_URL = process.env.BSC_RPC_URL || "https://bsc-dataseed.binance.org
61
61
  const ANVIL_DEFAULT_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
62
62
 
63
63
  const DIAMOND = "0x6a11B30d3a70727d5477D6d8090e144443fA1c78" as Address;
64
- const ROUTER = "0x34a64c4EbDe830773083BA8c9469456616F6723b" as Address;
64
+ const ROUTER = "0x1Ca976d2043dfb785c7F3A17535B3A38c50113f3" as Address;
65
65
 
66
66
  const TOKENS = {
67
67
  WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" as Address,
@@ -1224,7 +1224,7 @@ describe.skipIf(!IS_FORK && !IS_LIVE)("Risk Control Tests", () => {
1224
1224
 
1225
1225
  await approve(TOKENS.apUSD, DIAMOND, depositedApUSD);
1226
1226
  try {
1227
- await waitTx(await diamondWrite.deposit({ apUSDAmount: depositedApUSD }));
1227
+ await waitTx(await diamondWrite.deposit({ assets: depositedApUSD, receiver: account.address }));
1228
1228
  } catch (err: any) {
1229
1229
  console.log(` ⚠️ Deposit failed (AccessControl or not configured): ${err.shortMessage || err.message?.slice(0, 100)}`);
1230
1230
  console.log(` Skipping remaining FC-02 tests`);
@@ -1351,7 +1351,7 @@ describe.skipIf(!IS_FORK && !IS_LIVE)("Risk Control Tests", () => {
1351
1351
 
1352
1352
  console.log(` Withdrawing ${formatAmount(currentShares)} shares...`);
1353
1353
  try {
1354
- await waitTx(await diamondWrite.withdraw({ shares: currentShares }));
1354
+ await waitTx(await diamondWrite.redeem({ shares: currentShares, receiver: account.address, owner: account.address }));
1355
1355
  } catch (err: any) {
1356
1356
  console.log(` ⚠️ Withdraw failed: ${err.shortMessage || err.message?.slice(0, 100)}`);
1357
1357
  return;
@@ -243,15 +243,25 @@ export const DiamondABI = [
243
243
  {
244
244
  type: "function",
245
245
  name: "deposit",
246
- inputs: [{ name: "_apUSDAmount", type: "uint256", internalType: "uint256" }],
246
+ inputs: [
247
+ { name: "assets", type: "uint256", internalType: "uint256" },
248
+ { name: "receiver", type: "address", internalType: "address" }
249
+ ],
247
250
  outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
248
251
  stateMutability: "nonpayable"
249
252
  },
250
253
  {
251
254
  type: "function",
252
- name: "withdraw",
253
- inputs: [{ name: "_shares", type: "uint256", internalType: "uint256" }],
254
- outputs: [{ name: "assets", type: "uint256", internalType: "uint256" }],
255
+ name: "redeem",
256
+ inputs: [
257
+ { name: "shares", type: "uint256", internalType: "uint256" },
258
+ { name: "receiver", type: "address", internalType: "address" },
259
+ { name: "owner", type: "address", internalType: "address" }
260
+ ],
261
+ outputs: [
262
+ { name: "apUSDOut", type: "uint256", internalType: "uint256" },
263
+ { name: "xBNBOut", type: "uint256", internalType: "uint256" }
264
+ ],
255
265
  stateMutability: "nonpayable"
256
266
  },
257
267
  {
package/src/client.ts CHANGED
@@ -74,7 +74,7 @@ import type {
74
74
  MintXBNBParams,
75
75
  RedeemXBNBParams,
76
76
  DepositParams,
77
- WithdrawParams,
77
+ RedeemParams,
78
78
  } from "./types";
79
79
 
80
80
  // ============ Configuration ============
@@ -117,6 +117,7 @@ export class AspanReadClient {
117
117
  this.publicClient = createPublicClient({
118
118
  chain: this.chain,
119
119
  transport: http(config.rpcUrl),
120
+ batch: { multicall: true },
120
121
  });
121
122
  }
122
123
 
@@ -1189,23 +1190,23 @@ export class AspanClient extends AspanReadClient {
1189
1190
  address: this.diamondAddress,
1190
1191
  abi: DiamondABI,
1191
1192
  functionName: "deposit",
1192
- args: [params.apUSDAmount],
1193
+ args: [params.assets, params.receiver],
1193
1194
  });
1194
1195
  }
1195
1196
 
1196
1197
  /**
1197
- * Withdraw from stability pool by shares
1198
- * @param params Withdraw parameters
1198
+ * Redeem from stability pool by shares
1199
+ * @param params Redeem parameters
1199
1200
  * @returns Transaction hash
1200
1201
  */
1201
- async withdraw(params: WithdrawParams): Promise<Hash> {
1202
+ async redeem(params: RedeemParams): Promise<Hash> {
1202
1203
  return this.walletClient.writeContract({
1203
1204
  chain: this.chain,
1204
1205
  account: this.walletClient.account!,
1205
1206
  address: this.diamondAddress,
1206
1207
  abi: DiamondABI,
1207
- functionName: "withdraw",
1208
- args: [params.shares],
1208
+ functionName: "redeem",
1209
+ args: [params.shares, params.receiver, params.owner],
1209
1210
  });
1210
1211
  }
1211
1212
 
package/src/index.ts CHANGED
@@ -67,7 +67,7 @@ export type {
67
67
  MintXBNBParams,
68
68
  RedeemXBNBParams,
69
69
  DepositParams,
70
- WithdrawParams,
70
+ RedeemParams,
71
71
  // Events
72
72
  ApUSDMintedEvent,
73
73
  ApUSDRedeemedEvent,
@@ -116,7 +116,7 @@ export const PRICE_PRECISION = 10n ** 8n; // Chainlink price precision
116
116
  // ============ Contract Addresses (BSC Mainnet) ============
117
117
  export const BSC_ADDRESSES = {
118
118
  diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78" as const,
119
- router: "0x34a64c4EbDe830773083BA8c9469456616F6723b" as const,
119
+ router: "0x1Ca976d2043dfb785c7F3A17535B3A38c50113f3" as const,
120
120
  apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as const,
121
121
  xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as const,
122
122
  sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB" as const,