Skip to content

Commit 18ee5ac

Browse files
committed
improve docs, wip
1 parent 6f727f5 commit 18ee5ac

File tree

5 files changed

+128
-4
lines changed

5 files changed

+128
-4
lines changed

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,21 @@ Sample JSON response:
8383

8484
Security note: Private keys are shown once. Persist them securely (e.g. Vault, KMS). Never commit them.
8585

86+
### Log Filtering & Event Decoding
87+
```php
88+
use EvmLogs;
89+
use Farbcode\LaravelEvm\Support\LogFilterBuilder;
90+
$abi = file_get_contents(storage_path('app/abi/ERC20.abi.json'));
91+
$logs = EvmLogs::query()
92+
->fromBlock(18_000_000)
93+
->toBlock('latest')
94+
->address('0xToken')
95+
->eventByAbi($abi, 'Transfer')
96+
->topicAny(1, [LogFilterBuilder::padAddress($addrA), LogFilterBuilder::padAddress($addrB)])
97+
->get();
98+
$decoded = array_map(fn($l) => LogFilterBuilder::decodeEvent($abi, $l), $logs);
99+
```
100+
86101
### Facades Overview
87102

88103
Facade aliases (registered in `composer.json`):
@@ -95,6 +110,7 @@ Facade aliases (registered in `composer.json`):
95110
| `EvmSigner` | Signer |
96111
| `EvmFees` | FeePolicy |
97112
| `EvmNonce` | NonceManager |
113+
| `EvmLogs` | LogFilterBuilder |
98114

99115
Example usage:
100116
```php
@@ -105,6 +121,32 @@ $address = \EvmSigner::getAddress();
105121
// $fees = \EvmFees::suggest();
106122
```
107123

124+
### Chainable Casting
125+
126+
`call()` now returns the client instance for fluent casting. Raw hex is stored internally. Use `result()` to fetch it, then `as(type)` to cast.
127+
128+
```php
129+
$contract = \LaravelEvm::at('0xContract', $abi)->call('name');
130+
$raw = $contract->result(); // e.g. 0x0000...
131+
$name = $contract->as('string'); // decoded
132+
133+
$owner = $contract->call('owner')->as('address');
134+
$supply = $contract->call('totalSupply')->as('uint');
135+
$flag = $contract->call('isActive')->as('bool');
136+
```
137+
138+
Supported types: `string`, `address`, `uint|uint256`, `bool`, `bytes32` (returns hex). Unknown types fall back to raw value.
139+
140+
### Signer Robustness & Environment
141+
142+
Address derivation uses secp256k1 (via `kornrunner/ethereum-address`). On some PHP patch builds older GMP versions can throw a `ValueError` during point math with edge-case keys. Recommendations:
143+
1. Use a freshly generated private key (command above) – most issues disappear.
144+
2. Prefer latest PHP patch (8.4.x) where GMP edge cases are fixed.
145+
3. If derivation fails, you will get a `SignerException` with a clear message; do not bypass by hardcoding a mismatched address (nonce and signatures become inconsistent).
146+
4. For read-only calls in future you can implement a custom Signer driver returning only `getAddress()` without signing logic.
147+
148+
If you consistently see overflow errors, open an issue with your PHP version, GMP version, and the (non-sensitive) pattern of the key (do NOT share the full private key). This helps us improve cross-version resilience without adding unsafe fallbacks.
149+
108150
## Testing
109151

