Skip to content

Commit

Permalink
feat: implemented eth_newFilter to WS server (hashgraph#2553)
Browse files Browse the repository at this point in the history
* feat: implemented eth_newFilter to WS server

Signed-off-by: Logan Nguyen <logan.nguyen@swirldslabs.com>

* test: added acceptance tests for eth_newFilter

Signed-off-by: Logan Nguyen <logan.nguyen@swirldslabs.com>

* fix: updated validateBlockRangeAndAddTimestampToParams for eth_newFilter

Signed-off-by: Logan Nguyen <logan.nguyen@swirldslabs.com>

---------

Signed-off-by: Logan Nguyen <logan.nguyen@swirldslabs.com>
  • Loading branch information
quiet-node authored Jun 3, 2024
1 parent 084547f commit 3c16200
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ICommonService {
fromBlock: string,
toBlock: string,
requestIdPrefix?: string,
address?: string | string[] | null,
): Promise<boolean>;

getHistoricalBlockResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ export class FilterService implements IFilterService {
try {
FilterService.requireFiltersEnabled();

if (!(await this.common.validateBlockRangeAndAddTimestampToParams({}, fromBlock, toBlock, requestIdPrefix))) {
if (
!(await this.common.validateBlockRangeAndAddTimestampToParams({}, fromBlock, toBlock, requestIdPrefix, address))
) {
throw predefined.INVALID_BLOCK_RANGE;
}

Expand Down
10 changes: 9 additions & 1 deletion packages/ws-server/src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,15 @@ const handleSendingRequestsToRelay = async ({

// Call the relay method with the resolved parameters.
// Method will be validated by "verifySupportedMethod" before reaching this point.
const txRes = await relay[service]()[methodName](...resolvedParams, requestIdPrefix);
let txRes: any;
if (method === WS_CONSTANTS.METHODS.ETH_NEWFILTER) {
txRes = await relay
.eth()
.filterService()
[methodName](...resolvedParams, requestIdPrefix);
} else {
txRes = await relay[service]()[methodName](...resolvedParams, requestIdPrefix);
}

if (!txRes) {
logger.trace(
Expand Down
1 change: 1 addition & 0 deletions packages/ws-server/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const WS_CONSTANTS = {
ETH_GETCODE: 'eth_getCode',
ETH_GASPRICE: 'eth_gasPrice',
ETH_SUBSCRIBE: 'eth_subscribe',
ETH_NEWFILTER: 'eth_newFilter',
ETH_GETBALANCE: 'eth_getBalance',
ETH_UNSUBSCRIBE: 'eth_unsubscribe',
ETH_BLOCKNUMBER: 'eth_blockNumber',
Expand Down
2 changes: 2 additions & 0 deletions packages/ws-server/src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ export const resolveParams = (method: string, params: any): any[] => {
switch (method) {
case WS_CONSTANTS.METHODS.ETH_GETLOGS:
return [params[0].blockHash, params[0].fromBlock, params[0].toBlock, params[0].address, params[0].topics];
case WS_CONSTANTS.METHODS.ETH_NEWFILTER:
return [params[0].fromBlock, params[0].toBlock, params[0].address, params[0].topics];
default:
return params;
}
Expand Down
113 changes: 113 additions & 0 deletions packages/ws-server/tests/acceptance/newFilter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*-
*
* Hedera JSON RPC Relay
*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import { expect } from 'chai';
import { ethers, WebSocketProvider } from 'ethers';
import { WsTestConstant, WsTestHelper } from '../helper';
import { Utils } from '@hashgraph/json-rpc-server/tests/helpers/utils';

describe('@release @web-socket-batch-2 eth_newFilter', async function () {
let wsFilterObj: any, ethersWsProvider: WebSocketProvider;
const METHOD_NAME = 'eth_newFilter';
const INVALID_PARAMS = [
[],
[
{
address: WsTestConstant.FAKE_TX_HASH,
fromBlock: '0xhedera',
toBlock: 'latest',
},
],
[
{
address: WsTestConstant.FAKE_TX_HASH,
fromBlock: 'latest',
toBlock: '0xhedera',
},
],
];

const SIMPLE_CONTRACT_BYTECODE =
'0x6080604052348015600f57600080fd5b507f4e7df42af9a017b7c655a28ef10cbc8f05b2b088f087ee02416cfa1a96ac3be26007604051603e91906091565b60405180910390a160aa565b6000819050919050565b6000819050919050565b6000819050919050565b6000607d6079607584604a565b605e565b6054565b9050919050565b608b816068565b82525050565b600060208201905060a460008301846084565b92915050565b603f8060b76000396000f3fe6080604052600080fdfea264697066735822122084db7fe76bde5c9c041d61bb40294c56dc6d339bdbc8e0cd285fc4008ccefc2c64736f6c63430008180033';

before(async () => {
// deploy contract
const contract = await Utils.deployContract([], SIMPLE_CONTRACT_BYTECODE, global.accounts[0].wallet);

wsFilterObj = {
address: [contract.target],
fromBlock: '0x0',
toBlock: 'latest',
};
});

beforeEach(async () => {
ethersWsProvider = new ethers.WebSocketProvider(WsTestConstant.WS_RELAY_URL);
});

afterEach(async () => {
if (ethersWsProvider) await ethersWsProvider.destroy();
});

after(async () => {
// expect all the connections to be closed after all
expect(global.socketServer._connections).to.eq(0);
});

describe(WsTestConstant.STANDARD_WEB_SOCKET, () => {
for (const params of INVALID_PARAMS) {
it(`Should fail eth_newFilter on Standard Web Socket and throw predefined.INVALID_PARAMETERS if the request's params variable is invalid. params=[${JSON.stringify(
params,
)}]`, async () => {
await WsTestHelper.assertFailInvalidParamsStandardWebSocket(METHOD_NAME, params);
});
}

it(`Should execute eth_newFilter on Standard Web Socket and handle valid requests correctly`, async () => {
const response = await WsTestHelper.sendRequestToStandardWebSocket(METHOD_NAME, [wsFilterObj]);
WsTestHelper.assertJsonRpcObject(response);
const filterId = response.result;

await new Promise((r) => setTimeout(r, 90000));

expect(filterId).to.exist;
expect(filterId.startsWith('0x')).to.be.true;
expect(filterId.slice(2).length).to.eq(32); // 16 bytes
});
});

describe(WsTestConstant.ETHERS_WS_PROVIDER, () => {
for (const params of INVALID_PARAMS) {
it(`Should fail eth_newFilter on Ethers Web Socket Provider and throw predefined.INVALID_PARAMETERS if the request's params variable is invalid. params=[${JSON.stringify(
params,
)}]`, async () => {
await WsTestHelper.assertFailInvalidParamsEthersWsProvider(ethersWsProvider, METHOD_NAME, params);
});
}

it(`Should execute eth_newFilter on Ethers Web Socket Provider and handle valid requests correctly`, async () => {
const filterId = await ethersWsProvider.send(METHOD_NAME, [wsFilterObj]);

expect(filterId).to.exist;
expect(filterId.startsWith('0x')).to.be.true;
expect(filterId.slice(2).length).to.eq(32); // 16 bytes
});
});
});

0 comments on commit 3c16200

Please sign in to comment.