@aspan/sdk 0.4.7 → 0.4.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/dist/index.d.mts CHANGED
@@ -702,7 +702,9 @@ declare class AspanRouterReadClient {
702
702
  protected readonly publicClient: PublicClient;
703
703
  protected readonly routerAddress: Address;
704
704
  protected readonly chain: Chain;
705
+ private readonly _addressCache;
705
706
  constructor(config: AspanRouterClientConfig);
707
+ protected _getCachedAddress(key: string, fetcher: () => Promise<Address>): Promise<Address>;
706
708
  /**
707
709
  * Get the default LST address
708
710
  */
package/dist/index.d.ts CHANGED
@@ -702,7 +702,9 @@ declare class AspanRouterReadClient {
702
702
  protected readonly publicClient: PublicClient;
703
703
  protected readonly routerAddress: Address;
704
704
  protected readonly chain: Chain;
705
+ private readonly _addressCache;
705
706
  constructor(config: AspanRouterClientConfig);
707
+ protected _getCachedAddress(key: string, fetcher: () => Promise<Address>): Promise<Address>;
706
708
  /**
707
709
  * Get the default LST address
708
710
  */
package/dist/index.js CHANGED
@@ -892,7 +892,8 @@ var AspanReadClient = class _AspanReadClient {
892
892
  this.chain = config.chain ?? import_chains.bsc;
893
893
  this.publicClient = (0, import_viem.createPublicClient)({
894
894
  chain: this.chain,
895
- transport: (0, import_viem.http)(config.rpcUrl)
895
+ transport: (0, import_viem.http)(config.rpcUrl),
896
+ batch: { multicall: true }
896
897
  });
897
898
  }
898
899
  /**
@@ -2383,14 +2384,23 @@ var AspanRouterReadClient = class {
2383
2384
  publicClient;
2384
2385
  routerAddress;
2385
2386
  chain;
2387
+ _addressCache = /* @__PURE__ */ new Map();
2386
2388
  constructor(config) {
2387
2389
  this.routerAddress = config.routerAddress;
2388
2390
  this.chain = config.chain ?? import_chains2.bsc;
2389
2391
  this.publicClient = (0, import_viem2.createPublicClient)({
2390
2392
  chain: this.chain,
2391
- transport: (0, import_viem2.http)(config.rpcUrl)
2393
+ transport: (0, import_viem2.http)(config.rpcUrl),
2394
+ batch: { multicall: true }
2392
2395
  });
2393
2396
  }
2397
+ async _getCachedAddress(key, fetcher) {
2398
+ const cached = this._addressCache.get(key);
2399
+ if (cached) return cached;
2400
+ const addr = await fetcher();
2401
+ this._addressCache.set(key, addr);
2402
+ return addr;
2403
+ }
2394
2404
  // ============ View Functions ============
2395
2405
  /**
2396
2406
  * Get the default LST address
@@ -2451,11 +2461,14 @@ var AspanRouterReadClient = class {
2451
2461
  * Get the Diamond contract address
2452
2462
  */
2453
2463
  async getDiamond() {
2454
- return this.publicClient.readContract({
2455
- address: this.routerAddress,
2456
- abi: RouterABI,
2457
- functionName: "diamond"
2458
- });
2464
+ return this._getCachedAddress(
2465
+ "diamond",
2466
+ async () => this.publicClient.readContract({
2467
+ address: this.routerAddress,
2468
+ abi: RouterABI,
2469
+ functionName: "diamond"
2470
+ })
2471
+ );
2459
2472
  }
2460
2473
  /**
2461
2474
  * Preview mint output for a given LST amount
@@ -2491,39 +2504,41 @@ var AspanRouterReadClient = class {
2491
2504
  */
2492
2505
  async previewMintByInput(inputToken, inputAmount, targetLST, mintXBNB) {
2493
2506
  if (inputAmount === 0n) return { lstAmount: 0n, mintedAmount: 0n };
2494
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
2495
- this.getDiamond(),
2496
- this.getWBNB(),
2497
- this.getUSDT(),
2498
- this.getUSDC()
2499
- ]);
2500
- const [bnbPrice8, lstPrice] = await Promise.all([
2501
- this.publicClient.readContract({
2502
- address: diamond,
2503
- abi: DiamondABI,
2504
- functionName: "getBNBPriceUSD"
2505
- }),
2506
- this.publicClient.readContract({
2507
- address: diamond,
2508
- abi: DiamondABI,
2509
- functionName: "getLSTPriceUSD",
2510
- args: [targetLST]
2511
- })
2512
- ]);
2513
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2514
- const lstPrice18 = BigInt(lstPrice);
2515
- const one = 10n ** 18n;
2516
2507
  let lstAmount = 0n;
2517
2508
  const inNorm = inputToken.toLowerCase();
2518
2509
  if (inNorm === targetLST.toLowerCase()) {
2519
2510
  lstAmount = inputAmount;
2520
- } else if (inNorm === import_viem2.zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
2521
- const usdValue = inputAmount * bnbPrice18 / one;
2522
- lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
2523
- } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
2524
- lstAmount = lstPrice18 === 0n ? 0n : inputAmount * one / lstPrice18;
2525
2511
  } else {
2526
- throw new Error("Unsupported input token for SDK preview");
2512
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2513
+ this.getDiamond(),
2514
+ this.getWBNB(),
2515
+ this.getUSDT(),
2516
+ this.getUSDC()
2517
+ ]);
2518
+ const [bnbPrice8, lstPrice] = await Promise.all([
2519
+ this.publicClient.readContract({
2520
+ address: diamond,
2521
+ abi: DiamondABI,
2522
+ functionName: "getBNBPriceUSD"
2523
+ }),
2524
+ this.publicClient.readContract({
2525
+ address: diamond,
2526
+ abi: DiamondABI,
2527
+ functionName: "getLSTPriceUSD",
2528
+ args: [targetLST]
2529
+ })
2530
+ ]);
2531
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2532
+ const lstPrice18 = BigInt(lstPrice);
2533
+ const one = 10n ** 18n;
2534
+ if (inNorm === import_viem2.zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
2535
+ const usdValue = inputAmount * bnbPrice18 / one;
2536
+ lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
2537
+ } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
2538
+ lstAmount = lstPrice18 === 0n ? 0n : inputAmount * one / lstPrice18;
2539
+ } else {
2540
+ throw new Error("Unsupported input token for SDK preview");
2541
+ }
2527
2542
  }
