Skip to content
This repository has been archived by the owner on Feb 9, 2023. It is now read-only.

feat: add eth_getLogs #31 #32

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/Contracts/Validator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Web3\Contracts;

/**
* @template TArgumentValue
*
* @method static bool validate(TArgumentValue $value)
*
* @internal
*/
interface Validator
{
/**
* Validates an argument.
*
* @param mixed $arg
* @param array $config
*
* @throws ErrorException|ValidatorException
*
* @return bool
*/
public static function validate($arg, array $config): bool;
}
12 changes: 12 additions & 0 deletions src/Exceptions/ValidatorException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Web3\Exceptions;

use Exception;

final class ValidatorException extends Exception
{
// ..
}
37 changes: 37 additions & 0 deletions src/Namespaces/Eth.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -237,6 +238,42 @@ 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<array<string,string|array<string>>>
*/
public function getLogs($filterObject = []): array
{
FilterObject::validate($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<array<string, string|array<string>>> $result */
assert(is_array($result));

/** @var array<string, string|array<string> $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.
*
Expand Down
40 changes: 40 additions & 0 deletions src/Validators/FilterObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Web3\Validators;

use Web3\Contracts\Validator;
use Web3\Exceptions\ValidatorException;

final class FilterObject implements Validator
{
/**
* Validates a filter object.
*
* @param array<string, string|array<string>> $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;
}
}
64 changes: 64 additions & 0 deletions tests/Namespaces/Eth.php
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
]);
});
26 changes: 26 additions & 0 deletions tests/Validators/FilterObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

use Web3\Exceptions\ValidatorException;
use Web3\Validators\FilterObject;

it('validates filter objects', function () {
$result = FilterObject::validate([
'address' => '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',
]);
});