Skip to content

Commit 51625d3

Browse files
authored
DAO-528 Fixed transactions crashing due to .to.hash not being existent. Created new endpoint to fetch events by topic0 from an address. This is used to fetch governor ProposalCreated event - openapi.js implementation is pending. (#152)
1 parent 16e3a91 commit 51625d3

File tree

6 files changed

+70
-2
lines changed

6 files changed

+70
-2
lines changed

src/blockscoutApi/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
fromApiToInternalTransaction, fromApiToNft, fromApiToNftOwner, fromApiToRtbcBalance, fromApiToTEvents,
1212
fromApiToTokenWithBalance, fromApiToTokens, fromApiToTransaction
1313
} from './utils'
14+
import { GetEventLogsByAddressAndTopic0 } from '../service/address/AddressService'
1415

1516
export class BlockscoutAPI extends DataSource {
1617
private chainId: number
@@ -118,4 +119,30 @@ export class BlockscoutAPI extends DataSource {
118119
}
119120
return fromApiToNftOwner(address, [...(response?.items || []), ...items])
120121
}
122+
123+
async getEventLogsByAddressAndTopic0 ({
124+
address, topic0, toBlock = 'latest', fromBlock
125+
}: Omit<GetEventLogsByAddressAndTopic0, 'chainId'>) {
126+
let fromBlockToUse = fromBlock
127+
if (!fromBlock) {
128+
const tx = await this.getTransactionsByAddress(address)
129+
// @ts-ignore ignored because it's using never as type
130+
const lastTx = tx.data.pop() // The last tx is the first transaction
131+
132+
if (lastTx) fromBlockToUse = lastTx.blockNumber
133+
}
134+
135+
if (!fromBlockToUse) return []
136+
const params = {
137+
module: 'logs',
138+
action: 'getLogs',
139+
address: address.toLowerCase(),
140+
toBlock,
141+
fromBlock: fromBlockToUse,
142+
topic0
143+
}
144+
return this.axios?.get<ServerResponse<TokenTransferApi>>(`${this.url}`, { params })
145+
.then(({ data }) => data.result)
146+
.catch(() => [])
147+
}
121148
}

src/blockscoutApi/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export const fromApiToTransaction = (transaction: TransactionServerResponse): IT
147147
blockNumber: transaction.block,
148148
transactionIndex: 0,
149149
from: transaction.from.hash,
150-
to: transaction.to.hash,
150+
to: transaction.to?.hash,
151151
gas: Number(transaction.gas_used),
152152
gasPrice: transaction.gas_price,
153153
value: transaction.value,
@@ -167,7 +167,7 @@ export const fromApiToTransaction = (transaction: TransactionServerResponse): IT
167167
contractAddress: null,
168168
logs: [],
169169
from: transaction.from.hash,
170-
to: transaction.to.hash,
170+
to: transaction.to?.hash,
171171
status: transaction.status === 'ok' ? '0x1' : '0x0',
172172
logsBloom: '',
173173
type: String(transaction.type)

src/controller/httpsAPI.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,27 @@ export class HttpsAPI {
173173
}
174174
})
175175

176+
this.app.get('/address/:address/eventsByTopic0',
177+
async ({ params: { address }, query: { chainId = '31', topic0, fromBlock, toBlock } } : Request, res: Response,
178+
nextFunction: NextFunction) => {
179+
try {
180+
chainIdSchema.validateSync({ chainId })
181+
addressSchema.validateSync({ address })
182+
const result = await this.addressService
183+
.getEventLogsByAddressAndTopic0({
184+
chainId: chainId as string,
185+
address: address as string,
186+
topic0: topic0 as string,
187+
fromBlock: fromBlock as string,
188+
toBlock: toBlock as string
189+
})
190+
.catch(nextFunction)
191+
return this.responseJsonOk(res)(result)
192+
} catch (e) {
193+
this.handleValidationError(e, res)
194+
}
195+
})
196+
176197
this.app.get(
177198
'/price',
178199
async (req: Request<{}, {}, {}, PricesQueryParams>, res: Response) => {

src/repository/DataSource.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import _axios from 'axios'
22
import { ethers } from 'ethers'
33
import BitcoinCore from '../service/bitcoin/BitcoinCore'
4+
import { GetEventLogsByAddressAndTopic0 } from '../service/address/AddressService'
45

56
export abstract class DataSource {
67
readonly url: string
@@ -27,6 +28,8 @@ export abstract class DataSource {
2728

2829
abstract getNft(address: string);
2930
abstract getNftOwnedByAddress(address: string, nft: string);
31+
abstract getEventLogsByAddressAndTopic0({ address, topic0, toBlock, fromBlock } :
32+
Omit<GetEventLogsByAddressAndTopic0, 'chainId'>);
3033
}
3134

3235
export type RSKDatasource = {

src/rskExplorerApi/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,8 @@ export class RSKExplorerAPI extends DataSource {
139139
getNftOwnedByAddress () {
140140
throw new Error('Feature not supported')
141141
}
142+
143+
getEventLogsByAddressAndTopic0 () {
144+
throw new Error('Feature not supported')
145+
}
142146
}

src/service/address/AddressService.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ interface GetNftsByAddress extends GetTokensByAddress {
3333
nftAddress: string
3434
}
3535

36+
export interface GetEventLogsByAddressAndTopic0 {
37+
address: string
38+
topic0: string
39+
toBlock: string
40+
chainId: string
41+
fromBlock?: string
42+
}
43+
3644
type GetBalancesTransactionsPricesByAddress = {
3745
chainId: string
3846
address: string
@@ -139,4 +147,9 @@ export class AddressService {
139147
const dataSource = this.dataSourceMapping[chainId]
140148
return dataSource.getNftOwnedByAddress(address, nftAddress)
141149
}
150+
151+
async getEventLogsByAddressAndTopic0 ({ chainId, ...rest }: GetEventLogsByAddressAndTopic0) {
152+
const dataSource = this.dataSourceMapping[chainId]
153+
return dataSource.getEventLogsByAddressAndTopic0(rest)
154+
}
142155
}

0 commit comments

Comments
 (0)