2528
2543
  const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
2529
2544
  return { lstAmount, mintedAmount };
@@ -2535,39 +2550,41 @@ var AspanRouterReadClient = class {
2535
2550
  async previewRedeemToOutput(lst, redeemXBNB, amount, outputToken) {
2536
2551
  const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
2537
2552
  if (lstAmount === 0n) return { lstAmount: 0n, outputAmount: 0n };
2538
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
2539
- this.getDiamond(),
2540
- this.getWBNB(),
2541
- this.getUSDT(),
2542
- this.getUSDC()
2543
- ]);
2544
- const [bnbPrice8, lstPrice] = await Promise.all([
2545
- this.publicClient.readContract({
2546
- address: diamond,
2547
- abi: DiamondABI,
2548
- functionName: "getBNBPriceUSD"
2549
- }),
2550
- this.publicClient.readContract({
2551
- address: diamond,
2552
- abi: DiamondABI,
2553
- functionName: "getLSTPriceUSD",
2554
- args: [lst]
2555
- })
2556
- ]);
2557
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2558
- const lstPrice18 = BigInt(lstPrice);
2559
- const one = 10n ** 18n;
2560
- const usdValue = lstAmount * lstPrice18 / one;
2561
2553
  let outputAmount = 0n;
2562
2554
  const outNorm = outputToken.toLowerCase();
2563
2555
  if (outNorm === lst.toLowerCase()) {
2564
2556
  outputAmount = lstAmount;
2565
- } else if (outNorm === import_viem2.zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
2566
- outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
2567
- } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
2568
- outputAmount = usdValue;
2569
2557
  } else {
2570
- throw new Error("Unsupported output token for SDK preview");
2558
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2559
+ this.getDiamond(),
2560
+ this.getWBNB(),
2561
+ this.getUSDT(),
2562
+ this.getUSDC()
2563
+ ]);
2564
+ const [bnbPrice8, lstPrice] = await Promise.all([
2565
+ this.publicClient.readContract({
2566
+ address: diamond,
2567
+ abi: DiamondABI,
2568
+ functionName: "getBNBPriceUSD"
2569
+ }),
2570
+ this.publicClient.readContract({
2571
+ address: diamond,
2572
+ abi: DiamondABI,
2573
+ functionName: "getLSTPriceUSD",
2574
+ args: [lst]
2575
+ })
2576
+ ]);
2577
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2578
+ const lstPrice18 = BigInt(lstPrice);
2579
+ const one = 10n ** 18n;
2580
+ const usdValue = lstAmount * lstPrice18 / one;
2581
+ if (outNorm === import_viem2.zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
2582
+ outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
2583
+ } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
2584
+ outputAmount = usdValue;
2585
+ } else {
2586
+ throw new Error("Unsupported output token for SDK preview");
2587
+ }
2571
2588
  }
