@aspan/sdk 0.4.5 → 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 +9 -1
- package/dist/index.d.mts +69 -27
- package/dist/index.d.ts +69 -27
- package/dist/index.js +192 -87
- package/dist/index.mjs +192 -87
- 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 +10 -7
- package/src/abi/router.ts +14 -0
- package/src/abi/sApUSD.ts +47 -33
- package/src/client.ts +17 -50
- package/src/index.ts +1 -2
- package/src/router.ts +136 -0
- package/src/types.ts +0 -5
package/dist/index.js
CHANGED
|
@@ -314,13 +314,6 @@ var DiamondABI = [
|
|
|
314
314
|
outputs: [{ name: "assets", type: "uint256", internalType: "uint256" }],
|
|
315
315
|
stateMutability: "nonpayable"
|
|
316
316
|
},
|
|
317
|
-
{
|
|
318
|
-
type: "function",
|
|
319
|
-
name: "withdrawAssets",
|
|
320
|
-
inputs: [{ name: "_assets", type: "uint256", internalType: "uint256" }],
|
|
321
|
-
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
322
|
-
stateMutability: "nonpayable"
|
|
323
|
-
},
|
|
324
317
|
{
|
|
325
318
|
type: "function",
|
|
326
319
|
name: "getShares",
|
|
@@ -363,6 +356,16 @@ var DiamondABI = [
|
|
|
363
356
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
364
357
|
stateMutability: "view"
|
|
365
358
|
},
|
|
359
|
+
{
|
|
360
|
+
type: "function",
|
|
361
|
+
name: "previewRedeemMulti",
|
|
362
|
+
inputs: [{ name: "_shares", type: "uint256", internalType: "uint256" }],
|
|
363
|
+
outputs: [
|
|
364
|
+
{ name: "assets", type: "address[]", internalType: "address[]" },
|
|
365
|
+
{ name: "amounts", type: "uint256[]", internalType: "uint256[]" }
|
|
366
|
+
],
|
|
367
|
+
stateMutability: "view"
|
|
368
|
+
},
|
|
366
369
|
{
|
|
367
370
|
type: "function",
|
|
368
371
|
name: "getPendingYield",
|
|
@@ -729,13 +732,13 @@ var SApUSDABI = [
|
|
|
729
732
|
},
|
|
730
733
|
{
|
|
731
734
|
type: "function",
|
|
732
|
-
name: "
|
|
735
|
+
name: "previewRedeem",
|
|
733
736
|
inputs: [
|
|
734
737
|
{ name: "shares", type: "uint256", internalType: "uint256" }
|
|
735
738
|
],
|
|
736
739
|
outputs: [
|
|
737
|
-
{ name: "
|
|
738
|
-
{ name: "
|
|
740
|
+
{ name: "apUSDOut", type: "uint256", internalType: "uint256" },
|
|
741
|
+
{ name: "xBNBOut", type: "uint256", internalType: "uint256" }
|
|
739
742
|
],
|
|
740
743
|
stateMutability: "view"
|
|
741
744
|
},
|
|
@@ -782,56 +785,69 @@ var SApUSDABI = [
|
|
|
782
785
|
},
|
|
783
786
|
{
|
|
784
787
|
type: "function",
|
|
785
|
-
name: "
|
|
788
|
+
name: "hasRole",
|
|
786
789
|
inputs: [
|
|
787
|
-
{ name: "
|
|
788
|
-
{ name: "
|
|
789
|
-
{ name: "_path", type: "address[]", internalType: "address[]" }
|
|
790
|
+
{ name: "role", type: "bytes32", internalType: "bytes32" },
|
|
791
|
+
{ name: "account", type: "address", internalType: "address" }
|
|
790
792
|
],
|
|
791
|
-
outputs: [{ name: "
|
|
793
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
792
794
|
stateMutability: "view"
|
|
793
795
|
},
|
|
796
|
+
// ============ Write Functions ============
|
|
794
797
|
{
|
|
795
798
|
type: "function",
|
|
796
|
-
name: "
|
|
797
|
-
inputs: [
|
|
798
|
-
|
|
799
|
-
|
|
799
|
+
name: "redeem",
|
|
800
|
+
inputs: [
|
|
801
|
+
{ name: "shares", type: "uint256", internalType: "uint256" },
|
|
802
|
+
{ name: "receiver", type: "address", internalType: "address" },
|
|
803
|
+
{ name: "owner", type: "address", internalType: "address" }
|
|
804
|
+
],
|
|
805
|
+
outputs: [
|
|
806
|
+
{ name: "apUSDOut", type: "uint256", internalType: "uint256" },
|
|
807
|
+
{ name: "xBNBOut", type: "uint256", internalType: "uint256" }
|
|
808
|
+
],
|
|
809
|
+
stateMutability: "nonpayable"
|
|
800
810
|
},
|
|
801
811
|
{
|
|
802
812
|
type: "function",
|
|
803
|
-
name: "
|
|
813
|
+
name: "deposit",
|
|
804
814
|
inputs: [
|
|
805
|
-
{ name: "
|
|
806
|
-
{ name: "
|
|
815
|
+
{ name: "assets", type: "uint256", internalType: "uint256" },
|
|
816
|
+
{ name: "receiver", type: "address", internalType: "address" }
|
|
807
817
|
],
|
|
808
|
-
outputs: [{ name: "", type: "
|
|
809
|
-
stateMutability: "
|
|
818
|
+
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
819
|
+
stateMutability: "nonpayable"
|
|
810
820
|
},
|
|
811
|
-
// ============
|
|
821
|
+
// ============ Accounting Functions ============
|
|
812
822
|
{
|
|
813
823
|
type: "function",
|
|
814
|
-
name: "
|
|
824
|
+
name: "addAccounting",
|
|
815
825
|
inputs: [
|
|
816
|
-
{ name: "
|
|
817
|
-
{ name: "
|
|
818
|
-
{ name: "_router", type: "address", internalType: "address" },
|
|
819
|
-
{ name: "_path", type: "address[]", internalType: "address[]" },
|
|
820
|
-
{ name: "_deadline", type: "uint256", internalType: "uint256" }
|
|
826
|
+
{ name: "apUSD", type: "uint256", internalType: "uint256" },
|
|
827
|
+
{ name: "xBNB", type: "uint256", internalType: "uint256" }
|
|
821
828
|
],
|
|
822
|
-
outputs: [
|
|
829
|
+
outputs: [],
|
|
823
830
|
stateMutability: "nonpayable"
|
|
824
831
|
},
|
|
825
|
-
// ============ Events ============
|
|
826
832
|
{
|
|
827
|
-
type: "
|
|
828
|
-
name: "
|
|
833
|
+
type: "function",
|
|
834
|
+
name: "subAccounting",
|
|
829
835
|
inputs: [
|
|
830
|
-
{ name: "
|
|
831
|
-
{ name: "
|
|
832
|
-
{ name: "keeper", type: "address", indexed: true, internalType: "address" }
|
|
836
|
+
{ name: "apUSD", type: "uint256", internalType: "uint256" },
|
|
837
|
+
{ name: "xBNB", type: "uint256", internalType: "uint256" }
|
|
833
838
|
],
|
|
834
|
-
|
|
839
|
+
outputs: [],
|
|
840
|
+
stateMutability: "nonpayable"
|
|
841
|
+
},
|
|
842
|
+
// ============ Admin Functions ============
|
|
843
|
+
{
|
|
844
|
+
type: "function",
|
|
845
|
+
name: "sweepExcess",
|
|
846
|
+
inputs: [
|
|
847
|
+
{ name: "recipient", type: "address", internalType: "address" }
|
|
848
|
+
],
|
|
849
|
+
outputs: [],
|
|
850
|
+
stateMutability: "nonpayable"
|
|
835
851
|
}
|
|
836
852
|
];
|
|
837
853
|
|
|
@@ -1291,45 +1307,26 @@ var AspanReadClient = class _AspanReadClient {
|
|
|
1291
1307
|
throw error;
|
|
1292
1308
|
}
|
|
1293
1309
|
}
|
|
1294
|
-
async previewRedeem(shares) {
|
|
1295
|
-
try {
|
|
1296
|
-
return await this.publicClient.readContract({
|
|
1297
|
-
address: this.diamondAddress,
|
|
1298
|
-
abi: DiamondABI,
|
|
1299
|
-
functionName: "previewRedeem",
|
|
1300
|
-
args: [shares]
|
|
1301
|
-
});
|
|
1302
|
-
} catch (error) {
|
|
1303
|
-
if (this.isZeroSupplyError(error)) {
|
|
1304
|
-
return shares;
|
|
1305
|
-
}
|
|
1306
|
-
throw error;
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
1310
|
/**
|
|
1310
1311
|
* Preview withdraw with multi-asset support (apUSD + xBNB)
|
|
1312
|
+
* Replaces previewRedeem — works for both clean and dirty pools.
|
|
1311
1313
|
* @param shares Amount of sApUSD shares to redeem
|
|
1312
1314
|
* @returns Object with apUSD and xBNB amounts, plus whether vault has xBNB
|
|
1313
1315
|
*/
|
|
1314
1316
|
async previewRedeemMulti(shares) {
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
}),
|
|
1323
|
-
this.publicClient.readContract({
|
|
1324
|
-
address: sApUSDAddress,
|
|
1325
|
-
abi: SApUSDABI,
|
|
1326
|
-
functionName: "hasStabilityConversion"
|
|
1327
|
-
})
|
|
1328
|
-
]);
|
|
1317
|
+
const [assets, amounts] = await this.publicClient.readContract({
|
|
1318
|
+
address: this.diamondAddress,
|
|
1319
|
+
abi: DiamondABI,
|
|
1320
|
+
functionName: "previewRedeemMulti",
|
|
1321
|
+
args: [shares]
|
|
1322
|
+
});
|
|
1323
|
+
const hasXBNB = amounts.length > 1 && amounts[1] > 0n;
|
|
1329
1324
|
return {
|
|
1330
|
-
apUSD:
|
|
1331
|
-
xBNB:
|
|
1332
|
-
hasXBNB
|
|
1325
|
+
apUSD: amounts[0] ?? 0n,
|
|
1326
|
+
xBNB: amounts[1] ?? 0n,
|
|
1327
|
+
hasXBNB,
|
|
1328
|
+
assets,
|
|
1329
|
+
amounts
|
|
1333
1330
|
};
|
|
1334
1331
|
}
|
|
1335
1332
|
async getPendingYield() {
|
|
@@ -1822,21 +1819,6 @@ var AspanClient = class extends AspanReadClient {
|
|
|
1822
1819
|
args: [params.shares]
|
|
1823
1820
|
});
|
|
1824
1821
|
}
|
|
1825
|
-
/**
|
|
1826
|
-
* Withdraw from stability pool by asset amount
|
|
1827
|
-
* @param params Withdraw parameters
|
|
1828
|
-
* @returns Transaction hash
|
|
1829
|
-
*/
|
|
1830
|
-
async withdrawAssets(params) {
|
|
1831
|
-
return this.walletClient.writeContract({
|
|
1832
|
-
chain: this.chain,
|
|
1833
|
-
account: this.walletClient.account,
|
|
1834
|
-
address: this.diamondAddress,
|
|
1835
|
-
abi: DiamondABI,
|
|
1836
|
-
functionName: "withdrawAssets",
|
|
1837
|
-
args: [params.assets]
|
|
1838
|
-
});
|
|
1839
|
-
}
|
|
1840
1822
|
/**
|
|
1841
1823
|
* Harvest yield from LSTs
|
|
1842
1824
|
* @returns Transaction hash
|
|
@@ -2166,6 +2148,20 @@ var RouterABI = [
|
|
|
2166
2148
|
outputs: [{ type: "bool" }],
|
|
2167
2149
|
stateMutability: "view"
|
|
2168
2150
|
},
|
|
2151
|
+
{
|
|
2152
|
+
type: "function",
|
|
2153
|
+
name: "lstModes",
|
|
2154
|
+
inputs: [{ name: "lst", type: "address" }],
|
|
2155
|
+
outputs: [{ type: "uint8" }],
|
|
2156
|
+
stateMutability: "view"
|
|
2157
|
+
},
|
|
2158
|
+
{
|
|
2159
|
+
type: "function",
|
|
2160
|
+
name: "isLSTRoutable",
|
|
2161
|
+
inputs: [{ name: "lst", type: "address" }],
|
|
2162
|
+
outputs: [{ type: "bool" }],
|
|
2163
|
+
stateMutability: "view"
|
|
2164
|
+
},
|
|
2169
2165
|
// Preview functions - unified
|
|
2170
2166
|
{
|
|
2171
2167
|
type: "function",
|
|
@@ -2428,6 +2424,29 @@ var AspanRouterReadClient = class {
|
|
|
2428
2424
|
args: [lst]
|
|
2429
2425
|
});
|
|
2430
2426
|
}
|
|
2427
|
+
/**
|
|
2428
|
+
* Get LST mode (0 = SYNC, 1 = ASYNC_DIRECT_ONLY)
|
|
2429
|
+
*/
|
|
2430
|
+
async getLSTMode(lst) {
|
|
2431
|
+
const mode = await this.publicClient.readContract({
|
|
2432
|
+
address: this.routerAddress,
|
|
2433
|
+
abi: RouterABI,
|
|
2434
|
+
functionName: "lstModes",
|
|
2435
|
+
args: [lst]
|
|
2436
|
+
});
|
|
2437
|
+
return Number(mode);
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Check whether an LST supports routed flows (swap/stake/redeemAndSwap)
|
|
2441
|
+
*/
|
|
2442
|
+
async isLSTRoutable(lst) {
|
|
2443
|
+
return this.publicClient.readContract({
|
|
2444
|
+
address: this.routerAddress,
|
|
2445
|
+
abi: RouterABI,
|
|
2446
|
+
functionName: "isLSTRoutable",
|
|
2447
|
+
args: [lst]
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2431
2450
|
/**
|
|
2432
2451
|
* Get the Diamond contract address
|
|
2433
2452
|
*/
|
|
@@ -2466,6 +2485,92 @@ var AspanRouterReadClient = class {
|
|
|
2466
2485
|
args: [lst, redeemXBNB, amount]
|
|
2467
2486
|
});
|
|
2468
2487
|
}
|
|
2488
|
+
/**
|
|
2489
|
+
* SDK-only preview: input token -> estimated LST -> previewMint
|
|
2490
|
+
* Note: oracle-based estimation (does not include live DEX slippage/price impact)
|
|
2491
|
+
*/
|
|
2492
|
+
async previewMintByInput(inputToken, inputAmount, targetLST, mintXBNB) {
|
|
2493
|
+
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
|
+
let lstAmount = 0n;
|
|
2517
|
+
const inNorm = inputToken.toLowerCase();
|
|
2518
|
+
if (inNorm === targetLST.toLowerCase()) {
|
|
2519
|
+
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
|
+
} else {
|
|
2526
|
+
throw new Error("Unsupported input token for SDK preview");
|
|
2527
|
+
}
|
|
2528
|
+
const mintedAmount = await this.previewMint(targetLST, lstAmount, mintXBNB);
|
|
2529
|
+
return { lstAmount, mintedAmount };
|
|
2530
|
+
}
|
|
2531
|
+
/**
|
|
2532
|
+
* SDK-only preview: previewRedeem -> estimated output token
|
|
2533
|
+
* Note: oracle-based estimation (does not include live DEX slippage/price impact)
|
|
2534
|
+
*/
|
|
2535
|
+
async previewRedeemToOutput(lst, redeemXBNB, amount, outputToken) {
|
|
2536
|
+
const lstAmount = await this.previewRedeem(lst, redeemXBNB, amount);
|
|
2537
|
+
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
|
+
let outputAmount = 0n;
|
|
2562
|
+
const outNorm = outputToken.toLowerCase();
|
|
2563
|
+
if (outNorm === lst.toLowerCase()) {
|
|
2564
|
+
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
|
+
} else {
|
|
2570
|
+
throw new Error("Unsupported output token for SDK preview");
|
|
2571
|
+
}
|
|
2572
|
+
return { lstAmount, outputAmount };
|
|
2573
|
+
}
|
|
2469
2574
|
/**
|
|
2470
2575
|
* Get user's withdrawal request indices
|
|
2471
2576
|
*/
|
|
@@ -2804,7 +2909,7 @@ var BPS_PRECISION = 10000n;
|
|
|
2804
2909
|
var PRICE_PRECISION = 10n ** 8n;
|
|
2805
2910
|
var BSC_ADDRESSES = {
|
|
2806
2911
|
diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
|
|
2807
|
-
router: "
|
|
2912
|
+
router: "0x34a64c4EbDe830773083BA8c9469456616F6723b",
|
|
2808
2913
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
|
|
2809
2914
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
|
|
2810
2915
|
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
|