Skip to content

Commit

Permalink
Fix converting dict block to eth block, add tests (#265)
Browse files Browse the repository at this point in the history
* Fix converting dict block to eth block, add tests

* Fix tx being empty
  • Loading branch information
stwiname authored Mar 21, 2024
1 parent 1943764 commit 09973bd
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ import {
} from '../../../configure/SubqueryProject';
import {
buildDictionaryV2QueryEntry,
DEFAULT_DICTIONARY,
EthDictionaryV2,
} from './ethDictionaryV2';

const DEFAULT_DICTIONARY = 'http://localhost:3000/rpc/eth-mainnet';

const HTTP_ENDPOINT = 'https://polygon.api.onfinality.io/public';
const mockDs: EthereumProjectDs[] = [
{
Expand Down
2 changes: 0 additions & 2 deletions packages/node/src/indexer/dictionary/v2/ethDictionaryV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ const MIN_FETCH_LIMIT = 200;

const logger = getLogger('eth-dictionary-v2');

export const DEFAULT_DICTIONARY = 'http://localhost:3000/rpc';

function extractOptionAddresses(
dsOptions: SubqlEthereumProcessorOptions | SubqlEthereumProcessorOptions[],
): string[] {
Expand Down
108 changes: 108 additions & 0 deletions packages/node/src/indexer/dictionary/v2/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2020-2024 SubQuery Pte Ltd authors & contributors
// SPDX-License-Identifier: GPL-3.0

import { IBlock } from '@subql/node-core';
import { EthereumBlock } from '@subql/types-ethereum';
import EventEmitter2 from 'eventemitter2';
import fetch from 'node-fetch';
import { EthereumApi } from '../../../ethereum';
import { RawEthBlock } from './types';
import { rawBlockToEthBlock } from './utils';

const DICTIONARY_URL = 'http://localhost:3000/rpc/eth-mainnet';
const RPC_URL = 'https://eth.llamarpc.com';

async function fetchDictionaryBlock(): Promise<RawEthBlock> {
const res = await fetch(DICTIONARY_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'subql_filterBlocks',
params: [
{
fromBlock: '0x3e579e',
toBlock: '0x3e579e',
limit: '0x1',
blockFilter: {
logs: [
{
address: ['0x6f28B146804dBa2D6f944C03528A8FDbc673df2C'],
topics0: [
'0xb76d0edd90c6a07aa3ff7a222d7f5933e29c6acc660c059c97837f05c4ca1a84',
],
},
],
},
fieldSelector: {
blockHeader: true,
logs: {
transaction: true,
},
transactions: {
log: true,
},
},
},
],
}),
});

return (await res.json()).result.blocks[0];
}

async function fetchRPCBlock(): Promise<IBlock<EthereumBlock>> {
const api = new EthereumApi(RPC_URL, 1, new EventEmitter2());

return api.fetchBlock(4085662);
}

describe('rawBlockToEthBlock', () => {
it('successfully convers a block', async () => {
const [raw, rpcBlock] = await Promise.all([
fetchDictionaryBlock(),
fetchRPCBlock(),
]);

const block = rawBlockToEthBlock(raw);

expect(block.getHeader()).toEqual({
blockHash:
'0xde8e614cc05b483fe092fd0aff435011138c15c9ede862579074218d4aff5132',
blockHeight: 4085662,
parentHash:
'0x669c7a2c66e38c144ad1e2845ec345b6ce7e2107edbdb331ab88d355982126a7',
});

expect(block.block.transactions.length).toBeGreaterThan(0);
expect(block.block.logs.length).toBeGreaterThan(0);

// Dictionry is going to return a subset of events/transactions so we base off dictionary block
for (const log of block.block.logs) {
// Remove linked types
const { block: _1, transaction: _2, ...logRest } = log;
const {
block: _3,
transaction: _4,
...rpcLogRest
} = rpcBlock.block.logs[log.logIndex];
expect(JSON.stringify(logRest)).toEqual(JSON.stringify(rpcLogRest));
}

for (const tx of block.block.transactions) {
// Cast to any to remove toJSON which results in different key order
const { logs: _1, receipt: _3, toJSON: _5, ...txRest } = tx as any;
const {
logs: _2,
receipt: _4,
toJSON: _6,
...rpcTxRest
} = rpcBlock.block.transactions[Number(tx.transactionIndex)] as any;

expect(txRest).toEqual(rpcTxRest);
}
}, 15000);
});
18 changes: 6 additions & 12 deletions packages/node/src/indexer/dictionary/v2/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Formatter } from '@ethersproject/providers';
import { IBlock } from '@subql/node-core';
import { EthereumBlock } from '@subql/types-ethereum';
import {
formatBlock,
formatBlockUtil,
formatLog,
formatTransaction,
Expand All @@ -15,26 +16,19 @@ export function rawBlockToEthBlock(block: RawEthBlock): IBlock<EthereumBlock> {
try {
const formatter = new Formatter();

// Add gasLimit to each transaction from the block header
if (block.transactions !== null && !!block.transactions.length) {
block.transactions.map((tx) => (tx.gasLimit = block.header.gasLimit));
}

const ethBlock = formatter.blockWithTransactions({
const ethBlock = formatBlock({
...block.header,
transactions: block.transactions,
}) as unknown as EthereumBlock;
transactions: [],
});

ethBlock.logs = Formatter.arrayOf(formatter.filterLog.bind(formatter))(
block.logs ?? [],
).map((l) => formatLog(l, ethBlock));

ethBlock.transactions = Formatter.arrayOf(
formatter.transactionResponse.bind(formatter),
)(block.transactions ?? []).map((tx) => ({
ethBlock.transactions = (block.transactions ?? []).map((tx) => ({
...formatTransaction(tx, ethBlock),
logs: ethBlock.logs.filter((l) => l.transactionHash === tx.hash),
input: tx.data, // Why is ethers renaming this to data?
// TODO add method for receipts
}));

return formatBlockUtil(ethBlock);
Expand Down

0 comments on commit 09973bd

Please sign in to comment.