From f1da7a9f43515e22c0d5e63bd31675cb05dd651d Mon Sep 17 00:00:00 2001 From: Hoang Anh Tuan Date: Thu, 16 Feb 2023 16:52:57 +0700 Subject: [PATCH] add decimal --- .../java/com/one/web3/ktx/Web3Test.kt | 111 ++++++++++++++---- web3/src/main/java/com/one/web3/Web3.kt | 15 ++- .../decimalmulti/DecimalMultiEvmCallTask.kt | 50 ++++++++ .../task/decimalmulti/DecimalMultiTask.kt | 8 ++ 4 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiEvmCallTask.kt create mode 100644 web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiTask.kt diff --git a/app/src/androidTest/java/com/one/web3/ktx/Web3Test.kt b/app/src/androidTest/java/com/one/web3/ktx/Web3Test.kt index ce0e32b..d2378b0 100644 --- a/app/src/androidTest/java/com/one/web3/ktx/Web3Test.kt +++ b/app/src/androidTest/java/com/one/web3/ktx/Web3Test.kt @@ -23,10 +23,31 @@ import java.util.concurrent.TimeUnit @RunWith(AndroidJUnit4::class) class Web3Test { + private var web3: Web3? = null + + private var retrofit: Retrofit? = null + private var chainList: List? = null - @Test - fun testBalanceNative() = runBlocking { + private fun getWeb3(retrofit: Retrofit): Web3 { + + if (web3 != null) { + + return web3!! + } + + return Web3(retrofit).apply { + + web3 = this + } + } + + private fun getRetrofit(): Retrofit { + + if (retrofit != null) { + + return retrofit!! + } val okHttpClient = OkHttpClient .Builder() @@ -38,58 +59,96 @@ class Web3Test { .build() - val retrofit = Retrofit.Builder() + return Retrofit.Builder() .baseUrl("https://github.com/hoanganhtuan95ptit/Web3Ktx/") .addConverterFactory(JacksonConverterFactory.create()) .client(okHttpClient) - .build() + .build().apply { + + retrofit = this + } + } + private suspend fun getChainList(retrofit: Retrofit): List { - val list = chainList ?: retrofit.create(ChainService::class.java).call("https://raw.githubusercontent.com/hoanganhtuan95ptit/config/main/chain/chains.json").apply { + if (chainList != null) { + + return chainList!! + } + + return retrofit.create(ChainService::class.java).call("https://raw.githubusercontent.com/hoanganhtuan95ptit/config/main/chain/chains.json").apply { chainList = this } + } + @Test + fun testDecimalMulti() = runBlocking { - list.map { chain -> + val retrofit = getRetrofit() + + val list = getChainList(retrofit) + + + val tokens = listOf("0x0000000000085d4780b73119b644ae5ecd22b376", "0x028171bca77440897b824ca71d1c56cac55b68a3") + + list.first().let { chain -> val rpcUrls = chain.urls.filter { it.type == "PRC" }.sortedByDescending { it.priority }.map { it.url } - if (rpcUrls.isEmpty()) return@map + if (rpcUrls.isEmpty()) return@let - val balance = Web3(retrofit).runCatching { balanceNative("0x8d61ab7571b117644a52240456df66ef846cd999", chain.id, rpcUrls) }.getOrNull() + val balance = getWeb3(retrofit).runCatching { - Log.d("tuanha", "testBalanceNative: chainName:${chain.name} chainId:${chain.id} - balance:$balance") + decimalMulti(tokens, "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696", chain.id, rpcUrls) + }.getOrElse { + + Log.d("tuanha", "testDecimalMulti: ", it) + null + } + + Log.d("tuanha", "testDecimalMulti: chainName:${chain.name} chainId:${chain.id} - balance:${balance.toJson()}") } Unit } @Test - fun testBalanceMulti() = runBlocking { + fun testBalanceNative() = runBlocking { - val okHttpClient = OkHttpClient - .Builder() - .readTimeout(20, TimeUnit.SECONDS) - .writeTimeout(20, TimeUnit.SECONDS) - .connectTimeout(20, TimeUnit.SECONDS) - .addInterceptor(HttpLoggingInterceptor().setLevel(if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE)) - .hostnameVerifier { _, _ -> true } - .build() + val retrofit = getRetrofit() + val list = getChainList(retrofit) - val retrofit = Retrofit.Builder() - .baseUrl("https://github.com/hoanganhtuan95ptit/Web3Ktx/") - .addConverterFactory(JacksonConverterFactory.create()) - .client(okHttpClient) - .build() + list.map { chain -> + + val rpcUrls = chain.urls.filter { it.type == "PRC" }.sortedByDescending { it.priority }.map { it.url } - val list = chainList ?: retrofit.create(ChainService::class.java).call("https://raw.githubusercontent.com/hoanganhtuan95ptit/config/main/chain/chains.json").apply { + if (rpcUrls.isEmpty()) return@map - chainList = this + val balance = getWeb3(retrofit).runCatching { + + balanceNative("0x8d61ab7571b117644a52240456df66ef846cd999", chain.id, rpcUrls) + }.getOrElse { + + Log.d("tuanha", "testBalanceNative: ", it) + null + } + + Log.d("tuanha", "testBalanceNative: chainName:${chain.name} chainId:${chain.id} - balance:$balance") } + Unit + } + + @Test + fun testBalanceMulti() = runBlocking { + + val retrofit = getRetrofit() + + val list = getChainList(retrofit) + val tokens = listOf("0x0000000000085d4780b73119b644ae5ecd22b376", "0x028171bca77440897b824ca71d1c56cac55b68a3") @@ -101,7 +160,7 @@ class Web3Test { if (rpcUrls.isEmpty()) return@let - val balance = Web3(retrofit).runCatching { + val balance = getWeb3(retrofit).runCatching { balanceMulti(tokens, wallets, "0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696", chain.id, rpcUrls) }.getOrElse { diff --git a/web3/src/main/java/com/one/web3/Web3.kt b/web3/src/main/java/com/one/web3/Web3.kt index 46ff3c6..9fdbc8c 100644 --- a/web3/src/main/java/com/one/web3/Web3.kt +++ b/web3/src/main/java/com/one/web3/Web3.kt @@ -15,6 +15,9 @@ import com.one.web3.task.decimal.DecimalCallTask import com.one.web3.task.decimal.DecimalEvmCallTask import com.one.web3.task.decimal.DecimalParam import com.one.web3.task.decimal.DecimalSolCallTask +import com.one.web3.task.decimalmulti.DecimalMultiEvmCallTask +import com.one.web3.task.decimalmulti.DecimalMultiParam +import com.one.web3.task.decimalmulti.DecimalMultiTask import com.one.web3.task.gasprice.GasPriceCallTask import com.one.web3.task.gasprice.GasPriceEvmCallTask import com.one.web3.task.gasprice.GasPriceParam @@ -25,12 +28,14 @@ import retrofit2.Retrofit import java.math.BigDecimal import java.math.BigInteger -class Web3(private val retrofit: Retrofit, private val tasks: List> = emptyList()) { +open class Web3(private val retrofit: Retrofit, private val tasks: List> = emptyList()) { val taskList: List> by lazy { arrayListOf>().apply { + add(DecimalMultiEvmCallTask(retrofit)) + add(BalanceMultiEvmCallTask(retrofit)) add(BalanceEvmCallTask(retrofit)) @@ -54,11 +59,18 @@ class Web3(private val retrofit: Retrofit, private val tasks: List(DecimalParam(tokenAddress, chainId, rpcUrls)) } + suspend fun decimalMulti(tokenAddressList: List, multiCallAddress: String, chainId: Long, rpcUrls: List): Map { + + return execute, DecimalMultiTask>(DecimalMultiParam(tokenAddressList, multiCallAddress, chainId, rpcUrls)) + } + + suspend fun gasPrice(chainId: Long, rpcUrls: List): BigInteger { return execute(GasPriceParam(chainId, rpcUrls)) } + suspend fun balance(tokenAddress: String, walletAddress: String, chainId: Long, rpcUrls: List): BigDecimal { return execute(BalanceParam(tokenAddress, walletAddress, chainId, rpcUrls)) @@ -69,6 +81,7 @@ class Web3(private val retrofit: Retrofit, private val tasks: List, BigDecimal>, BalanceMultiTask>(BalanceMultiParam(tokenAddressList, walletAddressList, multiCallAddress, chainId, rpcUrls)) } + suspend fun balanceNative(walletAddress: String, chainId: Long, rpcUrls: List): BigInteger { return execute(BalanceNativeParam(walletAddress, chainId, rpcUrls)) diff --git a/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiEvmCallTask.kt b/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiEvmCallTask.kt new file mode 100644 index 0000000..d20792d --- /dev/null +++ b/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiEvmCallTask.kt @@ -0,0 +1,50 @@ +package com.one.web3.task.decimalmulti + +import com.one.web3.task.EvmMultiCallV2 +import com.one.web3.task.decimal.functionDecimalEvmOf +import org.bouncycastle.util.encoders.Hex +import org.web3j.abi.FunctionEncoder +import org.web3j.abi.datatypes.Address +import org.web3j.abi.datatypes.DynamicBytes +import org.web3j.abi.datatypes.DynamicStruct +import org.web3j.utils.Numeric +import retrofit2.Retrofit + +class DecimalMultiEvmCallTask(private val retrofit: Retrofit) : DecimalMultiTask, EvmMultiCallV2 { + + override fun providerRetrofit(): Retrofit = retrofit + + override suspend fun executeTask(param: DecimalMultiParam): Map { + + + val staticStruct = hashMapOf() + + param.tokenAddressList.map { tokenAddress -> + + val function = functionDecimalEvmOf() + + val encodeDataOfNameFunction = FunctionEncoder.encode(function) + + val struct = DynamicStruct(Address(tokenAddress), DynamicBytes(Hex.decode(encodeDataOfNameFunction.substring(2).toByteArray()))) + + staticStruct.put(tokenAddress, struct) + } + + + val results = hashMapOf() + + readMultiCall(param.multiCallAddress, staticStruct.values.toList(), param.rpcUrls).forEachIndexed { index, result -> + + if (result.success.value != true) return@forEachIndexed + + val key = staticStruct.keys.toList().getOrNull(index) ?: return@forEachIndexed + + val value = Numeric.toBigInt(result.returnData.value).toInt() + + results[key] = value + } + + + return results + } +} diff --git a/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiTask.kt b/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiTask.kt new file mode 100644 index 0000000..50b835f --- /dev/null +++ b/web3/src/main/java/com/one/web3/task/decimalmulti/DecimalMultiTask.kt @@ -0,0 +1,8 @@ +package com.one.web3.task.decimalmulti + +import com.one.web3.Param +import com.one.web3.Web3Task + +interface DecimalMultiTask : Web3Task> + +data class DecimalMultiParam(val tokenAddressList: List, val multiCallAddress: String, override val chainId: Long, override val rpcUrls: List) : Param(chainId, rpcUrls)