@sodax/sdk 1.0.4-beta-rc2 → 1.1.0-beta-rc1
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 +4 -4
- package/dist/index.cjs +139 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -5
- package/dist/index.d.ts +34 -5
- package/dist/index.mjs +141 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -7,21 +7,21 @@ The Sodax SDK provides a comprehensive interface for interacting with the Sodax
|
|
|
7
7
|
### Features
|
|
8
8
|
|
|
9
9
|
- [Swaps (Solver / Intents)](./docs/SWAPS.md) - Cross-chain intent-based swaps
|
|
10
|
-
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink) ✅
|
|
10
|
+
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink, Kaia) ✅
|
|
11
11
|
- Sui ✅
|
|
12
12
|
- Stellar ✅
|
|
13
13
|
- ICON ✅
|
|
14
14
|
- Solana ✅
|
|
15
15
|
- Injective ✅
|
|
16
16
|
- [Money Market](./docs/MONEY_MARKET.md) - Cross-chain lending and borrowing
|
|
17
|
-
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink) ✅
|
|
17
|
+
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink, Kaia) ✅
|
|
18
18
|
- Sui ✅
|
|
19
19
|
- Stellar ✅
|
|
20
20
|
- ICON ✅
|
|
21
21
|
- Solana ✅
|
|
22
22
|
- Injective ✅
|
|
23
23
|
- [Bridge](./docs/BRIDGE.md) - Cross-chain token bridging
|
|
24
|
-
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink) ✅
|
|
24
|
+
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink, Kaia) ✅
|
|
25
25
|
- Sui ✅
|
|
26
26
|
- Stellar ✅
|
|
27
27
|
- ICON ✅
|
|
@@ -29,7 +29,7 @@ The Sodax SDK provides a comprehensive interface for interacting with the Sodax
|
|
|
29
29
|
- Injective ✅
|
|
30
30
|
- [Migration](./docs/MIGRATION.md) - Token migration (ICX, bnUSD, BALN)
|
|
31
31
|
- [Staking](./docs/STAKING.md) - SODA token staking
|
|
32
|
-
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink) ✅
|
|
32
|
+
- EVM (Arbitrum, Avalanche, Base, BSC, Optimism, Polygon, Sonic, HyperEVM, Lightlink, Kaia) ✅
|
|
33
33
|
- Sui ✅
|
|
34
34
|
- Stellar ✅
|
|
35
35
|
- ICON ✅
|
package/dist/index.cjs
CHANGED
|
@@ -6826,6 +6826,8 @@ function getEvmViemChain(id) {
|
|
|
6826
6826
|
return chains.lightlinkPhoenix;
|
|
6827
6827
|
case types.ETHEREUM_MAINNET_CHAIN_ID:
|
|
6828
6828
|
return chains.mainnet;
|
|
6829
|
+
case types.KAIA_MAINNET_CHAIN_ID:
|
|
6830
|
+
return chains.kaia;
|
|
6829
6831
|
default:
|
|
6830
6832
|
throw new Error(`Unsupported EVM chain ID: ${id}`);
|
|
6831
6833
|
}
|
|
@@ -6871,6 +6873,7 @@ var getAllLegacybnUSDTokens = () => {
|
|
|
6871
6873
|
var ConfigService = class {
|
|
6872
6874
|
serviceConfig;
|
|
6873
6875
|
backendApiService;
|
|
6876
|
+
sharedConfig;
|
|
6874
6877
|
initialized = false;
|
|
6875
6878
|
sodaxConfig;
|
|
6876
6879
|
// data structures for quick lookup
|
|
@@ -6883,7 +6886,7 @@ var ConfigService = class {
|
|
|
6883
6886
|
supportedTokensPerChain;
|
|
6884
6887
|
moneyMarketReserveAssetsSet;
|
|
6885
6888
|
spokeChainIdsSet;
|
|
6886
|
-
constructor({ backendApiService, config }) {
|
|
6889
|
+
constructor({ backendApiService, config, sharedConfig }) {
|
|
6887
6890
|
this.serviceConfig = {
|
|
6888
6891
|
backendApiUrl: config?.backendApiUrl ?? DEFAULT_BACKEND_API_ENDPOINT,
|
|
6889
6892
|
timeout: config?.timeout ?? DEFAULT_BACKEND_API_TIMEOUT
|
|
@@ -6891,6 +6894,10 @@ var ConfigService = class {
|
|
|
6891
6894
|
this.backendApiService = backendApiService;
|
|
6892
6895
|
this.sodaxConfig = types.defaultSodaxConfig;
|
|
6893
6896
|
this.loadSodaxConfigDataStructures(this.sodaxConfig);
|
|
6897
|
+
this.sharedConfig = {
|
|
6898
|
+
...types.defaultSharedConfig,
|
|
6899
|
+
...sharedConfig
|
|
6900
|
+
};
|
|
6894
6901
|
}
|
|
6895
6902
|
async initialize() {
|
|
6896
6903
|
try {
|
|
@@ -7507,6 +7514,30 @@ var EvmVaultTokenService = class {
|
|
|
7507
7514
|
});
|
|
7508
7515
|
return { decimals, depositFee, withdrawalFee, maxDeposit, isSupported };
|
|
7509
7516
|
}
|
|
7517
|
+
/**
|
|
7518
|
+
* Fetches token information for a list of tokens in a vault using a multicall.
|
|
7519
|
+
* @param vault - The address of the vault contract.
|
|
7520
|
+
* @param tokens - An array of token addresses to fetch info for.
|
|
7521
|
+
* @param publicClient - The Viem PublicClient instance used to interact with the blockchain.
|
|
7522
|
+
* @returns A promise that resolves to an array of TokenInfo objects, one for each provided token.
|
|
7523
|
+
*/
|
|
7524
|
+
static async getTokenInfos(vault, tokens, publicClient) {
|
|
7525
|
+
const infos = await publicClient.multicall({
|
|
7526
|
+
contracts: tokens.map(
|
|
7527
|
+
(token) => ({
|
|
7528
|
+
address: vault,
|
|
7529
|
+
abi: vaultTokenAbi,
|
|
7530
|
+
functionName: "tokenInfo",
|
|
7531
|
+
args: [token]
|
|
7532
|
+
})
|
|
7533
|
+
),
|
|
7534
|
+
allowFailure: false
|
|
7535
|
+
});
|
|
7536
|
+
return infos.map((info) => {
|
|
7537
|
+
const [decimals, depositFee, withdrawalFee, maxDeposit, isSupported] = info;
|
|
7538
|
+
return { decimals, depositFee, withdrawalFee, maxDeposit, isSupported };
|
|
7539
|
+
});
|
|
7540
|
+
}
|
|
7510
7541
|
/**
|
|
7511
7542
|
* Retrieves the reserves of the vault.
|
|
7512
7543
|
* @param vault - The address of the vault.
|
|
@@ -10460,6 +10491,38 @@ var StellarSpokeService = class _StellarSpokeService {
|
|
|
10460
10491
|
const availableTrustAmount = limit - balance;
|
|
10461
10492
|
return availableTrustAmount >= amount;
|
|
10462
10493
|
}
|
|
10494
|
+
/**
|
|
10495
|
+
* Check if the user has sufficent trustline established for the token.
|
|
10496
|
+
* @param token - The token address to check the trustline for.
|
|
10497
|
+
* @param amount - The amount of tokens to check the trustline for.
|
|
10498
|
+
* @param spokeProvider - The Stellar spoke provider.
|
|
10499
|
+
* @returns True if the user has sufficent trustline established for the token, false otherwise.
|
|
10500
|
+
*/
|
|
10501
|
+
static async walletHasSufficientTrustline(token, amount, walletAddress, horizonRpcUrl) {
|
|
10502
|
+
const stellarChainConfig = types.spokeChainConfig[types.STELLAR_MAINNET_CHAIN_ID];
|
|
10503
|
+
if (token.toLowerCase() === stellarChainConfig.nativeToken.toLowerCase() || token.toLowerCase() === stellarChainConfig.supportedTokens.legacybnUSD.address.toLowerCase()) {
|
|
10504
|
+
return true;
|
|
10505
|
+
}
|
|
10506
|
+
const trustlineConfig = stellarChainConfig.trustlineConfigs.find(
|
|
10507
|
+
(config) => config.contractId.toLowerCase() === token.toLowerCase()
|
|
10508
|
+
);
|
|
10509
|
+
if (!trustlineConfig) {
|
|
10510
|
+
throw new Error(`Trustline config not found for token: ${token}`);
|
|
10511
|
+
}
|
|
10512
|
+
const server = new stellarSdk.Horizon.Server(horizonRpcUrl, { allowHttp: true });
|
|
10513
|
+
const { balances } = await server.accounts().accountId(walletAddress).call();
|
|
10514
|
+
const tokenBalance = balances.find(
|
|
10515
|
+
(balance2) => "limit" in balance2 && "balance" in balance2 && "asset_code" in balance2 && trustlineConfig.assetCode.toLowerCase() === balance2.asset_code?.toLowerCase() && "asset_issuer" in balance2 && trustlineConfig.assetIssuer.toLowerCase() === balance2.asset_issuer?.toLowerCase()
|
|
10516
|
+
);
|
|
10517
|
+
if (!tokenBalance) {
|
|
10518
|
+
console.error(`No token balances found for token: ${token}`);
|
|
10519
|
+
return false;
|
|
10520
|
+
}
|
|
10521
|
+
const limit = parseToStroops(tokenBalance.limit);
|
|
10522
|
+
const balance = parseToStroops(tokenBalance.balance);
|
|
10523
|
+
const availableTrustAmount = limit - balance;
|
|
10524
|
+
return availableTrustAmount >= amount;
|
|
10525
|
+
}
|
|
10463
10526
|
/**
|
|
10464
10527
|
* Request a trustline for a given token and amount.
|
|
10465
10528
|
* @param token - The token address to request the trustline for.
|
|
@@ -13919,7 +13982,27 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13919
13982
|
);
|
|
13920
13983
|
}
|
|
13921
13984
|
const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
|
|
13922
|
-
if (
|
|
13985
|
+
if (params.toChainId === types.STELLAR_MAINNET_CHAIN_ID && params.toAddress) {
|
|
13986
|
+
const targetHasTrustline = await StellarSpokeService.walletHasSufficientTrustline(
|
|
13987
|
+
params.token,
|
|
13988
|
+
params.amount,
|
|
13989
|
+
params.toAddress,
|
|
13990
|
+
this.configService.sharedConfig[types.STELLAR_MAINNET_CHAIN_ID].horizonRpcUrl
|
|
13991
|
+
);
|
|
13992
|
+
let srcHasTrustline = true;
|
|
13993
|
+
if (isStellarSpokeProviderType(spokeProvider)) {
|
|
13994
|
+
srcHasTrustline = await StellarSpokeService.hasSufficientTrustline(
|
|
13995
|
+
params.token,
|
|
13996
|
+
params.amount,
|
|
13997
|
+
spokeProvider
|
|
13998
|
+
);
|
|
13999
|
+
}
|
|
14000
|
+
return {
|
|
14001
|
+
ok: true,
|
|
14002
|
+
value: targetHasTrustline && srcHasTrustline
|
|
14003
|
+
};
|
|
14004
|
+
}
|
|
14005
|
+
if (isStellarSpokeProviderType(spokeProvider)) {
|
|
13923
14006
|
return {
|
|
13924
14007
|
ok: true,
|
|
13925
14008
|
value: await StellarSpokeService.hasSufficientTrustline(params.token, params.amount, spokeProvider)
|
|
@@ -13953,6 +14036,9 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13953
14036
|
* Approve amount spending if isAllowanceValid returns false.
|
|
13954
14037
|
* For evm spoke chains, the spender is the asset manager contract while
|
|
13955
14038
|
* for sonic spoke (hub) chain, the spender is the user router contract.
|
|
14039
|
+
* NOTE: Stellar requires trustline when being either sender or receiver. Thus
|
|
14040
|
+
* you should make sure that both src and destination wallets have sufficient trustlines.
|
|
14041
|
+
* Make sure to invoke this method using wallet address which is about to receive the tokens!
|
|
13956
14042
|
* @param token - ERC20 token address
|
|
13957
14043
|
* @param amount - Amount to approve
|
|
13958
14044
|
* @param spender - Spender address
|
|
@@ -13994,10 +14080,6 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13994
14080
|
}
|
|
13995
14081
|
const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
|
|
13996
14082
|
if (isStellarSpokeProviderType(spokeProvider)) {
|
|
13997
|
-
invariant6__default.default(
|
|
13998
|
-
params.action === "supply" || params.action === "repay",
|
|
13999
|
-
"Invalid action (only supply and repay are supported on stellar)"
|
|
14000
|
-
);
|
|
14001
14083
|
const result = await StellarSpokeService.requestTrustline(params.token, params.amount, spokeProvider, raw);
|
|
14002
14084
|
return {
|
|
14003
14085
|
ok: true,
|
|
@@ -15042,7 +15124,8 @@ var Sodax = class {
|
|
|
15042
15124
|
config: {
|
|
15043
15125
|
backendApiUrl: config?.backendApiConfig?.baseURL,
|
|
15044
15126
|
timeout: config?.backendApiConfig?.timeout
|
|
15045
|
-
}
|
|
15127
|
+
},
|
|
15128
|
+
sharedConfig: config?.sharedConfig
|
|
15046
15129
|
});
|
|
15047
15130
|
this.hubProvider = new EvmHubProvider({ config: config?.hubProviderConfig, configService: this.config });
|
|
15048
15131
|
this.swaps = config && config.swaps ? new SwapService({
|
|
@@ -16529,7 +16612,7 @@ var BridgeService = class {
|
|
|
16529
16612
|
*
|
|
16530
16613
|
* @param spokeProvider - The spoke provider instance
|
|
16531
16614
|
* @param token - The token address to query the balance for
|
|
16532
|
-
* @returns {Promise<
|
|
16615
|
+
* @returns {Promise<BridgeLimit>} - The max bridgeable amount with corresponding decimals
|
|
16533
16616
|
*/
|
|
16534
16617
|
async getBridgeableAmount(from, to) {
|
|
16535
16618
|
try {
|
|
@@ -16537,51 +16620,59 @@ var BridgeService = class {
|
|
|
16537
16620
|
const toHubAsset = this.configService.getHubAssetInfo(to.xChainId, to.address);
|
|
16538
16621
|
invariant6__default.default(fromHubAsset, `Hub asset not found for token ${from.address} on chain ${from.xChainId}`);
|
|
16539
16622
|
invariant6__default.default(toHubAsset, `Hub asset not found for token ${to.address} on chain ${to.xChainId}`);
|
|
16540
|
-
|
|
16541
|
-
|
|
16623
|
+
invariant6__default.default(this.isBridgeable({ from, to }), `Tokens ${from.address} and ${to.address} are not bridgeable`);
|
|
16624
|
+
const [tokenInfos, reserves] = await Promise.all([
|
|
16625
|
+
EvmVaultTokenService.getTokenInfos(
|
|
16626
|
+
fromHubAsset.vault,
|
|
16627
|
+
[fromHubAsset.asset, toHubAsset.asset],
|
|
16628
|
+
this.hubProvider.publicClient
|
|
16629
|
+
),
|
|
16542
16630
|
EvmVaultTokenService.getVaultReserves(toHubAsset.vault, this.hubProvider.publicClient)
|
|
16543
16631
|
]);
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
);
|
|
16550
|
-
const fromTokenDepositedAmount2 = reserves.balances[fromTokenIndex2] ?? 0n;
|
|
16551
|
-
const availableDeposit2 = depositTokenInfo.maxDeposit - fromTokenDepositedAmount2;
|
|
16632
|
+
invariant6__default.default(tokenInfos.length === 2, `Expected 2 token infos, got ${tokenInfos.length}`);
|
|
16633
|
+
const [fromTokenInfo, toTokenInfo] = tokenInfos;
|
|
16634
|
+
invariant6__default.default(fromTokenInfo, "From token info not found");
|
|
16635
|
+
invariant6__default.default(toTokenInfo, "To token info not found");
|
|
16636
|
+
if (!fromTokenInfo.isSupported) {
|
|
16552
16637
|
return {
|
|
16553
16638
|
ok: true,
|
|
16554
|
-
value:
|
|
16639
|
+
value: {
|
|
16640
|
+
amount: 0n,
|
|
16641
|
+
decimals: fromTokenInfo.decimals,
|
|
16642
|
+
type: "DEPOSIT_LIMIT"
|
|
16643
|
+
}
|
|
16555
16644
|
};
|
|
16556
16645
|
}
|
|
16557
|
-
if (this.
|
|
16558
|
-
const
|
|
16559
|
-
|
|
16560
|
-
tokenIndex2 !== -1,
|
|
16561
|
-
`Token ${toHubAsset.asset} not found in the vault reserves for chain ${to.xChainId}`
|
|
16562
|
-
);
|
|
16563
|
-
const assetManagerBalance2 = reserves.balances[tokenIndex2] ?? 0n;
|
|
16646
|
+
if (from.xChainId !== this.hubProvider.chainConfig.chain.id && to.xChainId === this.hubProvider.chainConfig.chain.id) {
|
|
16647
|
+
const fromTokenDepositedAmount2 = this.findTokenBalanceInReserves(reserves, from);
|
|
16648
|
+
const availableDeposit2 = fromTokenInfo.maxDeposit - fromTokenDepositedAmount2;
|
|
16564
16649
|
return {
|
|
16565
16650
|
ok: true,
|
|
16566
|
-
value:
|
|
16651
|
+
value: {
|
|
16652
|
+
amount: availableDeposit2,
|
|
16653
|
+
decimals: fromTokenInfo.decimals,
|
|
16654
|
+
type: "DEPOSIT_LIMIT"
|
|
16655
|
+
}
|
|
16567
16656
|
};
|
|
16568
16657
|
}
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
const assetManagerBalance = reserves
|
|
16658
|
+
if (from.xChainId === this.hubProvider.chainConfig.chain.id && to.xChainId !== this.hubProvider.chainConfig.chain.id) {
|
|
16659
|
+
return {
|
|
16660
|
+
ok: true,
|
|
16661
|
+
value: {
|
|
16662
|
+
amount: this.findTokenBalanceInReserves(reserves, to),
|
|
16663
|
+
decimals: toTokenInfo.decimals,
|
|
16664
|
+
type: "WITHDRAWAL_LIMIT"
|
|
16665
|
+
}
|
|
16666
|
+
};
|
|
16667
|
+
}
|
|
16668
|
+
const fromTokenDepositedAmount = this.findTokenBalanceInReserves(reserves, from);
|
|
16669
|
+
const availableDeposit = fromTokenInfo.maxDeposit - fromTokenDepositedAmount;
|
|
16670
|
+
const assetManagerBalance = this.findTokenBalanceInReserves(reserves, to);
|
|
16671
|
+
const availableDepositNormalised = BigNumber4__default.default(availableDeposit).shiftedBy(-fromTokenInfo.decimals);
|
|
16672
|
+
const assetManagerBalanceNormalised = BigNumber4__default.default(assetManagerBalance).shiftedBy(-toTokenInfo.decimals);
|
|
16582
16673
|
return {
|
|
16583
16674
|
ok: true,
|
|
16584
|
-
value: availableDeposit
|
|
16675
|
+
value: availableDepositNormalised.isLessThan(assetManagerBalanceNormalised) ? { amount: availableDeposit, decimals: fromTokenInfo.decimals, type: "DEPOSIT_LIMIT" } : { amount: assetManagerBalance, decimals: toTokenInfo.decimals, type: "WITHDRAWAL_LIMIT" }
|
|
16585
16676
|
};
|
|
16586
16677
|
} catch (error) {
|
|
16587
16678
|
console.error(error);
|
|
@@ -16658,6 +16749,13 @@ var BridgeService = class {
|
|
|
16658
16749
|
}
|
|
16659
16750
|
return bridgeableTokens;
|
|
16660
16751
|
}
|
|
16752
|
+
findTokenBalanceInReserves(reserves, token) {
|
|
16753
|
+
const hubAsset = this.configService.getHubAssetInfo(token.xChainId, token.address);
|
|
16754
|
+
invariant6__default.default(hubAsset, `Hub asset not found for token ${token.address} on chain ${token.xChainId}`);
|
|
16755
|
+
const tokenIndex = reserves.tokens.findIndex((t) => t.toLowerCase() === hubAsset.asset.toLowerCase());
|
|
16756
|
+
invariant6__default.default(tokenIndex !== -1, `Token ${hubAsset.asset} not found in the vault reserves for chain ${token.xChainId}`);
|
|
16757
|
+
return reserves.balances[tokenIndex] ?? 0n;
|
|
16758
|
+
}
|
|
16661
16759
|
};
|
|
16662
16760
|
var StakingLogic = class _StakingLogic {
|
|
16663
16761
|
constructor() {
|