@sodax/sdk 1.0.4-beta-rc1 → 1.0.4-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +142 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -4
- package/dist/index.d.ts +27 -4
- package/dist/index.mjs +143 -47
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -6871,6 +6871,7 @@ var getAllLegacybnUSDTokens = () => {
|
|
|
6871
6871
|
var ConfigService = class {
|
|
6872
6872
|
serviceConfig;
|
|
6873
6873
|
backendApiService;
|
|
6874
|
+
sharedConfig;
|
|
6874
6875
|
initialized = false;
|
|
6875
6876
|
sodaxConfig;
|
|
6876
6877
|
// data structures for quick lookup
|
|
@@ -6883,7 +6884,7 @@ var ConfigService = class {
|
|
|
6883
6884
|
supportedTokensPerChain;
|
|
6884
6885
|
moneyMarketReserveAssetsSet;
|
|
6885
6886
|
spokeChainIdsSet;
|
|
6886
|
-
constructor({ backendApiService, config }) {
|
|
6887
|
+
constructor({ backendApiService, config, sharedConfig }) {
|
|
6887
6888
|
this.serviceConfig = {
|
|
6888
6889
|
backendApiUrl: config?.backendApiUrl ?? DEFAULT_BACKEND_API_ENDPOINT,
|
|
6889
6890
|
timeout: config?.timeout ?? DEFAULT_BACKEND_API_TIMEOUT
|
|
@@ -6891,6 +6892,10 @@ var ConfigService = class {
|
|
|
6891
6892
|
this.backendApiService = backendApiService;
|
|
6892
6893
|
this.sodaxConfig = types.defaultSodaxConfig;
|
|
6893
6894
|
this.loadSodaxConfigDataStructures(this.sodaxConfig);
|
|
6895
|
+
this.sharedConfig = {
|
|
6896
|
+
...types.defaultSharedConfig,
|
|
6897
|
+
...sharedConfig
|
|
6898
|
+
};
|
|
6894
6899
|
}
|
|
6895
6900
|
async initialize() {
|
|
6896
6901
|
try {
|
|
@@ -7507,6 +7512,30 @@ var EvmVaultTokenService = class {
|
|
|
7507
7512
|
});
|
|
7508
7513
|
return { decimals, depositFee, withdrawalFee, maxDeposit, isSupported };
|
|
7509
7514
|
}
|
|
7515
|
+
/**
|
|
7516
|
+
* Fetches token information for a list of tokens in a vault using a multicall.
|
|
7517
|
+
* @param vault - The address of the vault contract.
|
|
7518
|
+
* @param tokens - An array of token addresses to fetch info for.
|
|
7519
|
+
* @param publicClient - The Viem PublicClient instance used to interact with the blockchain.
|
|
7520
|
+
* @returns A promise that resolves to an array of TokenInfo objects, one for each provided token.
|
|
7521
|
+
*/
|
|
7522
|
+
static async getTokenInfos(vault, tokens, publicClient) {
|
|
7523
|
+
const infos = await publicClient.multicall({
|
|
7524
|
+
contracts: tokens.map(
|
|
7525
|
+
(token) => ({
|
|
7526
|
+
address: vault,
|
|
7527
|
+
abi: vaultTokenAbi,
|
|
7528
|
+
functionName: "tokenInfo",
|
|
7529
|
+
args: [token]
|
|
7530
|
+
})
|
|
7531
|
+
),
|
|
7532
|
+
allowFailure: false
|
|
7533
|
+
});
|
|
7534
|
+
return infos.map((info) => {
|
|
7535
|
+
const [decimals, depositFee, withdrawalFee, maxDeposit, isSupported] = info;
|
|
7536
|
+
return { decimals, depositFee, withdrawalFee, maxDeposit, isSupported };
|
|
7537
|
+
});
|
|
7538
|
+
}
|
|
7510
7539
|
/**
|
|
7511
7540
|
* Retrieves the reserves of the vault.
|
|
7512
7541
|
* @param vault - The address of the vault.
|
|
@@ -10460,6 +10489,38 @@ var StellarSpokeService = class _StellarSpokeService {
|
|
|
10460
10489
|
const availableTrustAmount = limit - balance;
|
|
10461
10490
|
return availableTrustAmount >= amount;
|
|
10462
10491
|
}
|
|
10492
|
+
/**
|
|
10493
|
+
* Check if the user has sufficent trustline established for the token.
|
|
10494
|
+
* @param token - The token address to check the trustline for.
|
|
10495
|
+
* @param amount - The amount of tokens to check the trustline for.
|
|
10496
|
+
* @param spokeProvider - The Stellar spoke provider.
|
|
10497
|
+
* @returns True if the user has sufficent trustline established for the token, false otherwise.
|
|
10498
|
+
*/
|
|
10499
|
+
static async walletHasSufficientTrustline(token, amount, walletAddress, horizonRpcUrl) {
|
|
10500
|
+
const stellarChainConfig = types.spokeChainConfig[types.STELLAR_MAINNET_CHAIN_ID];
|
|
10501
|
+
if (token.toLowerCase() === stellarChainConfig.nativeToken.toLowerCase() || token.toLowerCase() === stellarChainConfig.supportedTokens.legacybnUSD.address.toLowerCase()) {
|
|
10502
|
+
return true;
|
|
10503
|
+
}
|
|
10504
|
+
const trustlineConfig = stellarChainConfig.trustlineConfigs.find(
|
|
10505
|
+
(config) => config.contractId.toLowerCase() === token.toLowerCase()
|
|
10506
|
+
);
|
|
10507
|
+
if (!trustlineConfig) {
|
|
10508
|
+
throw new Error(`Trustline config not found for token: ${token}`);
|
|
10509
|
+
}
|
|
10510
|
+
const server = new stellarSdk.Horizon.Server(horizonRpcUrl, { allowHttp: true });
|
|
10511
|
+
const { balances } = await server.accounts().accountId(walletAddress).call();
|
|
10512
|
+
const tokenBalance = balances.find(
|
|
10513
|
+
(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()
|
|
10514
|
+
);
|
|
10515
|
+
if (!tokenBalance) {
|
|
10516
|
+
console.error(`No token balances found for token: ${token}`);
|
|
10517
|
+
return false;
|
|
10518
|
+
}
|
|
10519
|
+
const limit = parseToStroops(tokenBalance.limit);
|
|
10520
|
+
const balance = parseToStroops(tokenBalance.balance);
|
|
10521
|
+
const availableTrustAmount = limit - balance;
|
|
10522
|
+
return availableTrustAmount >= amount;
|
|
10523
|
+
}
|
|
10463
10524
|
/**
|
|
10464
10525
|
* Request a trustline for a given token and amount.
|
|
10465
10526
|
* @param token - The token address to request the trustline for.
|
|
@@ -11878,7 +11939,7 @@ var SolanaSpokeService = class _SolanaSpokeService {
|
|
|
11878
11939
|
}
|
|
11879
11940
|
return spokeProvider.walletProvider.sendTransaction(serializedTransaction);
|
|
11880
11941
|
}
|
|
11881
|
-
static async waitForConfirmation(spokeProvider, signature, commitment = "finalized", timeoutMs =
|
|
11942
|
+
static async waitForConfirmation(spokeProvider, signature, commitment = "finalized", timeoutMs = 6e4) {
|
|
11882
11943
|
try {
|
|
11883
11944
|
const connection = new web3_js.Connection(spokeProvider.chainConfig.rpcUrl, commitment);
|
|
11884
11945
|
const deadline = Date.now() + timeoutMs;
|
|
@@ -13919,7 +13980,27 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13919
13980
|
);
|
|
13920
13981
|
}
|
|
13921
13982
|
const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
|
|
13922
|
-
if (
|
|
13983
|
+
if (params.toChainId === types.STELLAR_MAINNET_CHAIN_ID && params.toAddress) {
|
|
13984
|
+
const targetHasTrustline = await StellarSpokeService.walletHasSufficientTrustline(
|
|
13985
|
+
params.token,
|
|
13986
|
+
params.amount,
|
|
13987
|
+
params.toAddress,
|
|
13988
|
+
this.configService.sharedConfig[types.STELLAR_MAINNET_CHAIN_ID].horizonRpcUrl
|
|
13989
|
+
);
|
|
13990
|
+
let srcHasTrustline = true;
|
|
13991
|
+
if (isStellarSpokeProviderType(spokeProvider)) {
|
|
13992
|
+
srcHasTrustline = await StellarSpokeService.hasSufficientTrustline(
|
|
13993
|
+
params.token,
|
|
13994
|
+
params.amount,
|
|
13995
|
+
spokeProvider
|
|
13996
|
+
);
|
|
13997
|
+
}
|
|
13998
|
+
return {
|
|
13999
|
+
ok: true,
|
|
14000
|
+
value: targetHasTrustline && srcHasTrustline
|
|
14001
|
+
};
|
|
14002
|
+
}
|
|
14003
|
+
if (isStellarSpokeProviderType(spokeProvider)) {
|
|
13923
14004
|
return {
|
|
13924
14005
|
ok: true,
|
|
13925
14006
|
value: await StellarSpokeService.hasSufficientTrustline(params.token, params.amount, spokeProvider)
|
|
@@ -13953,6 +14034,9 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13953
14034
|
* Approve amount spending if isAllowanceValid returns false.
|
|
13954
14035
|
* For evm spoke chains, the spender is the asset manager contract while
|
|
13955
14036
|
* for sonic spoke (hub) chain, the spender is the user router contract.
|
|
14037
|
+
* NOTE: Stellar requires trustline when being either sender or receiver. Thus
|
|
14038
|
+
* you should make sure that both src and destination wallets have sufficient trustlines.
|
|
14039
|
+
* Make sure to invoke this method using wallet address which is about to receive the tokens!
|
|
13956
14040
|
* @param token - ERC20 token address
|
|
13957
14041
|
* @param amount - Amount to approve
|
|
13958
14042
|
* @param spender - Spender address
|
|
@@ -13994,10 +14078,6 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
13994
14078
|
}
|
|
13995
14079
|
const walletAddress = await spokeProvider.walletProvider.getWalletAddress();
|
|
13996
14080
|
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
14081
|
const result = await StellarSpokeService.requestTrustline(params.token, params.amount, spokeProvider, raw);
|
|
14002
14082
|
return {
|
|
14003
14083
|
ok: true,
|
|
@@ -14188,7 +14268,7 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
14188
14268
|
ok: true,
|
|
14189
14269
|
value: txResult,
|
|
14190
14270
|
data: {
|
|
14191
|
-
address:
|
|
14271
|
+
address: fromHubWallet,
|
|
14192
14272
|
payload: data
|
|
14193
14273
|
}
|
|
14194
14274
|
};
|
|
@@ -14255,7 +14335,7 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
14255
14335
|
if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id || params.toChainId && params.toAddress && params.toChainId !== this.hubProvider.chainConfig.chain.id) {
|
|
14256
14336
|
const packetResult = await relayTxAndWaitPacket(
|
|
14257
14337
|
txResult.value,
|
|
14258
|
-
|
|
14338
|
+
spokeProvider instanceof SolanaSpokeProvider ? txResult.data : void 0,
|
|
14259
14339
|
spokeProvider,
|
|
14260
14340
|
this.config.relayerApiEndpoint,
|
|
14261
14341
|
timeout
|
|
@@ -14540,7 +14620,7 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
14540
14620
|
if (spokeProvider.chainConfig.chain.id !== this.hubProvider.chainConfig.chain.id) {
|
|
14541
14621
|
const packetResult = await relayTxAndWaitPacket(
|
|
14542
14622
|
txResult.value,
|
|
14543
|
-
spokeProvider
|
|
14623
|
+
isSolanaSpokeProviderType(spokeProvider) ? txResult.data : void 0,
|
|
14544
14624
|
spokeProvider,
|
|
14545
14625
|
this.config.relayerApiEndpoint,
|
|
14546
14626
|
timeout
|
|
@@ -14640,7 +14720,7 @@ var MoneyMarketService = class _MoneyMarketService {
|
|
|
14640
14720
|
ok: true,
|
|
14641
14721
|
value: txResult,
|
|
14642
14722
|
data: {
|
|
14643
|
-
address:
|
|
14723
|
+
address: fromHubWallet,
|
|
14644
14724
|
payload: data
|
|
14645
14725
|
}
|
|
14646
14726
|
};
|
|
@@ -15042,7 +15122,8 @@ var Sodax = class {
|
|
|
15042
15122
|
config: {
|
|
15043
15123
|
backendApiUrl: config?.backendApiConfig?.baseURL,
|
|
15044
15124
|
timeout: config?.backendApiConfig?.timeout
|
|
15045
|
-
}
|
|
15125
|
+
},
|
|
15126
|
+
sharedConfig: config?.sharedConfig
|
|
15046
15127
|
});
|
|
15047
15128
|
this.hubProvider = new EvmHubProvider({ config: config?.hubProviderConfig, configService: this.config });
|
|
15048
15129
|
this.swaps = config && config.swaps ? new SwapService({
|
|
@@ -16529,7 +16610,7 @@ var BridgeService = class {
|
|
|
16529
16610
|
*
|
|
16530
16611
|
* @param spokeProvider - The spoke provider instance
|
|
16531
16612
|
* @param token - The token address to query the balance for
|
|
16532
|
-
* @returns {Promise<
|
|
16613
|
+
* @returns {Promise<BridgeLimit>} - The max bridgeable amount with corresponding decimals
|
|
16533
16614
|
*/
|
|
16534
16615
|
async getBridgeableAmount(from, to) {
|
|
16535
16616
|
try {
|
|
@@ -16537,51 +16618,59 @@ var BridgeService = class {
|
|
|
16537
16618
|
const toHubAsset = this.configService.getHubAssetInfo(to.xChainId, to.address);
|
|
16538
16619
|
invariant6__default.default(fromHubAsset, `Hub asset not found for token ${from.address} on chain ${from.xChainId}`);
|
|
16539
16620
|
invariant6__default.default(toHubAsset, `Hub asset not found for token ${to.address} on chain ${to.xChainId}`);
|
|
16540
|
-
|
|
16541
|
-
|
|
16621
|
+
invariant6__default.default(this.isBridgeable({ from, to }), `Tokens ${from.address} and ${to.address} are not bridgeable`);
|
|
16622
|
+
const [tokenInfos, reserves] = await Promise.all([
|
|
16623
|
+
EvmVaultTokenService.getTokenInfos(
|
|
16624
|
+
fromHubAsset.vault,
|
|
16625
|
+
[fromHubAsset.asset, toHubAsset.asset],
|
|
16626
|
+
this.hubProvider.publicClient
|
|
16627
|
+
),
|
|
16542
16628
|
EvmVaultTokenService.getVaultReserves(toHubAsset.vault, this.hubProvider.publicClient)
|
|
16543
16629
|
]);
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
);
|
|
16550
|
-
const fromTokenDepositedAmount2 = reserves.balances[fromTokenIndex2] ?? 0n;
|
|
16551
|
-
const availableDeposit2 = depositTokenInfo.maxDeposit - fromTokenDepositedAmount2;
|
|
16630
|
+
invariant6__default.default(tokenInfos.length === 2, `Expected 2 token infos, got ${tokenInfos.length}`);
|
|
16631
|
+
const [fromTokenInfo, toTokenInfo] = tokenInfos;
|
|
16632
|
+
invariant6__default.default(fromTokenInfo, "From token info not found");
|
|
16633
|
+
invariant6__default.default(toTokenInfo, "To token info not found");
|
|
16634
|
+
if (!fromTokenInfo.isSupported) {
|
|
16552
16635
|
return {
|
|
16553
16636
|
ok: true,
|
|
16554
|
-
value:
|
|
16637
|
+
value: {
|
|
16638
|
+
amount: 0n,
|
|
16639
|
+
decimals: fromTokenInfo.decimals,
|
|
16640
|
+
type: "DEPOSIT_LIMIT"
|
|
16641
|
+
}
|
|
16555
16642
|
};
|
|
16556
16643
|
}
|
|
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;
|
|
16644
|
+
if (from.xChainId !== this.hubProvider.chainConfig.chain.id && to.xChainId === this.hubProvider.chainConfig.chain.id) {
|
|
16645
|
+
const fromTokenDepositedAmount2 = this.findTokenBalanceInReserves(reserves, from);
|
|
16646
|
+
const availableDeposit2 = fromTokenInfo.maxDeposit - fromTokenDepositedAmount2;
|
|
16564
16647
|
return {
|
|
16565
16648
|
ok: true,
|
|
16566
|
-
value:
|
|
16649
|
+
value: {
|
|
16650
|
+
amount: availableDeposit2,
|
|
16651
|
+
decimals: fromTokenInfo.decimals,
|
|
16652
|
+
type: "DEPOSIT_LIMIT"
|
|
16653
|
+
}
|
|
16567
16654
|
};
|
|
16568
16655
|
}
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16575
|
-
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16579
|
-
|
|
16580
|
-
|
|
16581
|
-
const assetManagerBalance = reserves
|
|
16656
|
+
if (from.xChainId === this.hubProvider.chainConfig.chain.id && to.xChainId !== this.hubProvider.chainConfig.chain.id) {
|
|
16657
|
+
return {
|
|
16658
|
+
ok: true,
|
|
16659
|
+
value: {
|
|
16660
|
+
amount: this.findTokenBalanceInReserves(reserves, to),
|
|
16661
|
+
decimals: toTokenInfo.decimals,
|
|
16662
|
+
type: "WITHDRAWAL_LIMIT"
|
|
16663
|
+
}
|
|
16664
|
+
};
|
|
16665
|
+
}
|
|
16666
|
+
const fromTokenDepositedAmount = this.findTokenBalanceInReserves(reserves, from);
|
|
16667
|
+
const availableDeposit = fromTokenInfo.maxDeposit - fromTokenDepositedAmount;
|
|
16668
|
+
const assetManagerBalance = this.findTokenBalanceInReserves(reserves, to);
|
|
16669
|
+
const availableDepositNormalised = BigNumber4__default.default(availableDeposit).shiftedBy(-fromTokenInfo.decimals);
|
|
16670
|
+
const assetManagerBalanceNormalised = BigNumber4__default.default(assetManagerBalance).shiftedBy(-toTokenInfo.decimals);
|
|
16582
16671
|
return {
|
|
16583
16672
|
ok: true,
|
|
16584
|
-
value: availableDeposit
|
|
16673
|
+
value: availableDepositNormalised.isLessThan(assetManagerBalanceNormalised) ? { amount: availableDeposit, decimals: fromTokenInfo.decimals, type: "DEPOSIT_LIMIT" } : { amount: assetManagerBalance, decimals: toTokenInfo.decimals, type: "WITHDRAWAL_LIMIT" }
|
|
16585
16674
|
};
|
|
16586
16675
|
} catch (error) {
|
|
16587
16676
|
console.error(error);
|
|
@@ -16658,6 +16747,13 @@ var BridgeService = class {
|
|
|
16658
16747
|
}
|
|
16659
16748
|
return bridgeableTokens;
|
|
16660
16749
|
}
|
|
16750
|
+
findTokenBalanceInReserves(reserves, token) {
|
|
16751
|
+
const hubAsset = this.configService.getHubAssetInfo(token.xChainId, token.address);
|
|
16752
|
+
invariant6__default.default(hubAsset, `Hub asset not found for token ${token.address} on chain ${token.xChainId}`);
|
|
16753
|
+
const tokenIndex = reserves.tokens.findIndex((t) => t.toLowerCase() === hubAsset.asset.toLowerCase());
|
|
16754
|
+
invariant6__default.default(tokenIndex !== -1, `Token ${hubAsset.asset} not found in the vault reserves for chain ${token.xChainId}`);
|
|
16755
|
+
return reserves.balances[tokenIndex] ?? 0n;
|
|
16756
|
+
}
|
|
16661
16757
|
};
|
|
16662
16758
|
var StakingLogic = class _StakingLogic {
|
|
16663
16759
|
constructor() {
|