Skip to content

Commit

Permalink
Implement fetching token info from node via rpc call
Browse files Browse the repository at this point in the history
  • Loading branch information
abdrasulov committed Jan 23, 2023
1 parent 502913f commit 7aadf9d
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.horizontalsystems.erc20kit.contract

import io.horizontalsystems.ethereumkit.contracts.ContractMethod

class DecimalsMethod: ContractMethod() {
override var methodSignature = "decimals()"
override fun getArguments() = listOf<Any>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.horizontalsystems.erc20kit.contract

import io.horizontalsystems.ethereumkit.contracts.ContractMethod

class NameMethod: ContractMethod() {
override var methodSignature = "name()"
override fun getArguments() = listOf<Any>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.horizontalsystems.erc20kit.contract

import io.horizontalsystems.ethereumkit.contracts.ContractMethod

class SymbolMethod: ContractMethod() {
override var methodSignature = "symbol()"
override fun getArguments() = listOf<Any>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package io.horizontalsystems.erc20kit.core

import io.horizontalsystems.erc20kit.contract.DecimalsMethod
import io.horizontalsystems.erc20kit.contract.NameMethod
import io.horizontalsystems.erc20kit.contract.SymbolMethod
import io.horizontalsystems.erc20kit.events.TokenInfo
import io.horizontalsystems.ethereumkit.api.core.IRpcApiProvider
import io.horizontalsystems.ethereumkit.api.core.RpcBlockchain
import io.horizontalsystems.ethereumkit.contracts.ContractMethodHelper
import io.horizontalsystems.ethereumkit.core.EthereumKit
import io.horizontalsystems.ethereumkit.models.Address
import io.horizontalsystems.ethereumkit.models.DefaultBlockParameter
import io.horizontalsystems.ethereumkit.models.RpcSource
import io.horizontalsystems.ethereumkit.spv.core.toBigInteger
import io.reactivex.Single

class Eip20Provider(private val provider: IRpcApiProvider) {

class TokenNotFoundException : Throwable()

fun getTokenInfo(contractAddress: Address): Single<TokenInfo> {
val nameSingle = getTokenName(contractAddress)
val symbolSingle = getTokenSymbol(contractAddress)
val decimalsSingle = getDecimals(contractAddress)

return Single
.zip(nameSingle, symbolSingle, decimalsSingle) { name, symbol, decimals ->
TokenInfo(name, symbol, decimals)
}
}

private fun getDecimals(contractAddress: Address): Single<Int> {
val callRpc = RpcBlockchain.callRpc(
contractAddress,
DecimalsMethod().encodedABI(),
DefaultBlockParameter.Latest
)

return provider.single(callRpc)
.map {
if (it.isEmpty()) throw TokenNotFoundException()

it.sliceArray(IntRange(0, 31)).toBigInteger().toInt()
}
}

private fun getTokenSymbol(contractAddress: Address): Single<String> {
val callRpc = RpcBlockchain.callRpc(
contractAddress,
SymbolMethod().encodedABI(),
DefaultBlockParameter.Latest
)

return provider.single(callRpc)
.map {
if (it.isEmpty()) throw TokenNotFoundException()

val argumentTypes = listOf(ByteArray::class)

val parsedArguments = ContractMethodHelper.decodeABI(it, argumentTypes)
val stringBytes = parsedArguments[0] as? ByteArray ?: throw TokenNotFoundException()

String(stringBytes)
}
}

private fun getTokenName(contractAddress: Address): Single<String> {
val callRpc = RpcBlockchain.callRpc(
contractAddress,
NameMethod().encodedABI(),
DefaultBlockParameter.Latest
)

return provider.single(callRpc)
.map {
if (it.isEmpty()) throw TokenNotFoundException()

val argumentTypes = listOf(ByteArray::class)

val parsedArguments = ContractMethodHelper.decodeABI(it, argumentTypes)
val stringBytes = parsedArguments[0] as? ByteArray ?: throw TokenNotFoundException()

String(stringBytes)
}
}

companion object {

fun instance(rpcSource: RpcSource.Http): Eip20Provider {
return Eip20Provider(EthereumKit.getNodeApiProvider(rpcSource))
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ class TransferEventInstance(
}
}

class TokenInfo(val tokenName: String, val tokenSymbol: String, val tokenDecimal: Int)
data class TokenInfo(val tokenName: String, val tokenSymbol: String, val tokenDecimal: Int)

Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,10 @@ class EthereumKit(
EthereumDatabaseManager.clear(context, chain, walletId)
}

fun getNodeApiProvider(rpcSource: RpcSource.Http): NodeApiProvider {
return NodeApiProvider(rpcSource.urls, gson, rpcSource.auth)
}

private fun transactionProvider(transactionSource: TransactionSource, address: Address): ITransactionProvider {
when (transactionSource.type) {
is TransactionSource.SourceType.Etherscan -> {
Expand Down

0 comments on commit 7aadf9d

Please sign in to comment.