Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class MainActivity : AppCompatActivity() {
}

//account test
account.getTransactions("0x2c1ba59d6f58433fb1eaee7d20b26ed83bda51a3")
account.getERC20Tokens("0x4e83362442b8d1bec281594cea3050c8eb01311c")
.observeOn(AndroidSchedulers.mainThread())
?.subscribeBy {
Log.d(TAG, "The Account Size of Transactions is: ${it.size}")
Expand Down
43 changes: 43 additions & 0 deletions etherscanapi/src/main/java/jfyg/data/ERC20Token.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package jfyg.data

import com.google.gson.annotations.SerializedName

data class ERC20Token(var blockNumber: String? = null,

var timeStamp: String? = null,

var hash: String? = null,

var nonce: String? = null,

var blockHash: String? = null,

@SerializedName("from")
var transactionFrom: String? = null,

var contractAddress: String? = null,

@SerializedName("to")
var transactionTo: String? = null,

var value: String? = null,

var tokenName: String? = null,

var tokenSymbol: String? = null,

var tokenDecimal: String? = null,

var transactionIndex: String? = null,

var gas: String? = null,

var gasPrice: String? = null,

var gasUsed: String? = null,

var cumulativeGasUsed: String? = null,

var input: String? = null,

var confirmations: String? = null)
6 changes: 3 additions & 3 deletions etherscanapi/src/main/java/jfyg/data/Txs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ data class Txs(var blockNumber: String? = null,
var transactionIndex: String? = null,

@SerializedName("from")
var transactionFrom: String? = null,
var transactionFrom: String? = null,

@SerializedName("to")
var transactionTo: String? = null,
var transactionTo: String? = null,

var value: String? = null,

Expand All @@ -29,7 +29,7 @@ data class Txs(var blockNumber: String? = null,
var isError: String? = null,

@SerializedName("txreceipt_status")
var receiptStatus: String? = null,
var receiptStatus: String? = null,

var input: String? = null,

Expand Down
22 changes: 18 additions & 4 deletions etherscanapi/src/main/java/jfyg/data/account/Account.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package jfyg.data.account
import io.reactivex.Single
import jfyg.data.Balances
import jfyg.data.Blocks
import jfyg.data.ERC20Token
import jfyg.data.Txs
import jfyg.data.TxsInternal
import jfyg.network.queries.ApiQuery
import jfyg.utils.Const
import jfyg.utils.QueryUtils

/**
Expand All @@ -16,7 +18,7 @@ class Account : AccountContract {
private val query = ApiQuery()
private val genericNetworkQuery = query.accountBalance("account",
"balance",
"0x82e4499D4b2A669831a3881d61BB24f7b620c61a",
Const.GENERIC_PUBLIC_ADDRESS,
"latest")

/**
Expand Down Expand Up @@ -50,18 +52,30 @@ class Account : AccountContract {
* Get a list of 'Normal' Transactions By Address
*/
override fun getTransactions(address: String?): Single<ArrayList<Txs>> =
query.accountTransactions("account",
query.accountTxs("account",
"txlist",
address,
"0",
"99999999",
"asc").map { it.result }

/**
* Get a list of 'Internal' Transactions by Address
* [BETA] Get a list of "ERC20 - Token Transfer Events" by Address
*/
override fun getERC20Tokens(address: String?): Single<ArrayList<ERC20Token>> =
query.accountERC20Txs("account",
"tokentx",
address,
"0",
"999999999",
"asc").map { it.result }


/**
* [BETA] Get a list of 'Internal' Transactions by Address
*/
override fun getInternalTransactions(address: String?): Single<ArrayList<TxsInternal>> =
query.accountInternalTransactions("account",
query.accountInternalTxs("account",
"txlistinternal",
address,
"0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jfyg.data.account
import io.reactivex.Single
import jfyg.data.Balances
import jfyg.data.Blocks
import jfyg.data.ERC20Token
import jfyg.data.Txs
import jfyg.data.TxsInternal

Expand Down Expand Up @@ -32,7 +33,12 @@ internal interface AccountContract {
fun getTransactions(address: String?): Single<ArrayList<Txs>>

/**
* Get a list of 'Internal' Transactions by Address
* [BETA] Get a list of "ERC20 - Token Transfer Events" by Address
*/
fun getERC20Tokens(address: String?): Single<ArrayList<ERC20Token>>

/**
* [BETA] Get a list of 'Internal' Transactions by Address
*/
fun getInternalTransactions(address: String?): Single<ArrayList<TxsInternal>>

Expand Down
3 changes: 2 additions & 1 deletion etherscanapi/src/main/java/jfyg/data/contract/ContractABI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package jfyg.data.contract

import io.reactivex.Single
import jfyg.network.queries.ApiQuery
import jfyg.utils.Const

/**
* Newly verified Contracts are synced to the API servers within 5 minutes or less
Expand All @@ -12,7 +13,7 @@ class ContractABI : ContractABIContract {
private val query = ApiQuery()
private val abiQuery = query.contractABI("contract",
"getabi",
"0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413")
Const.CONTRACT_PUBLIC_ADDRESS)

/**
* Return contract ABI for Verified Contract Source Code
Expand Down
3 changes: 2 additions & 1 deletion etherscanapi/src/main/java/jfyg/data/transaction/TxStatus.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import io.reactivex.Single
import jfyg.data.TxExecutionStatus
import jfyg.data.TxReceiptStatus
import jfyg.network.queries.ApiQuery
import jfyg.utils.Const

/**
* https://etherscan.io/apis#transactions
Expand All @@ -13,7 +14,7 @@ class TxStatus : TxStatusContract {
private val query = ApiQuery()
private val genericNetworkQuery = query.txReceiptStatus("transaction",
"getstatus",
"0x15f8e5ea1079d9a0bb04a4c58ae5fe7654b5b2b4463375ff7ffb490aa0032f3a")
Const.TRANSACTION_PUBLIC_ADDRESS)

/**
* [BETA] Check Contract Execution Status (if there was an error during contract execution)
Expand Down
10 changes: 10 additions & 0 deletions etherscanapi/src/main/java/jfyg/network/NetworkService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jfyg.network
import io.reactivex.Single
import jfyg.network.response.account.AccountBalanceResponse
import jfyg.network.response.account.AccountBlockResponse
import jfyg.network.response.account.ERC20Response
import jfyg.network.response.account.AccountInternalTxResponse
import jfyg.network.response.account.AccountMultiBalanceResponse
import jfyg.network.response.account.AccountTxResponse
Expand Down Expand Up @@ -59,6 +60,15 @@ internal interface NetworkService {
@Query("sort") sort: String?,
@Query("apikey") apikey: String?): Single<AccountTxResponse>

@GET("api")
fun getAccountERC20Transactions(@Query("module") module: String?,
@Query("action") action: String?,
@Query("address") address: String?,
@Query("startblock") startblock: String?,
@Query("endblock") endblock: String?,
@Query("sort") sort: String?,
@Query("apikey") apikey: String?): Single<ERC20Response>

@GET("api")
fun getAccountInternalTransactions(@Query("module") module: String?,
@Query("action") action: String?,
Expand Down
15 changes: 13 additions & 2 deletions etherscanapi/src/main/java/jfyg/network/queries/AccountApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package jfyg.network.queries
import io.reactivex.Single
import jfyg.network.response.account.AccountBalanceResponse
import jfyg.network.response.account.AccountBlockResponse
import jfyg.network.response.account.ERC20Response
import jfyg.network.response.account.AccountInternalTxResponse
import jfyg.network.response.account.AccountMultiBalanceResponse
import jfyg.network.response.account.AccountTxResponse
Expand Down Expand Up @@ -36,17 +37,27 @@ internal interface AccountApi {
/**
* Get a list of 'Normal' transactions by address
*/
fun accountTransactions(module: String?,
fun accountTxs(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<AccountTxResponse>

/**
* Get a list of ERC20 transactions by address
*/
fun accountERC20Txs(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<ERC20Response>

/**
* Get a list of 'Internal' transactions by address
*/
fun accountInternalTransactions(module: String?,
fun accountInternalTxs(module: String?,
action: String?,
address: String?,
startblock: String?,
Expand Down
33 changes: 21 additions & 12 deletions etherscanapi/src/main/java/jfyg/network/queries/ApiQuery.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import jfyg.ApiKey
import jfyg.network.RestClient
import jfyg.network.response.account.AccountBalanceResponse
import jfyg.network.response.account.AccountBlockResponse
import jfyg.network.response.account.ERC20Response
import jfyg.network.response.account.AccountInternalTxResponse
import jfyg.network.response.account.AccountMultiBalanceResponse
import jfyg.network.response.account.AccountTxResponse
Expand Down Expand Up @@ -38,20 +39,28 @@ internal class ApiQuery : AccountApi, StatApi, ContractABIApi, TxApi {
blocktype: String?): Single<AccountBlockResponse> =
RestClient().getQuery().getAccountBlock(module, action, address, blocktype, ApiKey.takeOff.callApiKey())

override fun accountTransactions(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<AccountTxResponse> =
override fun accountTxs(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<AccountTxResponse> =
RestClient().getQuery().getAccountTransactions(module, action, address, startblock, endblock, sort, ApiKey.takeOff.callApiKey())

override fun accountInternalTransactions(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<AccountInternalTxResponse> =
override fun accountERC20Txs(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<ERC20Response> =
RestClient().getQuery().getAccountERC20Transactions(module, action, address, startblock, endblock, sort, ApiKey.takeOff.callApiKey())

override fun accountInternalTxs(module: String?,
action: String?,
address: String?,
startblock: String?,
endblock: String?,
sort: String?): Single<AccountInternalTxResponse> =
RestClient().getQuery().getAccountInternalTransactions(module, action, address, startblock, endblock, sort, ApiKey.takeOff.callApiKey())

override fun contractABI(module: String?, action: String?, address: String?): Single<ContractABIResponse> =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package jfyg.network.response.account

import jfyg.data.ERC20Token
import jfyg.network.response.BaseResponse

/**
* ERC20 Transactions recorded by an account
*/
internal class ERC20Response(var result: ArrayList<ERC20Token>? = null) : BaseResponse()
3 changes: 3 additions & 0 deletions etherscanapi/src/main/java/jfyg/utils/Const.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ package jfyg.utils
class Const {
companion object {
const val BASE_URL = "http://api.etherscan.io/"
const val GENERIC_PUBLIC_ADDRESS = "0x82e4499D4b2A669831a3881d61BB24f7b620c61a"
const val CONTRACT_PUBLIC_ADDRESS = "0xBB9bc244D798123fDe783fCc1C72d3Bb8C189413"
const val TRANSACTION_PUBLIC_ADDRESS = "0x15f8e5ea1079d9a0bb04a4c58ae5fe7654b5b2b4463375ff7ffb490aa0032f3a"
}
}
59 changes: 59 additions & 0 deletions etherscanapi/src/test/java/jfyg/data/account/AccountTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import jfyg.network.response.account.AccountBlockResponse
import jfyg.network.response.account.AccountInternalTxResponse
import jfyg.network.response.account.AccountMultiBalanceResponse
import jfyg.network.response.account.AccountTxResponse
import jfyg.network.response.account.ERC20Response
import org.junit.Assert.assertEquals
import org.junit.Assert
import org.junit.Before
Expand Down Expand Up @@ -162,6 +163,56 @@ internal class AccountTest {
"result": "Error!"
}"""

private val erc20Response = """
{
"status": "1",
"message": "OK",
"result": [
{
"blockNumber": "2231007",
"timeStamp": "1473473076",
"hash": "0x48b667b0d84c28e61fe3b5c8c8ba25d848d1b08a646ca79bcbb87475427e2129",
"nonce": "251",
"blockHash": "0x513be6f5e2af2f9f8912767a3f1b9a96edd4251a069649dbfb324d8ac002f48c",
"from": "0xac75b73394c329376c214663d92156afa864a77f",
"contractAddress": "0xecf8f87f810ecf450940c9f60066b4a7a501d6a7",
"to": "0x4e83362442b8d1bec281594cea3050c8eb01311c",
"value": "104000000000000000000",
"tokenName": "\u0001",
"tokenSymbol": "\u0001",
"tokenDecimal": "1",
"transactionIndex": "5",
"gas": "1000000",
"gasPrice": "22723508918",
"gasUsed": "93721",
"cumulativeGasUsed": "199121",
"input": "0x2ac9bf090000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000005f68e8131ecf80000000000000000000000000000000000000000000000000005386e53c7de1e0000",
"confirmations": "3274042"
},
{
"blockNumber": "2240334",
s"timeStamp": "1473605946",
"hash": "0x48ca19e7184f5cb923f2a11769dbf7d5e28c80a8c93e973a96bb2d0a5897bbc6",
"nonce": "12",
"blockHash": "0x43648e9dfd01ba42a177e1d2b1037395d8946a683bb5ce626de2168b27c7915b",
"from": "0x4e83362442b8d1bec281594cea3050c8eb01311c",
"contractAddress": "0xecf8f87f810ecf450940c9f60066b4a7a501d6a7",
"to": "0xe7b4dba7370f773888d197600d9955a7cc6e0015",
"value": "180000000000000000000",
"tokenName": "\u0001",
"tokenSymbol": "\u0001",
"tokenDecimal": "1",
"transactionIndex": "4",
"gas": "1000000",
"gasPrice": "20000000000",
"gasUsed": "93721",
"cumulativeGasUsed": "196143",
"input": "0x2ac9bf090000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000009f98351204fe00000000000000000000000000000000000000000000000000005386e53c7de1e0000",
"confirmations": "3264715"
}
]
}"""


@Before
fun setUp() {
Expand Down Expand Up @@ -209,6 +260,14 @@ internal class AccountTest {
assertEquals("0", response.result?.get(1)?.isError)
}

@Test
fun getERC20Token() {
val response = gson.fromJson(erc20Response, ERC20Response::class.java)
assertEquals("5", response.result?.get(0)?.transactionIndex)
assertEquals("1", response.result?.get(0)?.tokenDecimal)
assertEquals("\u0001", response.result?.get(0)?.tokenSymbol)
}

@Test
fun getInternalTransactions() {
val response = gson.fromJson(internalTxs, AccountInternalTxResponse::class.java)
Expand Down