From f5880ff043da6ac72b697e346774d586dcd95018 Mon Sep 17 00:00:00 2001 From: chyngyz Date: Wed, 17 Feb 2021 14:55:16 +0600 Subject: [PATCH] Add PancakeSwap support to UniswapKit --- .../ethereumkit/sample/MainViewModel.kt | 8 ++++--- .../uniswapkit/TokenFactory.kt | 15 ++++++------ .../uniswapkit/TradeManager.kt | 24 +++++++++++++------ .../uniswapkit/UniswapKit.kt | 2 +- .../uniswapkit/models/Pair.kt | 24 ++++++++++++++++--- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/io/horizontalsystems/ethereumkit/sample/MainViewModel.kt b/app/src/main/java/io/horizontalsystems/ethereumkit/sample/MainViewModel.kt index 9655ee57..b7eabcc0 100644 --- a/app/src/main/java/io/horizontalsystems/ethereumkit/sample/MainViewModel.kt +++ b/app/src/main/java/io/horizontalsystems/ethereumkit/sample/MainViewModel.kt @@ -31,7 +31,7 @@ class MainViewModel : ViewModel() { private val bscScanKey = "5ZGSHWYHZVA8XZHB8PF6UUTRNNB4KT43ZZ" private val walletId = "walletId" private val networkType: NetworkType = NetworkType.BscMainNet - private val webSocket = false + private val webSocket = true private val words = "mom year father track attend frown loyal goddess crisp abandon juice roof".split(" ") private val disposables = CompositeDisposable() @@ -62,14 +62,16 @@ class MainViewModel : ViewModel() { val swapStatus = SingleLiveEvent() val tokens = listOf( - Erc20Token("CAKE", "CAKE", Address("0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82"), 18), + Erc20Token("PancakeSwap", "CAKE", Address("0x0e09fabb73bd3ade0a17ecc321fd13a19e81ce82"), 18), //BEP20 + Erc20Token("Beefy.Finance", "BIFI", Address("0xCa3F508B8e4Dd382eE878A314789373D80A5190A"), 18), //BEP20 + Erc20Token("DAI", "DAI", Address("0xad6d458402f60fd3bd25163575031acdce07538d"), 18), Erc20Token("GMO coins", "GMOLW", Address("0xbb74a24d83470f64d5f0c01688fbb49a5a251b32"), 18), Erc20Token("USDT", "USDT", Address("0xdAC17F958D2ee523a2206206994597C13D831ec7"), 6), Erc20Token("DAI-MAINNET", "DAI", Address("0x6b175474e89094c44da98b954eedeac495271d0f"), 18) ) val fromToken: Erc20Token? = tokens[0] - val toToken: Erc20Token? = null//tokens[0] + val toToken: Erc20Token? = tokens[1] fun init() { ethereumKit = createKit() diff --git a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TokenFactory.kt b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TokenFactory.kt index 706c559f..191dd078 100644 --- a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TokenFactory.kt +++ b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TokenFactory.kt @@ -1,10 +1,10 @@ package io.horizontalsystems.uniswapkit -import io.horizontalsystems.ethereumkit.core.EthereumKit +import io.horizontalsystems.ethereumkit.core.EthereumKit.NetworkType import io.horizontalsystems.ethereumkit.models.Address import io.horizontalsystems.uniswapkit.models.Token -class TokenFactory(networkType: EthereumKit.NetworkType) { +class TokenFactory(networkType: NetworkType) { private val wethAddress = wethAddress(networkType) fun etherToken(): Token { @@ -16,12 +16,13 @@ class TokenFactory(networkType: EthereumKit.NetworkType) { } companion object { - private fun wethAddress(networkType: EthereumKit.NetworkType): Address { + private fun wethAddress(networkType: NetworkType): Address { val wethAddressHex = when (networkType) { - EthereumKit.NetworkType.EthMainNet -> "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" - EthereumKit.NetworkType.EthRopsten -> "0xc778417e063141139fce010982780140aa0cd5ab" - EthereumKit.NetworkType.EthKovan -> "0xd0A1E359811322d97991E03f863a0C30C2cF029C" - else -> "0xc778417e063141139fce010982780140aa0cd5ab" + NetworkType.EthMainNet -> "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" + NetworkType.EthRopsten -> "0xc778417e063141139fce010982780140aa0cd5ab" + NetworkType.EthKovan -> "0xd0A1E359811322d97991E03f863a0C30C2cF029C" + NetworkType.EthRinkeby -> "0xc778417e063141139fce010982780140aa0cd5ab" + NetworkType.BscMainNet -> "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c" } return Address(wethAddressHex) } diff --git a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TradeManager.kt b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TradeManager.kt index 0ef0c7ea..f3238ab5 100644 --- a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TradeManager.kt +++ b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/TradeManager.kt @@ -2,9 +2,9 @@ package io.horizontalsystems.uniswapkit import io.horizontalsystems.ethereumkit.contracts.ContractMethod import io.horizontalsystems.ethereumkit.core.EthereumKit +import io.horizontalsystems.ethereumkit.core.EthereumKit.NetworkType import io.horizontalsystems.ethereumkit.core.toHexString import io.horizontalsystems.ethereumkit.models.Address -import io.horizontalsystems.ethereumkit.models.Transaction import io.horizontalsystems.ethereumkit.models.TransactionData import io.horizontalsystems.uniswapkit.contract.* import io.horizontalsystems.uniswapkit.models.* @@ -16,20 +16,22 @@ import java.util.* import java.util.logging.Logger class TradeManager( - private val ethereumKit: EthereumKit + private val evmKit: EthereumKit ) { - private val address: Address = ethereumKit.receiveAddress + private val address: Address = evmKit.receiveAddress private val logger = Logger.getLogger(this.javaClass.simpleName) + val routerAddress: Address = getRouterAddress(evmKit.networkType) + fun pair(tokenA: Token, tokenB: Token): Single { val (token0, token1) = if (tokenA.sortsBefore(tokenB)) Pair(tokenA, tokenB) else Pair(tokenB, tokenA) - val pairAddress = Pair.address(token0, token1) + val pairAddress = Pair.address(token0, token1, evmKit.networkType) logger.info("pairAddress: ${pairAddress.hex}") - return ethereumKit.call(pairAddress, GetReservesMethod().encodedABI()) + return evmKit.call(pairAddress, GetReservesMethod().encodedABI()) .map { data -> logger.info("getReserves data: ${data.toHexString()}") @@ -59,7 +61,7 @@ class TradeManager( fun estimateSwap(tradeData: TradeData, gasPrice: Long): Single { val swapData = buildSwapData(tradeData) - return ethereumKit.estimateGas( + return evmKit.estimateGas( to = routerAddress, value = if (swapData.amount == BigInteger.ZERO) null else swapData.amount, gasPrice = gasPrice, @@ -139,7 +141,15 @@ class TradeManager( } companion object { - val routerAddress = Address("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D") + + private fun getRouterAddress(networkType: NetworkType) = + when (networkType) { + NetworkType.EthMainNet, + NetworkType.EthRopsten, + NetworkType.EthKovan, + NetworkType.EthRinkeby -> Address("0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D") + NetworkType.BscMainNet -> Address("0x05fF2B0DB69458A0750badebc4f9e13aDd608C7F") + } fun tradeExactIn(pairs: List, tokenAmountIn: TokenAmount, tokenOut: Token, maxHops: Int = 3, currentPairs: List = listOf(), originalTokenAmountIn: TokenAmount? = null): List { //todo validations diff --git a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/UniswapKit.kt b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/UniswapKit.kt index 1e7c9371..ed657156 100644 --- a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/UniswapKit.kt +++ b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/UniswapKit.kt @@ -16,7 +16,7 @@ class UniswapKit( private val logger = Logger.getLogger(this.javaClass.simpleName) val routerAddress: Address - get() = TradeManager.routerAddress + get() = tradeManager.routerAddress fun etherToken(): Token { return tokenFactory.etherToken() diff --git a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/models/Pair.kt b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/models/Pair.kt index 6a538fdd..101afd28 100644 --- a/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/models/Pair.kt +++ b/uniswapkit/src/main/java/io/horizontalsystems/uniswapkit/models/Pair.kt @@ -1,5 +1,6 @@ package io.horizontalsystems.uniswapkit.models +import io.horizontalsystems.ethereumkit.core.EthereumKit.NetworkType import io.horizontalsystems.ethereumkit.core.hexStringToByteArray import io.horizontalsystems.ethereumkit.crypto.CryptoUtils import io.horizontalsystems.ethereumkit.models.Address @@ -81,11 +82,28 @@ class Pair( } companion object { - fun address(token0: Token, token1: Token): Address { + fun address(token0: Token, token1: Token, networkType: NetworkType): Address { + val factoryAddress: String + val initCodeHash: String + + when (networkType) { + NetworkType.EthMainNet, + NetworkType.EthRopsten, + NetworkType.EthKovan, + NetworkType.EthRinkeby -> { + factoryAddress = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f" + initCodeHash = "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f" + } + NetworkType.BscMainNet -> { + factoryAddress = "0xBCfCcbde45cE874adCB698cC183deBcF17952812" + initCodeHash = "0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66" + } + } + val data = "0xff".hexStringToByteArray() + - "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f".hexStringToByteArray() + + factoryAddress.hexStringToByteArray() + CryptoUtils.sha3(token0.address.raw + token1.address.raw) + - "0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f".hexStringToByteArray() + initCodeHash.hexStringToByteArray() return Address(CryptoUtils.sha3(data).copyOfRange(12, 32)) }