2572
2589
  return { lstAmount, outputAmount };
2573
2590
  }
@@ -2600,60 +2617,84 @@ var AspanRouterReadClient = class {
2600
2617
  }
2601
2618
  // ============ Token Address Getters ============
2602
2619
  async getWBNB() {
2603
- return this.publicClient.readContract({
2604
- address: this.routerAddress,
2605
- abi: RouterABI,
2606
- functionName: "wbnb"
2607
- });
2620
+ return this._getCachedAddress(
2621
+ "wbnb",
2622
+ async () => this.publicClient.readContract({
2623
+ address: this.routerAddress,
2624
+ abi: RouterABI,
2625
+ functionName: "wbnb"
2626
+ })
2627
+ );
2608
2628
  }
2609
2629
  async getUSDT() {
2610
- return this.publicClient.readContract({
2611
- address: this.routerAddress,
2612
- abi: RouterABI,
2613
- functionName: "usdt"
2614
- });
2630
+ return this._getCachedAddress(
2631
+ "usdt",
2632
+ async () => this.publicClient.readContract({
2633
+ address: this.routerAddress,
2634
+ abi: RouterABI,
2635
+ functionName: "usdt"
2636
+ })
2637
+ );
2615
2638
  }
2616
2639
  async getUSDC() {
2617
- return this.publicClient.readContract({
2618
- address: this.routerAddress,
2619
- abi: RouterABI,
2620
- functionName: "usdc"
2621
- });
2640
+ return this._getCachedAddress(
2641
+ "usdc",
2642
+ async () => this.publicClient.readContract({
2643
+ address: this.routerAddress,
2644
+ abi: RouterABI,
2645
+ functionName: "usdc"
2646
+ })
2647
+ );
2622
2648
  }
2623
2649
  async getSlisBNB() {
2624
- return this.publicClient.readContract({
2625
- address: this.routerAddress,
2626
- abi: RouterABI,
2627
- functionName: "slisBNB"
2628
- });
2650
+ return this._getCachedAddress(
2651
+ "slisBNB",
2652
+ async () => this.publicClient.readContract({
2653
+ address: this.routerAddress,
2654
+ abi: RouterABI,
2655
+ functionName: "slisBNB"
2656
+ })
2657
+ );
2629
2658
  }
2630
2659
  async getAsBNB() {
2631
- return this.publicClient.readContract({
2632
- address: this.routerAddress,
2633
- abi: RouterABI,
2634
- functionName: "asBNB"
2635
- });
2660
+ return this._getCachedAddress(
2661
+ "asBNB",
2662
+ async () => this.publicClient.readContract({
2663
+ address: this.routerAddress,
2664
+ abi: RouterABI,
2665
+ functionName: "asBNB"
2666
+ })
2667
+ );
2636
2668
  }
2637
2669
  async getWclisBNB() {
2638
- return this.publicClient.readContract({
2639
- address: this.routerAddress,
2640
- abi: RouterABI,
2641
- functionName: "wclisBNB"
2642
- });
2670
+ return this._getCachedAddress(
2671
+ "wclisBNB",
2672
+ async () => this.publicClient.readContract({
2673
+ address: this.routerAddress,
2674
+ abi: RouterABI,
2675
+ functionName: "wclisBNB"
2676
+ })
2677
+ );
2643
2678
  }
2644
2679
  async getApUSD() {
2645
- return this.publicClient.readContract({
2646
- address: this.routerAddress,
2647
- abi: RouterABI,
2648
- functionName: "apUSD"
2649
- });
2680
+ return this._getCachedAddress(
2681
+ "apUSD",
2682
+ async () => this.publicClient.readContract({
2683
+ address: this.routerAddress,
2684
+ abi: RouterABI,
2685
+ functionName: "apUSD"
2686
+ })
2687
+ );
2650
2688
  }
2651
2689
  async getXBNB() {
2652
- return this.publicClient.readContract({
2653
- address: this.routerAddress,
2654
- abi: RouterABI,
2655
- functionName: "xBNB"
2656
- });
2690
+ return this._getCachedAddress(
2691
+ "xBNB",
2692
+ async () => this.publicClient.readContract({
2693
+ address: this.routerAddress,
2694
+ abi: RouterABI,
2695
+ functionName: "xBNB"
2696
+ })
2697
+ );
2657
2698
  }
