Skip to content

Commit

Permalink
feat: add date filters to transactions endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
sleyter93 committed May 9, 2024
1 parent f546495 commit 969f7d6
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 115 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ 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
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

0 comments on commit 969f7d6

Please sign in to comment.