@aspan/sdk 0.4.6 → 0.4.7

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
@@ -256,13 +256,6 @@ var DiamondABI = [
256
256
  outputs: [{ name: "assets", type: "uint256", internalType: "uint256" }],
257
257
  stateMutability: "nonpayable"
258
258
  },
259
- {
260
- type: "function",
261
- name: "withdrawAssets",
262
- inputs: [{ name: "_assets", type: "uint256", internalType: "uint256" }],
263
- outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
264
- stateMutability: "nonpayable"
265
- },
266
259
  {
267
260
  type: "function",
268
261
  name: "getShares",
@@ -681,13 +674,13 @@ var SApUSDABI = [
681
674
  },
682
675
  {
683
676
  type: "function",
684
- name: "previewRedeemMulti",
677
+ name: "previewRedeem",
685
678
  inputs: [
686
679
  { name: "shares", type: "uint256", internalType: "uint256" }
687
680
  ],
688
681
  outputs: [
689
- { name: "assets", type: "address[]", internalType: "address[]" },
690
- { name: "amounts", type: "uint256[]", internalType: "uint256[]" }
682
+ { name: "apUSDOut", type: "uint256", internalType: "uint256" },
683
+ { name: "xBNBOut", type: "uint256", internalType: "uint256" }
691
684
  ],
692
685
  stateMutability: "view"
693
686
  },
@@ -734,56 +727,69 @@ var SApUSDABI = [
734
727
  },
735
728
  {
736
729
  type: "function",
737
- name: "previewCleanXBNB",
730
+ name: "hasRole",
738
731
  inputs: [
739
- { name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
740
- { name: "_router", type: "address", internalType: "address" },
741
- { name: "_path", type: "address[]", internalType: "address[]" }
732
+ { name: "role", type: "bytes32", internalType: "bytes32" },
733
+ { name: "account", type: "address", internalType: "address" }
742
734
  ],
743
- outputs: [{ name: "expectedApUSD", type: "uint256", internalType: "uint256" }],
735
+ outputs: [{ name: "", type: "bool", internalType: "bool" }],
744
736
  stateMutability: "view"
745
737
  },
738
+ // ============ Write Functions ============
746
739
  {
747
740
  type: "function",
748
- name: "KEEPER_ROLE",
749
- inputs: [],
750
- outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }],
751
- stateMutability: "view"
741
+ name: "redeem",
742
+ inputs: [
743
+ { name: "shares", type: "uint256", internalType: "uint256" },
744
+ { name: "receiver", type: "address", internalType: "address" },
745
+ { name: "owner", type: "address", internalType: "address" }
746
+ ],
747
+ outputs: [
748
+ { name: "apUSDOut", type: "uint256", internalType: "uint256" },
749
+ { name: "xBNBOut", type: "uint256", internalType: "uint256" }
750
+ ],
751
+ stateMutability: "nonpayable"
752
752
  },
753
753
  {
754
754
  type: "function",
755
- name: "hasRole",
755
+ name: "deposit",
756
756
  inputs: [
757
- { name: "role", type: "bytes32", internalType: "bytes32" },
758
- { name: "account", type: "address", internalType: "address" }
757
+ { name: "assets", type: "uint256", internalType: "uint256" },
758
+ { name: "receiver", type: "address", internalType: "address" }
759
759
  ],
760
- outputs: [{ name: "", type: "bool", internalType: "bool" }],
761
- stateMutability: "view"
760
+ outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
761
+ stateMutability: "nonpayable"
762
762
  },
763
- // ============ Keeper Functions ============
763
+ // ============ Accounting Functions ============
764
764
  {
765
765
  type: "function",
766
- name: "cleanXBNB",
766
+ name: "addAccounting",
767
767
  inputs: [
768
- { name: "_xBNBAmount", type: "uint256", internalType: "uint256" },
769
- { name: "_minApUSDOut", type: "uint256", internalType: "uint256" },
770
- { name: "_router", type: "address", internalType: "address" },
771
- { name: "_path", type: "address[]", internalType: "address[]" },
772
- { name: "_deadline", type: "uint256", internalType: "uint256" }
768
+ { name: "apUSD", type: "uint256", internalType: "uint256" },
769
+ { name: "xBNB", type: "uint256", internalType: "uint256" }
773
770
  ],
774
- outputs: [{ name: "apUSDReceived", type: "uint256", internalType: "uint256" }],
771
+ outputs: [],
775
772
  stateMutability: "nonpayable"
776
773
  },
777
- // ============ Events ============
778
774
  {
779
- type: "event",
780
- name: "VaultCleaned",
775
+ type: "function",
776
+ name: "subAccounting",
781
777
  inputs: [
782
- { name: "xBNBSold", type: "uint256", indexed: false, internalType: "uint256" },
783
- { name: "apUSDReceived", type: "uint256", indexed: false, internalType: "uint256" },
784
- { name: "keeper", type: "address", indexed: true, internalType: "address" }
778
+ { name: "apUSD", type: "uint256", internalType: "uint256" },
779
+ { name: "xBNB", type: "uint256", internalType: "uint256" }
785
780
  ],
786
- anonymous: false
781
+ outputs: [],
782
+ stateMutability: "nonpayable"
783
+ },
784
+ // ============ Admin Functions ============
785
+ {
786
+ type: "function",
787
+ name: "sweepExcess",
788
+ inputs: [
789
+ { name: "recipient", type: "address", internalType: "address" }
790
+ ],
791
+ outputs: [],
792
+ stateMutability: "nonpayable"
787
793
  }
788
794
  ];
789
795
 
@@ -1755,21 +1761,6 @@ var AspanClient = class extends AspanReadClient {
1755
1761
  args: [params.shares]
1756
1762
  });
1757
1763
  }