2658
2699
  };
2659
2700
  var AspanRouterClient = class extends AspanRouterReadClient {
package/dist/index.mjs CHANGED
@@ -834,7 +834,8 @@ var AspanReadClient = class _AspanReadClient {
834
834
  this.chain = config.chain ?? bsc;
835
835
  this.publicClient = createPublicClient({
836
836
  chain: this.chain,
837
- transport: http(config.rpcUrl)
837
+ transport: http(config.rpcUrl),
838
+ batch: { multicall: true }
838
839
  });
839
840
  }
840
841
  /**
@@ -2330,14 +2331,23 @@ var AspanRouterReadClient = class {
2330
2331
  publicClient;
2331
2332
  routerAddress;
2332
2333
  chain;
2334
+ _addressCache = /* @__PURE__ */ new Map();
2333
2335
  constructor(config) {
2334
2336
  this.routerAddress = config.routerAddress;
2335
2337
  this.chain = config.chain ?? bsc2;
2336
2338
  this.publicClient = createPublicClient2({
2337
2339
  chain: this.chain,
2338
- transport: http2(config.rpcUrl)
2340
+ transport: http2(config.rpcUrl),
2341
+ batch: { multicall: true }
2339
2342
  });
2340
2343
  }
2344
+ async _getCachedAddress(key, fetcher) {
2345
+ const cached = this._addressCache.get(key);
2346
+ if (cached) return cached;
2347
+ const addr = await fetcher();
2348
+ this._addressCache.set(key, addr);
2349
+ return addr;
2350
+ }
2341
2351
  // ============ View Functions ============
2342
2352
  /**
2343
2353
  * Get the default LST address
@@ -2398,11 +2408,14 @@ var AspanRouterReadClient = class {
2398
2408
  * Get the Diamond contract address
2399
2409
  */
2400
2410
  async getDiamond() {
2401
- return this.publicClient.readContract({
2402
- address: this.routerAddress,
2403
- abi: RouterABI,
2404
- functionName: "diamond"
2405
- });
2411
+ return this._getCachedAddress(
2412
+ "diamond",
2413
+ async () => this.publicClient.readContract({
2414
+ address: this.routerAddress,
2415
+ abi: RouterABI,
2416
+ functionName: "diamond"
2417
+ })
2418
+ );
2406
2419
  }
2407
2420
  /**
2408
2421
  * Preview mint output for a given LST amount
@@ -2438,39 +2451,41 @@ var AspanRouterReadClient = class {
2438
2451
  */
2439
2452
  async previewMintByInput(inputToken, inputAmount, targetLST, mintXBNB) {
2440
2453
  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
2454
  let lstAmount = 0n;
2464
2455
  const inNorm = inputToken.toLowerCase();
2465
2456
  if (inNorm === targetLST.toLowerCase()) {
2466
2457
  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
2458
  } else {
2473
- throw new Error("Unsupported input token for SDK preview");
2459
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2460
+ this.getDiamond(),
2461
+ this.getWBNB(),
2462
+ this.getUSDT(),
2463
+ this.getUSDC()
2464
+ ]);
2465
+ const [bnbPrice8, lstPrice] = await Promise.all([
2466
+ this.publicClient.readContract({
2467
+ address: diamond,
2468
+ abi: DiamondABI,
2469
+ functionName: "getBNBPriceUSD"
2470
+ }),
2471
+ this.publicClient.readContract({
2472
+ address: diamond,
2473
+ abi: DiamondABI,
2474
+ functionName: "getLSTPriceUSD",
2475
+ args: [targetLST]
2476
+ })
2477
+ ]);
2478
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2479
+ const lstPrice18 = BigInt(lstPrice);
2480
+ const one = 10n ** 18n;
2481
+ if (inNorm === zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
2482
+ const usdValue = inputAmount * bnbPrice18 / one;
2483
+ lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
2484
+ } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
2485
+ lstAmount = lstPrice18 === 0n ? 0n : inputAmount * one / lstPrice18;
2486
+ } else {
2487
+ throw new Error("Unsupported input token for SDK preview");
2488
+ }
2474
2489
  }
2475
2490
  const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
2476
2491
  return { lstAmount, mintedAmount };
