@aspan/sdk 0.4.9 → 0.5.1
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 +2 -2
- package/dist/index.d.mts +22 -33
- package/dist/index.d.ts +22 -33
- package/dist/index.js +61 -20
- package/dist/index.mjs +61 -20
- package/package.json +7 -7
- package/src/__tests__/risk.test.ts +4 -4
- package/src/__tests__/router.test.ts +24 -14
- package/src/abi/diamond.ts +4 -10
- package/src/client.ts +7 -7
- package/src/index.ts +6 -3
- package/src/router.ts +53 -3
- package/src/types.ts +4 -7
package/README.md
CHANGED
|
@@ -22,11 +22,11 @@ import { BSC_ADDRESSES } from "@aspan/sdk";
|
|
|
22
22
|
| Contract | Address |
|
|
23
23
|
|----------|---------|
|
|
24
24
|
| **Diamond (Main Entry)** | `0x6a11B30d3a70727d5477D6d8090e144443fA1c78` |
|
|
25
|
-
| **Router** | `
|
|
25
|
+
| **Router** | `0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E` |
|
|
26
26
|
| **ApUSD** | `0x4570047eeB5aDb4081c5d470494EB5134e34A287` |
|
|
27
27
|
| **XBNB** | `0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43` |
|
|
28
28
|
| **SApUSD** | `0xE2BE739C4aA4126ee72D612d9548C38B1B0e5A1b` |
|
|
29
|
-
| **wclisBNB** | `
|
|
29
|
+
| **wclisBNB** | `0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07` |
|
|
30
30
|
|
|
31
31
|
## Quick Start
|
|
32
32
|
|
package/dist/index.d.mts
CHANGED
|
@@ -97,14 +97,11 @@ interface RedeemXBNBParams {
|
|
|
97
97
|
}
|
|
98
98
|
/** Parameters for depositing to stability pool */
|
|
99
99
|
interface DepositParams {
|
|
100
|
-
|
|
101
|
-
receiver: Address;
|
|
100
|
+
apUSDAmount: bigint;
|
|
102
101
|
}
|
|
103
|
-
/** Parameters for
|
|
104
|
-
interface
|
|
102
|
+
/** Parameters for withdrawing from stability pool */
|
|
103
|
+
interface WithdrawParams {
|
|
105
104
|
shares: bigint;
|
|
106
|
-
receiver: Address;
|
|
107
|
-
owner: Address;
|
|
108
105
|
}
|
|
109
106
|
/** Overall protocol statistics */
|
|
110
107
|
interface ProtocolStats {
|
|
@@ -206,7 +203,7 @@ interface RouterSwapParams {
|
|
|
206
203
|
targetLST: Address;
|
|
207
204
|
/** Minimum LST to receive from swap (slippage protection) */
|
|
208
205
|
minLSTOut: bigint;
|
|
209
|
-
/** PancakeSwap V3 pool fee tier (500, 2500, 10000) */
|
|
206
|
+
/** PancakeSwap V3 pool fee tier (100, 500, 2500, 10000) */
|
|
210
207
|
poolFee: number;
|
|
211
208
|
}
|
|
212
209
|
/** Router mint parameters */
|
|
@@ -580,11 +577,11 @@ declare class AspanClient extends AspanReadClient {
|
|
|
580
577
|
*/
|
|
581
578
|
deposit(params: DepositParams): Promise<Hash>;
|
|
582
579
|
/**
|
|
583
|
-
*
|
|
584
|
-
* @param params
|
|
580
|
+
* Withdraw from stability pool by shares
|
|
581
|
+
* @param params Withdraw parameters
|
|
585
582
|
* @returns Transaction hash
|
|
586
583
|
*/
|
|
587
|
-
|
|
584
|
+
withdraw(params: WithdrawParams): Promise<Hash>;
|
|
588
585
|
/**
|
|
589
586
|
* Harvest yield from LSTs
|
|
590
587
|
* @returns Transaction hash
|
|
@@ -773,6 +770,11 @@ declare class AspanRouterReadClient {
|
|
|
773
770
|
getWBNB(): Promise<Address>;
|
|
774
771
|
getUSDT(): Promise<Address>;
|
|
775
772
|
getUSDC(): Promise<Address>;
|
|
773
|
+
/**
|
|
774
|
+
* Get stablecoin price in USD (18 decimals) from Chainlink.
|
|
775
|
+
* Returns 1e18 if feed unavailable (graceful fallback).
|
|
776
|
+
*/
|
|
777
|
+
getStablecoinPrice(token: Address): Promise<bigint>;
|
|
776
778
|
getSlisBNB(): Promise<Address>;
|
|
777
779
|
getAsBNB(): Promise<Address>;
|
|
778
780
|
getWclisBNB(): Promise<Address>;
|
|
@@ -1334,13 +1336,9 @@ declare const DiamondABI: readonly [{
|
|
|
1334
1336
|
readonly type: "function";
|
|
1335
1337
|
readonly name: "deposit";
|
|
1336
1338
|
readonly inputs: readonly [{
|
|
1337
|
-
readonly name: "
|
|
1339
|
+
readonly name: "_amount";
|
|
1338
1340
|
readonly type: "uint256";
|
|
1339
1341
|
readonly internalType: "uint256";
|
|
1340
|
-
}, {
|
|
1341
|
-
readonly name: "receiver";
|
|
1342
|
-
readonly type: "address";
|
|
1343
|
-
readonly internalType: "address";
|
|
1344
1342
|
}];
|
|
1345
1343
|
readonly outputs: readonly [{
|
|
1346
1344
|
readonly name: "shares";
|
|
@@ -1350,26 +1348,14 @@ declare const DiamondABI: readonly [{
|
|
|
1350
1348
|
readonly stateMutability: "nonpayable";
|
|
1351
1349
|
}, {
|
|
1352
1350
|
readonly type: "function";
|
|
1353
|
-
readonly name: "
|
|
1351
|
+
readonly name: "withdraw";
|
|
1354
1352
|
readonly inputs: readonly [{
|
|
1355
|
-
readonly name: "
|
|
1353
|
+
readonly name: "_shares";
|
|
1356
1354
|
readonly type: "uint256";
|
|
1357
1355
|
readonly internalType: "uint256";
|
|
1358
|
-
}, {
|
|
1359
|
-
readonly name: "receiver";
|
|
1360
|
-
readonly type: "address";
|
|
1361
|
-
readonly internalType: "address";
|
|
1362
|
-
}, {
|
|
1363
|
-
readonly name: "owner";
|
|
1364
|
-
readonly type: "address";
|
|
1365
|
-
readonly internalType: "address";
|
|
1366
1356
|
}];
|
|
1367
1357
|
readonly outputs: readonly [{
|
|
1368
|
-
readonly name: "
|
|
1369
|
-
readonly type: "uint256";
|
|
1370
|
-
readonly internalType: "uint256";
|
|
1371
|
-
}, {
|
|
1372
|
-
readonly name: "xBNBOut";
|
|
1358
|
+
readonly name: "assets";
|
|
1373
1359
|
readonly type: "uint256";
|
|
1374
1360
|
readonly internalType: "uint256";
|
|
1375
1361
|
}];
|
|
@@ -2828,15 +2814,18 @@ declare const BPS_PRECISION = 10000n;
|
|
|
2828
2814
|
declare const PRICE_PRECISION: bigint;
|
|
2829
2815
|
declare const BSC_ADDRESSES: {
|
|
2830
2816
|
readonly diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78";
|
|
2831
|
-
readonly router: "
|
|
2817
|
+
readonly router: "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E";
|
|
2832
2818
|
readonly apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287";
|
|
2833
2819
|
readonly xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43";
|
|
2834
2820
|
readonly sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB";
|
|
2835
2821
|
readonly slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
|
|
2836
2822
|
readonly asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6";
|
|
2837
|
-
readonly wclisBNB: "
|
|
2823
|
+
readonly wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07";
|
|
2838
2824
|
readonly USDT: "0x55d398326f99059fF775485246999027B3197955";
|
|
2839
2825
|
readonly USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d";
|
|
2826
|
+
/** Chainlink price feeds (BSC Mainnet) */
|
|
2827
|
+
readonly USDT_USD_FEED: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320";
|
|
2828
|
+
readonly USDC_USD_FEED: "0x51597f405303C4377E36123cBc172b13269EA163";
|
|
2840
2829
|
readonly WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
|
|
2841
2830
|
};
|
|
2842
2831
|
declare const PHAROS_ADDRESSES: {
|
|
@@ -2888,4 +2877,4 @@ declare function formatPriceUSD(price: bigint): string;
|
|
|
2888
2877
|
*/
|
|
2889
2878
|
declare function calculateAPY(previousRate: bigint, currentRate: bigint, periodDays: number): number;
|
|
2890
2879
|
|
|
2891
|
-
export { type ApUSDMintedEvent, type ApUSDRedeemedEvent, AspanClient, type AspanClientConfig, AspanReadClient, AspanRouterClient, type AspanRouterClientConfig, AspanRouterReadClient, type AspanRouterWriteClientConfig, type AspanWriteClientConfig, BPS_PRECISION, BSC_ADDRESSES, type BigIntString, CHAIN_IDS, type CurrentFeeTier, type CurrentFees, type DepositParams, type DepositedEvent, DiamondABI, type ExpectedOutput, type FeeTier, type LSTInfo, type LSTYieldInfo, type MintApUSDParams, type MintXBNBParams, type OracleBounds, PHAROS_ADDRESSES, PRECISION, PRICE_PRECISION, type ProtocolStats, type RedeemAndSwapEvent, type RedeemApUSDParams, type
|
|
2880
|
+
export { type ApUSDMintedEvent, type ApUSDRedeemedEvent, AspanClient, type AspanClientConfig, AspanReadClient, AspanRouterClient, type AspanRouterClientConfig, AspanRouterReadClient, type AspanRouterWriteClientConfig, type AspanWriteClientConfig, BPS_PRECISION, BSC_ADDRESSES, type BigIntString, CHAIN_IDS, type CurrentFeeTier, type CurrentFees, type DepositParams, type DepositedEvent, DiamondABI, type ExpectedOutput, type FeeTier, type LSTInfo, type LSTYieldInfo, type MintApUSDParams, type MintXBNBParams, type OracleBounds, PHAROS_ADDRESSES, PRECISION, PRICE_PRECISION, type ProtocolStats, type RedeemAndSwapEvent, type RedeemApUSDParams, type RedeemXBNBParams, RouterABI, type RouterMintEvent, type RouterMintParams, type RouterMintParams2, type RouterRedeemAndSwapParams, type RouterRedeemAndUnstakeParams, type RouterRedeemEvent, type RouterRedeemParams, type RouterSwapParams, type StabilityMode2Info, type StabilityModeInfo, type StabilityPoolStats, type StakeAndMintEvent, type StakeAndMintParams, type SwapAndMintDefaultParams, type SwapAndMintEvent, type SwapAndMintParams, type TokenAddresses, type TransactionReceipt, type TransactionResult, type UnstakeClaimedEvent, type UnstakeRequestedEvent, type UserStabilityPoolPosition, type WithdrawParams, type WithdrawalRequestInfo, type WithdrawnEvent, type XBNBMintedEvent, type XBNBRedeemedEvent, type YieldHarvestedEvent, type YieldStats, calculateAPY, createAspanClient, createAspanPharosClient, createAspanPharosReadClient, createAspanReadClient, createAspanReadClientForChain, createAspanTestnetClient, createAspanTestnetReadClient, createAspanWriteClientForChain, createRouterClient, createRouterPharosClient, createRouterPharosReadClient, createRouterReadClient, createRouterReadClientForChain, createRouterTestnetClient, createRouterTestnetReadClient, createRouterWriteClientForChain, encodeV3Path, formatAmount, formatCR, formatFeeBPS, formatPriceUSD, getChainById, parseAmount, pharosTestnet };
|
package/dist/index.d.ts
CHANGED
|
@@ -97,14 +97,11 @@ interface RedeemXBNBParams {
|
|
|
97
97
|
}
|
|
98
98
|
/** Parameters for depositing to stability pool */
|
|
99
99
|
interface DepositParams {
|
|
100
|
-
|
|
101
|
-
receiver: Address;
|
|
100
|
+
apUSDAmount: bigint;
|
|
102
101
|
}
|
|
103
|
-
/** Parameters for
|
|
104
|
-
interface
|
|
102
|
+
/** Parameters for withdrawing from stability pool */
|
|
103
|
+
interface WithdrawParams {
|
|
105
104
|
shares: bigint;
|
|
106
|
-
receiver: Address;
|
|
107
|
-
owner: Address;
|
|
108
105
|
}
|
|
109
106
|
/** Overall protocol statistics */
|
|
110
107
|
interface ProtocolStats {
|
|
@@ -206,7 +203,7 @@ interface RouterSwapParams {
|
|
|
206
203
|
targetLST: Address;
|
|
207
204
|
/** Minimum LST to receive from swap (slippage protection) */
|
|
208
205
|
minLSTOut: bigint;
|
|
209
|
-
/** PancakeSwap V3 pool fee tier (500, 2500, 10000) */
|
|
206
|
+
/** PancakeSwap V3 pool fee tier (100, 500, 2500, 10000) */
|
|
210
207
|
poolFee: number;
|
|
211
208
|
}
|
|
212
209
|
/** Router mint parameters */
|
|
@@ -580,11 +577,11 @@ declare class AspanClient extends AspanReadClient {
|
|
|
580
577
|
*/
|
|
581
578
|
deposit(params: DepositParams): Promise<Hash>;
|
|
582
579
|
/**
|
|
583
|
-
*
|
|
584
|
-
* @param params
|
|
580
|
+
* Withdraw from stability pool by shares
|
|
581
|
+
* @param params Withdraw parameters
|
|
585
582
|
* @returns Transaction hash
|
|
586
583
|
*/
|
|
587
|
-
|
|
584
|
+
withdraw(params: WithdrawParams): Promise<Hash>;
|
|
588
585
|
/**
|
|
589
586
|
* Harvest yield from LSTs
|
|
590
587
|
* @returns Transaction hash
|
|
@@ -773,6 +770,11 @@ declare class AspanRouterReadClient {
|
|
|
773
770
|
getWBNB(): Promise<Address>;
|
|
774
771
|
getUSDT(): Promise<Address>;
|
|
775
772
|
getUSDC(): Promise<Address>;
|
|
773
|
+
/**
|
|
774
|
+
* Get stablecoin price in USD (18 decimals) from Chainlink.
|
|
775
|
+
* Returns 1e18 if feed unavailable (graceful fallback).
|
|
776
|
+
*/
|
|
777
|
+
getStablecoinPrice(token: Address): Promise<bigint>;
|
|
776
778
|
getSlisBNB(): Promise<Address>;
|
|
777
779
|
getAsBNB(): Promise<Address>;
|
|
778
780
|
getWclisBNB(): Promise<Address>;
|
|
@@ -1334,13 +1336,9 @@ declare const DiamondABI: readonly [{
|
|
|
1334
1336
|
readonly type: "function";
|
|
1335
1337
|
readonly name: "deposit";
|
|
1336
1338
|
readonly inputs: readonly [{
|
|
1337
|
-
readonly name: "
|
|
1339
|
+
readonly name: "_amount";
|
|
1338
1340
|
readonly type: "uint256";
|
|
1339
1341
|
readonly internalType: "uint256";
|
|
1340
|
-
}, {
|
|
1341
|
-
readonly name: "receiver";
|
|
1342
|
-
readonly type: "address";
|
|
1343
|
-
readonly internalType: "address";
|
|
1344
1342
|
}];
|
|
1345
1343
|
readonly outputs: readonly [{
|
|
1346
1344
|
readonly name: "shares";
|
|
@@ -1350,26 +1348,14 @@ declare const DiamondABI: readonly [{
|
|
|
1350
1348
|
readonly stateMutability: "nonpayable";
|
|
1351
1349
|
}, {
|
|
1352
1350
|
readonly type: "function";
|
|
1353
|
-
readonly name: "
|
|
1351
|
+
readonly name: "withdraw";
|
|
1354
1352
|
readonly inputs: readonly [{
|
|
1355
|
-
readonly name: "
|
|
1353
|
+
readonly name: "_shares";
|
|
1356
1354
|
readonly type: "uint256";
|
|
1357
1355
|
readonly internalType: "uint256";
|
|
1358
|
-
}, {
|
|
1359
|
-
readonly name: "receiver";
|
|
1360
|
-
readonly type: "address";
|
|
1361
|
-
readonly internalType: "address";
|
|
1362
|
-
}, {
|
|
1363
|
-
readonly name: "owner";
|
|
1364
|
-
readonly type: "address";
|
|
1365
|
-
readonly internalType: "address";
|
|
1366
1356
|
}];
|
|
1367
1357
|
readonly outputs: readonly [{
|
|
1368
|
-
readonly name: "
|
|
1369
|
-
readonly type: "uint256";
|
|
1370
|
-
readonly internalType: "uint256";
|
|
1371
|
-
}, {
|
|
1372
|
-
readonly name: "xBNBOut";
|
|
1358
|
+
readonly name: "assets";
|
|
1373
1359
|
readonly type: "uint256";
|
|
1374
1360
|
readonly internalType: "uint256";
|
|
1375
1361
|
}];
|
|
@@ -2828,15 +2814,18 @@ declare const BPS_PRECISION = 10000n;
|
|
|
2828
2814
|
declare const PRICE_PRECISION: bigint;
|
|
2829
2815
|
declare const BSC_ADDRESSES: {
|
|
2830
2816
|
readonly diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78";
|
|
2831
|
-
readonly router: "
|
|
2817
|
+
readonly router: "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E";
|
|
2832
2818
|
readonly apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287";
|
|
2833
2819
|
readonly xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43";
|
|
2834
2820
|
readonly sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB";
|
|
2835
2821
|
readonly slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B";
|
|
2836
2822
|
readonly asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6";
|
|
2837
|
-
readonly wclisBNB: "
|
|
2823
|
+
readonly wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07";
|
|
2838
2824
|
readonly USDT: "0x55d398326f99059fF775485246999027B3197955";
|
|
2839
2825
|
readonly USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d";
|
|
2826
|
+
/** Chainlink price feeds (BSC Mainnet) */
|
|
2827
|
+
readonly USDT_USD_FEED: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320";
|
|
2828
|
+
readonly USDC_USD_FEED: "0x51597f405303C4377E36123cBc172b13269EA163";
|
|
2840
2829
|
readonly WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
|
|
2841
2830
|
};
|
|
2842
2831
|
declare const PHAROS_ADDRESSES: {
|
|
@@ -2888,4 +2877,4 @@ declare function formatPriceUSD(price: bigint): string;
|
|
|
2888
2877
|
*/
|
|
2889
2878
|
declare function calculateAPY(previousRate: bigint, currentRate: bigint, periodDays: number): number;
|
|
2890
2879
|
|
|
2891
|
-
export { type ApUSDMintedEvent, type ApUSDRedeemedEvent, AspanClient, type AspanClientConfig, AspanReadClient, AspanRouterClient, type AspanRouterClientConfig, AspanRouterReadClient, type AspanRouterWriteClientConfig, type AspanWriteClientConfig, BPS_PRECISION, BSC_ADDRESSES, type BigIntString, CHAIN_IDS, type CurrentFeeTier, type CurrentFees, type DepositParams, type DepositedEvent, DiamondABI, type ExpectedOutput, type FeeTier, type LSTInfo, type LSTYieldInfo, type MintApUSDParams, type MintXBNBParams, type OracleBounds, PHAROS_ADDRESSES, PRECISION, PRICE_PRECISION, type ProtocolStats, type RedeemAndSwapEvent, type RedeemApUSDParams, type
|
|
2880
|
+
export { type ApUSDMintedEvent, type ApUSDRedeemedEvent, AspanClient, type AspanClientConfig, AspanReadClient, AspanRouterClient, type AspanRouterClientConfig, AspanRouterReadClient, type AspanRouterWriteClientConfig, type AspanWriteClientConfig, BPS_PRECISION, BSC_ADDRESSES, type BigIntString, CHAIN_IDS, type CurrentFeeTier, type CurrentFees, type DepositParams, type DepositedEvent, DiamondABI, type ExpectedOutput, type FeeTier, type LSTInfo, type LSTYieldInfo, type MintApUSDParams, type MintXBNBParams, type OracleBounds, PHAROS_ADDRESSES, PRECISION, PRICE_PRECISION, type ProtocolStats, type RedeemAndSwapEvent, type RedeemApUSDParams, type RedeemXBNBParams, RouterABI, type RouterMintEvent, type RouterMintParams, type RouterMintParams2, type RouterRedeemAndSwapParams, type RouterRedeemAndUnstakeParams, type RouterRedeemEvent, type RouterRedeemParams, type RouterSwapParams, type StabilityMode2Info, type StabilityModeInfo, type StabilityPoolStats, type StakeAndMintEvent, type StakeAndMintParams, type SwapAndMintDefaultParams, type SwapAndMintEvent, type SwapAndMintParams, type TokenAddresses, type TransactionReceipt, type TransactionResult, type UnstakeClaimedEvent, type UnstakeRequestedEvent, type UserStabilityPoolPosition, type WithdrawParams, type WithdrawalRequestInfo, type WithdrawnEvent, type XBNBMintedEvent, type XBNBRedeemedEvent, type YieldHarvestedEvent, type YieldStats, calculateAPY, createAspanClient, createAspanPharosClient, createAspanPharosReadClient, createAspanReadClient, createAspanReadClientForChain, createAspanTestnetClient, createAspanTestnetReadClient, createAspanWriteClientForChain, createRouterClient, createRouterPharosClient, createRouterPharosReadClient, createRouterReadClient, createRouterReadClientForChain, createRouterTestnetClient, createRouterTestnetReadClient, createRouterWriteClientForChain, encodeV3Path, formatAmount, formatCR, formatFeeBPS, formatPriceUSD, getChainById, parseAmount, pharosTestnet };
|
package/dist/index.js
CHANGED
|
@@ -303,24 +303,18 @@ var DiamondABI = [
|
|
|
303
303
|
{
|
|
304
304
|
type: "function",
|
|
305
305
|
name: "deposit",
|
|
306
|
-
inputs: [
|
|
307
|
-
{ name: "assets", type: "uint256", internalType: "uint256" },
|
|
308
|
-
{ name: "receiver", type: "address", internalType: "address" }
|
|
309
|
-
],
|
|
306
|
+
inputs: [{ name: "_amount", type: "uint256", internalType: "uint256" }],
|
|
310
307
|
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
311
308
|
stateMutability: "nonpayable"
|
|
312
309
|
},
|
|
313
310
|
{
|
|
314
311
|
type: "function",
|
|
315
|
-
name: "
|
|
312
|
+
name: "withdraw",
|
|
316
313
|
inputs: [
|
|
317
|
-
{ name: "
|
|
318
|
-
{ name: "receiver", type: "address", internalType: "address" },
|
|
319
|
-
{ name: "owner", type: "address", internalType: "address" }
|
|
314
|
+
{ name: "_shares", type: "uint256", internalType: "uint256" }
|
|
320
315
|
],
|
|
321
316
|
outputs: [
|
|
322
|
-
{ name: "
|
|
323
|
-
{ name: "xBNBOut", type: "uint256", internalType: "uint256" }
|
|
317
|
+
{ name: "assets", type: "uint256", internalType: "uint256" }
|
|
324
318
|
],
|
|
325
319
|
stateMutability: "nonpayable"
|
|
326
320
|
},
|
|
@@ -1812,22 +1806,22 @@ var AspanClient = class extends AspanReadClient {
|
|
|
1812
1806
|
address: this.diamondAddress,
|
|
1813
1807
|
abi: DiamondABI,
|
|
1814
1808
|
functionName: "deposit",
|
|
1815
|
-
args: [params.
|
|
1809
|
+
args: [params.apUSDAmount]
|
|
1816
1810
|
});
|
|
1817
1811
|
}
|
|
1818
1812
|
/**
|
|
1819
|
-
*
|
|
1820
|
-
* @param params
|
|
1813
|
+
* Withdraw from stability pool by shares
|
|
1814
|
+
* @param params Withdraw parameters
|
|
1821
1815
|
* @returns Transaction hash
|
|
1822
1816
|
*/
|
|
1823
|
-
async
|
|
1817
|
+
async withdraw(params) {
|
|
1824
1818
|
return this.walletClient.writeContract({
|
|
1825
1819
|
chain: this.chain,
|
|
1826
1820
|
account: this.walletClient.account,
|
|
1827
1821
|
address: this.diamondAddress,
|
|
1828
1822
|
abi: DiamondABI,
|
|
1829
|
-
functionName: "
|
|
1830
|
-
args: [params.shares
|
|
1823
|
+
functionName: "withdraw",
|
|
1824
|
+
args: [params.shares]
|
|
1831
1825
|
});
|
|
1832
1826
|
}
|
|
1833
1827
|
/**
|
|
@@ -2390,6 +2384,21 @@ var RouterABI = [
|
|
|
2390
2384
|
];
|
|
2391
2385
|
|
|
2392
2386
|
// src/router.ts
|
|
2387
|
+
var ChainlinkABI = [
|
|
2388
|
+
{
|
|
2389
|
+
type: "function",
|
|
2390
|
+
name: "latestRoundData",
|
|
2391
|
+
inputs: [],
|
|
2392
|
+
outputs: [
|
|
2393
|
+
{ name: "roundId", type: "uint80" },
|
|
2394
|
+
{ name: "answer", type: "int256" },
|
|
2395
|
+
{ name: "startedAt", type: "uint256" },
|
|
2396
|
+
{ name: "updatedAt", type: "uint256" },
|
|
2397
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
2398
|
+
],
|
|
2399
|
+
stateMutability: "view"
|
|
2400
|
+
}
|
|
2401
|
+
];
|
|
2393
2402
|
var AspanRouterReadClient = class {
|
|
2394
2403
|
publicClient;
|
|
2395
2404
|
routerAddress;
|
|
@@ -2545,7 +2554,9 @@ var AspanRouterReadClient = class {
|
|
|
2545
2554
|
const usdValue = inputAmount * bnbPrice18 / one;
|
|
2546
2555
|
lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
|
|
2547
2556
|
} else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
|
|
2548
|
-
|
|
2557
|
+
const stablePrice18 = await this.getStablecoinPrice(inputToken);
|
|
2558
|
+
const usdValue = inputAmount * stablePrice18 / one;
|
|
2559
|
+
lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
|
|
2549
2560
|
} else {
|
|
2550
2561
|
throw new Error("Unsupported input token for SDK preview");
|
|
2551
2562
|
}
|
|
@@ -2591,7 +2602,8 @@ var AspanRouterReadClient = class {
|
|
|
2591
2602
|
if (outNorm === import_viem2.zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
|
|
2592
2603
|
outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
|
|
2593
2604
|
} else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
|
|
2594
|
-
|
|
2605
|
+
const stablePrice18 = await this.getStablecoinPrice(outputToken);
|
|
2606
|
+
outputAmount = stablePrice18 === 0n ? 0n : usdValue * one / stablePrice18;
|
|
2595
2607
|
} else {
|
|
2596
2608
|
throw new Error("Unsupported output token for SDK preview");
|
|
2597
2609
|
}
|
|
@@ -2656,6 +2668,32 @@ var AspanRouterReadClient = class {
|
|
|
2656
2668
|
})
|
|
2657
2669
|
);
|
|
2658
2670
|
}
|
|
2671
|
+
/**
|
|
2672
|
+
* Get stablecoin price in USD (18 decimals) from Chainlink.
|
|
2673
|
+
* Returns 1e18 if feed unavailable (graceful fallback).
|
|
2674
|
+
*/
|
|
2675
|
+
async getStablecoinPrice(token) {
|
|
2676
|
+
const usdt = await this.getUSDT();
|
|
2677
|
+
const usdc = await this.getUSDC();
|
|
2678
|
+
const norm = token.toLowerCase();
|
|
2679
|
+
let feed = null;
|
|
2680
|
+
if (norm === usdt.toLowerCase()) {
|
|
2681
|
+
feed = BSC_ADDRESSES.USDT_USD_FEED;
|
|
2682
|
+
} else if (norm === usdc.toLowerCase()) {
|
|
2683
|
+
feed = BSC_ADDRESSES.USDC_USD_FEED;
|
|
2684
|
+
}
|
|
2685
|
+
if (!feed) return 10n ** 18n;
|
|
2686
|
+
try {
|
|
2687
|
+
const [, answer] = await this.publicClient.readContract({
|
|
2688
|
+
address: feed,
|
|
2689
|
+
abi: ChainlinkABI,
|
|
2690
|
+
functionName: "latestRoundData"
|
|
2691
|
+
});
|
|
2692
|
+
return BigInt(answer) * 10n ** 10n;
|
|
2693
|
+
} catch {
|
|
2694
|
+
return 10n ** 18n;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2659
2697
|
async getSlisBNB() {
|
|
2660
2698
|
return this._getCachedAddress(
|
|
2661
2699
|
"slisBNB",
|
|
@@ -2960,17 +2998,20 @@ var BPS_PRECISION = 10000n;
|
|
|
2960
2998
|
var PRICE_PRECISION = 10n ** 8n;
|
|
2961
2999
|
var BSC_ADDRESSES = {
|
|
2962
3000
|
diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
|
|
2963
|
-
router: "
|
|
3001
|
+
router: "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E",
|
|
2964
3002
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
|
|
2965
3003
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
|
|
2966
3004
|
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
|
|
2967
3005
|
// LSTs
|
|
2968
3006
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
|
|
2969
3007
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6",
|
|
2970
|
-
wclisBNB: "
|
|
3008
|
+
wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07",
|
|
2971
3009
|
// Stablecoins
|
|
2972
3010
|
USDT: "0x55d398326f99059fF775485246999027B3197955",
|
|
2973
3011
|
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
3012
|
+
/** Chainlink price feeds (BSC Mainnet) */
|
|
3013
|
+
USDT_USD_FEED: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320",
|
|
3014
|
+
USDC_USD_FEED: "0x51597f405303C4377E36123cBc172b13269EA163",
|
|
2974
3015
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"
|
|
2975
3016
|
};
|
|
2976
3017
|
var PHAROS_ADDRESSES = {
|
package/dist/index.mjs
CHANGED
|
@@ -245,24 +245,18 @@ var DiamondABI = [
|
|
|
245
245
|
{
|
|
246
246
|
type: "function",
|
|
247
247
|
name: "deposit",
|
|
248
|
-
inputs: [
|
|
249
|
-
{ name: "assets", type: "uint256", internalType: "uint256" },
|
|
250
|
-
{ name: "receiver", type: "address", internalType: "address" }
|
|
251
|
-
],
|
|
248
|
+
inputs: [{ name: "_amount", type: "uint256", internalType: "uint256" }],
|
|
252
249
|
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
253
250
|
stateMutability: "nonpayable"
|
|
254
251
|
},
|
|
255
252
|
{
|
|
256
253
|
type: "function",
|
|
257
|
-
name: "
|
|
254
|
+
name: "withdraw",
|
|
258
255
|
inputs: [
|
|
259
|
-
{ name: "
|
|
260
|
-
{ name: "receiver", type: "address", internalType: "address" },
|
|
261
|
-
{ name: "owner", type: "address", internalType: "address" }
|
|
256
|
+
{ name: "_shares", type: "uint256", internalType: "uint256" }
|
|
262
257
|
],
|
|
263
258
|
outputs: [
|
|
264
|
-
{ name: "
|
|
265
|
-
{ name: "xBNBOut", type: "uint256", internalType: "uint256" }
|
|
259
|
+
{ name: "assets", type: "uint256", internalType: "uint256" }
|
|
266
260
|
],
|
|
267
261
|
stateMutability: "nonpayable"
|
|
268
262
|
},
|
|
@@ -1754,22 +1748,22 @@ var AspanClient = class extends AspanReadClient {
|
|
|
1754
1748
|
address: this.diamondAddress,
|
|
1755
1749
|
abi: DiamondABI,
|
|
1756
1750
|
functionName: "deposit",
|
|
1757
|
-
args: [params.
|
|
1751
|
+
args: [params.apUSDAmount]
|
|
1758
1752
|
});
|
|
1759
1753
|
}
|
|
1760
1754
|
/**
|
|
1761
|
-
*
|
|
1762
|
-
* @param params
|
|
1755
|
+
* Withdraw from stability pool by shares
|
|
1756
|
+
* @param params Withdraw parameters
|
|
1763
1757
|
* @returns Transaction hash
|
|
1764
1758
|
*/
|
|
1765
|
-
async
|
|
1759
|
+
async withdraw(params) {
|
|
1766
1760
|
return this.walletClient.writeContract({
|
|
1767
1761
|
chain: this.chain,
|
|
1768
1762
|
account: this.walletClient.account,
|
|
1769
1763
|
address: this.diamondAddress,
|
|
1770
1764
|
abi: DiamondABI,
|
|
1771
|
-
functionName: "
|
|
1772
|
-
args: [params.shares
|
|
1765
|
+
functionName: "withdraw",
|
|
1766
|
+
args: [params.shares]
|
|
1773
1767
|
});
|
|
1774
1768
|
}
|
|
1775
1769
|
/**
|
|
@@ -2337,6 +2331,21 @@ var RouterABI = [
|
|
|
2337
2331
|
];
|
|
2338
2332
|
|
|
2339
2333
|
// src/router.ts
|
|
2334
|
+
var ChainlinkABI = [
|
|
2335
|
+
{
|
|
2336
|
+
type: "function",
|
|
2337
|
+
name: "latestRoundData",
|
|
2338
|
+
inputs: [],
|
|
2339
|
+
outputs: [
|
|
2340
|
+
{ name: "roundId", type: "uint80" },
|
|
2341
|
+
{ name: "answer", type: "int256" },
|
|
2342
|
+
{ name: "startedAt", type: "uint256" },
|
|
2343
|
+
{ name: "updatedAt", type: "uint256" },
|
|
2344
|
+
{ name: "answeredInRound", type: "uint80" }
|
|
2345
|
+
],
|
|
2346
|
+
stateMutability: "view"
|
|
2347
|
+
}
|
|
2348
|
+
];
|
|
2340
2349
|
var AspanRouterReadClient = class {
|
|
2341
2350
|
publicClient;
|
|
2342
2351
|
routerAddress;
|
|
@@ -2492,7 +2501,9 @@ var AspanRouterReadClient = class {
|
|
|
2492
2501
|
const usdValue = inputAmount * bnbPrice18 / one;
|
|
2493
2502
|
lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
|
|
2494
2503
|
} else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
|
|
2495
|
-
|
|
2504
|
+
const stablePrice18 = await this.getStablecoinPrice(inputToken);
|
|
2505
|
+
const usdValue = inputAmount * stablePrice18 / one;
|
|
2506
|
+
lstAmount = lstPrice18 === 0n ? 0n : usdValue * one / lstPrice18;
|
|
2496
2507
|
} else {
|
|
2497
2508
|
throw new Error("Unsupported input token for SDK preview");
|
|
2498
2509
|
}
|
|
@@ -2538,7 +2549,8 @@ var AspanRouterReadClient = class {
|
|
|
2538
2549
|
if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
|
|
2539
2550
|
outputAmount = bnbPrice18 === 0n ? 0n : usdValue * one / bnbPrice18;
|
|
2540
2551
|
} else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
|
|
2541
|
-
|
|
2552
|
+
const stablePrice18 = await this.getStablecoinPrice(outputToken);
|
|
2553
|
+
outputAmount = stablePrice18 === 0n ? 0n : usdValue * one / stablePrice18;
|
|
2542
2554
|
} else {
|
|
2543
2555
|
throw new Error("Unsupported output token for SDK preview");
|
|
2544
2556
|
}
|
|
@@ -2603,6 +2615,32 @@ var AspanRouterReadClient = class {
|
|
|
2603
2615
|
})
|
|
2604
2616
|
);
|
|
2605
2617
|
}
|
|
2618
|
+
/**
|
|
2619
|
+
* Get stablecoin price in USD (18 decimals) from Chainlink.
|
|
2620
|
+
* Returns 1e18 if feed unavailable (graceful fallback).
|
|
2621
|
+
*/
|
|
2622
|
+
async getStablecoinPrice(token) {
|
|
2623
|
+
const usdt = await this.getUSDT();
|
|
2624
|
+
const usdc = await this.getUSDC();
|
|
2625
|
+
const norm = token.toLowerCase();
|
|
2626
|
+
let feed = null;
|
|
2627
|
+
if (norm === usdt.toLowerCase()) {
|
|
2628
|
+
feed = BSC_ADDRESSES.USDT_USD_FEED;
|
|
2629
|
+
} else if (norm === usdc.toLowerCase()) {
|
|
2630
|
+
feed = BSC_ADDRESSES.USDC_USD_FEED;
|
|
2631
|
+
}
|
|
2632
|
+
if (!feed) return 10n ** 18n;
|
|
2633
|
+
try {
|
|
2634
|
+
const [, answer] = await this.publicClient.readContract({
|
|
2635
|
+
address: feed,
|
|
2636
|
+
abi: ChainlinkABI,
|
|
2637
|
+
functionName: "latestRoundData"
|
|
2638
|
+
});
|
|
2639
|
+
return BigInt(answer) * 10n ** 10n;
|
|
2640
|
+
} catch {
|
|
2641
|
+
return 10n ** 18n;
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2606
2644
|
async getSlisBNB() {
|
|
2607
2645
|
return this._getCachedAddress(
|
|
2608
2646
|
"slisBNB",
|
|
@@ -2907,17 +2945,20 @@ var BPS_PRECISION = 10000n;
|
|
|
2907
2945
|
var PRICE_PRECISION = 10n ** 8n;
|
|
2908
2946
|
var BSC_ADDRESSES = {
|
|
2909
2947
|
diamond: "0x6a11B30d3a70727d5477D6d8090e144443fA1c78",
|
|
2910
|
-
router: "
|
|
2948
|
+
router: "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E",
|
|
2911
2949
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287",
|
|
2912
2950
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43",
|
|
2913
2951
|
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB",
|
|
2914
2952
|
// LSTs
|
|
2915
2953
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B",
|
|
2916
2954
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6",
|
|
2917
|
-
wclisBNB: "
|
|
2955
|
+
wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07",
|
|
2918
2956
|
// Stablecoins
|
|
2919
2957
|
USDT: "0x55d398326f99059fF775485246999027B3197955",
|
|
2920
2958
|
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
2959
|
+
/** Chainlink price feeds (BSC Mainnet) */
|
|
2960
|
+
USDT_USD_FEED: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320",
|
|
2961
|
+
USDC_USD_FEED: "0x51597f405303C4377E36123cBc172b13269EA163",
|
|
2921
2962
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"
|
|
2922
2963
|
};
|
|
2923
2964
|
var PHAROS_ADDRESSES = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aspan/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
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",
|
|
@@ -45,18 +45,18 @@
|
|
|
45
45
|
"author": "",
|
|
46
46
|
"license": "MIT",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"viem": "
|
|
48
|
+
"viem": ">=2.0.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^20.10.0",
|
|
52
|
-
"tsup": "^8.0.1",
|
|
53
|
-
"typescript": "^5.3.0",
|
|
54
|
-
"vitest": "^1.0.0",
|
|
55
|
-
"eslint": "^8.55.0",
|
|
56
52
|
"@typescript-eslint/eslint-plugin": "^6.13.0",
|
|
57
53
|
"@typescript-eslint/parser": "^6.13.0",
|
|
54
|
+
"dotenv": "^16.3.1",
|
|
55
|
+
"eslint": "^8.55.0",
|
|
56
|
+
"tsup": "^8.0.1",
|
|
58
57
|
"tsx": "^4.7.0",
|
|
59
|
-
"
|
|
58
|
+
"typescript": "^5.3.0",
|
|
59
|
+
"vitest": "^1.6.1"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"viem": ">=2.0.0"
|
|
@@ -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 = "
|
|
64
|
+
const ROUTER = "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E" as Address;
|
|
65
65
|
|
|
66
66
|
const TOKENS = {
|
|
67
67
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" as Address,
|
|
@@ -69,7 +69,7 @@ const TOKENS = {
|
|
|
69
69
|
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" as Address,
|
|
70
70
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B" as Address,
|
|
71
71
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6" as Address,
|
|
72
|
-
wclisBNB: "
|
|
72
|
+
wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07" as Address,
|
|
73
73
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as Address,
|
|
74
74
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as Address,
|
|
75
75
|
sApUSD: "0xE2BE739C4aA4126ee72D612d9548C38B1B0e5A1b" 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({
|
|
1227
|
+
await waitTx(await diamondWrite.deposit({ apUSDAmount: depositedApUSD }));
|
|
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.
|
|
1354
|
+
await waitTx(await diamondWrite.withdraw({ shares: currentShares }));
|
|
1355
1355
|
} catch (err: any) {
|
|
1356
1356
|
console.log(` ⚠️ Withdraw failed: ${err.shortMessage || err.message?.slice(0, 100)}`);
|
|
1357
1357
|
return;
|
|
@@ -43,9 +43,9 @@ const TOKENS = {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// Minimal amounts — just enough to verify path connectivity
|
|
46
|
-
const BNB_AMOUNT = parseEther("0.
|
|
46
|
+
const BNB_AMOUNT = parseEther("0.002");
|
|
47
47
|
const USDT_AMOUNT = parseAmount("1");
|
|
48
|
-
const WBNB_AMOUNT = parseEther("0.
|
|
48
|
+
const WBNB_AMOUNT = parseEther("0.002");
|
|
49
49
|
const USDC_AMOUNT = parseAmount("1");
|
|
50
50
|
|
|
51
51
|
const ERC20_ABI = [
|
|
@@ -589,17 +589,26 @@ describe("AspanRouter SDK", () => {
|
|
|
589
589
|
|
|
590
590
|
const indicesBefore = await readClient.getUserWithdrawalIndices(account.address);
|
|
591
591
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
592
|
+
try {
|
|
593
|
+
const unstakeHash = await writeClient.redeemAndRequestUnstake({
|
|
594
|
+
redeemXBNB: true,
|
|
595
|
+
amount: freshMinted,
|
|
596
|
+
});
|
|
597
|
+
const unstakeReceipt = await publicClient.waitForTransactionReceipt({ hash: unstakeHash });
|
|
598
|
+
await sleep(2000);
|
|
599
|
+
expect(unstakeReceipt.status).toBe("success");
|
|
600
|
+
|
|
601
|
+
const indicesAfter = await readClient.getUserWithdrawalIndices(account.address);
|
|
602
|
+
expect(indicesAfter.length).toBeGreaterThan(indicesBefore.length);
|
|
603
|
+
console.log(` Unstake requested ✓ (new indices: ${indicesAfter.length - indicesBefore.length})`);
|
|
604
|
+
} catch (err: any) {
|
|
605
|
+
const msg = err.shortMessage || err.message || "";
|
|
606
|
+
if (msg.includes("too small")) {
|
|
607
|
+
console.log(` ⚠️ Amount too small for Lista unstake (min ~0.001 BNB equivalent), skipped`);
|
|
608
|
+
} else {
|
|
609
|
+
throw err;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
603
612
|
}, 180000);
|
|
604
613
|
|
|
605
614
|
// Test 9: stakeAndMint xBNB
|
|
@@ -854,7 +863,8 @@ describe("AspanRouter SDK", () => {
|
|
|
854
863
|
return;
|
|
855
864
|
}
|
|
856
865
|
|
|
857
|
-
|
|
866
|
+
// Lista requires minimum ~0.001 BNB equivalent; at ~$670/BNB, that's ~$0.67 apUSD min
|
|
867
|
+
const unstakeAmount = apUSDBalance > parseAmount("1.0") ? parseAmount("1.0") : apUSDBalance;
|
|
858
868
|
console.log(` Requesting unstake for ${formatAmount(unstakeAmount)} apUSD (of ${formatAmount(apUSDBalance)} total)...`);
|
|
859
869
|
await approve(TOKENS.apUSD, unstakeAmount);
|
|
860
870
|
|
package/src/abi/diamond.ts
CHANGED
|
@@ -243,24 +243,18 @@ export const DiamondABI = [
|
|
|
243
243
|
{
|
|
244
244
|
type: "function",
|
|
245
245
|
name: "deposit",
|
|
246
|
-
inputs: [
|
|
247
|
-
{ name: "assets", type: "uint256", internalType: "uint256" },
|
|
248
|
-
{ name: "receiver", type: "address", internalType: "address" }
|
|
249
|
-
],
|
|
246
|
+
inputs: [{ name: "_amount", type: "uint256", internalType: "uint256" }],
|
|
250
247
|
outputs: [{ name: "shares", type: "uint256", internalType: "uint256" }],
|
|
251
248
|
stateMutability: "nonpayable"
|
|
252
249
|
},
|
|
253
250
|
{
|
|
254
251
|
type: "function",
|
|
255
|
-
name: "
|
|
252
|
+
name: "withdraw",
|
|
256
253
|
inputs: [
|
|
257
|
-
{ name: "
|
|
258
|
-
{ name: "receiver", type: "address", internalType: "address" },
|
|
259
|
-
{ name: "owner", type: "address", internalType: "address" }
|
|
254
|
+
{ name: "_shares", type: "uint256", internalType: "uint256" }
|
|
260
255
|
],
|
|
261
256
|
outputs: [
|
|
262
|
-
{ name: "
|
|
263
|
-
{ name: "xBNBOut", type: "uint256", internalType: "uint256" }
|
|
257
|
+
{ name: "assets", type: "uint256", internalType: "uint256" }
|
|
264
258
|
],
|
|
265
259
|
stateMutability: "nonpayable"
|
|
266
260
|
},
|
package/src/client.ts
CHANGED
|
@@ -74,7 +74,7 @@ import type {
|
|
|
74
74
|
MintXBNBParams,
|
|
75
75
|
RedeemXBNBParams,
|
|
76
76
|
DepositParams,
|
|
77
|
-
|
|
77
|
+
WithdrawParams,
|
|
78
78
|
} from "./types";
|
|
79
79
|
|
|
80
80
|
// ============ Configuration ============
|
|
@@ -1190,23 +1190,23 @@ export class AspanClient extends AspanReadClient {
|
|
|
1190
1190
|
address: this.diamondAddress,
|
|
1191
1191
|
abi: DiamondABI,
|
|
1192
1192
|
functionName: "deposit",
|
|
1193
|
-
args: [params.
|
|
1193
|
+
args: [params.apUSDAmount],
|
|
1194
1194
|
});
|
|
1195
1195
|
}
|
|
1196
1196
|
|
|
1197
1197
|
/**
|
|
1198
|
-
*
|
|
1199
|
-
* @param params
|
|
1198
|
+
* Withdraw from stability pool by shares
|
|
1199
|
+
* @param params Withdraw parameters
|
|
1200
1200
|
* @returns Transaction hash
|
|
1201
1201
|
*/
|
|
1202
|
-
async
|
|
1202
|
+
async withdraw(params: WithdrawParams): Promise<Hash> {
|
|
1203
1203
|
return this.walletClient.writeContract({
|
|
1204
1204
|
chain: this.chain,
|
|
1205
1205
|
account: this.walletClient.account!,
|
|
1206
1206
|
address: this.diamondAddress,
|
|
1207
1207
|
abi: DiamondABI,
|
|
1208
|
-
functionName: "
|
|
1209
|
-
args: [params.shares
|
|
1208
|
+
functionName: "withdraw",
|
|
1209
|
+
args: [params.shares],
|
|
1210
1210
|
});
|
|
1211
1211
|
}
|
|
1212
1212
|
|
package/src/index.ts
CHANGED
|
@@ -67,7 +67,7 @@ export type {
|
|
|
67
67
|
MintXBNBParams,
|
|
68
68
|
RedeemXBNBParams,
|
|
69
69
|
DepositParams,
|
|
70
|
-
|
|
70
|
+
WithdrawParams,
|
|
71
71
|
// Events
|
|
72
72
|
ApUSDMintedEvent,
|
|
73
73
|
ApUSDRedeemedEvent,
|
|
@@ -116,17 +116,20 @@ 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: "
|
|
119
|
+
router: "0xb8a90CD2811d6DDbB4B7969d30B036574842cb6E" as const,
|
|
120
120
|
apUSD: "0x4570047eeB5aDb4081c5d470494EB5134e34A287" as const,
|
|
121
121
|
xBNB: "0x0A0c9CD826e747D99F90D63e780B3727Da4D0d43" as const,
|
|
122
122
|
sApUSD: "0x896770Dba7c0481539E25aaB56bE285ECF6D65eB" as const,
|
|
123
123
|
// LSTs
|
|
124
124
|
slisBNB: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B" as const,
|
|
125
125
|
asBNB: "0x77734e70b6E88b4d82fE632a168EDf6e700912b6" as const,
|
|
126
|
-
wclisBNB: "
|
|
126
|
+
wclisBNB: "0xb2A0631bF0aC326fEefc201E7337E13C63Bbed07" as const,
|
|
127
127
|
// Stablecoins
|
|
128
128
|
USDT: "0x55d398326f99059fF775485246999027B3197955" as const,
|
|
129
129
|
USDC: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d" as const,
|
|
130
|
+
/** Chainlink price feeds (BSC Mainnet) */
|
|
131
|
+
USDT_USD_FEED: "0xB97Ad0E74fa7d920791E90258A6E2085088b4320" as const,
|
|
132
|
+
USDC_USD_FEED: "0x51597f405303C4377E36123cBc172b13269EA163" as const,
|
|
130
133
|
WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" as const,
|
|
131
134
|
} as const;
|
|
132
135
|
|
package/src/router.ts
CHANGED
|
@@ -19,8 +19,26 @@ import {
|
|
|
19
19
|
} from "viem";
|
|
20
20
|
import { bsc, bscTestnet } from "viem/chains";
|
|
21
21
|
import { pharosTestnet, CHAIN_IDS, getChainById } from "./client";
|
|
22
|
+
import { BSC_ADDRESSES } from "./index";
|
|
22
23
|
import { RouterABI } from "./abi/router";
|
|
23
24
|
import { DiamondABI } from "./abi/diamond";
|
|
25
|
+
|
|
26
|
+
/** Chainlink AggregatorV3 — only latestRoundData needed */
|
|
27
|
+
const ChainlinkABI = [
|
|
28
|
+
{
|
|
29
|
+
type: "function",
|
|
30
|
+
name: "latestRoundData",
|
|
31
|
+
inputs: [],
|
|
32
|
+
outputs: [
|
|
33
|
+
{ name: "roundId", type: "uint80" },
|
|
34
|
+
{ name: "answer", type: "int256" },
|
|
35
|
+
{ name: "startedAt", type: "uint256" },
|
|
36
|
+
{ name: "updatedAt", type: "uint256" },
|
|
37
|
+
{ name: "answeredInRound", type: "uint80" },
|
|
38
|
+
],
|
|
39
|
+
stateMutability: "view",
|
|
40
|
+
},
|
|
41
|
+
] as const;
|
|
24
42
|
import type {
|
|
25
43
|
SwapAndMintParams,
|
|
26
44
|
StakeAndMintParams,
|
|
@@ -233,8 +251,10 @@ export class AspanRouterReadClient {
|
|
|
233
251
|
const usdValue = (inputAmount * bnbPrice18) / one;
|
|
234
252
|
lstAmount = lstPrice18 === 0n ? 0n : (usdValue * one) / lstPrice18;
|
|
235
253
|
} else if (inNorm === usdt.toLowerCase() || inNorm === usdc.toLowerCase()) {
|
|
236
|
-
// stablecoin
|
|
237
|
-
|
|
254
|
+
// stablecoin -> USD (via Chainlink) -> LST
|
|
255
|
+
const stablePrice18 = await this.getStablecoinPrice(inputToken);
|
|
256
|
+
const usdValue = (inputAmount * stablePrice18) / one;
|
|
257
|
+
lstAmount = lstPrice18 === 0n ? 0n : (usdValue * one) / lstPrice18;
|
|
238
258
|
} else {
|
|
239
259
|
throw new Error("Unsupported input token for SDK preview");
|
|
240
260
|
}
|
|
@@ -292,7 +312,9 @@ export class AspanRouterReadClient {
|
|
|
292
312
|
if (outNorm === zeroAddress.toLowerCase() || outNorm === wbnb.toLowerCase()) {
|
|
293
313
|
outputAmount = bnbPrice18 === 0n ? 0n : (usdValue * one) / bnbPrice18;
|
|
294
314
|
} else if (outNorm === usdt.toLowerCase() || outNorm === usdc.toLowerCase()) {
|
|
295
|
-
|
|
315
|
+
// USD value -> stablecoin amount (via Chainlink price)
|
|
316
|
+
const stablePrice18 = await this.getStablecoinPrice(outputToken);
|
|
317
|
+
outputAmount = stablePrice18 === 0n ? 0n : (usdValue * one) / stablePrice18;
|
|
296
318
|
} else {
|
|
297
319
|
throw new Error("Unsupported output token for SDK preview");
|
|
298
320
|
}
|
|
@@ -365,6 +387,34 @@ export class AspanRouterReadClient {
|
|
|
365
387
|
);
|
|
366
388
|
}
|
|
367
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Get stablecoin price in USD (18 decimals) from Chainlink.
|
|
392
|
+
* Returns 1e18 if feed unavailable (graceful fallback).
|
|
393
|
+
*/
|
|
394
|
+
async getStablecoinPrice(token: Address): Promise<bigint> {
|
|
395
|
+
const usdt = await this.getUSDT();
|
|
396
|
+
const usdc = await this.getUSDC();
|
|
397
|
+
const norm = token.toLowerCase();
|
|
398
|
+
let feed: Address | null = null;
|
|
399
|
+
if (norm === usdt.toLowerCase()) {
|
|
400
|
+
feed = BSC_ADDRESSES.USDT_USD_FEED as Address;
|
|
401
|
+
} else if (norm === usdc.toLowerCase()) {
|
|
402
|
+
feed = BSC_ADDRESSES.USDC_USD_FEED as Address;
|
|
403
|
+
}
|
|
404
|
+
if (!feed) return 10n ** 18n; // not a stablecoin, assume 1:1
|
|
405
|
+
try {
|
|
406
|
+
const [, answer] = await this.publicClient.readContract({
|
|
407
|
+
address: feed,
|
|
408
|
+
abi: ChainlinkABI,
|
|
409
|
+
functionName: "latestRoundData",
|
|
410
|
+
});
|
|
411
|
+
// Chainlink returns 8 decimals, normalize to 18
|
|
412
|
+
return BigInt(answer) * 10n ** 10n;
|
|
413
|
+
} catch {
|
|
414
|
+
return 10n ** 18n; // fallback: 1 USD
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
368
418
|
async getSlisBNB(): Promise<Address> {
|
|
369
419
|
return this._getCachedAddress("slisBNB", async () =>
|
|
370
420
|
this.publicClient.readContract({
|
package/src/types.ts
CHANGED
|
@@ -120,15 +120,12 @@ export interface RedeemXBNBParams {
|
|
|
120
120
|
|
|
121
121
|
/** Parameters for depositing to stability pool */
|
|
122
122
|
export interface DepositParams {
|
|
123
|
-
|
|
124
|
-
receiver: Address;
|
|
123
|
+
apUSDAmount: bigint;
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
/** Parameters for
|
|
128
|
-
export interface
|
|
126
|
+
/** Parameters for withdrawing from stability pool */
|
|
127
|
+
export interface WithdrawParams {
|
|
129
128
|
shares: bigint;
|
|
130
|
-
receiver: Address;
|
|
131
|
-
owner: Address;
|
|
132
129
|
}
|
|
133
130
|
|
|
134
131
|
// ============ Protocol Stats ============
|
|
@@ -254,7 +251,7 @@ export interface RouterSwapParams {
|
|
|
254
251
|
targetLST: Address;
|
|
255
252
|
/** Minimum LST to receive from swap (slippage protection) */
|
|
256
253
|
minLSTOut: bigint;
|
|
257
|
-
/** PancakeSwap V3 pool fee tier (500, 2500, 10000) */
|
|
254
|
+
/** PancakeSwap V3 pool fee tier (100, 500, 2500, 10000) */
|
|
258
255
|
poolFee: number;
|
|
259
256
|
}
|
|
260
257
|
|