Skip to content

Commit 1ae13e8

Browse files
authored
Merge pull request #6 from farbcodegmbh/feat/eventPayload
event payload support for async EVM transactions
2 parents f430eaa + caa839a commit 1ae13e8

File tree

11 files changed

+82
-53
lines changed

11 files changed

+82
-53
lines changed

docs/pages/advanced-events.md

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
# Events
22

33
Transactional events provide lifecycle visibility for asynchronous writes. Use them for logging, metrics, user
4-
notifications, and fee escalation monitoring.
4+
notifications, and fee escalation monitoring. Each write-related event includes an optional `$payload` that you can attach via `sendAsync(..., $payload)`.
55

66
## Event List
77

8-
| Event | When Fired | Key Fields | Purpose |
9-
|-----------------|-----------------------|-----------------------------------------|-------------------------------------|
10-
| `TxQueued` | Job dispatched | request_id, function, address | Track submission before broadcast |
11-
| `TxBroadcasted` | First raw tx accepted | tx_hash, nonce, fees | Persist hash, start monitoring |
12-
| `TxReplaced` | Replacement broadcast | old_tx_hash, new_tx_hash, attempt, fees | Fee bump / speed-up diagnostics |
13-
| `TxMined` | Receipt obtained | tx_hash, receipt | Success; update state models |
14-
| `TxFailed` | Terminal failure | reason, attempts | Alert; possible manual intervention |
15-
| `CallPerformed` | Read call completed | from, to, function, raw_result | Auditing read queries |
8+
| Event | When Fired | Key Fields (excerpt) | Purpose |
9+
|-----------------|-----------------------|-------------------------------------|-------------------------------------|
10+
| `TxQueued` | Job dispatched | to, data, payload | Track submission before broadcast |
11+
| `TxBroadcasted` | First raw tx accepted | txHash, fields(fees,nonce), payload | Persist hash, start monitoring |
12+
| `TxReplaced` | Replacement broadcast | oldTxHash, newFields, attempt, payload | Fee bump / speed-up diagnostics |
13+
| `TxMined` | Receipt obtained | txHash, receipt, payload | Success; update state models |
14+
| `TxFailed` | Terminal failure | to, data, reason, payload | Alert; possible manual intervention |
15+
| `CallPerformed` | Read call completed | from, address, function, rawResult | Auditing read queries |
16+
17+
`payload` is `mixed` and can hold any serializable context (e.g. Eloquent model) to correlate app state and blockchain lifecycle.
18+
19+
## Attaching Payload Example
20+
21+
```php
22+
$order = Order::find(123);
23+
$contract->sendAsync('transfer', ['0xRecipient', 1000], [], $order);
24+
```
1625

1726
## Example Listener Registration
1827

@@ -37,8 +46,12 @@ class LogTxBroadcasted
3746
{
3847
Log::info('TX broadcasted', [
3948
'hash' => $e->txHash,
40-
'nonce' => $e->nonce,
41-
'fees' => $e->fees,
49+
'nonce' => $e->fields['nonce'] ?? null,
50+
'fees' => [
51+
'maxFeePerGas' => $e->fields['maxFeePerGas'] ?? null,
52+
'maxPriorityFeePerGas' => $e->fields['maxPriorityFeePerGas'] ?? null,
53+
],
54+
'payload_id' => method_exists($e->payload, 'getKey') ? $e->payload->getKey() : null,
4255
]);
4356
}
4457
}
@@ -84,4 +97,3 @@ On `TxFailed`, inspect `reason`:
8497
- Gas estimation failure: review contract & args.
8598
- Broadcast rejection: fees or nonce invalid.
8699
- Timeout without receipt: consider manual bump or external explorer check.
87-

docs/pages/basic-usage.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ $requestId = $contract->sendAsync('transfer', ['0xRecipient', 1000]);
6565
Writes enqueue a `SendTransaction` job. You need a running queue worker for progress (unless using the sync queue
6666
driver).
6767

