@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/README.md +1 -1
- package/dist/index.d.mts +48 -26
- package/dist/index.d.ts +48 -26
- package/dist/index.js +169 -55
- package/dist/index.mjs +169 -55
- package/package.json +3 -1
- package/src/__tests__/fork.test.ts +1 -0
- package/src/__tests__/risk.test.ts +2084 -0
- package/src/__tests__/router.test.ts +676 -62
- package/src/abi/diamond.ts +0 -7
- package/src/abi/router.ts +14 -0
- package/src/abi/sApUSD.ts +47 -33
- package/src/client.ts +0 -17
- package/src/index.ts +1 -2
- package/src/router.ts +136 -0
- package/src/types.ts +0 -5
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: "
|
|
677
|
+
name: "previewRedeem",
|
|
685
678
|
inputs: [
|
|
686
679
|
{ name: "shares", type: "uint256", internalType: "uint256" }
|
|
687
680
|
],
|
|
688
681
|
outputs: [
|
|
689
|
-
{ name: "
|
|
690
|
-
{ name: "
|
|
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: "
|
|
730
|
+
name: "hasRole",
|
|
738
731
|
inputs: [
|
|
739
|
-
{ name: "
|
|
740
|
-
{ name: "
|
|
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: "
|
|
735
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
744
736
|
stateMutability: "view"
|
|
745
737
|
},
|
|
738
|
+
// ============ Write Functions ============
|
|
746
739
|
{
|
|
747
740
|
type: "function",
|
|
748
|
-
name: "
|
|
749
|
-
inputs: [
|
|
750
|
-
|
|
751
|
-
|
|
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: "
|
|
755
|
+
name: "deposit",
|
|
756
756
|
inputs: [
|
|
757
|
-
{ name: "
|
|
758
|
-
{ name: "
|
|
757
|
+
{ name: "assets", type: "uint256", internalType: "uint256" },
|
|
758
|
+
{ name: "receiver", type: "address", internalType: "address" }
|
|
759
759
|
],
|
|
760
|
-
outputs: [{ name: "", type: "
|
|
761
|
-
stateMutability: "
|
|
760
|
+
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
761
|
+
stateMutability: "nonpayable"
|
|
762
762
|
},
|
|
763
|
-
// ============
|
|
763
|
+
// ============ Accounting Functions ============
|
|
764
764
|
{
|
|
765
765
|
type: "function",
|
|
766
|
-
name: "
|
|
766
|
+
name: "addAccounting",
|
|
767
767
|
inputs: [
|
|
768
|
-
{ name: "
|
|
769
|
-
{ name: "
|
|
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: [
|
|
771
|
+
outputs: [],
|
|
775
772
|
stateMutability: "nonpayable"
|
|
776
773
|
},
|
|
777
|
-
// ============ Events ============
|
|
778
774
|
{
|
|
779
|
-
type: "
|
|
780
|
-
name: "
|
|
775
|
+
type: "function",
|
|
776
|
+
name: "subAccounting",
|
|
781
777
|
inputs: [
|
|
782
|
-
{ name: "
|
|
783
|
-
{ name: "
|
|
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
|
-
|
|
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: "
|
|
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.
|
|
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,
|