110152
```bash

docs/.vitepress/config.mts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { defineConfig } from 'vitepress';
2+
import pkg from '../package.json'
23

34
export default defineConfig({
45
title: 'Laravel EVM',
56
description: 'Reliable EVM interaction for Laravel (contracts, async transactions, fees, nonces, multi-RPC)',
6-
srcDir: '.',
7-
outDir: '../build/docs',
7+
srcDir: './pages',
88
cleanUrls: true,
99
lastUpdated: true,
10+
markdown: {
11+
theme: {
12+
light: 'github-light',
13+
dark: 'github-dark'
14+
}
15+
},
1016
themeConfig: {
1117
nav: [
1218
{ text: 'Guide', link: '/pages/README' },
@@ -60,7 +66,7 @@ export default defineConfig({
6066
],
6167
footer: {
6268
message: 'MIT Licensed',
63-
copyright: 'Copyright © 2025 Farbcode GmbH'
69+
copyright: 'Copyright © 2025 //farbcode GmbH'
6470
}
6571
}
6672
});

docs/pages/architecture.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,16 @@ Queue concurrency MUST be limited per address. Recommended: single worker for si
103103
- Plug-in system for fee strategies.
104104
- Configurable receipt polling backoff.
105105
- Adaptive RPC selection based on latency.
106+
107+
## Log Filtering & Event Decoding
108+
A dedicated fluent builder (`LogFilterBuilder`) powers the `EvmLogs` facade for convenient retrieval and optional decoding of contract events:
109+
- `event('Transfer(address,address,uint256)')` sets topic0 (keccak hash of signature).
110+
- `eventByAbi($abi, 'Transfer')` resolves the signature from an ABI entry.
111+
- `topic(i, value)` / `topicAny(i, [...])` / `topicWildcard(i)` for selective indexed filtering.
112+
- `padAddress($addr)` produces a 32-byte padded address topic value.
113+
- `decodeEvent($abi, $log)` returns associative array of decoded indexed + non-indexed params (static types only).
114+
115+
This keeps raw log querying decoupled from higher level transaction flow and enables post-processing / analytics (e.g. U18 election vote counting) without re‑implementing filtering logic.
116+
117+
## Added Facade: EvmLogs
118+
The `EvmLogs` facade resolves the builder (container binding: `LogFilterBuilder::class`). It integrates seamlessly with other components and uses the already configured `RpcClient` for network access.

docs/pages/examples.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,34 @@ If you detect repeated replacements:
9393
## 14. Fee Escalation Monitoring
9494
Listen to `TxReplaced` and log attempt number and fee delta.
9595

96+
## 15. Fetch and Decode Event Logs
97+
```php
98+
use EvmLogs; // facade
99+
use Farbcode\LaravelEvm\Support\LogFilterBuilder;
100+
101+
$abi = file_get_contents(storage_path('app/abi/ERC20.abi.json'));
102+
$logs = EvmLogs::query()
103+
->fromBlock(18_000_000)
104+
->toBlock('latest')
105+
->address('0xTokenAddress')
106+
->eventByAbi($abi, 'Transfer')
107+
->topic(1, LogFilterBuilder::padAddress('0xSender'))
108+
->get();
109+
110+
$decoded = array_map(fn($l) => LogFilterBuilder::decodeEvent($abi, $l), $logs);
111+
```
112+
OR topic match & wildcard:
113+
```php
114+
$logs = EvmLogs::query()
115+
->fromBlock('latest')
116+
->address(['0xTokenA','0xTokenB'])
117+
->event('Transfer(address,address,uint256)')
118+
->topicAny(1, [LogFilterBuilder::padAddress($addr1), LogFilterBuilder::padAddress($addr2)])
119+
->topicWildcard(2)
120+
->get();
121+
```
122+
123+
Performance tip: split large ranges into windows for high-volume contracts.
124+
96125
---
97126
Next: [Transactions](/pages/transactions) | Previous: [Facades](/pages/facades)

docs/pages/facades.md

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ The package registers multiple facades to streamline access to underlying servic
1010
| `EvmRpc` | `RpcClient` | Raw JSON-RPC calls and health checks |
1111
| `EvmSigner` | `Signer` | Access signing key & related helpers |
1212
| `EvmFees` | `FeePolicy` | Suggest and adjust fees |
13-
| `EvmNonce` | `NonceManager` | Nonce tracking
13+
| `EvmNonce` | `NonceManager` | Nonce tracking |
14+
| `EvmLogs` | `LogFilterBuilder` | Log filtering and event decoding |
1415

1516
## Using `LaravelEvm`
1617
```php
@@ -41,6 +42,39 @@ $key = EvmSigner::privateKey(); // avoid logging this
4142
$current = EvmNonce::current('0xSignerAddress');
4243
```
4344

45+
## EvmLogs (Log Filtering & Decoding)
46+
Fluent access to log filtering and basic event decoding.
47+
48+
Methods:
49+
- `query()` start a builder.
50+
- `fromBlock($n)` / `toBlock($n)` / `blockHash($hash)` define range.
51+
- `address($addrOrArray)` filter by one or multiple contract addresses.
52+
- `event($signature)` set topic0 via keccak hash.
53+
- `eventByAbi($abi, $name)` resolve signature from ABI.
54+
- `topic($i, $value)` exact match at index.
55+
- `topicAny($i, [...])` OR match alternatives.
56+
- `topicWildcard($i)` allow any topic value at index.
57+
- `padAddress($addr)` helper to produce a 32-byte topic form for indexed addresses.
58+
- `decodeEvent($abi, $log)` return associative array of values.
59+
60+
Example:
61+
```php
62+
$logs = EvmLogs::query()
63+
->fromBlock(18_000_000)
64+
->toBlock('latest')
65+
->address('0xContract')
66+
->event('Transfer(address,address,uint256)')
67+
->topic(1, LogFilterBuilder::padAddress($sender))
68+
->topicAny(2, [LogFilterBuilder::padAddress($recipientA), LogFilterBuilder::padAddress($recipientB)])
69+
->get();
70+
71+
$decoded = array_map(fn($l) => LogFilterBuilder::decodeEvent($abi, $l), $logs);
72+
```
73+
74+
Performance tip: For very large ranges split block intervals (e.g. batches of 5k blocks) and merge results.
75+
76+
Security tip: Do not feed unvalidated user input directly into `event()` or `topic()` without sanity checks.
77+
4478
## Static Analysis
4579
The `LaravelEvm` facade includes `@method` annotations for IDE autocomplete and PHPStan awareness.
4680

0 commit comments

Comments
 (0)