1758
- /**
1759
- * Withdraw from stability pool by asset amount
1760
- * @param params Withdraw parameters
1761
- * @returns Transaction hash
1762
- */
1763
- async withdrawAssets(params) {
1764
- return this.walletClient.writeContract({
1765
- chain: this.chain,
1766
- account: this.walletClient.account,
1767
- address: this.diamondAddress,
1768
- abi: DiamondABI,
1769
- functionName: "withdrawAssets",
1770
- args: [params.assets]
1771
- });
1772
- }
1773
1764
  /**
1774
1765
  * Harvest yield from LSTs
1775
1766
  * @returns Transaction hash
@@ -2104,6 +2095,20 @@ var RouterABI = [
2104
2095
  outputs: [{ type: "bool" }],
2105
2096
  stateMutability: "view"
2106
2097
  },
2098
+ {
2099
+ type: "function",
2100
+ name: "lstModes",
2101
+ inputs: [{ name: "lst", type: "address" }],
2102
+ outputs: [{ type: "uint8" }],
2103
+ stateMutability: "view"
2104
+ },
2105
+ {
2106
+ type: "function",
2107
+ name: "isLSTRoutable",
2108
+ inputs: [{ name: "lst", type: "address" }],
2109
+ outputs: [{ type: "bool" }],
2110
+ stateMutability: "view"
2111
+ },
2107
2112
  // Preview functions - unified
2108
2113
  {
2109
2114
  type: "function",
@@ -2366,6 +2371,29 @@ var AspanRouterReadClient = class {
2366
2371
  args: [lst]
2367
2372
  });
2368
2373
  }
2374
+ /**
2375
+ * Get LST mode (0 = SYNC, 1 = ASYNC_DIRECT_ONLY)
2376
+ */
2377
+ async getLSTMode(lst) {
2378
+ const mode = await this.publicClient.readContract({
2379
+ address: this.routerAddress,
2380
+ abi: RouterABI,
2381
+ functionName: "lstModes",
2382
+ args: [lst]
2383
+ });
2384
+ return Number(mode);
2385
+ }
2386
+ /**
2387
+ * Check whether an LST supports routed flows (swap/stake/redeemAndSwap)
2388
+ */
2389
+ async isLSTRoutable(lst) {
2390
+ return this.publicClient.readContract({
2391
+ address: this.routerAddress,
2392
+ abi: RouterABI,
2393
+ functionName: "isLSTRoutable",
2394
+ args: [lst]
2395
+ });
2396
+ }
2369
2397
  /**
2370
2398
  * Get the Diamond contract address
2371
2399
  */
@@ -2404,6 +2432,92 @@ var AspanRouterReadClient = class {
2404
2432
  args: [lst, redeemXBNB, amount]
2405
2433
  });
2406
2434
  }
2435
+ /**
2436
+ * SDK-only preview: input token -> estimated LST -> previewMint
2437
+ * Note: oracle-based estimation (does not include live DEX slippage/price impact)
2438
+ */
2439
+ async previewMintByInput(inputToken, inputAmount, targetLST, mintXBNB) {
2440
+ 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
+ let lstAmount = 0n;
2464
+ const inNorm = inputToken.toLowerCase();
2465
+ if (inNorm === targetLST.toLowerCase()) {
2466
+ 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
+ } else {
2473
+ throw new Error("Unsupported input token for SDK preview");
2474
+ }
2475
+ const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
2476
+ return { lstAmount, mintedAmount };
2477
+ }
2478
+ /**
2479
+ * SDK-only preview: previewRedeem -> estimated output token
2480
+ * Note: oracle-based estimation (does not include live DEX slippage/price impact)
2481
+ */
2482
+ async previewRedeemToOutput(lst, redeemXBNB, amount, outputToken) {
2483
+ const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
2484
+ 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
+ let outputAmount = 0n;
2509
+ const outNorm = outputToken.toLowerCase();
2510
+ if (outNorm === lst.toLowerCase()) {
2511
+ 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
+ } else {
2517
+ throw new Error("Unsupported output token for SDK preview");
2518
+ }
2519
+ return { lstAmount, outputAmount };
2520
+ }
2407
2521
  /**
2408
2522
  * Get user's withdrawal request indices
2409
2523
  */
@@ -2742,7 +2856,7 @@ var BPS_PRECISION = 10000n;
2742
2856
  var PRICE_PRECISION = 10n ** 8n;
2743
2857
  var BSC_ADDRESSES = {
2744
2858
  diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
2745
- router: "0x29dd49b2e98674ee7531f17e4d40a7725918c3f6",
2859
+ router: "0x34a64c4EbDe830773083BA8c9469456616F6723b",
2746
2860
  apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
2747
2861
  xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
2748
2862
  sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspan/sdk",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
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",
@@ -23,6 +23,8 @@
23
23
  "typecheck": "tsc --noEmit",
24
24
  "test": "vitest run",
25
25
  "test:fork": "ANVIL_RPC=http://127.0.0.1:8545 vitest run fork.test.ts",
26
+ "test:risk": "ANVIL_RPC=http://127.0.0.1:8545 vitest run risk.test.ts",
27
+ "test:risk:live": "vitest run risk.test.ts",
26
28
  "test:e2e": "vitest run router.test.ts",
27
29
  "test:watch": "vitest",
28
30
  "clean": "rm -rf dist",
@@ -26,6 +26,7 @@ const ANVIL_RPC = process.env.ANVIL_RPC || "http://127.0.0.1:8545";
26
26
  const TOKENS = {
27
27
  WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" as Address,
28
28
  USDT: "0x55d398326f99059fF775485246999027B3197955" as Address,
29
+ USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" as Address,
29
30
  slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B" as Address,
30
31
  apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as Address,
31
32
  xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as Address,