-
Notifications
You must be signed in to change notification settings - Fork 10
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
Implement the eth_getFilterLogs
endpoint
#217
Changes from all commits
4a7ea81
9fed7c6
d2952b8
75a5815
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const { assert } = require('chai') | ||
const conf = require('./config') | ||
const helpers = require('./helpers') | ||
const web3 = conf.web3 | ||
|
||
it('returns a null result for missing filter', async () => { | ||
// check that null is returned when the filter could not be found. | ||
let response = await helpers.callRPCMethod('eth_getFilterLogs', ['0xffa1']) | ||
|
||
assert.equal(200, response.status) | ||
assert.isUndefined(response.body['result']) | ||
}) | ||
|
||
it('create logs filter and call eth_getFilterLogs', async () => { | ||
// deploy contract | ||
let deployed = await helpers.deployContract('storage') | ||
let contractAddress = deployed.receipt.contractAddress | ||
|
||
// create logs filter on the address of the deployed contract | ||
let response = await helpers.callRPCMethod('eth_newFilter', [{ 'address': contractAddress }]) | ||
|
||
assert.equal(200, response.status) | ||
assert.isDefined(response.body['result']) | ||
let filterID = response.body['result'] | ||
|
||
// make contract function call that emits a log | ||
let res = await helpers.signAndSend({ | ||
from: conf.eoa.address, | ||
to: contractAddress, | ||
data: deployed.contract.methods.sum(15, 20).encodeABI(), | ||
gas: 1000000, | ||
gasPrice: 0 | ||
}) | ||
assert.equal(res.receipt.status, conf.successStatus) | ||
|
||
// check the matching items from the logs filter | ||
response = await helpers.callRPCMethod('eth_getFilterLogs', [filterID]) | ||
|
||
assert.equal(200, response.status) | ||
assert.equal(1, response.body['result'].length) | ||
|
||
let logs = response.body['result'] | ||
assert.equal(contractAddress.toLowerCase(), logs[0].address) | ||
assert.lengthOf(logs[0].topics, 4) | ||
assert.equal( | ||
'35', | ||
web3.eth.abi.decodeParameter("int256", logs[0].data) | ||
) | ||
|
||
// make contract function call that emits another log | ||
res = await helpers.signAndSend({ | ||
from: conf.eoa.address, | ||
to: contractAddress, | ||
data: deployed.contract.methods.sum(30, 20).encodeABI(), | ||
gas: 1000000, | ||
gasPrice: 0 | ||
}) | ||
|
||
assert.equal(res.receipt.status, conf.successStatus) | ||
|
||
// check the matching items from the logs filter include both logs | ||
// from the above 2 contract function calls | ||
response = await helpers.callRPCMethod('eth_getFilterLogs', [filterID]) | ||
|
||
assert.equal(200, response.status) | ||
assert.equal(2, response.body['result'].length) | ||
logs = response.body['result'] | ||
console.log() | ||
|
||
assert.equal(contractAddress.toLowerCase(), logs[1].address) | ||
assert.lengthOf(logs[1].topics, 4) | ||
assert.equal( | ||
'50', | ||
web3.eth.abi.decodeParameter("int256", logs[1].data) | ||
) | ||
|
||
}).timeout(10 * 1000) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,70 @@ | ||
const fs = require("fs") | ||
const conf = require("./config") | ||
const {assert} = require("chai"); | ||
const chai = require("chai") | ||
const chaiHttp = require('chai-http') | ||
const web3 = conf.web3 | ||
|
||
chai.use(chaiHttp); | ||
|
||
// deployContract deploys a contract by name, the contract files must be saved in | ||
// fixtures folder, each contract must have two files: ABI and bytecode, | ||
// the ABI file must be named {name}ABI.json and contain ABI definition for the contract | ||
// and bytecode file must be named {name}.byte and must contain compiled byte code of the contract. | ||
// | ||
// Returns the contract object as well as the receipt deploying the contract. | ||
async function deployContract(name) { | ||
const abi = require(`../fixtures/${name}ABI.json`) | ||
const code = await fs.promises.readFile(`${__dirname}/../fixtures/${name}.byte`, 'utf8') | ||
const contractABI = new web3.eth.Contract(abi) | ||
|
||
let data = contractABI | ||
.deploy({ data: `0x${code}` }) | ||
.encodeABI() | ||
|
||
let signed = await conf.eoa.signTransaction({ | ||
from: conf.eoa.address, | ||
data: data, | ||
value: '0', | ||
gasPrice: '0', | ||
}) | ||
const abi = require(`../fixtures/${name}ABI.json`) | ||
const code = await fs.promises.readFile(`${__dirname}/../fixtures/${name}.byte`, 'utf8') | ||
const contractABI = new web3.eth.Contract(abi) | ||
|
||
let data = contractABI | ||
.deploy({ data: `0x${code}` }) | ||
.encodeABI() | ||
|
||
let signed = await conf.eoa.signTransaction({ | ||
from: conf.eoa.address, | ||
data: data, | ||
value: '0', | ||
gasPrice: '0', | ||
}) | ||
|
||
let receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction) | ||
let receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction) | ||
|
||
return { | ||
contract: new web3.eth.Contract(abi, receipt.contractAddress), | ||
receipt: receipt | ||
} | ||
return { | ||
contract: new web3.eth.Contract(abi, receipt.contractAddress), | ||
receipt: receipt | ||
} | ||
Comment on lines
+16
to
+36
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding explicit error handling for operations like file reading and contract deployment to enhance robustness. |
||
} | ||
|
||
// signAndSend signs a transactions and submits it to the network, | ||
// returning a transaction hash and receipt | ||
async function signAndSend(tx) { | ||
const signedTx = await conf.eoa.signTransaction(tx) | ||
// send transaction and make sure interaction was success | ||
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction) | ||
|
||
return { | ||
hash: signedTx.transactionHash, | ||
receipt: receipt, | ||
} | ||
const signedTx = await conf.eoa.signTransaction(tx) | ||
// send transaction and make sure interaction was success | ||
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction) | ||
|
||
return { | ||
hash: signedTx.transactionHash, | ||
receipt: receipt, | ||
} | ||
Comment on lines
+42
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add explicit error handling for the network operations to ensure robustness, especially in case of network failures. |
||
} | ||
|
||
// callRPCMethod accepts a method name and its params and | ||
// makes a POST request to the JSON-RPC API server. | ||
// Returns a promise for the response. | ||
async function callRPCMethod(methodName, params) { | ||
return chai.request('http://127.0.0.1:8545') | ||
.post('/') | ||
.set('Content-Type', 'application/json') | ||
.set('Accept', 'application/json') | ||
.send({ | ||
'jsonrpc': '2.0', | ||
'method': methodName, | ||
'id': 1, | ||
'params': params | ||
}) | ||
Comment on lines
+52
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider adding error handling for the HTTP requests to handle potential issues like network errors or invalid responses. |
||
} | ||
|
||
exports.signAndSend = signAndSend | ||
exports.deployContract = deployContract | ||
exports.deployContract = deployContract | ||
exports.callRPCMethod = callRPCMethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
according to the above description it should return empty array if not found, I suggest adding a test where the filter is not found as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point regarding the test case, I will add it right away.
Good catch as well regarding the description. This is actually a wrong description copied from geth, See https://github.com/ethereum/go-ethereum/blob/8d42e115b1cae4f09fd02b71c06ec9c85f22ad4f/eth/filters/api.go#L383-L417 😅 I will update the description, the geth behavior is to always return
nil
, instead of an empty array, at least for this specific endpoint.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in d2952b8