68+
### Attaching Context Payload
69+
70+
You can attach any serializable payload (e.g. an Eloquent model instance) that will travel through all lifecycle events:
71+
72+
```php
73+
$order = Order::find(123);
74+
$requestId = $contract->sendAsync('transfer', ['0xRecipient', 1000], [], $order);
75+
```
76+
77+
Each emitted event (`TxQueued`, `TxBroadcasted`, `TxReplaced`, `TxMined`, `TxFailed`) will expose `$payload` so you can correlate blockchain progress with your domain object.
78+
6879
### Transaction Job Lifecycle
6980

7081
The queued job executes these steps:
@@ -181,4 +192,4 @@ $block = \Farbcode\LaravelEvm\Facades\EvmRpc::call('eth_blockNumber');
181192

182193
Direct access for diagnostics or unsupported methods.
183194

184-
Proceed to Advanced Usage for log filtering and custom components.
195+
Proceed to Advanced Usage for log filtering, events, payload handling details and custom components.

docs/pages/reference.md

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515

1616
## ContractClient (via `Evm`)
1717

18-
| Method | Args | Returns | Notes |
19-
|--------------------------------------------|----------------------------|----------------------|------------------------------------------|
20-
| `at(address, abi)` | `string`, `array\| string` | self | Set target contract & ABI JSON/array |
21-
| `call(fn, args=[])` | `string`, `array` | `CallResult\| mixed` | eth_call; hex wrapped for decoding |
22-
| `sendAsync(fn, args=[], opts=[])` | `string`, `array`, `array` | `string` | Dispatch async job; returns request UUID |
23-
| `wait(txHash, timeoutSec=120, pollMs=800)` | `string`, `int`, `int` | `array\| null` | Poll receipt until mined/timeout |
24-
| `estimateGas(data, from?)` | `string`, `?string` | `int` | Uses eth_estimateGas + padding |
18+
| Method | Args | Returns | Notes |
19+
|-------------------------------------------------|-----------------------------------|----------------------|------------------------------------------------------------------------|
20+
| `at(address, abi)` | `string`, `array\| string` | self | Set target contract & ABI JSON/array |
21+
| `call(fn, args=[])` | `string`, `array` | `CallResult\| mixed` | eth_call; hex wrapped for decoding |
22+
| `sendAsync(fn, args=[], opts=[], payload=null)` | `string`, `array`, `array`, mixed | `string` | Dispatch async job; returns request UUID; payload flows through events |
23+
| `wait(txHash, timeoutSec=120, pollMs=800)` | `string`, `int`, `int` | `array\| null` | Poll receipt until mined/timeout |
24+
| `estimateGas(data, from?)` | `string`, `?string` | `int` | Uses eth_estimateGas + padding |
2525

2626
### CallResult
2727

@@ -62,10 +62,10 @@
6262

6363
## FeePolicy (via `EvmFees`)
6464

65-
| Method | Args | Returns | Notes |
66-
|---------------------------|----------------|-----------------------------------------------------------|-----------------------------|
67-
| `suggest()` | - | `['maxFeePerGas'=>string,'maxPriorityFeePerGas'=>string]` | Initial fee suggestion |
68-
| `bump(previous, attempt)` | `array`, `int` | `array` | Adjust fees for replacement |
65+
| Method | Args | Returns | Notes |
66+
|----------------------------------------|--------------------------------------|--------------------------------|------------------------|
67+
| `suggest(callable $gasPriceFetcher)` | `callable $gasPriceFetcher` | `[priorityWei, maxFeeWei]` | Initial fee suggestion |
68+
| `replace(int $oldPriority, int $oldMax)`| `int $oldPriority, int $oldMax` | `[priorityWei, maxFeeWei]` | Replacement bump |
6969

7070
---
7171

@@ -104,14 +104,14 @@ Start with `EvmLogs::query()` then chain:
104104

105105
## Events
106106

107-
| Event | When | Key Data |
108-
|-----------------|--------------------|-----------------------------------|
109-
| `TxQueued` | Job pushed | request_id, function, address |
110-
| `TxBroadcasted` | First broadcast ok | tx_hash, nonce, fees |
111-
| `TxReplaced` | Fee bump broadcast | old_tx_hash, new_tx_hash, attempt |
112-
| `TxMined` | Receipt found | tx_hash, receipt |
113-
| `TxFailed` | Terminal failure | reason, attempts |
114-
| `CallPerformed` | Read executed | from, to, function, raw_result |
107+
| Event | When | Key Data (excerpt) |
108+
|-----------------|--------------------|----------------------------------------|
109+
| `TxQueued` | Job pushed | to, data, payload |
110+
| `TxBroadcasted` | First broadcast ok | txHash, fields, payload |
111+
| `TxReplaced` | Fee bump broadcast | oldTxHash, newFields, attempt, payload |
112+
| `TxMined` | Receipt found | txHash, receipt, payload |
113+
| `TxFailed` | Terminal failure | to, data, reason, payload |
114+
| `CallPerformed` | Read executed | from, address, function, rawResult |
115115