@@ -2482,39 +2497,41 @@ var AspanRouterReadClient = class {
2482
2497
  async previewRedeemToOutput(lst, redeemXBNB, amount, outputToken) {
2483
2498
  const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
2484
2499
  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
2500
  let outputAmount = 0n;
2509
2501
  const outNorm = outputToken.toLowerCase();
2510
2502
  if (outNorm === lst.toLowerCase()) {
2511
2503
  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
2504
  } else {
2517
- throw new Error("Unsupported output token for SDK preview");
2505
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
2506
+ this.getDiamond(),
2507
+ this.getWBNB(),
2508
+ this.getUSDT(),
2509
+ this.getUSDC()
2510
+ ]);
2511
+ const [bnbPrice8, lstPrice] = await Promise.all([
2512
+ this.publicClient.readContract({
2513
+ address: diamond,
2514
+ abi: DiamondABI,
2515
+ functionName: "getBNBPriceUSD"
2516
+ }),
2517
+ this.publicClient.readContract({
2518
+ address: diamond,
2519
+ abi: DiamondABI,
2520
+ functionName: "getLSTPriceUSD",
2521
+ args: [lst]
2522
+ })
2523
+ ]);
2524
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
2525
+ const lstPrice18 = BigInt(lstPrice);
2526
+ const one = 10n ** 18n;
2527
+ const usdValue = lstAmount * lstPrice18 / one;
2528
+ if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
2529
+ outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
2530
+ } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
2531
+ outputAmount = usdValue;
2532
+ } else {
2533
+ throw new Error("Unsupported output token for SDK preview");
2534
+ }
2518
2535
  }
2519
2536
  return { lstAmount, outputAmount };
2520
2537
  }
@@ -2547,60 +2564,84 @@ var AspanRouterReadClient = class {
2547
2564
  }
2548
2565
  // ============ Token Address Getters ============
2549
2566
  async getWBNB() {
2550
- return this.publicClient.readContract({
2551
- address: this.routerAddress,
2552
- abi: RouterABI,
2553
- functionName: "wbnb"
2554
- });
2567
+ return this._getCachedAddress(
2568
+ "wbnb",
2569
+ async () => this.publicClient.readContract({
2570
+ address: this.routerAddress,
2571
+ abi: RouterABI,
2572
+ functionName: "wbnb"
2573
+ })
2574
+ );
2555
2575
  }
2556
2576
  async getUSDT() {
2557
- return this.publicClient.readContract({
2558
- address: this.routerAddress,
2559
- abi: RouterABI,
2560
- functionName: "usdt"
2561
- });
2577
+ return this._getCachedAddress(
2578
+ "usdt",
2579
+ async () => this.publicClient.readContract({
2580
+ address: this.routerAddress,
2581
+ abi: RouterABI,
2582
+ functionName: "usdt"
2583
+ })
2584
+ );
2562
2585
  }
2563
2586
  async getUSDC() {
2564
- return this.publicClient.readContract({
2565
- address: this.routerAddress,
2566
- abi: RouterABI,
2567
- functionName: "usdc"
2568
- });
2587
+ return this._getCachedAddress(
2588
+ "usdc",
2589
+ async () => this.publicClient.readContract({
2590
+ address: this.routerAddress,
2591
+ abi: RouterABI,
2592
+ functionName: "usdc"
2593
+ })
2594
+ );
2569
2595
  }
2570
2596
  async getSlisBNB() {
2571
- return this.publicClient.readContract({
2572
- address: this.routerAddress,
2573
- abi: RouterABI,
2574
- functionName: "slisBNB"
2575
- });
2597
+ return this._getCachedAddress(
2598
+ "slisBNB",
2599
+ async () => this.publicClient.readContract({
2600
+ address: this.routerAddress,
2601
+ abi: RouterABI,
2602
+ functionName: "slisBNB"
2603
+ })
2604
+ );
2576
2605
  }
2577
2606
  async getAsBNB() {
2578
- return this.publicClient.readContract({
2579
- address: this.routerAddress,
2580
- abi: RouterABI,
2581
- functionName: "asBNB"
2582
- });
2607
+ return this._getCachedAddress(
2608
+ "asBNB",
2609
+ async () => this.publicClient.readContract({
2610
+ address: this.routerAddress,
2611
+ abi: RouterABI,
2612
+ functionName: "asBNB"
2613
+ })
2614
+ );
2583
2615
  }
2584
2616
  async getWclisBNB() {
2585
- return this.publicClient.readContract({
2586
- address: this.routerAddress,
2587
- abi: RouterABI,
2588
- functionName: "wclisBNB"
2589
- });
2617
+ return this._getCachedAddress(
2618
+ "wclisBNB",
2619
+ async () => this.publicClient.readContract({
2620
+ address: this.routerAddress,
2621
+ abi: RouterABI,
2622
+ functionName: "wclisBNB"
2623
+ })
2624
+ );
2590
2625
  }
