Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DAO-347: add date filters to transactions endpoint #141

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ NODE_URL=https://public-node.testnet.rsk.co
NODE_MAINNET_URL=https://public-node.rsk.co
CYPHER_ESTIMATE_FEE_URL=https://api.blockcypher.com/v1/btc/test3
CYPHER_ESTIMATE_FEE_MAINNET_URL=https://api.blockcypher.com/v1/btc/main
# API_URL=https://rootstock-testnet.blockscout.com/api
API_URL=https://rootstock-testnet.blockscout.com/api
API_MAINNET_URL=https://rootstock.blockscout.com/api
36 changes: 36 additions & 0 deletions src/api/openapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ module.exports = {
required: false,
schema: { type: 'string' }
},
{
name: 'startTimestamp',
in: 'query',
description: 'starting block unix timestamp.',
required: false,
schema: {
type: 'string'
}
},
{
name: 'endTimestamp',
in: 'query',
description: 'ending block unix timestamp.',
required: false,
schema: {
type: 'string'
}
},
{
name: 'limit',
in: 'query',
Expand Down Expand Up @@ -295,6 +313,24 @@ module.exports = {
default: '0'
}
},
{
name: 'startTimestamp',
in: 'query',
description: 'starting block unix timestamp.',
required: false,
schema: {
type: 'string'
}
},
{
name: 'endTimestamp',
in: 'query',
description: 'ending block unix timestamp.',
required: false,
schema: {
type: 'string'
}
},
{
name: 'prev',
in: 'query',
Expand Down
70 changes: 53 additions & 17 deletions src/blockscoutApi/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import _axios from 'axios'
import { DataSource } from '../repository/DataSource'
import {
BalanceServerResponse, InternalTransactionResponse, ServerResponse, TokenBalanceServerResponse,
TokenServerResponse, TokenTransferApi, TransactionServerResponse,
TransactionsServerResponse
BalanceServerResponse, BlockResponse, InternalTransaction, ServerResponse, TokenBalanceServerResponse,
TokenServerResponse, TokenTransferApi, TransactionResponse
} from './types'
import {
fromApiToInternalTransaction, fromApiToRtbcBalance, fromApiToTEvents,
Expand All @@ -22,6 +21,18 @@ export class BlockscoutAPI extends DataSource {
this.chainId = chainId
}

getBlockNumberByTimestamp (timestamp: number, timeDirection: string) {
const params = {
module: 'block',
action: 'getblocknobytime',
timestamp,
closest: timeDirection
}
return this.axios?.get<ServerResponse<BlockResponse>>(this.url, { params })
.then(response => response.data.result.blockNumber)
.catch(() => '0')
}

getTokens () {
return this.axios?.get<TokenServerResponse>(`${this.url}/v2/tokens`)
.then(response => response.data.items
Expand All @@ -47,13 +58,15 @@ export class BlockscoutAPI extends DataSource {
.catch(this.errorHandling)
}

async getEventsByAddress (address: string) {
async getEventsByAddress (address: string, limit?: string, startBlock?: number, endBlock?: number) {
const params = {
module: 'account',
action: 'tokentx',
address: address.toLowerCase()
address: address.toLowerCase(),
...(startBlock && { startblock: startBlock }),
...(endBlock && { endblock: endBlock })
}
return this.axios?.get<ServerResponse<TokenTransferApi>>(`${this.url}`, { params })
return this.axios?.get<ServerResponse<TokenTransferApi[]>>(`${this.url}`, { params })
.then(response =>
response.data.result
.map(tokenTranfer => {
Expand All @@ -63,25 +76,48 @@ export class BlockscoutAPI extends DataSource {
}

getTransaction (hash: string) {
return this.axios?.get<TransactionServerResponse>(`${this.url}/v2/transactions/${hash}`)
const params = {
module: 'transaction',
action: 'gettxinfo',
txhash: hash
}
return this.axios?.get<ServerResponse<TransactionResponse>>(`${this.url}`, { params })
.then(response =>
fromApiToTransaction(response.data))
fromApiToTransaction(response.data.result))
.catch(this.errorHandling)
}

getInternalTransactionByAddress (address: string) {
return this.axios?.get<InternalTransactionResponse>(
`${this.url}/v2/addresses/${address.toLowerCase()}/internal-transactions`
)
.then(response => response.data.items.map(fromApiToInternalTransaction))
getInternalTransactionByAddress (address: string, limit?: string, startBlock?: number, endBlock?: number) {
const params = {
module: 'account',
action: 'txlistinternal',
address,
...(startBlock && { startblock: startBlock }),
...(endBlock && { endblock: endBlock })
}
return this.axios?.get<ServerResponse<InternalTransaction[]>>(this.url, { params })
.then(response => response.data.result.map(fromApiToInternalTransaction))
.catch(this.errorHandling)
}

getTransactionsByAddress (address: string) {
return this.axios?.get<TransactionsServerResponse>(
`${this.url}/v2/addresses/${address.toLowerCase()}/transactions`
getTransactionsByAddress (address: string, limit?: string,
prev?: string,
next?: string,
blockNumber?: string,
startTimestamp?: number,
endTimestamp?: number) {
const params = {
module: 'account',
action: 'txlist',
startblock: blockNumber,
address: address.toLowerCase(),
...(startTimestamp && { start_timestamp: startTimestamp }),
...(endTimestamp && { end_timestamp: endTimestamp })
}
return this.axios?.get<ServerResponse<TransactionResponse[]>>(
`${this.url}`, { params }
)
.then(response => ({ data: response.data.items.map(fromApiToTransaction) }))
.then(response => ({ data: response.data.result.map(fromApiToTransaction) }))
.catch(this.errorHandling)
}
}
80 changes: 33 additions & 47 deletions src/blockscoutApi/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,60 +110,46 @@ export interface DecodedInput {
}

export interface InternalTransaction {
block: number
created_contract: any
error: any
from: Account
gas_limit: string
index: number
success: boolean
timestamp: string
to: Account
transaction_hash: string
blockNumber: string
callType: string
contractAddress: string
errCode: string
from: string
gas: string
gasUsed: string
index: string
input: string
isError: string
timeStamp: string
to: string
transactionHash: string
type: string
value: string
}

export interface TransactionServerResponse {
timestamp: string
fee: Fee
gas_limit: string
block: number
status: string
method: string
confirmations: number
type: number
exchange_rate: any
to: Account
tx_burnt_fee: any
max_fee_per_gas: any
result: string
export interface TransactionResponse {
blockHash: string
blockNumber: string
confirmations: string
contractAddress: string
cumulativeGasUsed: string
from: string
gas: string
gasPrice: string
gasUsed: string
hash: string
gas_price: string
priority_fee: any
base_fee_per_gas: any
from: Account
token_transfers: TokenTransfer[]
tx_types: string[]
gas_used: string
created_contract: any
position: number
nonce: number
has_error_in_internal_txs: boolean
actions: any[]
decoded_input: DecodedInput
token_transfers_overflow: boolean
raw_input: string
input: string
isError: string
nonce: string
timeStamp: string
to: string
transactionIndex: string
txreceipt_status: string
value: string
max_priority_fee_per_gas: any
revert_reason: any
confirmation_duration: number[]
tx_tag: any
}

export interface TransactionsServerResponse {
items: TransactionServerResponse[]
next_page_params: NextPageParams
export interface BlockResponse {
blockNumber: string
}

export interface BalanceServerResponse {
Expand Down Expand Up @@ -229,5 +215,5 @@ export interface TokenTransferApi {
export interface ServerResponse<T> {
message: string
status: string
result: T[]
result: T
}
62 changes: 32 additions & 30 deletions src/blockscoutApi/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
IApiToken, ITokenWithBalance, InternalTransaction,
Token, TokenTransferApi, TransactionServerResponse
Token, TokenTransferApi, TransactionResponse
} from './types'
import tokens from '@rsksmart/rsk-contract-metadata'
import { toChecksumAddress } from '@rsksmart/rsk-utils'
Expand Down Expand Up @@ -126,68 +126,70 @@ export const fromApiToTEvents = (tokenTransfer:TokenTransferApi): IEvent =>
txStatus: '0x1'
})

export const fromApiToTransaction = (transaction: TransactionServerResponse): ITransaction =>
({
export const fromApiToTransaction = (transaction: TransactionResponse): ITransaction => {
const txType = transaction.input === '0x' ? 'normal' : 'contract call'
return ({
_id: '',
hash: transaction.hash,
nonce: transaction.nonce,
blockHash: '',
blockNumber: transaction.block,
nonce: Number(transaction.nonce),
blockHash: transaction.blockHash,
blockNumber: Number(transaction.blockNumber),
transactionIndex: 0,
from: transaction.from.hash,
to: transaction.to.hash,
gas: Number(transaction.gas_used),
gasPrice: transaction.gas_price,
from: transaction.from,
to: transaction.to,
gas: Number(transaction.gas),
gasPrice: transaction.gasPrice,
value: transaction.value,
input: transaction.raw_input,
input: transaction.input,
v: '',
r: '',
s: '',
type: String(transaction.type),
timestamp: Date.parse(transaction.timestamp) / 1000,
type: String(),
timestamp: Number(transaction.timeStamp),
receipt: {
transactionHash: transaction.hash,
transactionIndex: 0,
blockHash: '',
blockNumber: transaction.block,
cumulativeGasUsed: Number(transaction.gas_limit),
gasUsed: Number(transaction.gas_used),
blockNumber: Number(transaction.blockNumber),
cumulativeGasUsed: Number(transaction.gasUsed),
gasUsed: Number(transaction.gasUsed),
contractAddress: null,
logs: [],
from: transaction.from.hash,
to: transaction.to.hash,
status: transaction.status === 'ok' ? '0x1' : '0x0',
from: transaction.from,
to: transaction.to,
status: transaction.txreceipt_status === '1' ? '0x1' : '0x0',
logsBloom: '',
type: String(transaction.type)
type: txType
},
txType: transaction.tx_types[0],
txType,
txId: ''
})
}

export const fromApiToInternalTransaction = (internalTransaction: InternalTransaction): IInternalTransaction =>
({
_id: '',
action: {
callType: internalTransaction.type,
from: internalTransaction.from.hash,
to: internalTransaction.to.hash,
from: internalTransaction.from,
to: internalTransaction.to,
value: internalTransaction.value,
gas: internalTransaction.gas_limit,
gas: internalTransaction.gas,
input: '0x'
},
blockHash: '',
blockNumber: internalTransaction.block,
transactionHash: internalTransaction.transaction_hash,
transactionPosition: internalTransaction.index,
blockNumber: Number(internalTransaction.blockNumber),
transactionHash: internalTransaction.transactionHash,
transactionPosition: Number(internalTransaction.index),
type: internalTransaction.type,
subtraces: 0,
traceAddress: [],
result: {
gasUsed: internalTransaction.gas_limit,
gasUsed: internalTransaction.gasUsed,
output: '0x'
},
_index: internalTransaction.index,
timestamp: Date.parse(internalTransaction.timestamp) / 1000,
_index: Number(internalTransaction.index),
timestamp: Date.parse(internalTransaction.timeStamp) / 1000,
internalTxId: ''
})

Expand Down
Loading
Loading