From 9948fc637c5a31ae43a3faf57c479b4525df6c1a Mon Sep 17 00:00:00 2001 From: Kirill Demidov Date: Thu, 7 Sep 2023 13:05:37 +0300 Subject: [PATCH 1/3] add fusionX dex --- package.json | 2 +- .../uniswap-v3-trade-providers.ts | 2 + .../common/models/on-chain-trade-type.ts | 2 + .../fusionx-uniswap-v3-quoter-controller.ts | 212 ++++++++++++ .../models/liquidity-pool.ts | 2 +- .../models/unwrapWethMethodName.ts | 2 +- .../constants/provider-configuration.ts | 8 + .../fusionx/constants/router-configuration.ts | 312 ++++++++++++++++++ .../dexes/mantle/fusionx/fusionx-provider.ts | 21 ++ .../dexes/mantle/fusionx/fusionx-trade.ts | 19 ++ .../constants/quoter-contract-data.ts | 86 +++++ 11 files changed, 665 insertions(+), 3 deletions(-) create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/fusionx-uniswap-v3-quoter-controller.ts create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration.ts create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-provider.ts create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-trade.ts create mode 100644 src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/utils/quoter-controller/constants/quoter-contract-data.ts diff --git a/package.json b/package.json index 4c14a42c6a..e6ab77025b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rubic-sdk", - "version": "4.26.0", + "version": "4.27.0-alpha-fusionx.0", "description": "Simplify dApp creation", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/features/on-chain/calculation-manager/constants/trade-providers/uniswap-v3-trade-providers.ts b/src/features/on-chain/calculation-manager/constants/trade-providers/uniswap-v3-trade-providers.ts index cf0282f95d..bfa2fc5bcb 100644 --- a/src/features/on-chain/calculation-manager/constants/trade-providers/uniswap-v3-trade-providers.ts +++ b/src/features/on-chain/calculation-manager/constants/trade-providers/uniswap-v3-trade-providers.ts @@ -2,6 +2,7 @@ import { UniSwapV3ArbitrumProvider } from 'src/features/on-chain/calculation-man import { UniSwapV3EthereumProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/ethereum/uni-swap-v3-ethereum/uni-swap-v3-ethereum-provider'; import { UniSwapV3EthereumPowProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/ethereum-pow/uni-swap-v3-ethereum-pow/uni-swap-v3-ethereum-pow-provider'; import { HorizondexProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/linea/horizondex/horizondex-provider'; +import { FusionXProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-provider'; import { UniSwapV3PolygonProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/polygon/uni-swap-v3-polygon/uni-swap-v3-polygon-provider'; import { UniSwapV3PulsechainProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/pulsechain/uni-swap-v3-pulsechain/uni-swap-v3-ethereum-provider'; import { UniSwapV3ScrollSepoliaProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/scroll-sepolia/uni-swap-v3-scroll-sepolia/uni-swap-v3-scroll-sepolia-provider'; @@ -13,5 +14,6 @@ export const UniswapV3TradeProviders = [ UniSwapV3EthereumPowProvider, UniSwapV3PulsechainProvider, HorizondexProvider, + FusionXProvider, UniSwapV3ScrollSepoliaProvider ] as const; diff --git a/src/features/on-chain/calculation-manager/providers/common/models/on-chain-trade-type.ts b/src/features/on-chain/calculation-manager/providers/common/models/on-chain-trade-type.ts index 64ebac89f2..700928a7bb 100644 --- a/src/features/on-chain/calculation-manager/providers/common/models/on-chain-trade-type.ts +++ b/src/features/on-chain/calculation-manager/providers/common/models/on-chain-trade-type.ts @@ -36,6 +36,8 @@ export const ON_CHAIN_TRADE_TYPE = { ELK: 'ELK', + FUSIONX: 'FUSIONX', + HONEY_SWAP: 'HONEY_SWAP', HORIZONDEX: 'HORIZONDEX', diff --git a/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/fusionx-uniswap-v3-quoter-controller.ts b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/fusionx-uniswap-v3-quoter-controller.ts new file mode 100644 index 0000000000..f68372649f --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/fusionx-uniswap-v3-quoter-controller.ts @@ -0,0 +1,212 @@ +import BigNumber from 'bignumber.js'; +import { RubicSdkError } from 'src/common/errors'; +import { Token } from 'src/common/tokens'; +import { compareAddresses } from 'src/common/utils/blockchain'; +import { Cache } from 'src/common/utils/decorators'; +import { notNull } from 'src/common/utils/object'; +import { EvmBlockchainName } from 'src/core/blockchain/models/blockchain-name'; +import { MethodData } from 'src/core/blockchain/web3-public-service/web3-public/models/method-data'; +import { Exact } from 'src/features/on-chain/calculation-manager/providers/common/on-chain-trade/evm-on-chain-trade/models/exact'; +import { UniswapV3Route } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/models/uniswap-v3-route'; +import { UniswapV3RouterConfiguration } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/models/uniswap-v3-router-configuration'; +import { + FeeAmount, + LiquidityPool +} from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/models/liquidity-pool'; +import { UniswapV3QuoterController } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/uniswap-v3-quoter-controller'; +import { FUSIONX_UNISWAP_V3_FACTORY_CONTRACT_ADDRESS } from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration'; +import { + FUSIONX_QUOTER_CONTRACT_ABI, + FUSIONX_QUOTER_CONTRACT_ADDRESS +} from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/utils/quoter-controller/constants/quoter-contract-data'; + +interface GetQuoterMethodsDataOptions { + routesLiquidityPools: LiquidityPool[]; + from: Token; + to: Token; + exact: Exact; + weiAmount: string; + maxTransitTokens: number; +} +export class FusionXUniswapV3QuoterController extends UniswapV3QuoterController { + protected readonly feeAmounts: FeeAmount[] = [100, 500, 10000]; + + constructor( + blockchain: EvmBlockchainName, + routerConfiguration: UniswapV3RouterConfiguration + ) { + super( + blockchain, + routerConfiguration, + FUSIONX_QUOTER_CONTRACT_ADDRESS, + FUSIONX_QUOTER_CONTRACT_ABI, + FUSIONX_UNISWAP_V3_FACTORY_CONTRACT_ADDRESS + ); + } + + /** + * Returns swap method's name and arguments to pass it to Quoter contract. + * @param poolsPath Pools, included in the route. + * @param from From token. + * @param to To token. + * @param exact Is exact input or output trade. + * @param weiAmount Amount of tokens to trade. + */ + @Cache + protected static getQuoterMethodData( + poolsPath: LiquidityPool[], + from: Token, + to: Token, + exact: Exact, + weiAmount: string + ): { + poolsPath: LiquidityPool[]; + methodData: MethodData; + } { + if (poolsPath.length === 1 && poolsPath?.[0]) { + const methodName = + exact === 'input' ? 'quoteExactInputSingle' : 'quoteExactOutputSingle'; + const sqrtPriceLimitX96 = 0; + return { + poolsPath, + methodData: { + methodName, + methodArguments: [ + from.address, + to.address, + weiAmount, + poolsPath[0].fee, + sqrtPriceLimitX96 + ] + } + }; + } + + const methodName = exact === 'input' ? 'quoteExactInput' : 'quoteExactOutput'; + const tokensPath = exact === 'input' ? poolsPath : poolsPath.reverse(); + const initialTokenAddress = exact === 'input' ? from.address : to.address; + return { + poolsPath, + methodData: { + methodName, + methodArguments: [ + UniswapV3QuoterController.getEncodedPoolsPath(tokensPath, initialTokenAddress), + weiAmount + ] + } + }; + } + + public async getAllRoutes( + from: Token, + to: Token, + exact: Exact, + weiAmount: string, + routeMaxTransitTokens: number + ): Promise { + const routesLiquidityPools = await this.getAllLiquidityPools(from, to); + const options: Omit = { + routesLiquidityPools, + from, + to, + exact, + weiAmount + }; + const quoterMethodsData = [...Array(routeMaxTransitTokens + 1)] + .map((_, maxTransitTokens) => + this.getQuoterMethodsData( + { + ...options, + maxTransitTokens + }, + [], + from.address + ) + ) + .flat(); + + const results = await this.web3Public.multicallContractMethods< + string | { returnedAmount: string } + >( + this.quoterContractAddress, + this.quoterContractABI, + quoterMethodsData.map(quoterMethodData => { + if (quoterMethodData.methodData.methodName.toLowerCase().includes('single')) { + return { + methodName: quoterMethodData.methodData.methodName, + methodArguments: [quoterMethodData.methodData.methodArguments] + }; + } + + return quoterMethodData.methodData; + }) + ); + + return results + .map((result, index) => { + const pool = quoterMethodsData?.[index]; + if (!pool) { + throw new RubicSdkError('Pool has to be defined'); + } + if (result.success) { + return { + outputAbsoluteAmount: new BigNumber( + result?.output! instanceof Object + ? result?.output?.returnedAmount + : result.output! + ), + poolsPath: pool.poolsPath, + initialTokenAddress: from.address + }; + } + return null; + }) + .filter(notNull); + } + + /** + * Returns swap methods' names and arguments, built with passed pools' addresses, to use it in Quoter contract. + */ + protected getQuoterMethodsData( + options: GetQuoterMethodsDataOptions, + path: LiquidityPool[], + lastTokenAddress: string + ): { poolsPath: LiquidityPool[]; methodData: MethodData }[] { + const { routesLiquidityPools, from, to, exact, weiAmount, maxTransitTokens } = options; + + if (path.length === maxTransitTokens) { + const pools = routesLiquidityPools.filter(pool => + pool.isPoolWithTokens(lastTokenAddress, to.address) + ); + return pools.map(pool => + FusionXUniswapV3QuoterController.getQuoterMethodData( + path.concat(pool), + from, + to, + exact, + weiAmount + ) + ); + } + + return routesLiquidityPools + .filter(pool => !path.includes(pool)) + .map(pool => { + const methodsData: { poolsPath: LiquidityPool[]; methodData: MethodData }[] = []; + if (compareAddresses(pool.token0.address, lastTokenAddress)) { + const extendedPath = path.concat(pool); + methodsData.push( + ...this.getQuoterMethodsData(options, extendedPath, pool.token1.address) + ); + } + if (compareAddresses(pool.token1.address, lastTokenAddress)) { + const extendedPath = path.concat(pool); + methodsData.push( + ...this.getQuoterMethodsData(options, extendedPath, pool.token0.address) + ); + } + return methodsData; + }) + .flat(); + } +} diff --git a/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/models/liquidity-pool.ts b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/models/liquidity-pool.ts index 585df15379..a6a97e278c 100644 --- a/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/models/liquidity-pool.ts +++ b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/models/liquidity-pool.ts @@ -1,7 +1,7 @@ import { Token } from 'src/common/tokens'; import { compareAddresses } from 'src/common/utils/blockchain'; -export type FeeAmount = 8 | 40 | 300 | 500 | 1000 | 3000 | 10000; +export type FeeAmount = 8 | 40 | 100 | 300 | 500 | 1000 | 3000 | 10000; /** * Represents liquidity pool in uni v3. diff --git a/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-algebra-abstract/models/unwrapWethMethodName.ts b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-algebra-abstract/models/unwrapWethMethodName.ts index f49bcc9416..b6b1568ed2 100644 --- a/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-algebra-abstract/models/unwrapWethMethodName.ts +++ b/src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-algebra-abstract/models/unwrapWethMethodName.ts @@ -1 +1 @@ -export type UnwrapWethMethodName = 'unwrapWETH9' | 'unwrapWNativeToken' | 'unwrapWeth'; +export type UnwrapWethMethodName = 'unwrapWETH9' | 'unwrapWNativeToken' | 'unwrapWeth' | 'WETH9'; diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts new file mode 100644 index 0000000000..36311a880d --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts @@ -0,0 +1,8 @@ +import { wrappedNativeTokensList } from 'src/common/tokens'; +import { BLOCKCHAIN_NAME } from 'src/core/blockchain/models/blockchain-name'; +import { UniswapV3AlgebraProviderConfiguration } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-algebra-abstract/models/uniswap-v3-algebra-provider-configuration'; + +export const FUSIONX_PROVIDER_CONFIGURATION: UniswapV3AlgebraProviderConfiguration = { + wethAddress: wrappedNativeTokensList[BLOCKCHAIN_NAME.MANTLE]!.address, + maxTransitTokens: 1 +}; diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration.ts new file mode 100644 index 0000000000..3409f00d09 --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration.ts @@ -0,0 +1,312 @@ +import { wrappedNativeTokensList } from 'src/common/tokens'; +import { BLOCKCHAIN_NAME } from 'src/core/blockchain/models/blockchain-name'; +import { + UniswapV3RouterConfiguration, + UniswapV3RouterLiquidityPool +} from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/models/uniswap-v3-router-configuration'; +import { AbiItem } from 'web3-utils'; + +/** + * Most popular tokens in uni v3 to use in a route. + */ +const tokensSymbols = ['WETH', 'WMNT', 'USDT', 'USDC', 'WBTC', 'MINU'] as const; + +type TokenSymbol = (typeof tokensSymbols)[number]; + +const routerTokens: Record = { + WMNT: wrappedNativeTokensList[BLOCKCHAIN_NAME.MANTLE]!.address, + WETH: '0xdEAddEaDdeadDEadDEADDEAddEADDEAddead1111', + USDT: '0x201EBa5CC46D216Ce6DC03F6a759e8E766e956aE', + USDC: '0x09bc4e0d864854c6afb6eb9a9cdf58ac190d0df9', + WBTC: '0xcabae6f6ea1ecab08ad02fe02ce9a44f09aebfa2', + MINU: '0x51cfe5b1e764dc253f4c8c1f19a081ff4c3517ed' +}; + +const routerLiquidityPools: UniswapV3RouterLiquidityPool[] = [ + { + poolAddress: '0xa125af1a4704044501fe12ca9567ef1550e430e8', + tokenSymbolA: 'USDT', + tokenSymbolB: 'WETH', + fee: 500 + }, + { + poolAddress: '0x262255f4770aebe2d0c8b97a46287dcecc2a0aff', + tokenSymbolA: 'USDT', + tokenSymbolB: 'WMNT', + fee: 500 + }, + { + poolAddress: '0x16867d00d45347a2ded25b8cdb7022b3171d4ae0', + tokenSymbolA: 'USDC', + tokenSymbolB: 'USDT', + fee: 100 + }, + { + poolAddress: '0xb11d56e78076df5b4fea0f3f9f1febdb043fabf3', + tokenSymbolA: 'USDT', + tokenSymbolB: 'WBTC', + fee: 500 + }, + { + poolAddress: '0x3bfb98c0af1aca0e66d96624c7e545eb131f285e', + tokenSymbolA: 'MINU', + tokenSymbolB: 'WMNT', + fee: 10000 + }, + { + poolAddress: '0xb1d9358e08391e93593c6a1899dc77931912bb16', + tokenSymbolA: 'USDT', + tokenSymbolB: 'MINU', + fee: 10000 + } +]; + +export const FUSIONX_ROUTER_CONFIGURATION: UniswapV3RouterConfiguration = { + tokens: routerTokens, + liquidityPools: routerLiquidityPools +}; + +export const FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ADDRESS = + '0x5989FB161568b9F133eDf5Cf6787f5597762797F'; +export const FUSIONX_UNISWAP_V3_FACTORY_CONTRACT_ADDRESS = + '0x530d2766D1988CC1c000C8b7d00334c14B69AD71'; + +export const FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ABI = [ + { + type: 'constructor', + inputs: [ + { type: 'address', name: '_deployer', internalType: 'address' }, + { type: 'address', name: '_factory', internalType: 'address' }, + { type: 'address', name: '_WETH9', internalType: 'address' } + ] + }, + { + type: 'function', + stateMutability: 'view', + outputs: [{ type: 'address', name: '', internalType: 'address' }], + name: 'WETH9', + inputs: [] + }, + { + type: 'function', + stateMutability: 'view', + outputs: [{ type: 'address', name: '', internalType: 'address' }], + name: 'deployer', + inputs: [] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [{ type: 'uint256', name: 'amountOut', internalType: 'uint256' }], + name: 'exactInput', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct ISwapRouter.ExactInputParams', + components: [ + { type: 'bytes' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' } + ] + } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [{ type: 'uint256', name: 'amountOut', internalType: 'uint256' }], + name: 'exactInputSingle', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct ISwapRouter.ExactInputSingleParams', + components: [ + { type: 'address' }, + { type: 'address' }, + { type: 'uint24' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint160' } + ] + } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [{ type: 'uint256', name: 'amountIn', internalType: 'uint256' }], + name: 'exactOutput', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct ISwapRouter.ExactOutputParams', + components: [ + { type: 'bytes' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' } + ] + } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [{ type: 'uint256', name: 'amountIn', internalType: 'uint256' }], + name: 'exactOutputSingle', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct ISwapRouter.ExactOutputSingleParams', + components: [ + { type: 'address' }, + { type: 'address' }, + { type: 'uint24' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint256' }, + { type: 'uint160' } + ] + } + ] + }, + { + type: 'function', + stateMutability: 'view', + outputs: [{ type: 'address', name: '', internalType: 'address' }], + name: 'factory', + inputs: [] + }, + { + type: 'function', + stateMutability: 'nonpayable', + outputs: [], + name: 'fusionXV3SwapCallback', + inputs: [ + { type: 'int256', name: 'amount0Delta', internalType: 'int256' }, + { type: 'int256', name: 'amount1Delta', internalType: 'int256' }, + { type: 'bytes', name: '_data', internalType: 'bytes' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [{ type: 'bytes[]', name: 'results', internalType: 'bytes[]' }], + name: 'multicall', + inputs: [{ type: 'bytes[]', name: 'data', internalType: 'bytes[]' }] + }, + { type: 'function', stateMutability: 'payable', outputs: [], name: 'refundETH', inputs: [] }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'selfPermit', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'value', internalType: 'uint256' }, + { type: 'uint256', name: 'deadline', internalType: 'uint256' }, + { type: 'uint8', name: 'v', internalType: 'uint8' }, + { type: 'bytes32', name: 'r', internalType: 'bytes32' }, + { type: 'bytes32', name: 's', internalType: 'bytes32' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'selfPermitAllowed', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'nonce', internalType: 'uint256' }, + { type: 'uint256', name: 'expiry', internalType: 'uint256' }, + { type: 'uint8', name: 'v', internalType: 'uint8' }, + { type: 'bytes32', name: 'r', internalType: 'bytes32' }, + { type: 'bytes32', name: 's', internalType: 'bytes32' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'selfPermitAllowedIfNecessary', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'nonce', internalType: 'uint256' }, + { type: 'uint256', name: 'expiry', internalType: 'uint256' }, + { type: 'uint8', name: 'v', internalType: 'uint8' }, + { type: 'bytes32', name: 'r', internalType: 'bytes32' }, + { type: 'bytes32', name: 's', internalType: 'bytes32' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'selfPermitIfNecessary', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'value', internalType: 'uint256' }, + { type: 'uint256', name: 'deadline', internalType: 'uint256' }, + { type: 'uint8', name: 'v', internalType: 'uint8' }, + { type: 'bytes32', name: 'r', internalType: 'bytes32' }, + { type: 'bytes32', name: 's', internalType: 'bytes32' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'sweepToken', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'amountMinimum', internalType: 'uint256' }, + { type: 'address', name: 'recipient', internalType: 'address' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'sweepTokenWithFee', + inputs: [ + { type: 'address', name: 'token', internalType: 'address' }, + { type: 'uint256', name: 'amountMinimum', internalType: 'uint256' }, + { type: 'address', name: 'recipient', internalType: 'address' }, + { type: 'uint256', name: 'feeBips', internalType: 'uint256' }, + { type: 'address', name: 'feeRecipient', internalType: 'address' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'unwrapWETH9', + inputs: [ + { type: 'uint256', name: 'amountMinimum', internalType: 'uint256' }, + { type: 'address', name: 'recipient', internalType: 'address' } + ] + }, + { + type: 'function', + stateMutability: 'payable', + outputs: [], + name: 'unwrapWETH9WithFee', + inputs: [ + { type: 'uint256', name: 'amountMinimum', internalType: 'uint256' }, + { type: 'address', name: 'recipient', internalType: 'address' }, + { type: 'uint256', name: 'feeBips', internalType: 'uint256' }, + { type: 'address', name: 'feeRecipient', internalType: 'address' } + ] + }, + { type: 'receive' } +] as AbiItem[]; diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-provider.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-provider.ts new file mode 100644 index 0000000000..cf94250c01 --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-provider.ts @@ -0,0 +1,21 @@ +import { BLOCKCHAIN_NAME } from 'src/core/blockchain/models/blockchain-name'; +import { UniswapV3AbstractProvider } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/uniswap-v3-abstract-provider'; +import { FusionXUniswapV3QuoterController } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/utils/quoter-controller/fusionx-uniswap-v3-quoter-controller'; +import { FUSIONX_PROVIDER_CONFIGURATION } from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration'; +import { FUSIONX_ROUTER_CONFIGURATION } from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration'; +import { FusionXTrade } from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-trade'; + +export class FusionXProvider extends UniswapV3AbstractProvider { + public readonly blockchain = BLOCKCHAIN_NAME.MANTLE; + + public readonly OnChainTradeClass = FusionXTrade; + + public readonly providerConfiguration = FUSIONX_PROVIDER_CONFIGURATION; + + public readonly routerConfiguration = FUSIONX_ROUTER_CONFIGURATION; + + protected readonly quoterController = new FusionXUniswapV3QuoterController( + this.blockchain, + this.routerConfiguration + ); +} diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-trade.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-trade.ts new file mode 100644 index 0000000000..22cf0229b5 --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/fusionx-trade.ts @@ -0,0 +1,19 @@ +import { + ON_CHAIN_TRADE_TYPE, + OnChainTradeType +} from 'src/features/on-chain/calculation-manager/providers/common/models/on-chain-trade-type'; +import { UniswapV3AbstractTrade } from 'src/features/on-chain/calculation-manager/providers/dexes/common/uniswap-v3-abstract/uniswap-v3-abstract-trade'; +import { + FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ABI, + FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ADDRESS +} from 'src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/router-configuration'; + +export class FusionXTrade extends UniswapV3AbstractTrade { + public get type(): OnChainTradeType { + return ON_CHAIN_TRADE_TYPE.FUSIONX; + } + + public readonly dexContractAddress = FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ADDRESS; + + protected readonly contractAbi = FUSIONX_UNISWAP_V3_SWAP_ROUTER_CONTRACT_ABI; +} diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/utils/quoter-controller/constants/quoter-contract-data.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/utils/quoter-controller/constants/quoter-contract-data.ts new file mode 100644 index 0000000000..ade7f9d30d --- /dev/null +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/utils/quoter-controller/constants/quoter-contract-data.ts @@ -0,0 +1,86 @@ +import { AbiItem } from 'web3-utils'; + +export const FUSIONX_QUOTER_CONTRACT_ADDRESS = '0x90f72244294E7c5028aFd6a96E18CC2c1E913995'; + +export const FUSIONX_QUOTER_CONTRACT_ABI = [ + { + type: 'function', + stateMutability: 'nonpayable', + outputs: [ + { type: 'uint256', name: 'amountOut', internalType: 'uint256' }, + { type: 'uint160[]', name: 'sqrtPriceX96AfterList', internalType: 'uint160[]' }, + { type: 'uint32[]', name: 'initializedTicksCrossedList', internalType: 'uint32[]' }, + { type: 'uint256', name: 'gasEstimate', internalType: 'uint256' } + ], + name: 'quoteExactInput', + inputs: [ + { type: 'bytes', name: 'path', internalType: 'bytes' }, + { type: 'uint256', name: 'amountIn', internalType: 'uint256' } + ] + }, + { + type: 'function', + stateMutability: 'nonpayable', + outputs: [ + { type: 'uint256', name: 'amountOut', internalType: 'uint256' }, + { type: 'uint160', name: 'sqrtPriceX96After', internalType: 'uint160' }, + { type: 'uint32', name: 'initializedTicksCrossed', internalType: 'uint32' }, + { type: 'uint256', name: 'gasEstimate', internalType: 'uint256' } + ], + name: 'quoteExactInputSingle', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct IQuoterV2.QuoteExactInputSingleParams', + components: [ + { type: 'address' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint24' }, + { type: 'uint160' } + ] + } + ] + }, + { + type: 'function', + stateMutability: 'nonpayable', + outputs: [ + { type: 'uint256', name: 'amountIn', internalType: 'uint256' }, + { type: 'uint160[]', name: 'sqrtPriceX96AfterList', internalType: 'uint160[]' }, + { type: 'uint32[]', name: 'initializedTicksCrossedList', internalType: 'uint32[]' }, + { type: 'uint256', name: 'gasEstimate', internalType: 'uint256' } + ], + name: 'quoteExactOutput', + inputs: [ + { type: 'bytes', name: 'path', internalType: 'bytes' }, + { type: 'uint256', name: 'amountOut', internalType: 'uint256' } + ] + }, + { + type: 'function', + stateMutability: 'nonpayable', + outputs: [ + { type: 'uint256', name: 'amountIn', internalType: 'uint256' }, + { type: 'uint160', name: 'sqrtPriceX96After', internalType: 'uint160' }, + { type: 'uint32', name: 'initializedTicksCrossed', internalType: 'uint32' }, + { type: 'uint256', name: 'gasEstimate', internalType: 'uint256' } + ], + name: 'quoteExactOutputSingle', + inputs: [ + { + type: 'tuple', + name: 'params', + internalType: 'struct IQuoterV2.QuoteExactOutputSingleParams', + components: [ + { type: 'address' }, + { type: 'address' }, + { type: 'uint256' }, + { type: 'uint24' }, + { type: 'uint160' } + ] + } + ] + } +] as AbiItem[]; From 4a3ff3ad25bce891f9599387039b102a60851648 Mon Sep 17 00:00:00 2001 From: Kirill Demidov Date: Thu, 7 Sep 2023 14:55:07 +0300 Subject: [PATCH 2/3] upd transit token --- package.json | 2 +- .../dexes/mantle/fusionx/constants/provider-configuration.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e6ab77025b..c4d945e519 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rubic-sdk", - "version": "4.27.0-alpha-fusionx.0", + "version": "4.27.0-alpha-fusionx.1", "description": "Simplify dApp creation", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts index 36311a880d..6318fb215c 100644 --- a/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts +++ b/src/features/on-chain/calculation-manager/providers/dexes/mantle/fusionx/constants/provider-configuration.ts @@ -4,5 +4,5 @@ import { UniswapV3AlgebraProviderConfiguration } from 'src/features/on-chain/cal export const FUSIONX_PROVIDER_CONFIGURATION: UniswapV3AlgebraProviderConfiguration = { wethAddress: wrappedNativeTokensList[BLOCKCHAIN_NAME.MANTLE]!.address, - maxTransitTokens: 1 + maxTransitTokens: 2 }; From 5e2d6d9f1c6625fee0f7e4abf7c6596f569b8353 Mon Sep 17 00:00:00 2001 From: Kirill Demidov Date: Fri, 8 Sep 2023 11:47:35 +0300 Subject: [PATCH 3/3] set prod version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4d945e519..c5cb58e08e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rubic-sdk", - "version": "4.27.0-alpha-fusionx.1", + "version": "4.27.0", "description": "Simplify dApp creation", "main": "lib/index.js", "types": "lib/index.d.ts",