116116
---
117117

@@ -157,4 +157,4 @@ Maintains nonce ordering; for scaling use a distributed nonce manager.
157157
- Never log private keys.
158158
- Limit queue concurrency.
159159
- Use multiple RPC endpoints for resilience.
160-
160+
- Attach domain payloads to events for traceability.

src/Clients/ContractClientGeneric.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public function estimateGas(string $data, ?string $from = null): int
6868
return (int) max(150000, ceil($n * $pad));
6969
}
7070

71-
public function sendAsync(string $function, array $args = [], array $opts = []): string
71+
public function sendAsync(string $function, array $args = [], array $opts = [], mixed $payload = null): string
7272
{
7373
$data = $this->abi->encodeFunction($this->abiJson, $function, $args);
7474
$queue = (string) ($this->txCfg['queue'] ?? 'evm-send');
@@ -80,7 +80,8 @@ public function sendAsync(string $function, array $args = [], array $opts = []):
8080
data: $data,
8181
opts: array_merge($opts, ['request_id' => $requestId]),
8282
chainId: $this->chainId,
83-
txCfg: $this->txCfg
83+
txCfg: $this->txCfg,
84+
payload: $payload
8485
))->onQueue($queue);
8586

8687
return $requestId;

src/Contracts/ContractClient.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@ public function at(string $address, array|string $abi = []): self;
99
/** Synchronous read only call returning raw hex or decoded value depending on ABI usage. */
1010
public function call(string $function, array $args = []): mixed;
1111

12-
/** Enqueue a non blocking write job. Returns job id string. */
13-
public function sendAsync(string $function, array $args = [], array $opts = []): string;
12+
/**
13+
* Enqueue a non blocking write job. Returns job id string.
14+
* Optional $payload allows attaching any serializable context (e.g. an Eloquent model) that will
15+
* be forwarded to all transaction lifecycle events (TxQueued, TxBroadcasted, TxReplaced, TxMined, TxFailed).
16+
*/
17+
public function sendAsync(string $function, array $args = [], array $opts = [], mixed $payload = null): string;
1418

1519
/** Wait for a receipt with timeout returns receipt array or null. */
1620
public function wait(string $txHash, int $timeoutSec = 120, int $pollMs = 800): ?array;

src/Events/TxBroadcasted.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
class TxBroadcasted
88
{
9-
public function __construct(public string $txHash, public array $fields) {}
9+
public function __construct(public string $txHash, public array $fields, public mixed $payload = null) {}
1010
}

src/Events/TxFailed.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
class TxFailed
88
{
9-
public function __construct(public string $to, public string $data, public string $reason) {}
9+
public function __construct(public string $to, public string $data, public string $reason, public mixed $payload = null) {}
1010
}

src/Events/TxMined.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
class TxMined
88
{
9-
public function __construct(public string $txHash, public array $receipt) {}
9+
public function __construct(public string $txHash, public array $receipt, public mixed $payload = null) {}
1010
}

src/Events/TxQueued.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66

77
class TxQueued
88
{
9-
public function __construct(public string $to, public string $data) {}
9+
public function __construct(public string $to, public string $data, public mixed $payload = null) {}
1010
}

src/Events/TxReplaced.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ class TxReplaced
1111
* @param array $newFields Neue Felder inklusive angehobener Fees
1212
* @param int $attempt Laufende Ersatz-Versuchsnummer (1-basiert)
1313
*/
14-
public function __construct(public string $oldTxHash, public array $newFields, public int $attempt) {}
14+
public function __construct(public string $oldTxHash, public array $newFields, public int $attempt, public mixed $payload = null) {}
1515
}

0 commit comments

Comments
 (0)