2591
2626
  async getApUSD() {
2592
- return this.publicClient.readContract({
2593
- address: this.routerAddress,
2594
- abi: RouterABI,
2595
- functionName: "apUSD"
2596
- });
2627
+ return this._getCachedAddress(
2628
+ "apUSD",
2629
+ async () => this.publicClient.readContract({
2630
+ address: this.routerAddress,
2631
+ abi: RouterABI,
2632
+ functionName: "apUSD"
2633
+ })
2634
+ );
2597
2635
  }
2598
2636
  async getXBNB() {
2599
- return this.publicClient.readContract({
2600
- address: this.routerAddress,
2601
- abi: RouterABI,
2602
- functionName: "xBNB"
2603
- });
2637
+ return this._getCachedAddress(
2638
+ "xBNB",
2639
+ async () => this.publicClient.readContract({
2640
+ address: this.routerAddress,
2641
+ abi: RouterABI,
2642
+ functionName: "xBNB"
2643
+ })
2644
+ );
2604
2645
  }
2605
2646
  };
2606
2647
  var AspanRouterClient = class extends AspanRouterReadClient {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspan/sdk",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
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",
package/src/client.ts CHANGED
@@ -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
 
package/src/router.ts CHANGED
@@ -59,6 +59,7 @@ export class AspanRouterReadClient {
59
59
  protected readonly publicClient: PublicClient;
60
60
  protected readonly routerAddress: Address;
61
61
  protected readonly chain: Chain;
62
+ private readonly _addressCache = new Map<string, Address>();
62
63
 
63
64
  constructor(config: AspanRouterClientConfig) {
64
65
  this.routerAddress = config.routerAddress;
@@ -67,9 +68,18 @@ export class AspanRouterReadClient {
67
68
  this.publicClient = createPublicClient({
68
69
  chain: this.chain,
69
70
  transport: http(config.rpcUrl),
71
+ batch: { multicall: true },
70
72
  });
71
73
  }
72
74
 
75
+ protected async _getCachedAddress(key: string, fetcher: () => Promise<Address>): Promise<Address> {
76
+ const cached = this._addressCache.get(key);
77
+ if (cached) return cached;
78
+ const addr = await fetcher();
79
+ this._addressCache.set(key, addr);
80
+ return addr;
81
+ }
82
+
73
83
  // ============ View Functions ============
74
84
 
75
85
  /**
@@ -136,11 +146,13 @@ export class AspanRouterReadClient {
136
146
  * Get the Diamond contract address
137
147
  */
138
148
  async getDiamond(): Promise<Address> {
139
- return this.publicClient.readContract({
140
- address: this.routerAddress,
141
- abi: RouterABI,
142
- functionName: "diamond",
143
- });
149
+ return this._getCachedAddress("diamond", async () =>
150
+ this.publicClient.readContract({
151
+ address: this.routerAddress,
152
+ abi: RouterABI,
153
+ functionName: "diamond",
154
+ })
155
+ );
144
156
  }
145
157
 
146
158
  /**
@@ -185,44 +197,47 @@ export class AspanRouterReadClient {
185
197
  ): Promise<{ lstAmount: bigint; mintedAmount: bigint }> {
186
198
  if (inputAmount === 0n) return { lstAmount: 0n, mintedAmount: 0n };
187
199
 
188
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
189
- this.getDiamond(),
190
- this.getWBNB(),
191
- this.getUSDT(),
192
- this.getUSDC(),
193
- ]);
194
-
195
- const [bnbPrice8, lstPrice] = await Promise.all([
196
- this.publicClient.readContract({
197
- address: diamond,
198
- abi: DiamondABI,
199
- functionName: "getBNBPriceUSD",
200
- }),
201
- this.publicClient.readContract({
202
- address: diamond,
203
- abi: DiamondABI,
204
- functionName: "getLSTPriceUSD",
205
- args: [targetLST],
206
- }),
207
- ]);
208
-
209
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
210
- const lstPrice18 = BigInt(lstPrice);
211
- const one = 10n ** 18n;
212
-
213
200
  let lstAmount = 0n;
214
201
  const inNorm = inputToken.toLowerCase();
202
+
215
203
  if (inNorm === targetLST.toLowerCase()) {
216
204
  lstAmount = inputAmount;
217
- } else if (inNorm === zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
218
- // BNB/WBNB -> USD -> LST
219
- const usdValue = (inputAmount * bnbPrice18) / one;
220
- lstAmount = lstPrice18 === 0n ? 0n : (usdValue * one) / lstPrice18;
221
- } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
222
- // stablecoin (18-decimal normalized in this SDK path) -> LST
223
- lstAmount = lstPrice18 === 0n ? 0n : (inputAmount * one) / lstPrice18;
224
205
  } else {
225
- throw new Error("Unsupported input token for SDK preview");
206
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
207
+ this.getDiamond(),
208
+ this.getWBNB(),
209
+ this.getUSDT(),
210
+ this.getUSDC(),
211
+ ]);
212
+
213
+ const [bnbPrice8, lstPrice] = await Promise.all([
214
+ this.publicClient.readContract({
215
+ address: diamond,
216
+ abi: DiamondABI,
217
+ functionName: "getBNBPriceUSD",
218
+ }),
219
+ this.publicClient.readContract({
220
+ address: diamond,
221
+ abi: DiamondABI,
222
+ functionName: "getLSTPriceUSD",
223
+ args: [targetLST],
224
+ }),
225
+ ]);
226
+
227
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
228
+ const lstPrice18 = BigInt(lstPrice);
229
+ const one = 10n ** 18n;
230
+
231
+ if (inNorm === zeroAddress.toLowerCase() || inNorm === wbnb.toLowerCase()) {
232
+ // BNB/WBNB -> USD -> LST
233
+ const usdValue = (inputAmount * bnbPrice18) / one;
234
+ lstAmount = lstPrice18 === 0n ? 0n : (usdValue * one) / lstPrice18;
235
+ } else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
236
+ // stablecoin (18-decimal normalized in this SDK path) -> LST
237
+ lstAmount = lstPrice18 === 0n ? 0n : (inputAmount * one) / lstPrice18;
238
+ } else {
239
+ throw new Error("Unsupported input token for SDK preview");
240
+ }
226
241
  }
227
242
 
228
243
  const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
@@ -242,42 +257,45 @@ export class AspanRouterReadClient {
242
257
  const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
243
258
  if (lstAmount === 0n) return { lstAmount: 0n, outputAmount: 0n };
244
259
 
245
- const [diamond, wbnb, usdt, usdc] = await Promise.all([
246
- this.getDiamond(),
247
- this.getWBNB(),
248
- this.getUSDT(),
249
- this.getUSDC(),
250
- ]);
251
-
252
- const [bnbPrice8, lstPrice] = await Promise.all([
253
- this.publicClient.readContract({
254
- address: diamond,
255
- abi: DiamondABI,
256
- functionName: "getBNBPriceUSD",
257
- }),
258
- this.publicClient.readContract({
259
- address: diamond,
260
- abi: DiamondABI,
261
- functionName: "getLSTPriceUSD",
262
- args: [lst],
263
- }),
264
- ]);
265
-
266
- const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
267
- const lstPrice18 = BigInt(lstPrice);
268
- const one = 10n ** 18n;
269
- const usdValue = (lstAmount * lstPrice18) / one;
270
-
271
260
  let outputAmount = 0n;
272
261
  const outNorm = outputToken.toLowerCase();
262
+
273
263
  if (outNorm === lst.toLowerCase()) {
274
264
  outputAmount = lstAmount;
275
- } else if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
276
- outputAmount = bnbPrice18 === 0n ? 0n : (usdValue * one) / bnbPrice18;
277
- } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
278
- outputAmount = usdValue;
279
265
  } else {
280
- throw new Error("Unsupported output token for SDK preview");
266
+ const [diamond, wbnb, usdt, usdc] = await Promise.all([
267
+ this.getDiamond(),
268
+ this.getWBNB(),
269
+ this.getUSDT(),
270
+ this.getUSDC(),
271
+ ]);
272
+
273
+ const [bnbPrice8, lstPrice] = await Promise.all([
274
+ this.publicClient.readContract({
275
+ address: diamond,
276
+ abi: DiamondABI,
277
+ functionName: "getBNBPriceUSD",
278
+ }),
279
+ this.publicClient.readContract({
280
+ address: diamond,
281
+ abi: DiamondABI,
282
+ functionName: "getLSTPriceUSD",
283
+ args: [lst],
284
+ }),
285
+ ]);
286
+
287
+ const bnbPrice18 = BigInt(bnbPrice8) * 10n ** 10n;
288
+ const lstPrice18 = BigInt(lstPrice);
289
+ const one = 10n ** 18n;
290
+ const usdValue = (lstAmount * lstPrice18) / one;
291
+
292
+ if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
293
+ outputAmount = bnbPrice18 === 0n ? 0n : (usdValue * one) / bnbPrice18;
294
+ } else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
295
+ outputAmount = usdValue;
296
+ } else {
297
+ throw new Error("Unsupported output token for SDK preview");
298
+ }
281
299
  }
282
300
 
283
301
  return { lstAmount, outputAmount };
@@ -318,67 +336,83 @@ export class AspanRouterReadClient {
318
336
  // ============ Token Address Getters ============
319
337
 
320
338
  async getWBNB(): Promise<Address> {
321
- return this.publicClient.readContract({
322
- address: this.routerAddress,
323
- abi: RouterABI,
324
- functionName: "wbnb",
325
- });
339
+ return this._getCachedAddress("wbnb", async () =>
340
+ this.publicClient.readContract({
341
+ address: this.routerAddress,
342
+ abi: RouterABI,
343
+ functionName: "wbnb",
344
+ })
345
+ );
326
346
  }
327
347
 
328
348
  async getUSDT(): Promise<Address> {
329
- return this.publicClient.readContract({
330
- address: this.routerAddress,
331
- abi: RouterABI,
332
- functionName: "usdt",
333
- });
349
+ return this._getCachedAddress("usdt", async () =>
350
+ this.publicClient.readContract({
351
+ address: this.routerAddress,
352
+ abi: RouterABI,
353
+ functionName: "usdt",
354
+ })
355
+ );
334
356
  }
335
357
 
336
358
  async getUSDC(): Promise<Address> {
337
- return this.publicClient.readContract({
338
- address: this.routerAddress,
339
- abi: RouterABI,
340
- functionName: "usdc",
341
- });
359
+ return this._getCachedAddress("usdc", async () =>
360
+ this.publicClient.readContract({
361
+ address: this.routerAddress,
362
+ abi: RouterABI,
363
+ functionName: "usdc",
364
+ })
365
+ );
342
366
  }
343
367
 
344
368
  async getSlisBNB(): Promise<Address> {
345
- return this.publicClient.readContract({
346
- address: this.routerAddress,
347
- abi: RouterABI,
348
- functionName: "slisBNB",
349
- });
369
+ return this._getCachedAddress("slisBNB", async () =>
370
+ this.publicClient.readContract({
371
+ address: this.routerAddress,
372
+ abi: RouterABI,
373
+ functionName: "slisBNB",
374
+ })
375
+ );
350
376
  }
351
377
 
352
378
  async getAsBNB(): Promise<Address> {
353
- return this.publicClient.readContract({
354
- address: this.routerAddress,
355
- abi: RouterABI,
356
- functionName: "asBNB",
357
- });
379
+ return this._getCachedAddress("asBNB", async () =>
380
+ this.publicClient.readContract({
381
+ address: this.routerAddress,
382
+ abi: RouterABI,
383
+ functionName: "asBNB",
384
+ })
385
+ );
358
386
  }
359
387
 
360
388
  async getWclisBNB(): Promise<Address> {
361
- return this.publicClient.readContract({
362
- address: this.routerAddress,
363
- abi: RouterABI,
364
- functionName: "wclisBNB",
365
- });
389
+ return this._getCachedAddress("wclisBNB", async () =>
390
+ this.publicClient.readContract({
391
+ address: this.routerAddress,
392
+ abi: RouterABI,
393
+ functionName: "wclisBNB",
394
+ })
395
+ );
366
396
  }
367
397
 
368
398
  async getApUSD(): Promise<Address> {
369
- return this.publicClient.readContract({
370
- address: this.routerAddress,
371
- abi: RouterABI,
372
- functionName: "apUSD",
373
- });
399
+ return this._getCachedAddress("apUSD", async () =>
400
+ this.publicClient.readContract({
401
+ address: this.routerAddress,
402
+ abi: RouterABI,
403
+ functionName: "apUSD",
404
+ })
405
+ );
374
406
  }
375
407
 
376
408
  async getXBNB(): Promise<Address> {
377
- return this.publicClient.readContract({
378
- address: this.routerAddress,
379
- abi: RouterABI,
380
- functionName: "xBNB",
381
- });
409
+ return this._getCachedAddress("xBNB", async () =>
410
+ this.publicClient.readContract({
411
+ address: this.routerAddress,
412
+ abi: RouterABI,
413
+ functionName: "xBNB",
414
+ })
415
+ );
382
416
  }
383
417
  }
384
418