From b1976af538bac54f27ba92adccc616db67b1d611 Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Wed, 30 Mar 2022 10:30:13 -0300 Subject: [PATCH 1/7] Creates Validator contract and exception --- src/Contracts/Validator.php | 27 +++++++++++++++++++++++++++ src/Exceptions/ValidatorException.php | 12 ++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/Contracts/Validator.php create mode 100644 src/Exceptions/ValidatorException.php diff --git a/src/Contracts/Validator.php b/src/Contracts/Validator.php new file mode 100644 index 0000000..f4331ac --- /dev/null +++ b/src/Contracts/Validator.php @@ -0,0 +1,27 @@ + Date: Wed, 30 Mar 2022 10:30:26 -0300 Subject: [PATCH 2/7] Implement FilterObject validator --- src/Validators/FilterObject.php | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/Validators/FilterObject.php diff --git a/src/Validators/FilterObject.php b/src/Validators/FilterObject.php new file mode 100644 index 0000000..c45ce43 --- /dev/null +++ b/src/Validators/FilterObject.php @@ -0,0 +1,40 @@ +> $arg + * @param array $config + * + * @throws ValidatorException + * + * @return bool + */ + public static function validate($arg, array $config = []): bool + { + if (!is_array($arg)) { + throw new ValidatorException('Expected FilterObject to be an array.'); + } + + if (isset($arg['topics']) && !is_array($arg['topics'])) { + throw new ValidatorException('Expected FilterObject topics to be an array.'); + } + + foreach (['address', 'fromBlock', 'toBlock', 'blockhash'] as $key) { + if (isset($arg[$key]) && !is_string($arg[$key])) { + throw new ValidatorException("Expected FilterObject $key value to be string."); + } + } + + return true; + } +} From bc5edba9131771d78f5a6e3e7e4f7231a2dd5746 Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Wed, 30 Mar 2022 10:30:45 -0300 Subject: [PATCH 3/7] Implement FilterObject validator test --- tests/Validators/FilterObject.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/Validators/FilterObject.php diff --git a/tests/Validators/FilterObject.php b/tests/Validators/FilterObject.php new file mode 100644 index 0000000..161e669 --- /dev/null +++ b/tests/Validators/FilterObject.php @@ -0,0 +1,26 @@ + '0x1a94fce7ef36bc90959e206ba569a12afbc91ca1', + 'fromBlock' => '12', + 'toBlock' => '24', + 'topics' => ['ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'], + 'blockhash' => '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', + ]); + expect($result)->toBe(true); +}); + +it('throws errors on invalid filter objects', function () { + $this->expectException(ValidatorException::class); + FilterObject::validate([ + 'address' => '0x1a94fce7ef36bc90959e206ba569a12afbc91ca1', + 'fromBlock' => '12', + 'toBlock' => '24', + 'topics' => 'ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', + 'blockhash' => '0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70', + ]); +}); From 555a2c03dc2cf9191dc9f77570d8e32ab2153f8f Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Wed, 30 Mar 2022 10:31:06 -0300 Subject: [PATCH 4/7] Implement eth_getLogs method --- src/Namespaces/Eth.php | 27 +++++++++++++++++ tests/Namespaces/Eth.php | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/Namespaces/Eth.php b/src/Namespaces/Eth.php index 0ee6650..2449855 100644 --- a/src/Namespaces/Eth.php +++ b/src/Namespaces/Eth.php @@ -10,6 +10,7 @@ use Web3\Formatters\BigIntegerToHex; use Web3\Formatters\HexToBigInteger; use Web3\Formatters\HexToWei; +use Web3\Validators\FilterObject; use Web3\ValueObjects\Transaction; use Web3\ValueObjects\Wei; @@ -237,6 +238,32 @@ public function blockNumber(): string return HexToBigInteger::format($result); } + /** + * Returns an array of all logs matching a given filter object. + * + * @see https://docs.infura.io/infura/networks/ethereum/json-rpc-methods/eth_getlogs + * @throws ErrorException|TransporterException + * @return array<> + */ + public function getLogs($filterObject = []): array + { + FilterObject::validate($filterObject); + + $result = $this->transporter->request('eth_getLogs', $filterObject); + + /** @var array> $result */ + assert(is_array($result)); + + /** @var array $log */ + foreach ($result as $logKey => $log) { + foreach (['blockNumber', 'logIndex', 'transactionIndex'] as $key) { + $result[$logKey][$key] = HexToBigInteger::format($log[$key]); + } + } + + return $result; + } + /** * Returns the coinbase address of the client. * diff --git a/tests/Namespaces/Eth.php b/tests/Namespaces/Eth.php index f6da357..498e3e9 100644 --- a/tests/Namespaces/Eth.php +++ b/tests/Namespaces/Eth.php @@ -256,3 +256,67 @@ )) ->toBe(true); }); + +test('get logs', function () { + $this->transporter->shouldReceive('request')->with( + 'eth_getLogs', + [] + )->once()->andReturn([ + [ + "address" => "0x1a94fce7ef36bc90959e206ba569a12afbc91ca1", + "blockHash" => "0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70", + "blockNumber" => "0x5c29fb", + "data" => "0x0000000000000000000000003e3310720058c51f0de456e273c626cdd35065700000000000000000000000000000000000000000000000000000000000003185000000000000000000000000000000000000000000000000000000000000318200000000000000000000000000000000000000000000000000000000005c2a23", + "logIndex" => "0x1d", + "removed" => false, + "topics" => [ + "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80" + ], + "transactionHash" => "0x3dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50", + "transactionIndex" => "0x1d" + ], + [ + "address" => "0x06012c8cf97bead5deae237070f9587f8e7a266d", + "blockHash" => "0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70", + "blockNumber" => "0x5c29fb", + "data" => "0x00000000000000000000000077ea137625739598666ded665953d26b3d8e374400000000000000000000000000000000000000000000000000000000000749ff00000000000000000000000000000000000000000000000000000000000a749d00000000000000000000000000000000000000000000000000000000005c2a0f", + "logIndex" => "0x57", + "removed" => false, + "topics" => [ + "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80" + ], + "transactionHash" => "0x788b1442414cb9c9a36dba2abe250763161a6f6395788a2e808f1b34e92beec1", + "transactionIndex" => "0x54" + ] + ]); + + expect($this->eth->getLogs([])) + ->toBe([ + [ + "address" => "0x1a94fce7ef36bc90959e206ba569a12afbc91ca1", + "blockHash" => "0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70", + "blockNumber" => "6040059", + "data" => "0x0000000000000000000000003e3310720058c51f0de456e273c626cdd35065700000000000000000000000000000000000000000000000000000000000003185000000000000000000000000000000000000000000000000000000000000318200000000000000000000000000000000000000000000000000000000005c2a23", + "logIndex" => "29", + "removed" => false, + "topics" => [ + "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80" + ], + "transactionHash" => "0x3dc91b98249fa9f2c5c37486a2427a3a7825be240c1c84961dfb3063d9c04d50", + "transactionIndex" => "29" + ], + [ + "address" => "0x06012c8cf97bead5deae237070f9587f8e7a266d", + "blockHash" => "0x7c5a35e9cb3e8ae0e221ab470abae9d446c3a5626ce6689fc777dcffcab52c70", + "blockNumber" => "6040059", + "data" => "0x00000000000000000000000077ea137625739598666ded665953d26b3d8e374400000000000000000000000000000000000000000000000000000000000749ff00000000000000000000000000000000000000000000000000000000000a749d00000000000000000000000000000000000000000000000000000000005c2a0f", + "logIndex" => "87", + "removed" => false, + "topics" => [ + "0x241ea03ca20251805084d27d4440371c34a0b85ff108f6bb5611248f73818b80" + ], + "transactionHash" => "0x788b1442414cb9c9a36dba2abe250763161a6f6395788a2e808f1b34e92beec1", + "transactionIndex" => "84" + ] + ]); +}); \ No newline at end of file From ed45d80ff09058a10e7d4369b2c4f4d401dd48ff Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Wed, 30 Mar 2022 11:10:06 -0300 Subject: [PATCH 5/7] Fix param and test --- src/Namespaces/Eth.php | 2 +- tests/Namespaces/Eth.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Namespaces/Eth.php b/src/Namespaces/Eth.php index 2449855..ad0ddd6 100644 --- a/src/Namespaces/Eth.php +++ b/src/Namespaces/Eth.php @@ -249,7 +249,7 @@ public function getLogs($filterObject = []): array { FilterObject::validate($filterObject); - $result = $this->transporter->request('eth_getLogs', $filterObject); + $result = $this->transporter->request('eth_getLogs', [$filterObject]); /** @var array> $result */ assert(is_array($result)); diff --git a/tests/Namespaces/Eth.php b/tests/Namespaces/Eth.php index 498e3e9..139cb60 100644 --- a/tests/Namespaces/Eth.php +++ b/tests/Namespaces/Eth.php @@ -260,7 +260,7 @@ test('get logs', function () { $this->transporter->shouldReceive('request')->with( 'eth_getLogs', - [] + [[]] )->once()->andReturn([ [ "address" => "0x1a94fce7ef36bc90959e206ba569a12afbc91ca1", From 8b6d3ed2524894b99426dc7fe26252ef0e39accd Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Wed, 30 Mar 2022 11:16:51 -0300 Subject: [PATCH 6/7] Accept decimal in filterObject --- src/Namespaces/Eth.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Namespaces/Eth.php b/src/Namespaces/Eth.php index ad0ddd6..bd26e7f 100644 --- a/src/Namespaces/Eth.php +++ b/src/Namespaces/Eth.php @@ -243,13 +243,23 @@ public function blockNumber(): string * * @see https://docs.infura.io/infura/networks/ethereum/json-rpc-methods/eth_getlogs * @throws ErrorException|TransporterException - * @return array<> + * @return array */ public function getLogs($filterObject = []): array { FilterObject::validate($filterObject); - $result = $this->transporter->request('eth_getLogs', [$filterObject]); + // Accept decimal + if (isset($filterObject['fromBlock']) && is_int($filterObject['fromBlock'])) { + $filterObject['fromBlock'] = BigIntegerToHex::format((string) $filterObject['fromBlock']); + } + if (isset($filterObject['toBlock']) && is_int($filterObject['toBlock'])) { + $filterObject['toBlock'] = BigIntegerToHex::format((string) $filterObject['toBlock']); + } + + $params = empty($filterObject) ? [] : [$filterObject]; + + $result = $this->transporter->request('eth_getLogs', $params); /** @var array> $result */ assert(is_array($result)); From 43570f6489e8708788660129e77f69095ce80ab6 Mon Sep 17 00:00:00 2001 From: Yudi Kubota Date: Thu, 31 Mar 2022 10:31:41 -0300 Subject: [PATCH 7/7] Fix eth_getLogs variable types --- src/Namespaces/Eth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Namespaces/Eth.php b/src/Namespaces/Eth.php index bd26e7f..8f10cbc 100644 --- a/src/Namespaces/Eth.php +++ b/src/Namespaces/Eth.php @@ -243,7 +243,7 @@ public function blockNumber(): string * * @see https://docs.infura.io/infura/networks/ethereum/json-rpc-methods/eth_getlogs * @throws ErrorException|TransporterException - * @return array + * @return array>> */ public function getLogs($filterObject = []): array { @@ -261,10 +261,10 @@ public function getLogs($filterObject = []): array $result = $this->transporter->request('eth_getLogs', $params); - /** @var array> $result */ + /** @var array>> $result */ assert(is_array($result)); - /** @var array $log */ + /** @var array $log */ foreach ($result as $logKey => $log) { foreach (['blockNumber', 'logIndex', 'transactionIndex'] as $key) { $result[$logKey][$key] = HexToBigInteger::format($log[$key]);