diff --git a/packages/universal-swap/src/handler.ts b/packages/universal-swap/src/handler.ts index 0dba24bb..54972c22 100644 --- a/packages/universal-swap/src/handler.ts +++ b/packages/universal-swap/src/handler.ts @@ -10,7 +10,6 @@ import { generateError, getEncodedExecuteContractMsgs, toAmount, - // buildMultipleExecuteMessages, parseTokenInfo, calculateMinReceive, handleSentFunds, @@ -18,30 +17,29 @@ import { ORAI_BRIDGE_EVM_TRON_DENOM_PREFIX, oraichain2oraib, CosmosChainId, - findToTokenOnOraiBridge, + // findToTokenOnOraiBridge, getTokenOnSpecificChainId, UNISWAP_ROUTER_DEADLINE, gravityContracts, Bridge__factory, IUniswapV2Router02__factory, ethToTronAddress, - network, + // network, EvmResponse, - // TODO: INIT ORAI COMMON HERE - getTokenOnOraichain, + // getTokenOnOraichain, getCosmosGasPrice, CoinGeckoId, IBC_WASM_CONTRACT, IBC_WASM_CONTRACT_TEST, - tokenMap, + // tokenMap, buildMultipleExecuteMessages, ibcInfosOld, - checkValidateAddressWithNetwork, + // checkValidateAddressWithNetwork, BigDecimal, OSMOSIS_ROUTER_CONTRACT, - cosmosChains, toDisplay, - ChainIdEnum + ChainIdEnum, + OraidexCommon } from "@oraichain/oraidex-common"; import { ethers } from "ethers"; import { UniversalSwapHelper } from "./helper"; @@ -62,17 +60,19 @@ import { OraiswapRouterQueryClient } from "@oraichain/oraidex-contracts-sdk"; import { Affiliate } from "@oraichain/oraidex-contracts-sdk/build/OraiswapMixedRouter.types"; import { COSMOS_CHAIN_IDS, EVM_CHAIN_IDS } from "@oraichain/common"; import { generateMsgSwap } from "./msg/msgs"; +import { notAllowBEP20Token, notAllowDenom, notAllowSwapCoingeckoIds, notAllowSwapFromChainIds, notAllowSwapToChainIds } from "./swap-filter"; const AFFILIATE_DECIMAL = 1e4; // 10_000 export class UniversalSwapHandler { constructor( public swapData: UniversalSwapData, public config: UniversalSwapConfig, + private readonly oraidexCommon: OraidexCommon, private readonly currentTimestamp = Date.now() ) {} private getTokenOnOraichain(coinGeckoId: CoinGeckoId, isNative?: boolean): TokenItemType { - const fromTokenOnOrai = getTokenOnOraichain(coinGeckoId, isNative); + const fromTokenOnOrai = this.oraidexCommon.getTokenOnOraichain(coinGeckoId, isNative); if (!fromTokenOnOrai) throw generateError(`Could not find token ${coinGeckoId} on Oraichain. Could not swap`); return fromTokenOnOrai; } @@ -87,6 +87,28 @@ export class UniversalSwapHandler { return ibcInfo.testInfo; } + get swapFromTokens(): TokenItemType[] { + return this.oraidexCommon.flattenTokens.filter((token) => { + return ( + !notAllowDenom.includes(token?.denom) && + !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && + !notAllowSwapFromChainIds.includes(token.chainId) && + !notAllowBEP20Token.includes(token?.contractAddress) + ); + }); + } + + get swapToTokens(): TokenItemType[] { + return this.oraidexCommon.flattenTokens.filter((token) => { + return ( + !notAllowDenom.includes(token?.denom) && + !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && + !notAllowSwapToChainIds.includes(token.chainId) && + !notAllowBEP20Token.includes(token?.contractAddress) + ); + }); + } + async getUniversalSwapToAddress( toChainId: string, address: { metamaskAddress?: string; tronAddress?: string } @@ -124,7 +146,10 @@ export class UniversalSwapHandler { let ibcReceiveAddr = ""; if (this.swapData.recipientAddress) { - const isValidRecipient = checkValidateAddressWithNetwork(this.swapData.recipientAddress, toChainId); + const isValidRecipient = this.oraidexCommon.checkValidateAddressWithNetwork( + this.swapData.recipientAddress, + toChainId + ); if (!isValidRecipient.isValid) throw generateError("Recipient address invalid!"); ibcReceiveAddr = this.swapData.recipientAddress; @@ -137,7 +162,8 @@ export class UniversalSwapHandler { let toTokenInOrai = this.getTokenOnOraichain(toCoinGeckoId); const isSpecialChain = ["kawaii_6886-1", "injective-1"].includes(toChainId); const isSpecialCoingecko = ["kawaii-islands", "milky-token", "injective-protocol"].includes(toCoinGeckoId); - if (isSpecialChain && isSpecialCoingecko) toTokenInOrai = this.getTokenOnOraichain(toCoinGeckoId, true); + if (isSpecialChain && isSpecialCoingecko) + toTokenInOrai = this.getTokenOnOraichain(toCoinGeckoId, true); let msgTransfer: EncodeObject[]; // if ibc info source has wasm in it, it means we need to transfer IBC using IBC wasm contract, not normal ibc transfer @@ -176,13 +202,15 @@ export class UniversalSwapHandler { if (isSpecialChain) { // convert token if (isSpecialCoingecko) { - const evmToken = tokenMap[toTokenInOrai.denom]; + const evmToken = this.oraidexCommon.tokenMap[toTokenInOrai.denom]; const evmAmount = coin(toAmount(this.swapData.fromAmount, evmToken.decimals).toString(), evmToken.denom); const msgConvertReverses = UniversalSwapHelper.generateConvertCw20Erc20Message( this.swapData.amounts, this.getTokenOnOraichain(toCoinGeckoId), sender, - evmAmount + evmAmount, + this.oraidexCommon.tokenMap, + this.oraidexCommon.network ); const executeContractMsgs = buildMultipleExecuteMessages(undefined, ...msgConvertReverses); getEncodedExecuteMsgs = getEncodedExecuteContractMsgs(sender, executeContractMsgs); @@ -231,7 +259,7 @@ export class UniversalSwapHandler { ) { let transferAddress; if (recipientAddress) { - const isValidRecipient = checkValidateAddressWithNetwork(this.swapData.recipientAddress, toToken.originalChainId); + const isValidRecipient = this.oraidexCommon.checkValidateAddressWithNetwork(this.swapData.recipientAddress, toToken.originalChainId); if (!isValidRecipient.isValid) throw generateError("Recipient address invalid!"); transferAddress = toToken.originalChainId === ChainIdEnum.TRON ? tronToEthAddress(recipientAddress) : recipientAddress; @@ -256,7 +284,7 @@ export class UniversalSwapHandler { } // then find new _toToken in Oraibridge that have same coingeckoId with originalToToken. - const newToToken = findToTokenOnOraiBridge(originalToToken.coinGeckoId, originalToToken.chainId); + const newToToken = this.oraidexCommon.findToTokenOnOraiBridge(originalToToken.coinGeckoId, originalToToken.chainId); const toAddress = await this.config.cosmosWallet.getKeplrAddr(newToToken.chainId as CosmosChainId); if (!toAddress) throw generateError("Please login cosmos wallet!"); @@ -278,13 +306,15 @@ export class UniversalSwapHandler { let getEncodedExecuteMsgs = []; if (["kawaii-islands", "milky-token"].includes(originalToToken.coinGeckoId)) { const toTokenInOrai = this.getTokenOnOraichain(originalToToken.coinGeckoId, true); - const evmToken = tokenMap[toTokenInOrai.denom]; + const evmToken = this.oraidexCommon.tokenMap[toTokenInOrai.denom]; const evmAmount = coin(toAmount(this.swapData.fromAmount, evmToken.decimals).toString(), evmToken.denom); const msgConvertReverses = UniversalSwapHelper.generateConvertCw20Erc20Message( this.swapData.amounts, this.getTokenOnOraichain(originalToToken.coinGeckoId), this.swapData.sender.cosmos, - evmAmount + evmAmount, + this.oraidexCommon.tokenMap, + this.oraidexCommon.network ); // for KWT & MILKY tokens, we use the old ibc info channel const { chainId: fromChainId } = originalFromToken; @@ -318,8 +348,8 @@ export class UniversalSwapHandler { async swap(): Promise { const messages = this.generateMsgsSwap(); const { client } = await this.config.cosmosWallet.getCosmWasmClient( - { chainId: "Oraichain", rpc: network.rpc }, - { gasPrice: GasPrice.fromString(`${network.fee.gasPrice}${network.denom}`) } + { chainId: "Oraichain", rpc: this.oraidexCommon.network.rpc }, + { gasPrice: GasPrice.fromString(`${this.oraidexCommon.network.fee.gasPrice}${this.oraidexCommon.network.denom}`) } ); const result = await client.executeMultiple(this.swapData.sender.cosmos, messages, "auto"); return result; @@ -502,7 +532,7 @@ export class UniversalSwapHandler { throw generateError("Cannot transfer and swap if the cosmos wallet is not initialized"); // we get cosmwasm client on Oraichain because this is checking channel balance on Oraichain const { client } = await this.config.cosmosWallet.getCosmWasmClient( - { rpc: network.rpc, chainId: network.chainId as CosmosChainId }, + { rpc: this.oraidexCommon.network.rpc, chainId: this.oraidexCommon.network.chainId as CosmosChainId }, { gasPrice: this.getGasPriceFromToken() } @@ -520,12 +550,13 @@ export class UniversalSwapHandler { case "oraichain-to-evm": const { evm: metamaskAddress, tron: tronAddress } = this.swapData.sender; if (!this.config?.swapOptions?.isCheckBalanceIbc) { - const routerClient = new OraiswapRouterQueryClient(client, network.mixer_router); + const routerClient = new OraiswapRouterQueryClient(client, this.oraidexCommon.network.mixer_router); const isSufficient = await UniversalSwapHelper.checkFeeRelayer({ originalFromToken: this.swapData.originalFromToken, fromAmount: this.swapData.fromAmount, relayerFee: this.swapData.relayerFee, - routerClient + routerClient, + getTokenOnOraichain: this.oraidexCommon.getTokenOnOraichain }); if (!isSufficient) throw generateError( @@ -547,7 +578,9 @@ export class UniversalSwapHandler { originalToToken, simulateAmount, client, - this.getCwIcs20ContractAddr() + this.getCwIcs20ContractAddr(), + this.oraidexCommon.getTokenOnOraichain, + this.oraidexCommon.network ); } @@ -573,7 +606,7 @@ export class UniversalSwapHandler { if (!this.config.cosmosWallet) throw generateError("Cannot transfer and swap if cosmos wallet is not initialized"); // we get cosmwasm client on Oraichain because this is checking channel balance on Oraichain const { client } = await this.config.cosmosWallet.getCosmWasmClient( - { rpc: network.rpc, chainId: network.chainId as CosmosChainId }, + { rpc: this.oraidexCommon.network.rpc, chainId: this.oraidexCommon.network.chainId as CosmosChainId }, {} ); @@ -625,15 +658,18 @@ export class UniversalSwapHandler { fromAmount, simulateAmount, client, - this.getCwIcs20ContractAddr() + this.getCwIcs20ContractAddr(), + this.oraidexCommon.getTokenOnOraichain, + this.oraidexCommon.network ); - const routerClient = new OraiswapRouterQueryClient(client, network.mixer_router); + const routerClient = new OraiswapRouterQueryClient(client, this.oraidexCommon.network.mixer_router); const isSufficient = await UniversalSwapHelper.checkFeeRelayer({ originalFromToken, fromAmount, relayerFee, - routerClient + routerClient, + getTokenOnOraichain: this.oraidexCommon.getTokenOnOraichain }); if (!isSufficient) throw generateError( @@ -689,8 +725,12 @@ export class UniversalSwapHandler { originalToToken, minimumReceive, userSlippage, + this.oraidexCommon.cosmosTokens, + this.oraidexCommon.cosmosChains, + this.oraidexCommon.evmChains, + this.oraidexCommon.checkValidateAddressWithNetwork, this.config.swapOptions, - alphaSmartRoutes + alphaSmartRoutes, ); const swapRouteSplit = completeSwapRoute.split(":"); const swapRoute = swapRouteSplit.length === 1 ? "" : swapRouteSplit[1]; @@ -719,7 +759,7 @@ export class UniversalSwapHandler { // check if from chain is noble, use ibc-wasm instead of ibc-hooks if (originalFromToken.chainId === "noble-1") { if (this.swapData.recipientAddress) { - const isValidRecipient = checkValidateAddressWithNetwork(this.swapData.recipientAddress, "Oraichain"); + const isValidRecipient = this.oraidexCommon.checkValidateAddressWithNetwork(this.swapData.recipientAddress, "Oraichain"); if (!isValidRecipient.isValid || isValidRecipient.network !== "Oraichain") { throw generateError("Recipient address invalid! Only support bridge to Oraichain"); @@ -769,7 +809,9 @@ export class UniversalSwapHandler { originalToToken, simulateAmount, client, - this.getCwIcs20ContractAddr() + this.getCwIcs20ContractAddr(), + this.oraidexCommon.getTokenOnOraichain, + this.oraidexCommon.network ); } @@ -793,7 +835,7 @@ export class UniversalSwapHandler { async getToAddressUniversalSwap(evm, tron, recipientAddress, originalToToken) { if (this.swapData.recipientAddress) { - const isValidRecipient = checkValidateAddressWithNetwork(recipientAddress, originalToToken.chainId); + const isValidRecipient = this.oraidexCommon.checkValidateAddressWithNetwork(recipientAddress, originalToToken.chainId); if (!isValidRecipient.isValid) throw generateError("Recipient address invalid!"); @@ -817,7 +859,7 @@ export class UniversalSwapHandler { const toAddress = await this.getToAddressUniversalSwap(evm, tron, this.swapData.recipientAddress, originalToToken); const oraiAddress = await this.config.cosmosWallet.getKeplrAddr(COSMOS_CHAIN_IDS.ORAICHAIN); if (!oraiAddress) throw generateError("orai address and obridge address invalid!"); - const isValidRecipientOraichain = checkValidateAddressWithNetwork(oraiAddress, COSMOS_CHAIN_IDS.ORAICHAIN); + const isValidRecipientOraichain = this.oraidexCommon.checkValidateAddressWithNetwork(oraiAddress, COSMOS_CHAIN_IDS.ORAICHAIN); if (!isValidRecipientOraichain.isValid) throw generateError("orai get address invalid!"); let injAddress = undefined; @@ -881,12 +923,16 @@ export class UniversalSwapHandler { originalToToken, minimumReceive, userSlippage, + this.oraidexCommon.cosmosTokens, + this.oraidexCommon.cosmosChains, + this.oraidexCommon.evmChains, + this.oraidexCommon.checkValidateAddressWithNetwork, this.config.swapOptions, - alphaSmartRoutes + alphaSmartRoutes, ); if (isAlphaIbcWasmHasRoute) { - let receiverAddresses = UniversalSwapHelper.generateAddress(addressParams); + let receiverAddresses = UniversalSwapHelper.generateAddress({...addressParams, cosmosChains: this.oraidexCommon.cosmosChains}); if (recipientAddress) receiverAddresses[originalToToken.chainId] = toAddress; return this.alphaSmartRouterSwapNewMsg(swapRoute, universalSwapType, receiverAddresses); } @@ -907,16 +953,17 @@ export class UniversalSwapHandler { if (originalToToken.coinGeckoId !== "oraichain-token") { const { client } = await cosmosWallet.getCosmWasmClient( - { rpc: network.rpc, chainId: network.chainId as CosmosChainId }, - { gasPrice: GasPrice.fromString(`${network.fee.gasPrice}${network.denom}`) } + { rpc: this.oraidexCommon.network.rpc, chainId: this.oraidexCommon.network.chainId as CosmosChainId }, + { gasPrice: GasPrice.fromString(`${this.oraidexCommon.network.fee.gasPrice}${this.oraidexCommon.network.denom}`) } ); if (!!subRelayerFee) { - const routerClient = new OraiswapRouterQueryClient(client, network.mixer_router); + const routerClient = new OraiswapRouterQueryClient(client, this.oraidexCommon.network.mixer_router); const { amount } = await UniversalSwapHelper.handleSimulateSwap({ originalFromInfo: this.getTokenOnOraichain("oraichain-token"), originalToInfo: this.getTokenOnOraichain(originalToToken.coinGeckoId), originalAmount: toDisplay(subRelayerFee), routerClient: routerClient, + getTokenOnOraichain: this.oraidexCommon.getTokenOnOraichain, routerOption: { useIbcWasm: true }, @@ -953,7 +1000,7 @@ export class UniversalSwapHandler { * @returns */ generateMsgsSmartRouterSwap(route: Routes, isLastRoute: boolean) { - let contractAddr: string = network.mixer_router; + let contractAddr: string = this.oraidexCommon.network.mixer_router; const { originalFromToken, fromAmount, affiliates, userSlippage } = this.swapData; const fromTokenOnOrai = this.getTokenOnOraichain(originalFromToken.coinGeckoId); const _fromAmount = toAmount(fromAmount, fromTokenOnOrai.decimals).toString(); @@ -965,9 +1012,9 @@ export class UniversalSwapHandler { } const to = isLastRoute ? this.swapData.recipientAddress : undefined; const { info: offerInfo } = parseTokenInfo(fromTokenOnOrai, _fromAmount); - const msgConvertsFrom = UniversalSwapHelper.generateConvertErc20Cw20Message(this.swapData.amounts, fromTokenOnOrai); + const msgConvertsFrom = UniversalSwapHelper.generateConvertErc20Cw20Message(this.swapData.amounts, fromTokenOnOrai, this.oraidexCommon.tokenMap, this.oraidexCommon.network); - const routes = UniversalSwapHelper.generateMsgsSmartRouterV2withV3([route], offerInfo); + const routes = UniversalSwapHelper.generateMsgsSmartRouterV2withV3([route], offerInfo, this.oraidexCommon.parseAssetInfoFromContractAddrOrDenom); const msgs: ExecuteInstruction[] = UniversalSwapHelper.buildSwapMsgsFromSmartRoute( routes, fromTokenOnOrai, @@ -981,7 +1028,7 @@ export class UniversalSwapHandler { generateMsgsSwap() { let input: any; - let contractAddr: string = network.mixer_router; + let contractAddr: string = this.oraidexCommon.network.mixer_router; const { originalFromToken, originalToToken, fromAmount, affiliates, userSlippage } = this.swapData; // since we're swapping on Oraichain, we need to get from token on Oraichain const fromTokenOnOrai = this.getTokenOnOraichain(originalFromToken.coinGeckoId); @@ -990,9 +1037,11 @@ export class UniversalSwapHandler { const _fromAmount = toAmount(fromAmount, fromTokenOnOrai.decimals).toString(); const msgConvertsFrom = UniversalSwapHelper.generateConvertErc20Cw20Message( this.swapData.amounts, - fromTokenOnOrai + fromTokenOnOrai, + this.oraidexCommon.tokenMap, + this.oraidexCommon.network ); - const msgConvertTo = UniversalSwapHelper.generateConvertErc20Cw20Message(this.swapData.amounts, toTokenInOrai); + const msgConvertTo = UniversalSwapHelper.generateConvertErc20Cw20Message(this.swapData.amounts, toTokenInOrai, this.oraidexCommon.tokenMap, this.oraidexCommon.network); const isValidSlippage = userSlippage || userSlippage === 0; if (!this.swapData.simulatePrice || !isValidSlippage) { throw generateError( @@ -1005,7 +1054,7 @@ export class UniversalSwapHandler { const funds = handleSentFunds(offerSentFund, askSentFund); let to = undefined; if (this.swapData.recipientAddress && originalToToken.chainId === "Oraichain") { - const isValidRecipient = checkValidateAddressWithNetwork( + const isValidRecipient = this.oraidexCommon.checkValidateAddressWithNetwork( this.swapData.recipientAddress, this.swapData.originalToToken.chainId ); @@ -1031,7 +1080,7 @@ export class UniversalSwapHandler { if (hasRouteNotIsOraichain) throw "Only support routes in Oraichain!"; const routesFlatten = UniversalSwapHelper.flattenSmartRouters(routes); - const generatedRoutes = UniversalSwapHelper.generateMsgsSmartRouterV2withV3(routesFlatten, offerInfo); + const generatedRoutes = UniversalSwapHelper.generateMsgsSmartRouterV2withV3(routesFlatten, offerInfo, this.oraidexCommon.parseAssetInfoFromContractAddrOrDenom); msgs = UniversalSwapHelper.buildSwapMsgsFromSmartRoute( generatedRoutes, diff --git a/packages/universal-swap/src/helper.ts b/packages/universal-swap/src/helper.ts index 8a1f3f07..f2a57d4e 100644 --- a/packages/universal-swap/src/helper.ts +++ b/packages/universal-swap/src/helper.ts @@ -21,7 +21,7 @@ import { TokenItemType, parseTokenInfoRawDenom, // TODO: INIT ORAI COMMON HERE - getTokenOnOraichain, + // getTokenOnOraichain, isEthAddress, PAIRS, ORAI_INFO, @@ -30,27 +30,30 @@ import { toDisplay, getTokenOnSpecificChainId, IUniswapV2Router02__factory, - cosmosTokens, + // cosmosTokens, StargateMsg, isInPairList, BigDecimal, NEUTARO_INFO, USDC_INFO, - network, + // network, ORAIX_ETH_CONTRACT, AmountDetails, handleSentFunds, - tokenMap, + // tokenMap, oraib2oraichainTest, getSubAmountDetails, - evmChains, + // evmChains, getAxios, - parseAssetInfoFromContractAddrOrDenom, + // parseAssetInfoFromContractAddrOrDenom, parseAssetInfo, calculateTimeoutTimestamp, COSMOS_CHAIN_ID_COMMON, - checkValidateAddressWithNetwork, - cosmosChains + OraidexCommon, + CustomChainInfo, + NetworkConfig + // checkValidateAddressWithNetwork, + // cosmosChains } from "@oraichain/oraidex-common"; import { ConvertReverse, @@ -79,7 +82,7 @@ import isEqual from "lodash/isEqual"; import { ethers } from "ethers"; import { Amount, CwIcs20LatestQueryClient, Uint128 } from "@oraichain/common-contracts-sdk"; import { CosmWasmClient, ExecuteInstruction, toBinary } from "@cosmjs/cosmwasm-stargate"; -import { swapFromTokens, swapToTokens } from "./swap-filter"; +// import { swapFromTokens, swapToTokens } from "./swap-filter"; import { Coin } from "@cosmjs/proto-signing"; import { AXIOS_TIMEOUT, COSMOS_CHAIN_IDS, EVM_CHAIN_IDS, IBC_TRANSFER_TIMEOUT } from "@oraichain/common"; import { TransferBackMsg } from "@oraichain/common-contracts-sdk/build/CwIcs20Latest.types"; @@ -221,6 +224,7 @@ export class UniversalSwapHelper { */ static getSourceReceiver = ( oraiAddress: string, + checkValidateAddressWithNetwork: (address: string, chainId: string) => { isValid: boolean; error?: string }, contractAddress?: string, isSourceReceiverTest?: boolean ): string => { @@ -247,7 +251,12 @@ export class UniversalSwapHelper { * @param destReceiver - destination destReceiver * @returns destination in the format /: */ - static getRoute = (fromToken?: TokenItemType, toToken?: TokenItemType, destReceiver?: string): SwapRoute => { + static getRoute = ( + cosmosTokens: TokenItemType[], + fromToken?: TokenItemType, + toToken?: TokenItemType, + destReceiver?: string + ): SwapRoute => { if (!fromToken || !toToken || !destReceiver) return { swapRoute: "", universalSwapType: "other-networks-to-oraichain", isSmartRouter: false }; // this is the simplest case. Both tokens on the same Oraichain network => simple swap with to token denom @@ -336,10 +345,12 @@ export class UniversalSwapHelper { static generateAddress = ({ oraiAddress, injAddress, + cosmosChains, evmInfo }: { oraiAddress: string; injAddress?: string; + cosmosChains: CustomChainInfo[]; evmInfo?: { [key: string]: string; }; @@ -392,6 +403,16 @@ export class UniversalSwapHelper { toToken: TokenItemType, minimumReceive: string, userSlippage: number, + cosmosTokens: TokenItemType[], + cosmosChains: CustomChainInfo[], + evmChains: CustomChainInfo[], + checkValidateAddressWithNetwork: ( + address: string, + chainId: string + ) => { + isValid: boolean; + error?: string; + }, swapOption?: { isSourceReceiverTest?: boolean; isIbcWasm?: boolean; @@ -404,11 +425,13 @@ export class UniversalSwapHelper { if (!addresses.sourceReceiver) throw generateError(`Cannot get source if the sourceReceiver is empty!`); const source = UniversalSwapHelper.getSourceReceiver( addresses.sourceReceiver, + checkValidateAddressWithNetwork, fromToken.contractAddress, swapOption?.isSourceReceiverTest ); let { swapRoute, universalSwapType, isSmartRouter } = UniversalSwapHelper.getRoute( + cosmosTokens, fromToken, toToken, addresses.destReceiver @@ -434,6 +457,7 @@ export class UniversalSwapHelper { destChainId: toToken.chainId, destTokenPrefix: toToken.prefix }, + evmChains, swapOption.ibcInfoTestMode ); } @@ -461,6 +485,7 @@ export class UniversalSwapHelper { let receiverAddresses = UniversalSwapHelper.generateAddress({ injAddress: addresses.injAddress, oraiAddress: addresses.sourceReceiver, + cosmosChains, evmInfo: !toToken.cosmosBased ? { [toToken.chainId]: toToken.chainId === EVM_CHAIN_IDS.TRON ? addresses.tronAddress : addresses.evmAddress @@ -502,6 +527,7 @@ export class UniversalSwapHelper { remoteAddressObridge?: string; // add with oraibridge }, userSwap: RouterResponse & { destTokenPrefix: string; destAsset: string; destChainId: string }, + evmChains: CustomChainInfo[], ibcInfoTestMode?: boolean ) => { const { destReceiver, remoteAddressObridge } = basic; @@ -849,6 +875,7 @@ export class UniversalSwapHelper { originalToInfo: TokenItemType; originalAmount: number; routerClient: OraiswapRouterReadOnlyInterface; + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType; routerOption?: { useIbcWasm?: boolean; useAlphaIbcWasm?: boolean; @@ -885,8 +912,8 @@ export class UniversalSwapHelper { ignoreFee: query?.routerConfig?.ignoreFee ?? false }; - let fromInfo = getTokenOnOraichain(query.originalFromInfo.coinGeckoId); - let toInfo = getTokenOnOraichain(query.originalToInfo.coinGeckoId); + let fromInfo = query.getTokenOnOraichain(query.originalFromInfo.coinGeckoId); + let toInfo = query.getTokenOnOraichain(query.originalToInfo.coinGeckoId); /** * useAlphaIbcWasm case: (evm -> oraichain -> osmosis -> inj not using wasm) @@ -924,6 +951,7 @@ export class UniversalSwapHelper { }; fromAmount: number; routerClient: OraiswapRouterReadOnlyInterface; + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType; }): Promise => { const { originalFromToken, relayerFee, fromAmount, routerClient } = query; if (!relayerFee || !parseInt(relayerFee.relayerAmount)) return true; @@ -936,10 +964,11 @@ export class UniversalSwapHelper { } return UniversalSwapHelper.checkFeeRelayerNotOrai({ - fromTokenInOrai: getTokenOnOraichain(originalFromToken.coinGeckoId), + fromTokenInOrai: query.getTokenOnOraichain(originalFromToken.coinGeckoId), fromAmount, relayerAmount: relayerFee.relayerAmount, - routerClient + routerClient, + getTokenOnOraichain: query.getTokenOnOraichain }); }; @@ -948,6 +977,7 @@ export class UniversalSwapHelper { fromAmount: number; relayerAmount: string; routerClient: OraiswapRouterReadOnlyInterface; + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType; }): Promise => { const { fromTokenInOrai, fromAmount, routerClient, relayerAmount } = query; if (!fromTokenInOrai) return true; @@ -957,7 +987,7 @@ export class UniversalSwapHelper { ); // estimate exchange token when From Token not orai. Only need to swap & check if it is swappable with ORAI. Otherwise, we ignore the fees if (isInPairList(fromTokenInOrai.denom) || isInPairList(fromTokenInOrai.contractAddress)) { - const oraiToken = getTokenOnOraichain("oraichain-token"); + const oraiToken = query.getTokenOnOraichain("oraichain-token"); const { amount } = await UniversalSwapHelper.simulateSwap({ fromInfo: fromTokenInOrai, toInfo: oraiToken, @@ -979,7 +1009,9 @@ export class UniversalSwapHelper { toToken: TokenItemType, toSimulateAmount: string, client: CosmWasmClient, - ibcWasmContract: string + ibcWasmContract: string, + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType, + network: CustomChainInfo & NetworkConfig ) => { try { let pairKey = UniversalSwapHelper.buildIbcWasmPairKey(ibcInfo.source, ibcInfo.channel, toToken.denom); @@ -1052,7 +1084,9 @@ export class UniversalSwapHelper { fromAmount: number, toSimulateAmount: string, client: CosmWasmClient, - ibcWasmContract: string + ibcWasmContract: string, + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType, + network: CustomChainInfo & NetworkConfig ) => { // ORAI ( ETH ) -> check ORAI (ORAICHAIN) -> ORAI (BSC) // no need to check this case because users will swap directly. This case should be impossible because it is only called when transferring from evm to other networks @@ -1085,7 +1119,16 @@ export class UniversalSwapHelper { if (to.chainId === "0x01" || to.chainId === "0x38" || to.chainId === "0x2b6653dc") { const ibcInfo: IBCInfo | undefined = UniversalSwapHelper.getIbcInfo("Oraichain", to.chainId); if (!ibcInfo) throw generateError("IBC Info error when checking ibc balance"); - await UniversalSwapHelper.checkBalanceChannelIbc(ibcInfo, from, to, toSimulateAmount, client, ibcWasmContract); + await UniversalSwapHelper.checkBalanceChannelIbc( + ibcInfo, + from, + to, + toSimulateAmount, + client, + ibcWasmContract, + getTokenOnOraichain, + network + ); } }; @@ -1094,7 +1137,10 @@ export class UniversalSwapHelper { coingeckoId: CoinGeckoId, denom: string, searchTokenName: string, - direction: SwapDirection // direction = to means we are filtering to tokens + direction: SwapDirection, // direction = to means we are filtering to tokens + getTokenOnOraichain: (coingeckoId: CoinGeckoId, isNative?: boolean) => TokenItemType, + swapFromTokens: TokenItemType[], + swapToTokens: TokenItemType[] ) => { // basic filter. Dont include itself & only collect tokens with searched letters const listTokens = direction === SwapDirection.From ? swapFromTokens : swapToTokens; @@ -1137,6 +1183,8 @@ export class UniversalSwapHelper { static generateConvertErc20Cw20Message = ( amounts: AmountDetails, tokenInfo: TokenItemType, + tokenMap: Record, + network: CustomChainInfo & NetworkConfig, sender?: string ): ExecuteInstruction[] => { if (!tokenInfo.evmDenoms) return []; @@ -1152,7 +1200,7 @@ export class UniversalSwapHelper { sender, inputAmount: balance.toString(), inputToken: erc20TokenInfo - }); + }, network); return [msgConvert]; } } @@ -1163,7 +1211,9 @@ export class UniversalSwapHelper { amounts: AmountDetails, tokenInfo: TokenItemType, sender: string, - sendCoin: Coin + sendCoin: Coin, + tokenMap: Record, + network: CustomChainInfo & NetworkConfig ): ExecuteInstruction[] => { if (!tokenInfo.evmDenoms) return []; // we convert all mapped tokens to cw20 to unify the token @@ -1189,15 +1239,15 @@ export class UniversalSwapHelper { sender, inputAmount: balance, inputToken: tokenInfo, - outputToken - }); + outputToken, + }, network); return [msgConvert]; } } return []; }; - static generateConvertMsgs = (data: ConvertType): ExecuteInstruction => { + static generateConvertMsgs = (data: ConvertType, network: CustomChainInfo & NetworkConfig): ExecuteInstruction => { const { type, sender, inputToken, inputAmount } = data; let funds: Coin[] | null; // for withdraw & provide liquidity methods, we need to interact with the oraiswap pair contract @@ -1278,7 +1328,7 @@ export class UniversalSwapHelper { * @param offerInfo * @returns */ - static generateMsgsSmartRouterV2withV3(routes, offerInfo) { + static generateMsgsSmartRouterV2withV3(routes, offerInfo, parseAssetInfoFromContractAddrOrDenom: (addressOrDenomToken: string) => AssetInfo) { return routes.map((route) => { let ops = []; let currTokenIn = offerInfo; diff --git a/packages/universal-swap/src/swap-filter.ts b/packages/universal-swap/src/swap-filter.ts index a32ebe63..ec4194e8 100644 --- a/packages/universal-swap/src/swap-filter.ts +++ b/packages/universal-swap/src/swap-filter.ts @@ -5,7 +5,7 @@ import { MILKYBSC_ORAICHAIN_DENOM, MILKY_BSC_CONTRACT, // TODO: INIT ORAI COMMON HERE - flattenTokens + // flattenTokens } from "@oraichain/oraidex-common"; export const evmDenomsMap = { @@ -13,9 +13,9 @@ export const evmDenomsMap = { milky: [MILKYBSC_ORAICHAIN_DENOM], injective: [INJECTIVE_ORAICHAIN_DENOM] }; -const notAllowSwapCoingeckoIds = []; +export const notAllowSwapCoingeckoIds = []; // universal swap. Currently we dont support from tokens that are not using the ibc wasm channel -const notAllowSwapFromChainIds = [ +export const notAllowSwapFromChainIds = [ "0x1ae6", "kawaii_6886-1", "oraibridge-subnet-2", @@ -23,18 +23,18 @@ const notAllowSwapFromChainIds = [ "Neutaro-1", "bitcoin" ]; -const notAllowDenom = Object.values(evmDenomsMap).flat(); -const notAllowBEP20Token = [KWT_BSC_CONTRACT, MILKY_BSC_CONTRACT]; -export const swapFromTokens = flattenTokens.filter((token) => { - return ( - !notAllowDenom.includes(token?.denom) && - !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && - !notAllowSwapFromChainIds.includes(token.chainId) && - !notAllowBEP20Token.includes(token?.contractAddress) - ); -}); +export const notAllowDenom = Object.values(evmDenomsMap).flat(); +export const notAllowBEP20Token = [KWT_BSC_CONTRACT, MILKY_BSC_CONTRACT]; +// export const swapFromTokens = flattenTokens.filter((token) => { +// return ( +// !notAllowDenom.includes(token?.denom) && +// !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && +// !notAllowSwapFromChainIds.includes(token.chainId) && +// !notAllowBEP20Token.includes(token?.contractAddress) +// ); +// }); // universal swap. We dont support kwt & milky & injective for simplicity. We also skip OraiBridge tokens because users dont care about them -const notAllowSwapToChainIds = [ +export const notAllowSwapToChainIds = [ "0x1ae6", "kawaii_6886-1", "oraibridge-subnet-2", @@ -42,11 +42,11 @@ const notAllowSwapToChainIds = [ "Neutaro-1", "bitcoin" ]; -export const swapToTokens = flattenTokens.filter((token) => { - return ( - !notAllowDenom.includes(token?.denom) && - !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && - !notAllowSwapToChainIds.includes(token.chainId) && - !notAllowBEP20Token.includes(token?.contractAddress) - ); -}); +// export const swapToTokens = flattenTokens.filter((token) => { +// return ( +// !notAllowDenom.includes(token?.denom) && +// !notAllowSwapCoingeckoIds.includes(token.coinGeckoId) && +// !notAllowSwapToChainIds.includes(token.chainId) && +// !notAllowBEP20Token.includes(token?.contractAddress) +// ); +// }); diff --git a/packages/universal-swap/src/universal-demos/alpha-ibc-new.ts b/packages/universal-swap/src/universal-demos/alpha-ibc-new.ts index 823fdb93..8c4b1927 100644 --- a/packages/universal-swap/src/universal-demos/alpha-ibc-new.ts +++ b/packages/universal-swap/src/universal-demos/alpha-ibc-new.ts @@ -115,8 +115,10 @@ const alphaSwapToOraichain = async () => { }, { cosmosWallet: wallet, - swapOptions: { isIbcWasm: false, isAlphaIbcWasm: true } - } + swapOptions: { isIbcWasm: false, isAlphaIbcWasm: true }, + + }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/alpha-smart-router.ts b/packages/universal-swap/src/universal-demos/alpha-smart-router.ts index 67231635..aff0c98a 100644 --- a/packages/universal-swap/src/universal-demos/alpha-smart-router.ts +++ b/packages/universal-swap/src/universal-demos/alpha-smart-router.ts @@ -74,7 +74,8 @@ const alphaSwapToOraichain = async () => { { cosmosWallet: wallet, swapOptions: { isIbcWasm: false, isAlphaIbcWasm: true } - } + }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/evm-to-evm.ts b/packages/universal-swap/src/universal-demos/evm-to-evm.ts index f3f34129..8bd5db43 100644 --- a/packages/universal-swap/src/universal-demos/evm-to-evm.ts +++ b/packages/universal-swap/src/universal-demos/evm-to-evm.ts @@ -51,7 +51,8 @@ const evmToEvm = async () => { swapOptions: { isAlphaSmartRouter: true } - } + }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/from-cosmos-to-evm.ts b/packages/universal-swap/src/universal-demos/from-cosmos-to-evm.ts index 2a1e2a0f..6d67f230 100644 --- a/packages/universal-swap/src/universal-demos/from-cosmos-to-evm.ts +++ b/packages/universal-swap/src/universal-demos/from-cosmos-to-evm.ts @@ -41,7 +41,8 @@ const oraichainToEvm = async (chainId: "Oraichain") => { fromAmount, simulateAmount: toAmount(fromAmount, originalToToken.decimals).toString() }, - { cosmosWallet: wallet, swapOptions: {} } + { cosmosWallet: wallet, swapOptions: {} }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/from-oraichain-to-evm.ts b/packages/universal-swap/src/universal-demos/from-oraichain-to-evm.ts index 872e147d..138d388b 100644 --- a/packages/universal-swap/src/universal-demos/from-oraichain-to-evm.ts +++ b/packages/universal-swap/src/universal-demos/from-oraichain-to-evm.ts @@ -48,7 +48,8 @@ const oraichainToEvm = async () => { isAlphaSmartRouter: true, isIbcWasm: true } - } + }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/from-oraichain-to-oraichain.ts b/packages/universal-swap/src/universal-demos/from-oraichain-to-oraichain.ts index 705a92e0..6661b945 100644 --- a/packages/universal-swap/src/universal-demos/from-oraichain-to-oraichain.ts +++ b/packages/universal-swap/src/universal-demos/from-oraichain-to-oraichain.ts @@ -53,7 +53,8 @@ const oraichainToOraichain = async (chainId: "Oraichain") => { simulateAmount: toAmount(fromAmount, originalToToken.decimals).toString(), userSlippage: 0.01 }, - { cosmosWallet: wallet, swapOptions: {} } + { cosmosWallet: wallet, swapOptions: {} }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/handle-simulate-swap.ts b/packages/universal-swap/src/universal-demos/handle-simulate-swap.ts index 11b79420..7b95bd99 100644 --- a/packages/universal-swap/src/universal-demos/handle-simulate-swap.ts +++ b/packages/universal-swap/src/universal-demos/handle-simulate-swap.ts @@ -27,7 +27,8 @@ const simulate = async () => { url: "https://osor.oraidex.io", path: "/smart-router/alpha-router", protocols: ["Oraidex", "OraidexV3", "Osmosis"] - } + }, + getTokenOnOraichain: oraidexCommon.getTokenOnOraichain }); } catch (error) { console.log("error: ", error); diff --git a/packages/universal-swap/src/universal-demos/ibc-hooks-demo.ts b/packages/universal-swap/src/universal-demos/ibc-hooks-demo.ts index 5abc3af9..6ea8fe6c 100644 --- a/packages/universal-swap/src/universal-demos/ibc-hooks-demo.ts +++ b/packages/universal-swap/src/universal-demos/ibc-hooks-demo.ts @@ -33,7 +33,8 @@ const cosmosToOraichain = async ( fromAmount, simulateAmount: toAmount(fromAmount, originalToToken.decimals).toString() }, - { cosmosWallet: wallet } + { cosmosWallet: wallet }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/neutaro-ibc-demo.ts b/packages/universal-swap/src/universal-demos/neutaro-ibc-demo.ts index 3e492fd9..df79dd6f 100644 --- a/packages/universal-swap/src/universal-demos/neutaro-ibc-demo.ts +++ b/packages/universal-swap/src/universal-demos/neutaro-ibc-demo.ts @@ -33,7 +33,8 @@ const neutaroUsdcToOraiUsdc = async (chainId: "Neutaro-1" | "Oraichain") => { fromAmount, simulateAmount: toAmount(fromAmount, originalToToken.decimals).toString() }, - { cosmosWallet: wallet, swapOptions: { ibcInfoTestMode: true } } + { cosmosWallet: wallet, swapOptions: { ibcInfoTestMode: true } }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/universal-demos/noble-ibc-demo.ts b/packages/universal-swap/src/universal-demos/noble-ibc-demo.ts index 68bc4450..faf11be8 100644 --- a/packages/universal-swap/src/universal-demos/noble-ibc-demo.ts +++ b/packages/universal-swap/src/universal-demos/noble-ibc-demo.ts @@ -31,7 +31,8 @@ const nobleUsdcToOraiUsdc = async (chainId: "noble-1" | "Oraichain") => { fromAmount, simulateAmount: toAmount(fromAmount, originalToToken.decimals).toString() }, - { cosmosWallet: wallet, swapOptions: { ibcInfoTestMode: true } } + { cosmosWallet: wallet, swapOptions: { ibcInfoTestMode: true } }, + oraidexCommon ); try { diff --git a/packages/universal-swap/src/wrapper.ts b/packages/universal-swap/src/wrapper.ts index a0784c52..d522658c 100644 --- a/packages/universal-swap/src/wrapper.ts +++ b/packages/universal-swap/src/wrapper.ts @@ -1,4 +1,4 @@ -import { CosmosChainId, CosmosWallet, EvmResponse, EvmWallet, TokenItemType } from "@oraichain/oraidex-common"; +import { CosmosChainId, CosmosWallet, EvmResponse, EvmWallet, OraidexCommon, TokenItemType } from "@oraichain/oraidex-common"; import { UniversalSwapHandler } from "./handler"; import { ExecuteResult } from "@cosmjs/cosmwasm-stargate"; @@ -13,6 +13,7 @@ export const swapOraichainToOraichain = async (data: { }): Promise => { const { cosmosWallet, fromAmount, fromToken, toToken, simulatePrice, userSlippage, simulateAmount } = data; const sender = await cosmosWallet.getKeplrAddr("Oraichain"); + const oraidexCommon = await OraidexCommon.load(); const handler = new UniversalSwapHandler( { sender: { cosmos: sender }, @@ -23,7 +24,8 @@ export const swapOraichainToOraichain = async (data: { simulatePrice, userSlippage }, - { cosmosWallet } + { cosmosWallet }, + oraidexCommon ); return handler.swap(); }; @@ -39,6 +41,7 @@ export const swapOraichainToCosmos = async (data: { }) => { const { cosmosWallet, fromAmount, fromToken, toToken, simulatePrice, userSlippage, simulateAmount } = data; const cosmos = await cosmosWallet.getKeplrAddr(fromToken.chainId as CosmosChainId); + const oraidexCommon = await OraidexCommon.load(); const handler = new UniversalSwapHandler( { sender: { cosmos }, @@ -49,7 +52,8 @@ export const swapOraichainToCosmos = async (data: { simulateAmount, userSlippage }, - { cosmosWallet } + { cosmosWallet }, + oraidexCommon ); return handler.swapAndTransferToOtherNetworks("oraichain-to-cosmos"); }; @@ -68,6 +72,7 @@ export const swapOraichainToEvm = async (data: { const cosmos = await cosmosWallet.getKeplrAddr(fromToken.chainId as CosmosChainId); const evm = await evmWallet.getEthAddress(); const tron = evmWallet.tronWeb?.defaultAddress?.base58 as string; + const oraidexCommon = await OraidexCommon.load(); const handler = new UniversalSwapHandler( { sender: { cosmos, evm, tron }, @@ -78,7 +83,8 @@ export const swapOraichainToEvm = async (data: { simulateAmount, userSlippage }, - { cosmosWallet, evmWallet } + { cosmosWallet, evmWallet }, + oraidexCommon ); return handler.swapAndTransferToOtherNetworks("oraichain-to-evm"); }; @@ -101,6 +107,7 @@ export const swapEvmToOraichain = async (data: { const cosmos = await cosmosWallet.getKeplrAddr(fromToken.chainId as CosmosChainId); const evm = await evmWallet.getEthAddress(); const tron = evmWallet.tronWeb?.defaultAddress?.base58 as string; + const oraidexCommon = await OraidexCommon.load(); const handler = new UniversalSwapHandler( { sender: { cosmos, evm, tron }, @@ -111,7 +118,8 @@ export const swapEvmToOraichain = async (data: { simulateAmount, userSlippage }, - { cosmosWallet, evmWallet } + { cosmosWallet, evmWallet }, + oraidexCommon ); return handler.processUniversalSwap() as Promise; };